PipeEquipmentForm.vue 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. <template>
  2. <ContentWarp>
  3. <el-form
  4. ref="formRef"
  5. :model="formData"
  6. :rules="formRules"
  7. label-width="120px"
  8. v-loading="formLoading"
  9. class="form-container"
  10. >
  11. <!-- 使用单位信息 -->
  12. <div class="form-section">
  13. <h3>使用单位信息</h3>
  14. <div class="form-grid">
  15. <el-form-item label="使用单位名称" prop="unitName">
  16. <el-input v-model="formData.unitName" placeholder="请输入使用单位名称" @click="handleOpenUnitDialog" />
  17. </el-form-item>
  18. <el-form-item label="使用单位代码" prop="unitCode">
  19. <el-input v-model="formData.unitCode" placeholder="请输入使用单位代码" />
  20. </el-form-item>
  21. <el-form-item label="邮政编码" prop="postalCode">
  22. <el-input v-model="formData.postalCode" placeholder="请输入邮政编码" />
  23. </el-form-item>
  24. <el-form-item label="使用单位性质" prop="unitNature">
  25. <el-input v-model="formData.unitNature" placeholder="请输入使用单位性质" />
  26. </el-form-item>
  27. <el-form-item label="使用单位地址" prop="unitAddress">
  28. <el-input v-model="formData.unitAddress" placeholder="请输入使用单位地址" />
  29. </el-form-item>
  30. <el-form-item label="安全管理部门" prop="department">
  31. <el-input v-model="formData.department" placeholder="请输入安全管理部门" />
  32. </el-form-item>
  33. <el-form-item label="安全管理人" prop="securityMan">
  34. <el-input v-model="formData.securityMan" placeholder="请输入安全管理人" />
  35. </el-form-item>
  36. <el-form-item label="安全管理人电话" prop="securityManPhone">
  37. <el-input v-model="formData.securityManPhone" placeholder="请输入安全管理人电话" />
  38. </el-form-item>
  39. <el-form-item label="约检联系人" prop="contact">
  40. <el-input v-model="formData.contact" placeholder="请输入约检联系人" />
  41. </el-form-item>
  42. <el-form-item label="约检联系人电话" prop="contactPhone">
  43. <el-input v-model="formData.contactPhone" placeholder="请输入约检联系人电话" />
  44. </el-form-item>
  45. <el-form-item label="联系人邮箱" prop="contactEmail">
  46. <el-input v-model="formData.contactEmail" placeholder="请输入联系人邮箱" />
  47. </el-form-item>
  48. <el-form-item label="电子报告接收人" prop="recipient">
  49. <el-input v-model="formData.recipient" placeholder="请输入电子报告接收人" />
  50. </el-form-item>
  51. <el-form-item label="电子报告接收人手机" prop="recipientPhone">
  52. <el-input v-model="formData.recipientPhone" placeholder="请输入电子报告接收人手机" />
  53. </el-form-item>
  54. <el-form-item label="电子报告接收人邮箱" prop="recipientEmail">
  55. <el-input v-model="formData.recipientEmail" placeholder="请输入电子报告接收人邮箱" />
  56. </el-form-item>
  57. <el-form-item label="缴费联系人" prop="payment">
  58. <el-input v-model="formData.payment" placeholder="请输入缴费联系人" />
  59. </el-form-item>
  60. <el-form-item label="缴费联系人手机" prop="paymentPhone">
  61. <el-input v-model="formData.paymentPhone" placeholder="请输入缴费联系人手机" />
  62. </el-form-item>
  63. <el-form-item label="缴费联系人邮箱" prop="paymentEmail">
  64. <el-input v-model="formData.paymentEmail" placeholder="请输入缴费联系人邮箱" />
  65. </el-form-item>
  66. </div>
  67. </div>
  68. <!-- 管道信息 -->
  69. <div class="form-section">
  70. <div class="section-header">
  71. <h3>管道信息</h3>
  72. </div>
  73. <div class="form-grid">
  74. <el-form-item label="使用登记证编号" prop="pipeNum">
  75. <el-input v-model="formData.certificateNo" placeholder="请输入使用登记证编号" />
  76. </el-form-item>
  77. <el-form-item label="工程号" prop="projectNo">
  78. <el-input v-model="formData.projectNo" placeholder="请输入工程号" />
  79. </el-form-item>
  80. <el-form-item label="工程名称" prop="projectName">
  81. <el-input v-model="formData.projectName" placeholder="请输入工程名称" />
  82. </el-form-item>
  83. <el-form-item label="管道类别" prop="pipeCategory">
  84. <el-select v-model="formData.pipeCategory" placeholder="请选择管道类别">
  85. <el-option
  86. v-for="dict in getStrDictOptions(DICT_TYPE.PIPE_TYPE)"
  87. :key="dict.value"
  88. :label="dict.label"
  89. :value="dict.value"
  90. />
  91. </el-select>
  92. </el-form-item>
  93. <el-form-item label="管道最高级别" prop="pipeClass">
  94. <el-select v-model="formData.pipeClass" placeholder="请选择管道最高级别">
  95. <el-option
  96. v-for="dict in getStrDictOptions(DICT_TYPE.PRESSURE2_PIPE_LEVEL)"
  97. :key="dict.value"
  98. :label="dict.label"
  99. :value="dict.value"
  100. />
  101. </el-select>
  102. </el-form-item>
  103. <!-- <el-form-item label="管道使用场所" prop="pipeUsePlace">-->
  104. <!-- <el-input v-model="formData.pipeUsePlace" placeholder="请输入管道使用场所" />-->
  105. <!-- </el-form-item>-->
  106. <el-form-item label="所在行政区" prop="equipDistrict">
  107. <AreaSelect
  108. v-model="formData.equipDistrict"
  109. placeholder="请选择所在区"
  110. @change="handleAreaChange"
  111. @clear="handleAreaClear"
  112. />
  113. </el-form-item>
  114. <el-form-item label="所在街道" prop="equipStreet">
  115. <StreetSelect
  116. v-model="formData.equipStreet"
  117. :district-ids="[formData.equipDistrict]"
  118. placeholder="请选择所在街道"
  119. @change="handleStreetChange"
  120. @clear="handleStreetClear"
  121. />
  122. </el-form-item>
  123. <el-form-item label="管道使用地址" prop="pipeAddress">
  124. <el-input v-model="formData.pipeAddress" placeholder="请输入管道使用地址" />
  125. </el-form-item>
  126. <el-form-item label="地址经度" prop="lng">
  127. <el-input-number controls-position="right" v-model="formData.lng" placeholder="请输入地址经度" />
  128. </el-form-item>
  129. <el-form-item label="地址纬度" prop="lat">
  130. <el-input-number controls-position="right" v-model="formData.lat" placeholder="请输入地址纬度" />
  131. </el-form-item>
  132. <el-form-item label="使用状态" prop="useStatus">
  133. <el-select v-model="formData.useStatus" placeholder="请选择使用状态">
  134. <el-option
  135. v-for="dict in getStrDictOptions(DICT_TYPE.PIPE_USE_STATUS)"
  136. :key="dict.value"
  137. :label="dict.label"
  138. :value="dict.value"
  139. />
  140. </el-select>
  141. </el-form-item>
  142. <el-form-item label="是否有效" prop="isEffective">
  143. <el-radio-group v-model="formData.isEffective">
  144. <el-radio value="是">是</el-radio>
  145. <el-radio value="否">否</el-radio>
  146. </el-radio-group>
  147. </el-form-item>
  148. <el-form-item label="敷设方式" prop="layingMode">
  149. <el-input v-model="formData.layingMode" placeholder="请输入敷设方式" />
  150. </el-form-item>
  151. <el-form-item label="管道总长度" prop="pipeLengthTotal">
  152. <el-input controls-position="right" v-model="formData.pipeLengthTotal" placeholder="请输入总长度" />
  153. </el-form-item>
  154. <el-form-item label="是否存在埋地管道" prop="hasUndergroundPipe">
  155. <el-input v-model="hasUndergroundPipeText" placeholder="由子表汇总" disabled />
  156. </el-form-item>
  157. <el-form-item label="埋地管道总长度" prop="undergroundLengthTotal">
  158. <el-input controls-position="right" v-model="undergroundLengthTotal" placeholder="由子表汇总" disabled />
  159. </el-form-item>
  160. <el-form-item label="责任部门" prop="relationDept">
  161. <DeptSelect
  162. v-model="formData.relationDept"
  163. placeholder="请选择责任部门"
  164. clearable
  165. />
  166. </el-form-item>
  167. <el-form-item label="设计单位" prop="designUnit">
  168. <el-input v-model="formData.designUnit" placeholder="请输入设计单位" />
  169. </el-form-item>
  170. <el-form-item label="设计单位许可证书编号" prop="desognUnitPermitCode">
  171. <el-input v-model="formData.desognUnitPermitCode" placeholder="请输入设计单位许可证书编号" />
  172. </el-form-item>
  173. <el-form-item label="设计主图号" prop="designNo">
  174. <el-input v-model="formData.designNo" placeholder="请输入设计主图号" />
  175. </el-form-item>
  176. <el-form-item label="施工单位" prop="constructionUnit">
  177. <el-input v-model="formData.constructionUnit" placeholder="请输入施工单位" />
  178. </el-form-item>
  179. <el-form-item label="施工单位许可证书编号" prop="constructionUnitPermitCode">
  180. <el-input v-model="formData.constructionUnitPermitCode" placeholder="请输入施工单位许可证书编号" />
  181. </el-form-item>
  182. <el-form-item label="检测机构" prop="testingOrganization">
  183. <el-input v-model="formData.testingOrganization" placeholder="请输入检测机构" />
  184. </el-form-item>
  185. <el-form-item label="检测机构核准证书编号" prop="testingOrganizationPermitCode">
  186. <el-input v-model="formData.testingOrganizationPermitCode" placeholder="请输入检测机构核准证书编号" />
  187. </el-form-item>
  188. <el-form-item label="验收日期" prop="acceptdate">
  189. <el-date-picker v-model="formData.acceptdate" type="date" value-format="YYYY-MM-DD" placeholder="请选择验收日期" />
  190. </el-form-item>
  191. <el-form-item label="承受交变应力" prop="alternating">
  192. <el-input v-model="formData.alternating" placeholder="请输入承受交变应力" />
  193. </el-form-item>
  194. <el-form-item label="防腐层材料" prop="antisepsis">
  195. <el-input v-model="formData.antisepsis" placeholder="请输入防腐层材料" />
  196. </el-form-item>
  197. <el-form-item label="管道连接方式" prop="attendedMode">
  198. <el-input v-model="formData.attendedMode" placeholder="请输入管道连接方式" />
  199. </el-form-item>
  200. <el-form-item label="腐蚀裕量" prop="cautery">
  201. <el-input v-model="formData.cautery" placeholder="请输入腐蚀裕量" />
  202. </el-form-item>
  203. <el-form-item label="设计日期" prop="designdate">
  204. <el-date-picker v-model="formData.designdate" type="date" value-format="YYYY-MM-DD" placeholder="请选择设计日期" />
  205. </el-form-item>
  206. <el-form-item label="设计规范" prop="designstandard">
  207. <el-input v-model="formData.designstandard" placeholder="请输入设计规范" />
  208. </el-form-item>
  209. <el-form-item label="设计温度" prop="designtemperature">
  210. <el-input v-model="formData.designtemperature" placeholder="请输入设计温度" />
  211. </el-form-item>
  212. <el-form-item label="火灾危险性" prop="fireRisk">
  213. <el-input v-model="formData.fireRisk" placeholder="请输入火灾危险性" />
  214. </el-form-item>
  215. <el-form-item label="安装日期" prop="installdate">
  216. <el-date-picker v-model="formData.installdate" type="date" value-format="YYYY-MM-DD" placeholder="请选择安装日期" />
  217. </el-form-item>
  218. <el-form-item label="安装验收规范" prop="installstandard">
  219. <el-input v-model="formData.installstandard" placeholder="请输入安装验收规范" />
  220. </el-form-item>
  221. <el-form-item label="绝热层材料" prop="insulation">
  222. <el-input v-model="formData.insulation" placeholder="请输入绝热层材料" />
  223. </el-form-item>
  224. <el-form-item label="绝热层厚度" prop="insulationply">
  225. <el-input v-model="formData.insulationply" placeholder="请输入绝热层厚度" />
  226. </el-form-item>
  227. <!-- <el-form-item label="敷设方式" prop="laytype">-->
  228. <!-- <el-input v-model="formData.laytype" placeholder="请输入敷设方式" />-->
  229. <!-- </el-form-item>-->
  230. <el-form-item label="管材牌号" prop="materialno">
  231. <el-input v-model="formData.materialno" placeholder="请输入管材牌号" />
  232. </el-form-item>
  233. <el-form-item label="管材标准" prop="materialstandard">
  234. <el-input v-model="formData.materialstandard" placeholder="请输入管材标准" />
  235. </el-form-item>
  236. <el-form-item label="介质毒性程度" prop="mediumToxicityLevel">
  237. <el-input v-model="formData.mediumToxicityLevel" placeholder="请输入介质毒性程度" />
  238. </el-form-item>
  239. <!-- <el-form-item label="下次在线检验日期" prop="nextonlinedate">-->
  240. <!-- <el-date-picker v-model="formData.nextonlinedate" type="date" value-format="YYYY-MM-DD" placeholder="请选择下次在线检验日期" />-->
  241. <!-- </el-form-item>-->
  242. <el-form-item label="在线检验的项目" prop="onlineitem">
  243. <el-input v-model="formData.onlineitem" placeholder="请输入在线检验的项目" />
  244. </el-form-item>
  245. <el-form-item label="被计划的次数" prop="plannums">
  246. <el-input v-model="formData.plannums" placeholder="请输入被计划的次数" />
  247. </el-form-item>
  248. <el-form-item label="剧烈循环工况" prop="severeCyclic">
  249. <el-input v-model="formData.severeCyclic" placeholder="请输入剧烈循环工况" />
  250. </el-form-item>
  251. <el-form-item label="管道主要规格" prop="standard">
  252. <el-input v-model="formData.standard" placeholder="请输入管道主要规格" />
  253. </el-form-item>
  254. </div>
  255. </div>
  256. <!-- 管道明细子表 -->
  257. <div class="form-section">
  258. <div class="section-header">
  259. <h3>管道一览表</h3>
  260. <el-button plain type="primary" @click="openPipeDetailForm">
  261. <Icon icon="ep:plus" class="mr-5px" /> 新增管道设计安装信息
  262. </el-button>
  263. </div>
  264. <PipeEquipmentDetailList
  265. ref="pipeEquipmentDetailFormRef"
  266. v-model:rows="formData.detailSaveReqVOS"
  267. :project-no="formData.projectNo"
  268. :project-name="formData.projectName"
  269. />
  270. </div>
  271. <!-- 检验信息 -->
  272. <div class="form-section">
  273. <h3>安装监检信息</h3>
  274. <div class="form-grid">
  275. <el-form-item label="安装监检报告编号" prop="installCheckReportNo">
  276. <el-input v-model="formData.installCheckReportNo" placeholder="请输入安装监检报告编号">
  277. <template #append>
  278. <Copy :text="formData.installCheckReportNo" />
  279. </template>
  280. </el-input>
  281. </el-form-item>
  282. </div>
  283. </div>
  284. <!-- 法定检验信息 -->
  285. <div class="form-section">
  286. <h3>全面检验信息</h3>
  287. <div class="form-grid">
  288. <el-form-item label="上次全检报告编号" prop="lastLegalPeriodicalInspectionReportNo">
  289. <el-input v-model="formData.lastLegalPeriodicalInspectionReportNo" placeholder="请输入上次全检报告编号">
  290. <template #append>
  291. <Copy :text="formData.lastLegalPeriodicalInspectionReportNo" />
  292. </template>
  293. </el-input>
  294. </el-form-item>
  295. <el-form-item label="下次全面检验日期" prop="nextLegalCheckDate">
  296. <el-date-picker v-model="formData.nextLegalCheckDate" type="date" value-format="YYYY-MM-DD" placeholder="选择下次全面检验日期" />
  297. </el-form-item>
  298. <el-form-item label="最低安全状况等级" prop="minSafetyStatusReg">
  299. <el-input v-model="formData.minSafetyStatusReg" placeholder="请输入最低安全状况等级" />
  300. </el-form-item>
  301. <el-form-item label="上次检验检查结论" prop="lastLegalConclusion">
  302. <el-input v-model="formData.lastLegalConclusion" placeholder="请输入上次检验检查结论" />
  303. </el-form-item>
  304. <el-form-item label="上次检验检查发现的问题" prop="lastLegalIssues" class="full-width">
  305. <el-input type="textarea" v-model="formData.lastLegalIssues" placeholder="请输入上次检验检查发现的问题" />
  306. </el-form-item>
  307. </div>
  308. </div>
  309. <!-- 年度检查信息 -->
  310. <div class="form-section">
  311. <h3>年度检查信息</h3>
  312. <div class="form-grid">
  313. <el-form-item label="上次年检报告编号" prop="lastYearReportNo">
  314. <el-input v-model="formData.lastYearReportNo" placeholder="请输入上次年检报告编号">
  315. <template #append>
  316. <Copy :text="formData.lastYearReportNo" />
  317. </template>
  318. </el-input>
  319. </el-form-item>
  320. <el-form-item label="下次年检日期" prop="nextYearCheckDate">
  321. <el-date-picker v-model="formData.nextYearCheckDate" type="date" value-format="YYYY-MM-DD" placeholder="选择下次年检日期" />
  322. </el-form-item>
  323. <el-form-item label="最低安全状况等级" prop="installationStatusReg">
  324. <el-input v-model="formData.installationStatusReg" placeholder="请输入最低安全状况等级" />
  325. </el-form-item>
  326. <el-form-item label="上次检验检查结论" prop="lastYearConclusion">
  327. <el-input v-model="formData.lastYearConclusion" placeholder="请输入上次检验检查结论" />
  328. </el-form-item>
  329. <el-form-item label="上次检验检查发现的问题" prop="lastYearIssues" class="full-width">
  330. <el-input type="textarea" v-model="formData.lastYearIssues" placeholder="请输入上次检验检查发现的问题" />
  331. </el-form-item>
  332. </div>
  333. </div>
  334. <!-- 维修改造信息 -->
  335. <div class="form-section">
  336. <h3>维修改造监检信息</h3>
  337. <div class="form-grid">
  338. <el-form-item label="上次维修改造监检报告编号" prop="lastMaintenanceReportNo">
  339. <el-input v-model="formData.lastMaintenanceReportNo" placeholder="请输入上次维修改造监检报告编号">
  340. <template #append>
  341. <Copy :text="formData.lastMaintenanceReportNo" />
  342. </template>
  343. </el-input>
  344. </el-form-item>
  345. <el-form-item label="监督检验开始日期" prop="supervisionStartDate">
  346. <el-date-picker v-model="formData.supervisionStartDate" type="date" value-format="YYYY-MM-DD" placeholder="选择监督检验开始日期" />
  347. </el-form-item>
  348. <el-form-item label="监督检验结束日期" prop="supervisionEndDate">
  349. <el-date-picker v-model="formData.supervisionEndDate" type="date" value-format="YYYY-MM-DD" placeholder="选择监督检验结束日期" />
  350. </el-form-item>
  351. <el-form-item label="上次维修改造内容" prop="lastMaintenanceContent" class="full-width">
  352. <el-input type="textarea" v-model="formData.lastMaintenanceContent" placeholder="请输入上次维修改造内容" />
  353. </el-form-item>
  354. </div>
  355. </div>
  356. <!-- 历史信息组件 -->
  357. <PipeEquipmentHistory
  358. v-if="showHistory"
  359. ref="historyRef"
  360. />
  361. <!-- 底部按钮 -->
  362. <div class="form-footer">
  363. <el-button type="primary" @click="submitForm">保存</el-button>
  364. <el-button type="success" @click="toggleHistory">
  365. {{ showHistory ? '隐藏' : '显示' }}市局信息
  366. </el-button>
  367. <el-button @click="goBack">取消</el-button>
  368. </div>
  369. </el-form>
  370. <!-- 管道明细表单 -->
  371. <PipeEquipmentDetailForm ref="pipeDetailFormRef" @success="handleDetailSuccess" />
  372. </ContentWarp>
  373. <CustomDialog
  374. ref="customUnitDialogRef"
  375. v-model="customUnitDialogVisible"
  376. :dialogAttrs="{
  377. zIndex: 10006
  378. }"
  379. @confirm="handleUnitConfirm"
  380. >
  381. <SmartTable
  382. ref="unitTableRef"
  383. v-model:pageNo="unitPageNo"
  384. v-model:pagesize="unitPageSize"
  385. :total="unitTotal"
  386. :columns="unitColumns"
  387. :data="unitTableList"
  388. :buttons="[]"
  389. :showSettingTools="true"
  390. :showRefresh="false"
  391. :tableProps="{
  392. onSelect: handleUnitSelect
  393. }"
  394. @onPageNoChange="handleFetchUnitList"
  395. @onPageSizeChange="pageSizeChange"
  396. />
  397. </CustomDialog>
  398. </template>
  399. <script setup lang="ts">
  400. import { ref, unref, watch, onMounted, nextTick } from 'vue'
  401. import { useI18n } from '@/hooks/web/useI18n'
  402. import { useMessage } from '@/hooks/web/useMessage'
  403. import { useRouter, useRoute } from 'vue-router'
  404. import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
  405. import { EquipPipeApi } from '@/api/pressure2/equippipe'
  406. import type { EquipPipeDetailVO, EquipPipeVO } from '@/api/pressure2/equippipe'
  407. import { required } from '@/utils/formRules'
  408. import PipeEquipmentDetailList from './components/PipeEquipmentDetailList.vue'
  409. import AreaSelect from '@/views/system/equipcontainer/components/AreaSelect.vue'
  410. import StreetSelect from '@/views/system/equipcontainer/components/StreetSelect.vue'
  411. import PipeEquipmentDetailForm from './components/PipeEquipmentDetailForm.vue'
  412. import { useTagsViewStore } from '@/store/modules/tagsView'
  413. import dayjs from 'dayjs'
  414. import Copy from '@/views/system/equipcontainer/components/Copy.vue'
  415. import PipeEquipmentHistory from './components/PipeEquipmentHistory.vue'
  416. import SmartTable from "@/components/SmartTable/SmartTable";
  417. import {getUnitList} from "@/api/laboratory/unit";
  418. import {validatePhone} from "@/utils/validateRules";
  419. import {string} from "vue-types";
  420. import { useEmitt } from '@/hooks/web/useEmitt'
  421. defineOptions({ name: 'PipeEquipmentForm' })
  422. const { t } = useI18n() // 国际化
  423. const message = useMessage() // 消息弹窗
  424. const router = useRouter()
  425. const route = useRoute()
  426. const tagsViewStore = useTagsViewStore()
  427. const { emitter } = useEmitt()
  428. // 页面标题
  429. const pageTitle = ref('')
  430. // 表单相关变量
  431. const formLoading = ref(false)
  432. const formRef = ref()
  433. const formData = ref<EquipPipeVO>({} as EquipPipeVO)
  434. // 由子表计算的字段
  435. const hasUndergroundPipeText = ref('否')
  436. const undergroundLengthTotal = ref(0)
  437. const pipeEquipmentDetailFormRef = ref()
  438. const pipeDetailFormRef = ref()
  439. const historyRef = ref()
  440. const showHistory = ref(false)
  441. // 表单校验规则
  442. const formRules = {
  443. unitName: [required],
  444. equipDistrict : [required],
  445. useProjectCode: [required],
  446. projectNo: [required],
  447. projectName: [required],
  448. useStatus: [required],
  449. contactPhone: [
  450. { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
  451. ],
  452. contactEmail: [
  453. { pattern: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/, message: '请输入正确的邮箱', trigger: 'blur' }
  454. ],
  455. recipientPhone: [
  456. { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
  457. ],
  458. recipientEmail: [
  459. { pattern: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/, message: '请输入正确的邮箱', trigger: 'blur' }
  460. ],
  461. paymentPhone: [
  462. { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
  463. ],
  464. paymentEmail: [
  465. { pattern: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/, message: '请输入正确的邮箱', trigger: 'blur' }
  466. ]
  467. }
  468. const areaStreetMap = ref<Map<number, number[]>>(new Map())
  469. const handleAreaClear = () => {
  470. formData.value.equipDistrict = ''
  471. areaStreetMap.value.clear()
  472. }
  473. const handleAreaChange = (areas: number[]) => {
  474. formData.value.equipStreet = ''
  475. areaStreetMap.value.clear()
  476. return
  477. }
  478. const handleStreetClear = () => {
  479. areaStreetMap.value.clear()
  480. }
  481. const handleStreetChange = (streets: number[], areaId: number) => {
  482. if (formData.value.equipDistrict && areaId === formData.value.equipDistrict) {
  483. areaStreetMap.value.set(areaId, streets)
  484. }
  485. }
  486. // 返回上一页
  487. const goBack = () => {
  488. tagsViewStore.delView(route)
  489. router.back()
  490. }
  491. // 初始化数据
  492. const initData = async () => {
  493. const id = route.query.id as string
  494. const type = route.query.type as string
  495. if (type === 'create') {
  496. pageTitle.value = t('action.create')
  497. } else {
  498. pageTitle.value = t('action.update')
  499. if (id) {
  500. formLoading.value = true
  501. try {
  502. const data = await EquipPipeApi.getEquipPipe(id)
  503. // 格式化日期字段
  504. const dateFields = ['nextLegalCheckDate', 'nextYearCheckDate', 'supervisionStartDate', 'supervisionEndDate']
  505. dateFields.forEach(field => {
  506. if (data[field]) {
  507. data[field] = dayjs(data[field]).format('YYYY-MM-DD')
  508. }
  509. })
  510. formData.value = data
  511. } finally {
  512. formLoading.value = false
  513. }
  514. }
  515. }
  516. }
  517. // 提交表单
  518. const submitForm = async () => {
  519. const elForm = unref(formRef)
  520. if (!elForm) return
  521. await elForm.validate()
  522. formLoading.value = true
  523. try {
  524. // 转换明细数据
  525. const submitData = {
  526. ...formData.value,
  527. }
  528. // 使用 dayjs 将日期字段转换为时间戳
  529. // const dateFields = ['nextLegalCheckDate', 'nextYearCheckDate', 'supervisionStartDate', 'supervisionEndDate']
  530. // dateFields.forEach(field => {
  531. // if (submitData[field]) {
  532. // // 使用 dayjs().valueOf() 获取毫秒时间戳
  533. // submitData[field] = dayjs(submitData[field]).valueOf()
  534. // }
  535. // })
  536. // 去掉默认id
  537. submitData.detailSaveReqVOS?.forEach(item => {
  538. if (item.id && item.id.length !== 32){
  539. delete item.id
  540. }
  541. })
  542. if (route.query.type === 'create') {
  543. await EquipPipeApi.createEquipPipe(submitData)
  544. message.success(t('common.createSuccess'))
  545. } else {
  546. await EquipPipeApi.updateEquipPipe(submitData)
  547. message.success(t('common.updateSuccess'))
  548. // 发送设备编辑成功事件,通知任务详情页面刷新数据
  549. emitter.emit('equipment-edit-success')
  550. }
  551. tagsViewStore.delView(route)
  552. router.back()
  553. } finally {
  554. formLoading.value = false
  555. }
  556. }
  557. // 监听表单数据变化
  558. watch(
  559. () => formData.value,
  560. (newVal) => {
  561. if (newVal.equipDistrict) {
  562. // 确保行政区划是数字类型
  563. formData.value.equipDistrict = Number(newVal.equipDistrict)
  564. }
  565. if (newVal.equipStreet) {
  566. // 确保街道是数字类型
  567. formData.value.equipStreet = Number(newVal.equipStreet)
  568. }
  569. // 计算管道总长度
  570. if (newVal.detailSaveReqVOS){
  571. formData.value.pipeLengthTotal = formData.value.detailSaveReqVOS.reduce((total, item) => total + item.pipeLength, 0)
  572. // 计算是否存在埋地管道(任一条为是则为是,全否则为否)
  573. undergroundLengthTotal.value = newVal.detailSaveReqVOS.reduce((total, item) => total + (item.undergroundLength || 0), 0)
  574. }
  575. if (newVal.detailSaveReqVOS && newVal.detailSaveReqVOS.length > 0) {
  576. hasUndergroundPipeText.value = newVal.detailSaveReqVOS.some(item => item.isUnderground === true) ? '是' : '否'
  577. // 计算埋地管道总长度
  578. } else {
  579. hasUndergroundPipeText.value = '否'
  580. }
  581. },
  582. { deep: true, immediate: true }
  583. )
  584. // 处理管道明细保存成功
  585. const handleDetailSuccess = (detail: EquipPipeDetailVO,formType) => {
  586. // console.log('handleDetailSuccess', detail)
  587. if (!formData.value.detailSaveReqVOS) {
  588. formData.value.detailSaveReqVOS = []
  589. }
  590. if (formType.value == 'update') {
  591. const index = formData.value.detailSaveReqVOS.findIndex(item => item.id === detail.id)
  592. formData.value.detailSaveReqVOS[index] = detail
  593. } else if (formType.value == 'create'){
  594. // 如果是新增,直接追加
  595. formData.value.detailSaveReqVOS.push(detail)
  596. }
  597. }
  598. // 打开管道明细表单
  599. const openPipeDetailForm = () => {
  600. pipeDetailFormRef.value?.open('create', undefined, {
  601. projectNo: formData.value.projectNo,
  602. projectName: formData.value.projectName
  603. })
  604. }
  605. // 切换历史信息显示/隐藏
  606. const toggleHistory = async () => {
  607. showHistory.value = !showHistory.value
  608. if (showHistory.value && formData.value?.projectNo) {
  609. // 如果是显示且有工程号,则加载历史数据
  610. await nextTick()
  611. historyRef.value?.loadHistoryData(formData.value.projectNo)
  612. }
  613. }
  614. onMounted(() => {
  615. initData()
  616. })
  617. // 选择单位弹窗
  618. const unitTableRef = ref()
  619. const customUnitDialogVisible = ref(false)
  620. const unitColumns = ref([
  621. {
  622. type: 'selection',
  623. width: '50px'
  624. },
  625. {
  626. label: '单位代码',
  627. prop: 'code',
  628. },
  629. {
  630. label: '单位名称',
  631. prop: 'name',
  632. }
  633. ])
  634. const unitTableList = ref([])
  635. const unitPageNo = ref(1)
  636. const unitPageSize = ref(10)
  637. const unitTotal = ref(0)
  638. const handleUnitSelect = (selections, row) => {
  639. if(selections.length > 1) {
  640. ElMessage.warning(`最多可选择1个`)
  641. unitTableRef.value.getTableRef().toggleRowSelection(row, false)
  642. return
  643. }
  644. }
  645. const pageSizeChange = (value) => {
  646. unitPageSize.value = value
  647. handleFetchUnitList()
  648. }
  649. const handleFetchUnitList = async () => {
  650. const result = await getUnitList({
  651. pageNo: unitPageNo.value,
  652. pageSize: unitPageSize.value,
  653. })
  654. unitTableList.value = result.list
  655. unitTotal.value = result.total
  656. }
  657. const handleUnitConfirm = () => {
  658. const selectedRow = unitTableRef.value.getTableRef().getSelectionRows()
  659. if(selectedRow.length === 0) return
  660. formData.value.unitName = selectedRow[0].name
  661. formData.value.unitCode = selectedRow[0].code
  662. formData.value.unitId = selectedRow[0].id
  663. formData.value.postalCode = selectedRow[0].post
  664. }
  665. // 打开单位选择框
  666. const handleOpenUnitDialog = (ev) => {
  667. ev.target.blur()
  668. customUnitDialogVisible.value = true
  669. handleFetchUnitList()
  670. }
  671. </script>
  672. <style lang="scss" scoped>
  673. .form-container {
  674. padding: 20px;
  675. }
  676. .form-section {
  677. margin-bottom: 20px;
  678. padding: 16px;
  679. border: 1px solid #ebeef5;
  680. border-radius: 4px;
  681. }
  682. .section-header {
  683. display: flex;
  684. margin-bottom: 16px;
  685. align-items: center;
  686. h3 {
  687. align-items: center;
  688. margin: 0 16px 0 0 !important;
  689. }
  690. }
  691. .form-section h3 {
  692. margin: 0 0 16px;
  693. font-size: 16px;
  694. font-weight: 500;
  695. color: #303133;
  696. padding-left: 8px;
  697. border-left: 3px solid #409EFF;
  698. }
  699. .form-grid {
  700. display: grid;
  701. grid-template-columns: repeat(4, 1fr);
  702. gap: 8px 16px;
  703. }
  704. :deep(.el-form-item) {
  705. margin-bottom: 8px !important;
  706. margin-right: 0;
  707. }
  708. :deep(.el-form-item__label) {
  709. color: #606266;
  710. font-size: 14px;
  711. padding-right: 4px;
  712. height: 32px;
  713. display: flex;
  714. align-items: center;
  715. line-height: 1;
  716. }
  717. :deep(.el-input__wrapper),
  718. :deep(.el-select),
  719. :deep(.el-date-picker) {
  720. width: 100%;
  721. }
  722. :deep(.el-input__wrapper) {
  723. border-radius: 4px;
  724. height: 32px;
  725. line-height: 32px;
  726. }
  727. :deep(.el-input__inner) {
  728. height: 32px;
  729. line-height: 32px;
  730. font-size: 14px;
  731. }
  732. :deep(.el-form--label-right .el-form-item__label) {
  733. text-align: right;
  734. }
  735. :deep(.el-form-item__content) {
  736. line-height: 32px;
  737. }
  738. :deep(.el-select .el-input) {
  739. width: 100%;
  740. }
  741. :deep(.el-date-editor.el-input) {
  742. width: 100%;
  743. }
  744. .full-width {
  745. grid-column: span 4;
  746. }
  747. :deep(.el-textarea .el-input__wrapper) {
  748. height: auto;
  749. }
  750. .form-footer {
  751. margin-top: 20px;
  752. padding: 20px;
  753. border-top: 1px solid #ebeef5;
  754. display: flex;
  755. justify-content: flex-end;
  756. }
  757. </style>