TaskOrderDetailDialog.vue 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536
  1. <template>
  2. <!-- 主内容区域 -->
  3. <div :class="{ 'app-container': inPageMode }">
  4. <!-- 页面模式下的操作按钮 -->
  5. <div v-if="inPageMode" class="mb-4">
  6. <div class="flex justify-between items-center">
  7. <div v-if="taskOrderDetail">
  8. <el-button
  9. type="primary"
  10. @click="openModifyTimeDialog"
  11. :disabled="canNotModify"
  12. >修改检验时间</el-button
  13. >
  14. <el-button
  15. type="primary"
  16. @click="handleModifyTaskOrder"
  17. :disabled="canNotModify"
  18. >修改任务单</el-button
  19. >
  20. <el-button
  21. type="danger"
  22. @click="openVoidTaskDialog"
  23. :disabled="canNotModify"
  24. >作废任务单</el-button
  25. >
  26. <el-button
  27. type="success"
  28. @click="openCheckerSelectionDialog"
  29. :disabled="isTaskCancelled || isTaskCompleted"
  30. >修改检验人员</el-button
  31. >
  32. <!-- <el-button v-if="props.type !== 'checker'" type="success" @click="openCheckerSelectionDialog" :disabled="isTaskCancelled">修改检验人员</el-button>-->
  33. <el-button
  34. type="success"
  35. @click="handleModifyManager"
  36. :disabled="isTaskCancelled || isTaskCompleted"
  37. >修改项目负责人</el-button
  38. >
  39. <el-button
  40. type="primary"
  41. plain
  42. @click="handleAddSafetyRecord"
  43. :disabled="isTaskCancelled || isTaskCompleted"
  44. >添加安全记录检查</el-button
  45. >
  46. <el-button
  47. type="primary"
  48. plain
  49. @click="() => handleServiceOrder(100)"
  50. :disabled="isTaskCancelled"
  51. >服务单/受理单</el-button
  52. >
  53. <el-button
  54. type="primary"
  55. plain
  56. @click="() => handleServiceOrder(200)"
  57. :disabled="isTaskCancelled"
  58. >检验情况告知</el-button
  59. >
  60. </div>
  61. </div>
  62. </div>
  63. <!-- 任务单详情、异常信息、审核、设备清单 -->
  64. <div v-if="!taskOrderDetail" class="loading-text">
  65. 无法加载任务详情。
  66. </div>
  67. <div v-else>
  68. <ContentWrap class="mb-4" title="任务单详情">
  69. <div class="tip custom-block">单位信息</div>
  70. <el-descriptions :column="3" border>
  71. <el-descriptions-item label="任务单号">
  72. {{ taskOrderDetail.orderNo }}
  73. </el-descriptions-item>
  74. <el-descriptions-item label="检验类别">
  75. {{ PressureBoilerCheckTypeMap[taskOrderDetail.checkType] || '-' }}
  76. </el-descriptions-item>
  77. <el-descriptions-item label="检验设备数量">
  78. {{ taskOrderDetail.equipNum || '-' }}
  79. </el-descriptions-item>
  80. <el-descriptions-item label="申请单位名称">
  81. {{ taskOrderDetail.unitName || '-' }}
  82. </el-descriptions-item>
  83. <el-descriptions-item label="使用单位名称">
  84. {{ taskOrderDetail.useUnitName || '-' }}
  85. </el-descriptions-item>
  86. <el-descriptions-item label="检验日期">
  87. {{ Array.isArray(taskOrderDetail.checkDate) ? formatArrayDate(taskOrderDetail.checkDate) : taskOrderDetail.checkDate || '-' }}
  88. </el-descriptions-item>
  89. <el-descriptions-item label="申请单位地址">
  90. {{ taskOrderDetail.unitAddress || '-' }}
  91. </el-descriptions-item>
  92. <el-descriptions-item label="使用单位地址">
  93. {{ taskOrderDetail.useUnitAddress || '-' }}
  94. </el-descriptions-item>
  95. <el-descriptions-item label="收费性质">
  96. {{ PressureFeeNatureMap[taskOrderDetail.feeNature] || '-' }}
  97. </el-descriptions-item>
  98. <el-descriptions-item label="收费形式">
  99. {{ PressureFeeTypeMap[taskOrderDetail.feeType] || '-' }}
  100. </el-descriptions-item>
  101. <el-descriptions-item label="收费金额">
  102. {{ taskOrderDetail.payAmount || '-' }}
  103. </el-descriptions-item>
  104. <el-descriptions-item label="是否已交费">
  105. {{ taskOrderDetail.isPay === 1?'是':'否' }}
  106. </el-descriptions-item>
  107. <el-descriptions-item label="业务受理人">
  108. <el-tag v-if="taskOrderDetail.acceptUser" effect="light" :closable="false">
  109. {{
  110. taskOrderDetail.acceptUser
  111. ? `${taskOrderDetail.acceptUser.nickname} (${taskOrderDetail.acceptUser.employeeNo})`
  112. : '-'
  113. }}
  114. </el-tag>
  115. <span v-else>-</span>
  116. </el-descriptions-item>
  117. <el-descriptions-item label="项目负责人">
  118. <div v-if="taskOrderDetail.manager">
  119. <el-tag type="primary">
  120. {{ taskOrderDetail.manager ? `${taskOrderDetail.manager.nickname} (${taskOrderDetail.manager.employeeNo})` : '-' }}
  121. </el-tag>
  122. </div>
  123. <span v-else>-</span>
  124. </el-descriptions-item>
  125. <el-descriptions-item label="检验人员">
  126. <div
  127. v-if="taskOrderDetail.teamItemList && taskOrderDetail.teamItemList.length > 0">
  128. <div
  129. v-for="(team, teamIndex) in taskOrderDetail.teamItemList"
  130. :key="team.groupTeamId || 'team-' + teamIndex"
  131. style="margin-bottom: 8px">
  132. <div
  133. v-if="taskOrderDetail.teamItemList.length > 1"
  134. style="font-weight: bold; margin-bottom: 4px">
  135. 团队 {{ teamIndex + 1 }}:
  136. </div>
  137. <div
  138. style="display: flex; flex-wrap: wrap; align-items: center; gap: 6px">
  139. <template
  140. v-for="(leader, leaderIdx) in team.leaders"
  141. :key="
  142. leader.id
  143. ? 'leader-' + leader.id
  144. : 'leader-idx-' + leaderIdx + '-' + teamIndex
  145. ">
  146. <el-tag
  147. effect="light"
  148. :closable="false">
  149. <span class="leader-tag">组</span>
  150. {{ leader.nickname }}
  151. </el-tag>
  152. </template>
  153. <template
  154. v-for="(member, memberIdx) in team.members"
  155. :key="
  156. member.id
  157. ? 'member-' + member.id
  158. : 'member-idx-' + memberIdx + '-' + teamIndex
  159. ">
  160. <el-tag effect="light" :closable="false"
  161. >{{ member.nickname
  162. }}({{ member.employeeNo }})</el-tag
  163. >
  164. </template>
  165. <span
  166. v-if="
  167. (!team.leaders || team.leaders.length === 0) &&
  168. (!team.members || team.members.length === 0)
  169. "
  170. style="margin-left: 4px"
  171. >-</span
  172. >
  173. </div>
  174. </div>
  175. </div>
  176. <span v-else>-</span>
  177. </el-descriptions-item>
  178. <el-descriptions-item label="计划编制人">
  179. <el-tag v-if="taskOrderDetail.scheduleUser" effect="light" :closable="false">
  180. {{
  181. taskOrderDetail.scheduleUser
  182. ? `${taskOrderDetail.scheduleUser.nickname} (${taskOrderDetail.scheduleUser.employeeNo})`
  183. : '-'
  184. }}
  185. </el-tag>
  186. <span v-else>-</span>
  187. </el-descriptions-item>
  188. <el-descriptions-item label="中止检验">
  189. {{ taskOrderDetail.XXX || '-' }}
  190. </el-descriptions-item>
  191. <el-descriptions-item label="安全检查记录">
  192. <el-button link type="primary" @click="handleLookSecurityCheck">{{
  193. taskOrderDetail.securityCheckCount
  194. }}</el-button>
  195. </el-descriptions-item>
  196. <el-descriptions-item label="备注" :span="2">
  197. {{ taskOrderDetail.remark || '-' }}
  198. </el-descriptions-item>
  199. </el-descriptions>
  200. <div class="tip custom-block">联系人信息</div>
  201. <el-descriptions :column="3" border>
  202. <el-descriptions-item label="约检联系人">
  203. {{ taskOrderDetail.unitContact || '-' }}
  204. </el-descriptions-item>
  205. <el-descriptions-item label="约检联系人电话">
  206. {{ taskOrderDetail.unitPhone || '-' }}
  207. </el-descriptions-item>
  208. <el-descriptions-item label="约检联系人邮箱">
  209. {{ taskOrderDetail.unitEmail || '-' }}
  210. </el-descriptions-item>
  211. <el-descriptions-item label="电子报告接收人">
  212. {{ taskOrderDetail.recipient || '-' }}
  213. </el-descriptions-item>
  214. <el-descriptions-item label="报告接收人电话">
  215. {{ taskOrderDetail.recipientPhone || '-' }}
  216. </el-descriptions-item>
  217. <el-descriptions-item label="接收人邮箱">
  218. {{ taskOrderDetail.recipientEmail || '-' }}
  219. </el-descriptions-item>
  220. <el-descriptions-item label="缴费联系人">
  221. {{ taskOrderDetail.payerContactName || '-' }}
  222. </el-descriptions-item>
  223. <el-descriptions-item label="缴费人电话">
  224. {{ taskOrderDetail.payerContact || '-' }}
  225. </el-descriptions-item>
  226. <el-descriptions-item label="缴费人邮箱">
  227. {{ taskOrderDetail.payerMail || '-' }}
  228. </el-descriptions-item>
  229. </el-descriptions>
  230. </ContentWrap>
  231. <ContentWrap v-if="exceptionInfo.id" title="异常信息">
  232. <el-form
  233. v-if="exceptionInfo.id"
  234. disabled
  235. :model="exceptionInfo"
  236. ref="formRef"
  237. label-width="130px"
  238. class="p-3">
  239. <el-row
  240. v-if="exceptionInfo.id"
  241. class="form-group"
  242. :gutter="24">
  243. <el-col :span="8">
  244. <el-form-item
  245. label="有效日期调整原因"
  246. prop="effectiveDateAdjustReason">
  247. <el-input
  248. v-model="exceptionInfo.effectiveDateAdjustReason"
  249. placeholder="请输入有效日期调整原因" />
  250. </el-form-item>
  251. </el-col>
  252. <el-col :span="8">
  253. <el-form-item
  254. label="受理建议"
  255. prop="acceptSuggeston">
  256. <el-input
  257. v-model="exceptionInfo.acceptSuggeston"
  258. placeholder="请输入受理建议" />
  259. </el-form-item>
  260. </el-col>
  261. <el-col :span="8">
  262. <el-form-item
  263. label="调整有效日期"
  264. prop="adjustEffectiveDate">
  265. <el-date-picker
  266. v-model="exceptionInfo.adjustEffectiveDate"
  267. type="date"
  268. value-format="YYYY-MM-DD"
  269. placeholder="请选择调整有效日期" />
  270. </el-form-item>
  271. </el-col>
  272. <el-col :span="12">
  273. <el-form-item label="情况说明" prop="descrition">
  274. <component
  275. :is="getExceptionItem('descrition', 'descritionAttach')" />
  276. </el-form-item>
  277. </el-col>
  278. <el-col :span="12">
  279. <el-form-item label="重启表" prop="restartTable">
  280. <component
  281. :is="getExceptionItem('restartTable', 'restartTableAttach')" />
  282. </el-form-item>
  283. </el-col>
  284. <el-col :span="12">
  285. <el-form-item label="指令书" prop="instrustionBook">
  286. <component
  287. :is="getExceptionItem('instrustionBook', 'instrustionBookAttach')" />
  288. </el-form-item>
  289. </el-col>
  290. <el-col :span="12">
  291. <el-form-item label="受理回执" prop="acceptReceipt">
  292. <component
  293. :is="getExceptionItem('acceptReceipt', 'acceptReceiptAttach')" />
  294. </el-form-item>
  295. </el-col>
  296. <el-col :span="12">
  297. <el-form-item label="其他" prop="other">
  298. <component
  299. :is="getExceptionItem('other', 'otherAttach')" />
  300. </el-form-item>
  301. </el-col>
  302. <el-col :span="12">
  303. <el-form-item
  304. label="提前检验申请函"
  305. prop="earlyCheckApply">
  306. <component
  307. :is="getExceptionItem('earlyCheckApply', 'earlyCheckApplyAttach')" />
  308. </el-form-item>
  309. </el-col>
  310. </el-row>
  311. </el-form>
  312. </ContentWrap>
  313. <ContentWrap
  314. title="审核"
  315. v-if="supportingDocsAuditDataList.length > 0 && inPageMode">
  316. <SmartTable
  317. v-model:columns="supportingDocsAuditColumns"
  318. :data="supportingDocsAuditDataList"
  319. v-model:page-no="operationReportPageNo"
  320. v-model:page-size="operationReportPageSize"
  321. :total="operationReportTotal"
  322. @on-page-no-change="() => handleGetOperationReportAuditList()"
  323. @on-page-size-change="() => handleGetOperationReportAuditList()"
  324. @refresh="() => handleGetOperationReportAuditList()" />
  325. </ContentWrap>
  326. <ContentWrap title="设备清单">
  327. <div style="margin: 10px 0">
  328. <el-button
  329. type="primary"
  330. :disabled="taskOrder?.taskStatus === PressureTaskOrderTaskStatus['REPORT_END'] || isTaskCancelled"
  331. @click="() => handleAddCheckerItems()"
  332. >批量添加检验项目</el-button
  333. >
  334. <el-button
  335. type="primary"
  336. :disabled="selectedEquips.length !== 1 || isTaskCancelled"
  337. @click="() => handleMainquestionAddReport(PressureReportType['MAINQUESTION'], 'add')"
  338. >添加重大问题线索</el-button
  339. >
  340. <el-button
  341. type="primary"
  342. :disabled="selectedEquips.length !== 1 || isTaskCancelled"
  343. @click="handleAddInspectionplanReport">
  344. {{'添加检验方案'}}
  345. </el-button>
  346. <el-button
  347. type="primary"
  348. @click="handleBatchConcat"
  349. :disabled="selectedEquips.length === 0 || isTaskCancelled"
  350. >批量修改约检联系人</el-button
  351. >
  352. </div>
  353. <el-table
  354. :data="taskOrderDetail.orderItems"
  355. ref="orderItemsTableRef"
  356. @selection-change="handleEquipSelectionChange"
  357. border
  358. stripe
  359. empty-text="暂无设备信息">
  360. <el-table-column fixed="left" type="selection" width="40" />
  361. <el-table-column
  362. label="操作"
  363. fixed="left"
  364. align="center"
  365. width="200px">
  366. <template #default="scope">
  367. <div class="operation-buttons">
  368. <el-button type="primary" link size="small" @click="() => handleAddReport(PressureReportType['WORKINSTRUCTION'], scope.row)" :disabled="isTaskCancelled">添加作业指导书</el-button>
  369. <el-button v-if="showViewMainquestionBtn(scope.row)" type="primary" @click="handleViewMainquestionReport(scope.row)" link size="small">查看重大问题线索告知表</el-button>
  370. <el-button
  371. v-if="scope.row.mainCheckerUser?.id !== taskOrderDetail.manager?.id"
  372. link
  373. type="primary"
  374. size="small"
  375. :disabled="isTaskCancelled"
  376. @click="handleSetMainChecker(scope.row)"
  377. >修改主检人</el-button
  378. >
  379. <!-- <el-button-->
  380. <!-- v-if="scope.row.taskStatus === PressureCheckerMyTaskStatus.REPORT_END"-->
  381. <!-- link-->
  382. <!-- type="primary"-->
  383. <!-- size="small"-->
  384. <!-- :disabled="isTaskCancelled"-->
  385. <!-- @click="handleEntityReport(scope.row)"-->
  386. <!-- >添加作业指导书实体报告</el-button-->
  387. <!-- >-->
  388. </div>
  389. </template>
  390. </el-table-column>
  391. <el-table-column
  392. prop="equipDistrictName"
  393. align="center"
  394. label="区域"
  395. width="120px">
  396. <template #default="scope">
  397. <div>{{ scope.row.equipDistrictName }}</div>
  398. <div class="text-gray-400 text-sm">
  399. {{ scope.row.equipStreetName }}
  400. </div>
  401. </template>
  402. </el-table-column>
  403. <el-table-column
  404. prop="checkType"
  405. label="检验性质"
  406. width="150px"
  407. align="center">
  408. <template #default>
  409. {{ PressureBoilerCheckTypeMap[taskOrderDetail.checkType] || '-' }}
  410. </template>
  411. </el-table-column>
  412. <el-table-column
  413. prop="reportRespVOList"
  414. label="检验项目"
  415. width="150px"
  416. align="center">
  417. <template #default="{ row }">
  418. <template
  419. v-if="getRowReportVOList(row).length <= 2">
  420. <el-row
  421. v-for="item in getRowReportVOList(row)"
  422. :key="item?.templateId">
  423. <el-button
  424. :disabled="taskOrder?.taskStatus === PressureTaskOrderTaskStatus['REPORT_END'] || canAddReportItem(row.taskStatus) || isTaskCancelled"
  425. link
  426. type="primary"
  427. class="!whitespace-normal"
  428. @click="() => handleAddCheckerItems(row)"
  429. >{{ item?.reportName }}</el-button
  430. >
  431. <el-button
  432. :disabled="taskOrder?.taskStatus === PressureTaskOrderTaskStatus['REPORT_END']"
  433. link
  434. type="primary"
  435. @click.stop.prevent="() => handleInputCalcField(row.equipId, item)"
  436. >(费用:{{ getCheckItemFeeType(item)
  437. }})</el-button
  438. >
  439. </el-row>
  440. </template>
  441. <!-- 弹窗 -->
  442. <el-popover
  443. v-else
  444. placement="top-start"
  445. :width="200"
  446. trigger="hover">
  447. <!-- 弹窗内容 -->
  448. <el-scrollbar max-height="400px">
  449. <el-row
  450. v-for="item in getRowReportVOList(row)"
  451. :key="item?.templateId">
  452. <el-button
  453. :disabled="taskOrder?.taskStatus === PressureTaskOrderTaskStatus['REPORT_END'] || canAddReportItem(row.taskStatus)"
  454. link
  455. type="primary"
  456. class="!whitespace-normal"
  457. @click="() => handleAddCheckerItems(row)"
  458. >{{ item?.reportName }}</el-button
  459. >
  460. <el-button
  461. :disabled="taskOrder?.taskStatus === PressureTaskOrderTaskStatus['REPORT_END']"
  462. link
  463. type="primary"
  464. @click.stop.prevent="() => handleInputCalcField(row.equipId, item)"
  465. >(费用:{{ getCheckItemFeeType(item)
  466. }})</el-button
  467. >
  468. </el-row>
  469. </el-scrollbar>
  470. <template #reference>
  471. <div>
  472. <el-row
  473. v-for="item in getRowReportVOList(row).slice(0, 2)"
  474. :key="item?.templateId">
  475. <el-button
  476. :disabled="taskOrder?.taskStatus === PressureTaskOrderTaskStatus['REPORT_END']"
  477. link
  478. class="!whitespace-normal"
  479. type="primary"
  480. @click="() => handleAddCheckerItems(row)"
  481. >{{ item?.reportName }}</el-button
  482. >
  483. <el-button
  484. :disabled="taskOrder?.taskStatus === PressureTaskOrderTaskStatus['REPORT_END']"
  485. link
  486. type="primary"
  487. @click.stop.prevent="() => handleInputCalcField(row.equipId, item)"
  488. >(费用:{{ getCheckItemFeeType(item)
  489. }})</el-button
  490. >
  491. </el-row>
  492. </div>
  493. </template>
  494. </el-popover>
  495. </template>
  496. </el-table-column>
  497. <el-table-column
  498. prop="reportRespVOList"
  499. label="操作指导书"
  500. width="120px"
  501. align="center">
  502. <template #default="{row}">
  503. <template
  504. v-if="filterReportType(row.reportRespVOList).length">
  505. <div
  506. class="w-full"
  507. v-for="(item,index) in filterReportType(row.reportRespVOList)"
  508. :key="index">
  509. {{ item?.reportName }}
  510. </div>
  511. </template>
  512. <span v-else>-</span>
  513. </template>
  514. </el-table-column>
  515. <el-table-column
  516. prop="fee"
  517. label="收费金额"
  518. width="120px"
  519. align="center" />
  520. <el-table-column
  521. prop="taskStatus"
  522. label="主报告状态"
  523. width="150px"
  524. align="center">
  525. <template #default="scope">
  526. <el-tag :type="getTypeColor(scope.row.taskStatus)">
  527. {{ PressureTaskOrderTaskStatusMap[scope.row.taskStatus] || '-' }}
  528. </el-tag>
  529. </template>
  530. </el-table-column>
  531. <el-table-column
  532. prop="equipCode"
  533. label="设备注册代码"
  534. width="200px"
  535. align="center">
  536. <template #default="scope">
  537. <el-tag
  538. type="primary"
  539. size="small"
  540. class="ml-1"
  541. >{{ scope.row.equipCode }}</el-tag
  542. >
  543. </template>
  544. </el-table-column>
  545. <el-table-column
  546. prop="useCode"
  547. label="使用证编号"
  548. width="150px"
  549. align="center" />
  550. <el-table-column
  551. prop="maxContinueEvapor"
  552. label="蒸发量"
  553. min-width="200px"
  554. align="center" />
  555. <!-- <el-table-column-->
  556. <!-- prop="tonnage"-->
  557. <!-- label="吨位"-->
  558. <!-- width="80px"-->
  559. <!-- align="center" />-->
  560. <el-table-column
  561. prop="boilerModel"
  562. label="型号"
  563. width="150px"
  564. align="center" />
  565. <el-table-column
  566. label="下次内部检验"
  567. width="120px"
  568. align="center">
  569. <template #default="scope">
  570. {{ scope.row.nextInCheckDate ? dayjs(scope.row.nextInCheckDate).format('YYYY-MM-DD') : '-' }}
  571. </template>
  572. </el-table-column>
  573. <el-table-column
  574. label="下次外部检验"
  575. width="120px"
  576. align="center">
  577. <template #default="scope">
  578. {{ scope.row.nextOutCheckDate ? dayjs(scope.row.nextOutCheckDate).format('YYYY-MM-DD') : '-' }}
  579. </template>
  580. </el-table-column>
  581. <el-table-column
  582. label="下次耐压检验"
  583. width="120px"
  584. align="center">
  585. <template #default="scope">
  586. {{ scope.row.nextPressureCheckDate ? dayjs(scope.row.nextPressureCheckDate).format('YYYY-MM-DD') : '-' }}
  587. </template>
  588. </el-table-column>
  589. <el-table-column
  590. label="约检联系人"
  591. width="160px"
  592. align="center">
  593. <template #default="scope">
  594. <div>{{ scope.row.contact || '-' }}</div>
  595. </template>
  596. </el-table-column>
  597. <el-table-column
  598. label="约检联系人电话"
  599. width="160px"
  600. align="center">
  601. <template #default="scope">
  602. <div>{{ scope.row.contactPhone || '-' }}</div>
  603. </template>
  604. </el-table-column>
  605. </el-table>
  606. </ContentWrap>
  607. </div>
  608. <!-- 页面模式下的底部操作按钮 -->
  609. <div
  610. v-if="inPageMode && taskOrderDetail"
  611. class="flex justify-center mt-4">
  612. <!-- <el-button v-if="props.type !== 'checker'" type="success" @click="handlePrintCommitment" :disabled="isTaskCancelled">打印委托书</el-button>-->
  613. <!-- <el-button v-if="props.type !== 'checker'" type="success" @click="handlePrintEquipmentRecord" :disabled="isTaskCancelled">打印设备记录</el-button>-->
  614. <el-button
  615. type="primary"
  616. @click="handleConfirm"
  617. v-if="taskStatus === PressureTaskOrderTaskStatus.WAIT_CONFIRM"
  618. :disabled="isTaskCancelled"
  619. >认领</el-button
  620. >
  621. <el-button
  622. type="primary"
  623. @click="handleCancelConfirm"
  624. v-if="taskStatus === PressureTaskOrderTaskStatus.CONFIRMED"
  625. :disabled="isTaskCancelled || isTaskCompleted"
  626. >取消认领</el-button
  627. >
  628. <el-button @click="handleClosePage">关闭</el-button>
  629. </div>
  630. </div>
  631. <!-- 内部弹窗:修改检验时间、作废任务单、检验员选择 (仅在页面模式且有权限时出现) -->
  632. <template v-if="inPageMode && taskOrderDetail">
  633. <!-- 修改检验时间对话框 -->
  634. <el-dialog
  635. v-model="modifyTimeDialogVisible"
  636. title="修改检验时间"
  637. width="500px"
  638. draggable
  639. :close-on-click-modal="false"
  640. append-to-body>
  641. <el-form
  642. ref="modifyTimeFormRef"
  643. :model="modifyTimeForm"
  644. label-width="100px">
  645. <el-form-item label="检验日期" prop="newInspectionDate" required>
  646. <el-date-picker
  647. v-model="modifyTimeForm.newInspectionDate"
  648. type="date"
  649. placeholder="选择日期"
  650. value-format="YYYY-MM-DD"
  651. class="!w-full" />
  652. </el-form-item>
  653. <el-form-item label="修改原因" prop="reason" required>
  654. <el-input
  655. v-model="modifyTimeForm.reason"
  656. type="textarea"
  657. :rows="3"
  658. placeholder="请输入修改原因" />
  659. </el-form-item>
  660. </el-form>
  661. <template #footer>
  662. <el-button @click="modifyTimeDialogVisible = false"
  663. >取消</el-button
  664. >
  665. <el-button type="primary" @click="handleSubmitModifyTime"
  666. >确定</el-button
  667. >
  668. </template>
  669. </el-dialog>
  670. <!-- 作废任务单对话框 -->
  671. <el-dialog
  672. v-model="voidTaskDialogVisible"
  673. title="作废任务单"
  674. width="500px"
  675. draggable
  676. :close-on-click-modal="false"
  677. append-to-body>
  678. <el-form
  679. ref="voidTaskFormRef"
  680. :model="voidTaskForm"
  681. :rules="{
  682. reason: [
  683. { required: true, message: '请输入作废原因', trigger: 'blur' },
  684. ],
  685. }"
  686. label-width="100px">
  687. <el-form-item label="作废原因" prop="reason">
  688. <el-input
  689. v-model="voidTaskForm.reason"
  690. type="textarea"
  691. :rows="3"
  692. placeholder="请输入作废原因" />
  693. </el-form-item>
  694. </el-form>
  695. <template #footer>
  696. <el-button @click="voidTaskDialogVisible = false"
  697. >取消</el-button
  698. >
  699. <el-button type="primary" @click="handleSubmitVoidTask"
  700. >确定</el-button
  701. >
  702. </template>
  703. </el-dialog>
  704. <!-- 检验员选择弹窗 -->
  705. <el-dialog
  706. v-model="checkerSelectVisible"
  707. title="选择检验员"
  708. append-to-body
  709. width="800px"
  710. draggable
  711. :close-on-click-modal="false">
  712. <CheckerSelect
  713. ref="checkerSelectRef"
  714. v-model="tempSelectedCheckersInDialog"
  715. :dept-id="taskOrderDetail?.deptId?.toString() || userStore.getUser.deptId?.toString() || '1'"
  716. :disabled="false"
  717. :has-data="true"
  718. empty-text="暂无检验员数据"
  719. :multiple="true"
  720. @change="handleCheckerSelectionChangeInDialog"
  721. />
  722. <template #footer>
  723. <div class="flex justify-end">
  724. <el-button @click="checkerSelectVisible = false"
  725. >取消</el-button
  726. >
  727. <el-button
  728. type="primary"
  729. @click="confirmCheckerSelectionAndSubmit"
  730. >确定</el-button
  731. >
  732. </div>
  733. </template>
  734. </el-dialog>
  735. <UserSelectForm
  736. ref="userSelectFormRef"
  737. @confirm="handleManagerSelected"
  738. :single="true" />
  739. <!-- 出具报告对话框 -->
  740. <GenerateReportDialog
  741. v-model:visible="generateReportDialogVisible"
  742. :equip-id="currentReportEquip?.id || ''"
  743. :equip-name="currentReportEquip?.equipName"
  744. @success="handleGenerateReportSuccess" />
  745. <!-- 出具报告对话框(新版本) -->
  746. <IssueReportDialog
  747. v-model:visible="issueReportDialogVisible"
  748. :task-order-id="currentTaskOrderId"
  749. :report-type="currentReportType"
  750. :default-report-scope="200"
  751. :is-part-report="true"
  752. :default-selected-equipments="currentSelectedEquipment ? [currentSelectedEquipment] : []"
  753. @confirm="handleIssueReportConfirm" />
  754. <!-- 修改主检人对话框 -->
  755. <el-dialog
  756. v-model="mainCheckerDialogVisible"
  757. title="修改主检人"
  758. width="800px"
  759. draggable
  760. :close-on-click-modal="false"
  761. append-to-body>
  762. <div class="mb-4">
  763. <div class="text-sm text-gray-600 mb-2">
  764. 当前设备:{{ currentEquipmentRow?.equipCode }} -
  765. {{ currentEquipmentRow?.equipName }}
  766. </div>
  767. <div class="text-sm text-gray-600 mb-4">
  768. 请选择一个检验员作为主检人(单选)
  769. </div>
  770. </div>
  771. <CheckerSelect
  772. v-model="tempSelectedMainChecker"
  773. @change="handleMainCheckerSelectionChange"
  774. :max="1"/>
  775. <template #footer>
  776. <div class="flex justify-end">
  777. <el-button @click="mainCheckerDialogVisible = false"
  778. >取消</el-button
  779. >
  780. <el-button
  781. type="primary"
  782. @click="confirmMainCheckerSelection"
  783. >确定</el-button
  784. >
  785. </div>
  786. </template>
  787. </el-dialog>
  788. </template>
  789. <!-- 安全检查记录弹窗 -->
  790. <SavetyCheckRecordList
  791. v-if="savetyCheckRecordListVsible"
  792. v-model:visible="savetyCheckRecordListVsible"
  793. :checkId="savetyCheck.checkId"
  794. :orderId="savetyCheck.orderId"
  795. @success="handleUpdateSavetyCheckRecordList" />
  796. <CustomDialog
  797. v-if="showSavetyCheckRecordVersions"
  798. v-model="showSavetyCheckRecordVersions"
  799. title="安全检查记录列表"
  800. width="800px"
  801. :showFooter="false"
  802. :z-index="1001">
  803. <SmartTable
  804. ref="smartTableRef"
  805. v-model:pageNo="savetyRecordPageNo"
  806. v-model:pagesize="savetyRecordPageSize"
  807. v-model:total="savetyRecordTotal"
  808. v-model:columns="savetyRecordColumns"
  809. :useBorderLayout="false"
  810. :data="savetyRecordList"
  811. :buttons="[]"
  812. @on-page-no-change="() => fetchSafetyCheckRecordPage()"
  813. @on-page-size-change="() => fetchSafetyCheckRecordPage()"
  814. @refresh="() => fetchSafetyCheckRecordPage()" />
  815. </CustomDialog>
  816. <!-- 批量修改约检联系人 -->
  817. <batchEditForm ref="formRef" @success="handleScheduleSuccess" />
  818. <!-- 添加检验项目弹窗 -->
  819. <AddOrEditCheckItemForEquipment
  820. v-if="showAddCheckItemsDialog"
  821. v-model="showAddCheckItemsDialog"
  822. :orderInfo="taskOrder"
  823. :selectedIds="checkItemIds"
  824. :isBatch="isBatchAdd"
  825. :equipmentIds="selectedEquipmentIds"
  826. :orderItemIds="selectedOrderIds"
  827. :isShowItemPart="false"
  828. @refresh="() => emit('refresh')" />
  829. <!-- 添加检验方案 添加弹窗 -->
  830. <AddInspectionplan
  831. ref="addInspectionplanRef"
  832. @success="handleSuccessInspectionplan" />
  833. <!-- 添加检验方案详情 -->
  834. <AddInspectionplanDetail
  835. v-if="AddInspectionplanDetailVisible"
  836. v-model:visible="AddInspectionplanDetailVisible"
  837. :editInspectionplanParams="editInspectionplanParams"
  838. :inspectionplanDetail="inspectionplanDetail"
  839. :taskOrderDetail="taskOrderDetail"
  840. :isEdit="isEdit"
  841. @success="handleUpdateInspectionplanDetail"
  842. @refresh="handleRefreshInspectionplan"
  843. />
  844. <!-- 服务单/受理单 添加弹窗 -->
  845. <OrderDialog
  846. ref="orderDialogRef"
  847. :orderId="props.taskOrder.id"
  848. type="boiler"
  849. />
  850. <ServiceRecordList
  851. v-if="serviceRecordListVisible"
  852. v-model:visible="serviceRecordListVisible"
  853. :serverForm="serviceOrderDialogFormData"
  854. :businessType="businessType"
  855. :orderItemId="mainOrderItemId"
  856. :reportId="mainReportId"
  857. :isAddMainquestion="isAddMainquestion"
  858. :taskOrderDetail="taskOrderDetail"
  859. @success="handleUpdateServiceRecordList"
  860. />
  861. <!-- 作业指导书 添加弹窗 -->
  862. <AddBookAndCheckScheme ref="addBookAndCheckSchemeRef" @success="handleSuccessReport" />
  863. <!-- 作业指导书 编辑弹窗 -->
  864. <EditWorkBookReport
  865. v-if="editWorkBookReportVisible"
  866. v-model:visible="editWorkBookReportVisible"
  867. :title="editOperationReportTypeTitle"
  868. :templateId="editOperationReportParams?.templateId"
  869. :reportId="editOperationReportParams?.reportId"
  870. :orderId="editOperationReportParams?.orderId"
  871. :dataJSON="editOperationReportParams?.prepareJson"
  872. :curReportTypeInfo="curReportTypeInfo"
  873. :isCustomFileUrl="false"
  874. :isEdit="isWorkBookEdit"
  875. @success="handleEditOperationReportList"
  876. />
  877. <calcCheckItemFee
  878. v-if="showCalcCheckItemFeeDialog"
  879. v-model="showCalcCheckItemFeeDialog"
  880. :equipmentId="calcEquipmentId"
  881. :templateInfo="calcTemplateInfo"
  882. @save="handleSaveCalcFee"
  883. />
  884. </template>
  885. <script setup lang="tsx">
  886. import CustomDialog from '@/components/CustomDialog/index.vue'
  887. import SmartTable from '@/components/SmartTable/SmartTable'
  888. import calcCheckItemFee from './calcCheckItemFee.vue'
  889. import SavetyCheckRecordList from './SavetyCheckRecordList.vue'
  890. import AddOrEditCheckItemForEquipment from './AddOrEditCheckItemForEquipment.vue'
  891. import { ref, watch, defineProps, defineEmits, reactive, computed, nextTick } from 'vue'
  892. import { BoilerTaskOrderApi,BoilerTaskOrderItemVO } from '@/api/pressure2/boilertaskorder'
  893. import {
  894. PressureFeeTypeMap,
  895. PressureTaskOrderTaskStatus,
  896. PressureCheckerMyTaskStatus,
  897. PressureFeeNatureMap,
  898. PressureBoilerCheckTypeMap,
  899. PressureReportType,
  900. PressureReportTypeMap,
  901. PressureTaskOrderStatus,
  902. PressureTaskOrderStatusMap, PressureCheckerMyTaskStatusMap, PressureTaskOrderTaskStatusMap
  903. } from '@/utils/constants'
  904. import { formatArrayDate } from '@/utils/formatTime'
  905. import {
  906. ElMessage,
  907. FormInstance,
  908. ElMessageBox,
  909. dayjs,
  910. type ElForm,
  911. type ElTable,
  912. ElSelect, ElOption, type Action
  913. } from 'element-plus'
  914. import { useRouter, useRoute } from 'vue-router'
  915. import CheckerSelect, { type CheckerItem } from '@/views/pressure2/components/CheckerSelect'
  916. import UserSelectForm from '@/components/UserSelectForm/index.vue'
  917. import { useTagsViewStore } from '@/store/modules/tagsView'
  918. import GenerateReportDialog from './GenerateReportDialog.vue'
  919. import IssueReportDialog from './IssueReportDialog.vue'
  920. import VuePdfEmbed from 'vue-pdf-embed'
  921. import { Icon } from '@/components/Icon'
  922. import batchEditForm from '../../equipboilerscheduling/components/batchEditForm.vue'
  923. import {Message as message} from "@/layout/components/Message";
  924. import {buildFileUrl} from "@/utils";
  925. import FileUploadModal from '@/views/pressure2/boilertaskorder/components/ImportFile.vue'
  926. import {is} from "@/utils/is";
  927. import {BoilerAppointmentConfirmOrderApi} from "@/api/pressure2/appointmentconfirmorder";
  928. import { getPressureReportTemplateListNoLimit } from '@/api/pressure2/reportTemplate'
  929. import AddInspectionplan from "@/views/pressure2/boilertaskorder/components/AddInspectionplan.vue";
  930. import {useUserStore} from "@/store/modules/user";
  931. import AddInspectionplanDetail from "@/views/pressure2/boilertaskorder/components/AddInspectionplanDetail.vue";
  932. import ServiceRecordList from "@/views/pressure2/boilertaskorder/components/ServiceRecordList.vue";
  933. import AddBookAndCheckScheme from "@/views/pressure2/boilertaskorder/components/AddBookAndCheckScheme.vue";
  934. import EditWorkBookReport from "@/views/pressure2/boilertaskorder/components/EditWorkBookReport.vue";
  935. import {EquipBoilerApi} from "@/api/pressure2/equipboiler";
  936. import {TaskOrderApi} from "@/api/pressure/taskorder";
  937. import OrderDialog from "@/views/pressure2/boilertaskorder/components/OrderDialog.vue";
  938. const userStore = useUserStore()
  939. const userInfo = computed(() => userStore.user)
  940. const router = useRouter()
  941. const route = useRoute()
  942. const tagsViewStore = useTagsViewStore()
  943. const orderDialogRef = ref()
  944. const isWorkBookEdit = ref(false)
  945. // 异常信息
  946. const exceptionInfo = ref<Record<string, any>>({})
  947. // 定义emit事件
  948. const emit = defineEmits<{
  949. refresh: []
  950. }>()
  951. const props = defineProps({
  952. taskOrder: {
  953. type: Object as () => Record<string, any>, // Assuming a generic object, replace with TaskOrderVO or a more specific interface if available
  954. required: true
  955. },
  956. inPageMode: {
  957. type: Boolean,
  958. default: false
  959. },
  960. type: {
  961. type: String,
  962. default: 'taskorder'
  963. }
  964. })
  965. const taskOrderDetail = ref<any>(null) // This will hold the reactive copy of props.taskOrder
  966. const isTaskCancelled = computed(() => {
  967. return taskOrderDetail.value?.taskStatus === PressureTaskOrderTaskStatus.CANCELLED;
  968. });
  969. const isTaskCompleted = computed(() => {
  970. const completeStatus = [PressureTaskOrderTaskStatus.REPORT_CONFIRMATION, PressureTaskOrderTaskStatus.REPORT_END];
  971. return completeStatus.includes(taskOrderDetail.value.taskStatus)
  972. })
  973. const canNotModify = computed(() => {
  974. if (!taskOrderDetail.value) return true;
  975. if (taskOrderDetail.value.taskStatus === PressureTaskOrderTaskStatus.CANCELLED) {
  976. return true;
  977. }
  978. return taskOrderDetail.value.taskStatus !== PressureTaskOrderTaskStatus.WAIT_CONFIRM;
  979. });
  980. const taskStatus = computed(() => {
  981. return taskOrderDetail.value.taskStatus;
  982. });
  983. const modifyTimeDialogVisible = ref(false)
  984. const modifyTimeFormRef = ref<FormInstance>()
  985. const modifyTimeForm = reactive({
  986. newInspectionDate: undefined as string | undefined,
  987. reason: ''
  988. })
  989. const voidTaskDialogVisible = ref(false)
  990. const voidTaskFormRef = ref<FormInstance>()
  991. const voidTaskForm = reactive({
  992. reason: ''
  993. })
  994. const showDocPdfDialog = ref(false)
  995. const checkRowReport = ref()
  996. const showDesigner = ref(false)
  997. const checkerSelectVisible = ref(false)
  998. const currentSelectedCheckerIdsForDialog = ref<string[]>([])
  999. const tempSelectedCheckersInDialog = ref<CheckerItem[]>([])
  1000. // 检验员组件引用
  1001. const checkerSelectRef = ref()
  1002. const userSelectFormRef = ref<InstanceType<typeof UserSelectForm> | null>(null)
  1003. // 修改主检人相关状态
  1004. const mainCheckerDialogVisible = ref(false)
  1005. const currentEquipmentRow = ref<any>(null)
  1006. const tempSelectedMainChecker = ref<string[]>([])
  1007. const tempSelectedMainCheckerInfo = ref<any[]>([])
  1008. // 出具报告对话框状态
  1009. const generateReportDialogVisible = ref(false)
  1010. const currentReportEquip = ref<any>(null)
  1011. // 出具报告对话框状态(新的IssueReportDialog)
  1012. const issueReportDialogVisible = ref(false)
  1013. const currentTaskOrderId = ref('')
  1014. const currentReportType = ref<100 | 200>(100)
  1015. const currentSelectedEquipment = ref<any>(null)
  1016. const orderItemsTableRef = ref<InstanceType<typeof ElTable>>()
  1017. /** 服务单/受理单 */
  1018. const serviceOrderDialogFormRef = ref<FormInstance>()
  1019. const serviceOrderDialogVisible = ref(false)
  1020. const serviceRecordListVisible = ref(false)
  1021. const businessType = ref<BusinessType>()
  1022. const submitting = ref(false)
  1023. const serviceOrderDialogFormData = ref<Record<string,any>>({
  1024. serviceFormReceiver: '',
  1025. serviceFormReceiverPhone: '',
  1026. confirmStatus: ''
  1027. })
  1028. const formRef = ref()
  1029. // 选中的设备
  1030. const selectedEquips = ref<BoilerTaskOrderItemVO[]>([])
  1031. watch(() => props.taskOrder, (newVal) => {
  1032. if (newVal) {
  1033. taskOrderDetail.value = JSON.parse(JSON.stringify(newVal)); // Use deep copy if modifications are made locally, otherwise direct assignment is fine
  1034. // 更新异常单信息
  1035. const orderExceptionRespVO = taskOrderDetail.value.orderExceptionRespVO
  1036. if(orderExceptionRespVO){
  1037. exceptionInfo.value = {
  1038. ...orderExceptionRespVO,
  1039. adjustEffectiveDate: orderExceptionRespVO.adjustEffectiveDate ? dayjs(orderExceptionRespVO.adjustEffectiveDate.join('-')).format('YYYY-MM-DD') : '',
  1040. }
  1041. }
  1042. } else {
  1043. taskOrderDetail.value = null;
  1044. }
  1045. }, { immediate: true, deep: true })
  1046. const openModifyTimeDialog = () => {
  1047. if (!taskOrderDetail.value) return;
  1048. const currentApptDate = taskOrderDetail.value?.checkDate;
  1049. if (currentApptDate) {
  1050. modifyTimeForm.newInspectionDate = Array.isArray(currentApptDate) ? formatArrayDate(currentApptDate) : currentApptDate
  1051. } else {
  1052. modifyTimeForm.newInspectionDate = undefined;
  1053. }
  1054. modifyTimeForm.reason = ''
  1055. if(modifyTimeFormRef.value) {
  1056. modifyTimeFormRef.value.clearValidate()
  1057. }
  1058. modifyTimeDialogVisible.value = true
  1059. }
  1060. const handleModifyTaskOrder = () => {
  1061. if (!taskOrderDetail.value?.id) {
  1062. ElMessage.error('任务单ID不存在,无法修改!');
  1063. return;
  1064. }
  1065. router.push({
  1066. name: 'BoilerTaskOrderDetail', // Ensure this route name is correct for editing
  1067. query: {
  1068. id: taskOrderDetail.value.id
  1069. }
  1070. })
  1071. }
  1072. const handleModifyManager = () => {
  1073. if (!userSelectFormRef.value) {
  1074. ElMessage.error('用户选择组件未加载!');
  1075. return;
  1076. }
  1077. if (!taskOrderDetail.value?.id) {
  1078. ElMessage.error('任务ID无效,无法修改项目负责人!');
  1079. return;
  1080. }
  1081. if (!taskOrderDetail.value?.managerId) {
  1082. ElMessage.error('请先认领再修改项目负责人!');
  1083. return;
  1084. }
  1085. userSelectFormRef.value.open(taskOrderDetail.value.id); // ID is now from taskOrderDetail
  1086. }
  1087. const handleManagerSelected = async (emittedId: string, selectedUsers: any[]) => {
  1088. //console.log(emittedId);
  1089. if (!taskOrderDetail.value?.id) {
  1090. ElMessage.error('任务ID不存在,无法修改项目负责人!');
  1091. return;
  1092. }
  1093. if (selectedUsers.length === 0) {
  1094. ElMessage.info('未选择新的项目负责人。');
  1095. return;
  1096. }
  1097. const newManager = selectedUsers[0];
  1098. try {
  1099. const payload = {
  1100. id: taskOrderDetail.value.id, // ID from taskOrderDetail
  1101. managerId: newManager.id
  1102. };
  1103. await BoilerTaskOrderApi.updateTaskOrder(payload);
  1104. ElMessage.success('项目负责人更新成功!');
  1105. // 通知父组件刷新数据
  1106. emit('refresh');
  1107. } catch (error) {
  1108. console.error("Failed to update project manager:", error);
  1109. ElMessage.error('项目负责人更新失败!');
  1110. }
  1111. }
  1112. const openVoidTaskDialog = () => {
  1113. if (!taskOrderDetail.value) return;
  1114. voidTaskForm.reason = ''
  1115. if(voidTaskFormRef.value) {
  1116. voidTaskFormRef.value.clearValidate()
  1117. }
  1118. voidTaskDialogVisible.value = true
  1119. }
  1120. const openCheckerSelectionDialog = async () => {
  1121. if (!taskOrderDetail.value) {
  1122. ElMessage.warning('无法加载任务单信息');
  1123. return;
  1124. }
  1125. checkerSelectVisible.value = true;
  1126. // 先获取检验员列表
  1127. await nextTick()
  1128. const deptId = taskOrderDetail.value.deptId?.toString() || userStore.getUser.deptId?.toString() || '1'
  1129. await checkerSelectRef.value?.getCheckerList(deptId)
  1130. // 等待数据加载完成后,再从 teamItemList 中构建检验员列表
  1131. await nextTick()
  1132. // 从 teamItemList 中构建检验员列表
  1133. const checkers: CheckerItem[] = []
  1134. if (taskOrderDetail.value.teamItemList && taskOrderDetail.value.teamItemList.length > 0) {
  1135. taskOrderDetail.value.teamItemList.forEach(team => {
  1136. // 添加组长
  1137. if (team.leaders && team.leaders.length > 0) {
  1138. team.leaders.forEach(leader => {
  1139. checkers.push({
  1140. groupTeamId: team.groupTeamId,
  1141. memberId: leader.id,
  1142. leaderId: leader.id,
  1143. member: leader,
  1144. isLeader: true
  1145. })
  1146. })
  1147. }
  1148. // 添加组员
  1149. if (team.members && team.members.length > 0) {
  1150. team.members.forEach(member => {
  1151. checkers.push({
  1152. groupTeamId: team.groupTeamId,
  1153. memberId: member.id,
  1154. leaderId: team.leaders?.[0]?.id || '',
  1155. member: member,
  1156. isLeader: false
  1157. })
  1158. })
  1159. }
  1160. })
  1161. }
  1162. tempSelectedCheckersInDialog.value = checkers
  1163. // 等待赋值完成后,触发组件内部的状态更新
  1164. await nextTick()
  1165. // 手动触发组件内部的全选状态更新
  1166. checkerSelectRef.value?.processedDeptData?.forEach((dept: any) => {
  1167. dept.teamList?.forEach((team: any) => {
  1168. team.memberList?.forEach((subTeam: any) => {
  1169. const availableMembers = subTeam.memberList || []
  1170. const allSubTeamMembers = availableMembers.map((m: any) => subTeam.id + ':' + m.memberId)
  1171. if (allSubTeamMembers.length === 0) {
  1172. subTeam.checked = false
  1173. return
  1174. }
  1175. const selectedSubTeamMembers = checkers.filter((c: CheckerItem) =>
  1176. allSubTeamMembers.includes(c.groupTeamId + ':' + c.memberId)
  1177. )
  1178. subTeam.checked = selectedSubTeamMembers.length === allSubTeamMembers.length
  1179. })
  1180. })
  1181. })
  1182. }
  1183. /** 处理检验员变化 */
  1184. const handleCheckerSelectionChangeInDialog = (checkers: CheckerItem[]) => {
  1185. tempSelectedCheckersInDialog.value = checkers;
  1186. }
  1187. const confirmCheckerSelectionAndSubmit = async () => {
  1188. if (!taskOrderDetail.value?.id) {
  1189. ElMessage.error('任务ID不存在,无法修改检验员!');
  1190. return;
  1191. }
  1192. try {
  1193. const groupedByTeam: Record<string, { leaderId: string | null; userIds: string[] }> = {};
  1194. tempSelectedCheckersInDialog.value.forEach(checker => {
  1195. if (!checker.groupTeamId) {
  1196. console.warn('Checker missing groupTeamId:', checker);
  1197. return;
  1198. }
  1199. if (!groupedByTeam[checker.groupTeamId]) {
  1200. groupedByTeam[checker.groupTeamId] = { leaderId: null, userIds: [] };
  1201. }
  1202. if (checker.isLeader) {
  1203. groupedByTeam[checker.groupTeamId].leaderId = checker.memberId;
  1204. } else {
  1205. groupedByTeam[checker.groupTeamId].userIds.push(checker.memberId);
  1206. }
  1207. });
  1208. const teamList = Object.keys(groupedByTeam).map(groupTeamId => ({
  1209. groupTeamId: groupTeamId,
  1210. leaderId: groupedByTeam[groupTeamId].leaderId,
  1211. userIds: groupedByTeam[groupTeamId].userIds
  1212. }));
  1213. if (teamList.length < 1){
  1214. ElMessage.error('请选择检验员!');
  1215. return;
  1216. }
  1217. const data = {
  1218. id: taskOrderDetail.value.id, // ID from taskOrderDetail
  1219. teamList: teamList
  1220. };
  1221. await BoilerTaskOrderApi.updateCheckers(data);
  1222. ElMessage.success('检验人员更新成功!');
  1223. checkerSelectVisible.value = false;
  1224. // 通知父组件刷新数据
  1225. emit('refresh');
  1226. } catch (error) {
  1227. console.error("Failed to update checkers:", error);
  1228. ElMessage.error('检验人员更新失败!');
  1229. }
  1230. }
  1231. const handleSubmitModifyTime = async () => {
  1232. if (!modifyTimeFormRef.value) return
  1233. if (!taskOrderDetail.value?.id) {
  1234. ElMessage.error('任务ID不存在,无法修改检验时间!')
  1235. return
  1236. }
  1237. await modifyTimeFormRef.value.validate(async (valid) => {
  1238. if (valid) {
  1239. if (!taskOrderDetail.value) {
  1240. ElMessage.error('任务详情为空,无法修改!')
  1241. return
  1242. }
  1243. const taskOrderDetailCopy = JSON.parse(JSON.stringify(taskOrderDetail.value))
  1244. taskOrderDetailCopy.checkDate = modifyTimeForm.newInspectionDate
  1245. const data = {
  1246. id: taskOrderDetail.value.id, // ID from taskOrderDetail
  1247. objId: taskOrderDetail.value.id, // objId from taskOrderDetail
  1248. checkDate: modifyTimeForm.newInspectionDate,
  1249. reason: modifyTimeForm.reason,
  1250. changeType: 100,
  1251. afterJson: JSON.stringify(taskOrderDetailCopy)
  1252. }
  1253. try {
  1254. await BoilerTaskOrderApi.createTaskOrderOperationRecord(data)
  1255. ElMessage.success('修改检验时间请求已提交!')
  1256. modifyTimeDialogVisible.value = false
  1257. // 通知父组件刷新数据
  1258. emit('refresh');
  1259. } catch (error) {
  1260. ElMessage.error('提交修改检验时间失败!')
  1261. }
  1262. }
  1263. })
  1264. }
  1265. const handleSubmitVoidTask = async () => {
  1266. if (!voidTaskFormRef.value) return
  1267. if (!taskOrderDetail.value?.id) {
  1268. ElMessage.error('任务ID不存在,无法作废!')
  1269. return
  1270. }
  1271. await voidTaskFormRef.value.validate(async (valid) => {
  1272. if (valid) {
  1273. const data = {
  1274. id: taskOrderDetail.value.id, // ID from taskOrderDetail
  1275. objId: taskOrderDetail.value.id, // objId from taskOrderDetail
  1276. reason: voidTaskForm.reason,
  1277. changeType: 300
  1278. }
  1279. try {
  1280. await BoilerTaskOrderApi.createTaskOrderOperationRecord(data)
  1281. ElMessage.success('作废任务单请求已提交!')
  1282. voidTaskDialogVisible.value = false
  1283. // 通知父组件刷新数据
  1284. emit('refresh');
  1285. } catch (error) {
  1286. ElMessage.error('提交作废任务单失败!')
  1287. }
  1288. }
  1289. })
  1290. }
  1291. const handleSetMainChecker = (row: any) => {
  1292. if (!isCanAddFlag(row)){
  1293. return
  1294. }
  1295. currentEquipmentRow.value = row
  1296. // 如果当前有主检人,预选中该主检人
  1297. if (row.mainCheckerUserId) {
  1298. tempSelectedMainChecker.value = [row.mainCheckerUserId]
  1299. } else {
  1300. tempSelectedMainChecker.value = []
  1301. }
  1302. tempSelectedMainCheckerInfo.value = []
  1303. mainCheckerDialogVisible.value = true
  1304. }
  1305. /** 处理主检人选择变化 - 单选逻辑 */
  1306. const handleMainCheckerSelectionChange = (checkers: any[]) => {
  1307. // 实现单选逻辑:如果选择了新的检验员,只保留最后选择的一个
  1308. //console.log(checkers)
  1309. if (checkers.length > 1) {
  1310. // 获取新选择的检验员(最后一个)
  1311. const newSelected = checkers[checkers.length - 1]
  1312. tempSelectedMainChecker.value = [newSelected.groupTeamId + ':' + newSelected.memberId]
  1313. tempSelectedMainCheckerInfo.value = [newSelected]
  1314. } else if (checkers.length === 1) {
  1315. tempSelectedMainChecker.value = [checkers[0].groupTeamId + ':' + checkers[0].memberId]
  1316. tempSelectedMainCheckerInfo.value = [checkers[0]]
  1317. } else {
  1318. tempSelectedMainChecker.value = []
  1319. tempSelectedMainCheckerInfo.value = []
  1320. }
  1321. }
  1322. /** 确认修改主检人 */
  1323. const confirmMainCheckerSelection = async () => {
  1324. if (tempSelectedMainChecker.value.length === 0) {
  1325. ElMessage.warning('请选择一个主检人')
  1326. return
  1327. }
  1328. if (!currentEquipmentRow.value?.id) {
  1329. ElMessage.error('设备信息无效,无法修改主检人')
  1330. return
  1331. }
  1332. try {
  1333. // 调用修改主检人的API
  1334. const data = {
  1335. id: currentEquipmentRow.value.mainID,
  1336. mainCheckerId: tempSelectedMainChecker.value[0].split(':')[1]
  1337. }
  1338. await BoilerTaskOrderApi.updateTaskOrderMainChecker(data)
  1339. ElMessage.success('主检人修改成功')
  1340. mainCheckerDialogVisible.value = false
  1341. // 通知父组件刷新数据
  1342. emit('refresh');
  1343. } catch (error) {
  1344. console.error('修改主检人失败:', error)
  1345. ElMessage.error('修改主检人失败')
  1346. }
  1347. }
  1348. /** 实体报告 */
  1349. const handleEntityReport = (row: any) => {
  1350. currentTaskOrderId.value = taskOrderDetail.value?.id || ''
  1351. currentReportType.value = 100
  1352. currentSelectedEquipment.value = row
  1353. issueReportDialogVisible.value = true
  1354. }
  1355. /** 出具报告确认 */
  1356. const handleIssueReportConfirm = (data: any) => {
  1357. console.log('出具报告数据:', data)
  1358. // 刷新数据
  1359. emit('refresh')
  1360. }
  1361. /** 出具报告成功回调 */
  1362. const handleGenerateReportSuccess = () => {
  1363. // 刷新数据或其他处理
  1364. emit('refresh')
  1365. }
  1366. const handleConfirm = async () => {
  1367. //taskOrderDetail.value.id
  1368. try {
  1369. await ElMessageBox.confirm('是否认领该任务单?', '认领提示', {
  1370. confirmButtonText: '确定',
  1371. cancelButtonText: '取消',
  1372. type: 'warning'
  1373. })
  1374. await BoilerTaskOrderApi.confirmTaskOrder({ id:taskOrderDetail.value.id, "confirm": true })
  1375. ElMessage.success('认领成功')
  1376. if (props.inPageMode) {
  1377. tagsViewStore.closeSelectedTag(route)
  1378. }
  1379. } catch (error) {
  1380. if (error !== 'cancel') {
  1381. ElMessage.error('认领失败')
  1382. console.error('Confirm error:', error)
  1383. }
  1384. }
  1385. }
  1386. // 取消认领
  1387. const handleCancelConfirm = async () => {
  1388. try {
  1389. await ElMessageBox.confirm('是否取消认领该任务单?', '取消认领提示', {
  1390. confirmButtonText: '确定',
  1391. cancelButtonText: '取消',
  1392. type: 'warning'
  1393. })
  1394. await BoilerTaskOrderApi.confirmTaskOrder({ id:taskOrderDetail.value.id, "confirm": false })
  1395. ElMessage.success('取消认领成功')
  1396. if (props.inPageMode) {
  1397. tagsViewStore.closeSelectedTag(route)
  1398. }
  1399. } catch (error) {
  1400. if (error !== 'cancel') {
  1401. ElMessage.error('取消认领失败')
  1402. console.error('Cancel confirm error:', error)
  1403. }
  1404. }
  1405. }
  1406. const handleClosePage = () => {
  1407. if (props.inPageMode) {
  1408. tagsViewStore.closeSelectedTag(route)
  1409. }
  1410. }
  1411. /**
  1412. * 安全检查记录弹窗
  1413. * @param { visible } 显示状态
  1414. * ***/
  1415. const savetyCheckRecordListVsible = ref(false)
  1416. // 安全检查记录弹窗 携带参数
  1417. const savetyCheck = reactive({
  1418. checkId: '',
  1419. orderId: '',
  1420. })
  1421. const handleAddSafetyRecord = async () => {
  1422. const confirmed = await ElMessageBox.confirm('是否确定添加安全检查记录?', '添加安全检查记录提示', {
  1423. confirmButtonText: '确定',
  1424. cancelButtonText: '取消',
  1425. type: 'warning'
  1426. }).catch(() => false);
  1427. if (!confirmed) {
  1428. return;
  1429. }
  1430. savetyCheckRecordListVsible.value = true
  1431. savetyCheck.orderId = taskOrderDetail.value.id
  1432. }
  1433. watch(() => savetyCheckRecordListVsible.value, (savetyCheckRecordListVsible) => {
  1434. if(savetyCheckRecordListVsible) return
  1435. savetyCheck.checkId = ''
  1436. savetyCheck.orderId = ''
  1437. })
  1438. // 安全检查记录列表弹窗
  1439. const showSavetyCheckRecordVersions = ref(false)
  1440. const savetyRecordList = ref([])
  1441. const savetyRecordPageSize = ref(10)
  1442. const savetyRecordPageNo = ref(1)
  1443. const savetyRecordTotal = ref(0)
  1444. const savetyRecordColumns = ref([
  1445. {
  1446. label: '名称',
  1447. prop: 'name',
  1448. },
  1449. {
  1450. label: '日期',
  1451. prop: 'date',
  1452. render: (row, value) => (value ? dayjs(value).format('YYYY-MM-DD') : '-')
  1453. },
  1454. {
  1455. label: '有效期至',
  1456. prop: 'validityDate',
  1457. render: (row, value) => (value ? dayjs(value).format('YYYY-MM-DD') : '-')
  1458. },
  1459. {
  1460. label: '检查结论',
  1461. prop: 'conclusion',
  1462. },
  1463. {
  1464. label: '操作',
  1465. prop: '',
  1466. render: (row) => {
  1467. return <div>
  1468. <el-button link type="primary" onClick={() => handleModifySavetyRecord(row)}>修改</el-button>
  1469. <el-button link type="danger" onClick={() => handleDeleteSavetyRecord(row)}>删除</el-button>
  1470. </div>
  1471. }
  1472. }
  1473. ])
  1474. const fetchSafetyCheckRecordPage = async () => {
  1475. const result = await BoilerTaskOrderApi.getSafetyCheckRecordPage({
  1476. pageNo: savetyRecordPageNo.value,
  1477. pageSize: savetyRecordPageSize.value,
  1478. orderId: taskOrderDetail.value.id
  1479. })
  1480. if(result) {
  1481. savetyRecordList.value = result.list
  1482. savetyRecordTotal.value = result.total
  1483. taskOrderDetail.value.securityCheckCount = result.total
  1484. }
  1485. }
  1486. const handleModifySavetyRecord = (row) => {
  1487. // 修改安全检查记录
  1488. savetyCheckRecordListVsible.value = true
  1489. savetyCheck.orderId = taskOrderDetail.value.id
  1490. savetyCheck.checkId = row.id
  1491. }
  1492. const handleDeleteSavetyRecord = (row) => {
  1493. ElMessageBox.confirm(`确定要删除【${row.name}】吗?`, '提示', {
  1494. confirmButtonText: '确定',
  1495. cancelButtonText: '取消',
  1496. type: 'warning'
  1497. }).then(async () => {
  1498. // 恢复版本
  1499. // TODO: 这里发起删除请求 --- 缺少删除接口
  1500. const delRes = await BoilerTaskOrderApi.deleteSafetyCheckRecord({ id: row.id })
  1501. if(delRes) {
  1502. ElMessage.success('删除成功')
  1503. await fetchSafetyCheckRecordPage()
  1504. }
  1505. }).catch(() => {
  1506. // 取消恢复版本
  1507. })
  1508. }
  1509. const safetyCheckRecordPdfUrl = ref('')
  1510. const savetyCheckRecordPdfLoading = ref(false)
  1511. const handleSafetyCheckRecordPdfRendered = () => {
  1512. console.log('安全检查记录PDF渲染完成')
  1513. savetyCheckRecordPdfLoading.value = false
  1514. }
  1515. // 安全检查记录回调方法
  1516. const handleUpdateSavetyCheckRecordList = () => {
  1517. fetchSafetyCheckRecordPage()
  1518. }
  1519. /** 表格选择框变化 */
  1520. const handleEquipSelectionChange = (selection: BoilerTaskOrderItemVO[]) => {
  1521. // 实现设备选择逻辑
  1522. selectedEquips.value = selection
  1523. }
  1524. /** 处理批量修改约检联系人 */
  1525. const handleBatchConcat = () => {
  1526. if (selectedEquips.value.length === 0) {
  1527. message.warning('请至少选择一条记录')
  1528. return
  1529. }
  1530. if (!isCanAddFlag()){
  1531. return
  1532. }
  1533. formRef.value.open(selectedEquips.value, 'taskOrder')
  1534. }
  1535. /** 修改成功处理 */
  1536. const handleScheduleSuccess = () => {
  1537. selectedEquips.value = []
  1538. //通知父组件刷新数据
  1539. emit('refresh');
  1540. }
  1541. /***** 重大问题线索&检验方案&作业指导书 *****/
  1542. const supportingDocsAuditDataList = ref<Recordable[]>([])
  1543. const supportingDocsAuditColumns = ref([
  1544. {
  1545. label: '设备注册代码',
  1546. prop: 'equipCode',
  1547. },
  1548. {
  1549. label: '项目名称',
  1550. prop: 'reportName'
  1551. },
  1552. {
  1553. label: '类型',
  1554. prop: 'reportType',
  1555. render: (row, reportType) => {
  1556. return PressureReportTypeMap[reportType] || '-'
  1557. }
  1558. },
  1559. {
  1560. label: '状态',
  1561. prop: 'status',
  1562. render: (row, status) => !status ? '-' : PressureTaskOrderStatusMap[status]
  1563. },
  1564. {
  1565. label: '当前流程',
  1566. prop: 'currentNode',
  1567. render: (row) => {
  1568. switch(row.status) {
  1569. case PressureTaskOrderStatus['CANCELLED']:
  1570. return '-'
  1571. case PressureTaskOrderStatus['APPROVED']:
  1572. return '审核通过'
  1573. case PressureTaskOrderStatus['AUDITING']:
  1574. case PressureTaskOrderStatus['REJECTED']:
  1575. return <div>
  1576. <p>当前流程:{row?.currentNode || '-'}</p>
  1577. <p>状态:{row.status === PressureTaskOrderStatus['AUDITING'] ? '审核中' : `${row?.currentAuditor?.nickname}(${row?.currentAuditor?.id})拒绝`}</p>
  1578. </div>
  1579. default:
  1580. return '-'
  1581. }
  1582. }
  1583. },
  1584. {
  1585. label: '退回原因',
  1586. prop: 'returnReason',
  1587. render: (row, returnReason) => {
  1588. return returnReason || '-'
  1589. }
  1590. },
  1591. {
  1592. label: '提交人',
  1593. prop: 'submitUser',
  1594. render: (row, submitUser) => {
  1595. return submitUser?.nickname || '-'
  1596. }
  1597. },
  1598. {
  1599. label: '提交时间',
  1600. prop: 'submitTime',
  1601. render: (row, submitTime) => {
  1602. return !submitTime ? '-' : dayjs(submitTime).format('YYYY-MM-DD')
  1603. }
  1604. },
  1605. {
  1606. label: '操作',
  1607. prop: '',
  1608. render: (row) => {
  1609. switch(row.status) {
  1610. case PressureTaskOrderStatus['AUDITING']:
  1611. case PressureTaskOrderStatus['APPROVED']:
  1612. return <el-button link type="primary" onClick={() => newHandleOperationReport(row, 'view')}>查看详情</el-button>
  1613. // case PressureTaskOrderStatus['APPROVED']:
  1614. // return <el-button link type="primary" onClick={() => handleAssociateEquipment(row)}>关联设备</el-button>
  1615. case PressureTaskOrderStatus['REJECTED']:
  1616. return <div>
  1617. <el-button link type="primary" onClick={() => handleResubmitDocs(row)}>重新提交</el-button>
  1618. <el-button link type="primary" onClick={() => handleCancelDocs(row)}>作废</el-button>
  1619. </div>
  1620. case 0:
  1621. return <div>
  1622. <el-button link type="primary" onClick={() => handleCancelDocs(row)}>作废</el-button>
  1623. <el-button link type="primary" onClick={() => newHandleOperationReport(row, 'edit')}>编辑</el-button>
  1624. </div>
  1625. default:
  1626. return '-'
  1627. }
  1628. }
  1629. },
  1630. ])
  1631. /***** 异常信息 start *****/
  1632. const getExceptionItem = (field: string, fieldAttr: string)=>{
  1633. const fileUrl = exceptionInfo.value[fieldAttr] && buildFileUrl(exceptionInfo.value[fieldAttr])
  1634. const fileName = exceptionInfo.value[field]
  1635. if(fileUrl) {
  1636. return (
  1637. <>
  1638. <div class="flex items-center w-full p-l-10px p-r-10px hover:bg-gray-100 rounded-6px">
  1639. {/* <el-tooltip content={fileName}> */}
  1640. <span class="flex-1 text-ellipsis overflow-hidden whitespace-nowrap">{fileName}</span>
  1641. {/* </el-tooltip> */}
  1642. <div class="ml-10px">
  1643. <el-link href={fileUrl} underline={false} download target="_blank" type="primary">下载</el-link>
  1644. </div>
  1645. {/* <div class="ml-10px">
  1646. <el-button link type="danger" onClick={()=>handleRemove(field, fieldAttr)}>删除</el-button>
  1647. </div> */}
  1648. </div>
  1649. </>
  1650. )
  1651. } else {
  1652. return (
  1653. <el-button type="primary" onClick={()=>handleOpenFileUploadModal(field, fieldAttr)}>
  1654. <Icon icon="ep:upload-filled" />
  1655. <span>附件上传</span>
  1656. </el-button>
  1657. )
  1658. }
  1659. }
  1660. const handleGetExceptionInfo = (id: string) => {
  1661. BoilerAppointmentConfirmOrderApi.getExceptionInfo(id).then((res) => {
  1662. if(res) exceptionInfo.value = {
  1663. ...res,
  1664. adjustEffectiveDate: res.adjustEffectiveDate?.join('-')
  1665. }
  1666. }).catch((error)=>{
  1667. console.log(error, '-----error--->')
  1668. ElMessage.error(error)
  1669. })
  1670. }
  1671. const fileUploadModalRef = ref<InstanceType<typeof FileUploadModal>>();
  1672. const currentUploadMap = reactive({
  1673. field: '',
  1674. fieldAttr: '',
  1675. })
  1676. const handleOpenFileUploadModal = (type: string, attach: string) => {
  1677. currentUploadMap.field = type
  1678. currentUploadMap.fieldAttr = attach
  1679. fileUploadModalRef.value?.open()
  1680. }
  1681. const handleFileUploadSuccess = (fileInfo:{fileName: string, fileUrl: string}) => {
  1682. exceptionInfo.value[currentUploadMap.field] = fileInfo.fileName
  1683. exceptionInfo.value[currentUploadMap.fieldAttr] = fileInfo.fileUrl
  1684. console.log('handleFileUploadSuccess:', exceptionInfo.value)
  1685. }
  1686. /***** 异常信息 end *****/
  1687. // 获取服务单/受理单模板
  1688. type BusinessType = 100 | 200 | 400
  1689. const handleServiceOrder = (type: BusinessType) => {
  1690. console.log(type)
  1691. if (type == 100){
  1692. orderDialogRef.value?.open()
  1693. return
  1694. }
  1695. businessType.value = type
  1696. serviceRecordListVisible.value = true
  1697. // isAddMainquestion.value = 'edit'
  1698. // serviceOrderDialogVisible.value = true
  1699. // const currentBusinessType = getSignFilePath(type)
  1700. // serviceOrderDialogFormData.value.confirmStatus = currentBusinessType.isSignature || '0'
  1701. // downloadSignFilePdf.value = currentBusinessType.signFilePdf
  1702. }
  1703. // 获取审核列表
  1704. const operationReportPageNo = ref(1)
  1705. const operationReportPageSize = ref(10)
  1706. const operationReportTotal = ref(0)
  1707. const handleGetOperationReportAuditList = async () => {
  1708. const auditListResult = await BoilerTaskOrderApi.getMajorIssuesAuditList({
  1709. pageNo: operationReportPageNo.value,
  1710. pageSize: operationReportPageSize.value,
  1711. orderId: route.query.id,
  1712. // notStatusList: 200,
  1713. })
  1714. supportingDocsAuditDataList.value = auditListResult.list.filter(item => {
  1715. // if([PressureReportType.INSPECTIONPLAN, PressureReportType.WORKINSTRUCTION].includes(item.reportType)){
  1716. // return item.status !== 200
  1717. // } else {
  1718. // return item
  1719. // }
  1720. return item
  1721. })
  1722. operationReportTotal.value = auditListResult.total
  1723. }
  1724. handleGetOperationReportAuditList()
  1725. // 添加重大问题线索 & 检验方案 & 作业指导书
  1726. // reportType:500重大问题线索通知 600 检验方案 700 作业指导书
  1727. const curMainquestionEquipmentRow = ref<Recordable>({})
  1728. const isAddMainquestion = ref<'add' | 'edit' | 'view'>('view')
  1729. const mainOrderItemId = ref('')
  1730. const mainReportId = ref('')
  1731. const editOperationReportVisible = ref(false)
  1732. const editOperationReportTypeTitle = ref('')
  1733. const editOperationReportParams = ref<Record<string, any>>({
  1734. templateId: '',
  1735. reportId: '',
  1736. orderId: '',
  1737. prepareJson: ''
  1738. })
  1739. /***** 添加检验项目 *****/
  1740. const isBatchAdd = ref(false)
  1741. const showAddCheckItemsDialog = ref(false)
  1742. const selectedEquipmentIds = ref<string[]>([])
  1743. const selectedOrderIds = ref<string[]>([])
  1744. const checkItemIds = ref<string[]>([])
  1745. const canAddReportItem = (taskStatus)=>{
  1746. const {REPORT_AUDIT, REPORT_APPROVE, REPORT_END} = PressureCheckerMyTaskStatus
  1747. return [REPORT_AUDIT, REPORT_APPROVE, REPORT_END].includes(taskStatus)
  1748. }
  1749. const isCanAddFlag = (row?:any) =>{
  1750. let selectedItems = [] as any[]
  1751. if(row) {
  1752. isBatchAdd.value = false
  1753. selectedItems.push(row)
  1754. selectedEquipmentIds.value = [row?.equipId]
  1755. selectedOrderIds.value = [row?.mainID]
  1756. checkItemIds.value = (row.reportRespVOList || []).map(item => item.templateId)
  1757. } else {
  1758. isBatchAdd.value = true
  1759. selectedItems = orderItemsTableRef.value?.getSelectionRows() || []
  1760. selectedEquipmentIds.value = selectedItems.map(item => item?.equipId)
  1761. selectedOrderIds.value = selectedItems.map(item => item?.mainID)
  1762. if(selectedItems.length >= 1) {
  1763. checkItemIds.value = (selectedItems[0].reportRespVOList || []).map(item => item.templateId)
  1764. }
  1765. }
  1766. if(selectedItems.length === 0) {
  1767. ElMessage.warning('请选择设备单!')
  1768. return false
  1769. }
  1770. // 校验选中行的状态是否存在 报告审核/审核/办结
  1771. let canAddFlag = true
  1772. selectedItems.forEach(row=>{
  1773. if(canAddReportItem(row.taskStatus)) {
  1774. ElMessage.warning(`设备:${row.equipCode}的主报告状态为${PressureCheckerMyTaskStatusMap[row.taskStatus]},不能进行调整!`)
  1775. canAddFlag = false
  1776. }
  1777. })
  1778. return canAddFlag
  1779. }
  1780. const handleAddCheckerItems = (row?: any) => {
  1781. if (!isCanAddFlag(row)){
  1782. return
  1783. }
  1784. // let selectedItems = [] as any[]
  1785. // if(row) {
  1786. // isBatchAdd.value = false
  1787. // selectedItems.push(row)
  1788. // selectedEquipmentIds.value = [row?.equipId]
  1789. // selectedOrderIds.value = [row?.mainID]
  1790. // checkItemIds.value = (row.reportRespVOList || []).map(item => item.templateId)
  1791. // } else {
  1792. // isBatchAdd.value = true
  1793. // selectedItems = orderItemsTableRef.value?.getSelectionRows() || []
  1794. // selectedEquipmentIds.value = selectedItems.map(item => item?.equipId)
  1795. // selectedOrderIds.value = selectedItems.map(item => item?.mainID)
  1796. // if(selectedItems.length >= 1) {
  1797. // checkItemIds.value = (selectedItems[0].reportRespVOList || []).map(item => item.templateId)
  1798. // }
  1799. // }
  1800. // if(selectedItems.length === 0) {
  1801. // ElMessage.warning('请选择设备单!')
  1802. // return
  1803. // }
  1804. // // 校验选中行的状态是否存在 报告审核/审核/办结
  1805. // let canAddFlag = true
  1806. // selectedItems.forEach(row=>{
  1807. // if(canAddReportItem(row.taskStatus)) {
  1808. // ElMessage.warning(`设备:${row.equipCode}的主报告状态为${PressureCheckerMyTaskStatusMap[row.taskStatus]},不能添加检验项目!`)
  1809. // canAddFlag = false
  1810. // }
  1811. // })
  1812. // if(!canAddFlag) return
  1813. showAddCheckItemsDialog.value = true
  1814. }
  1815. /***** 添加检验项目 end *****/
  1816. //判断主报告状态
  1817. const checkMainStatus = (row?: any) => {
  1818. // 校验选中行的状态是否存在 报告审核/审核/办结
  1819. let canAddFlag = true
  1820. selectedItems.forEach(row=>{
  1821. if(canAddReportItem(row.taskStatus)) {
  1822. ElMessage.warning(`设备:${row.equipCode}的主报告状态为${PressureCheckerMyTaskStatusMap[row.taskStatus]},不能添加检验项目!`)
  1823. canAddFlag = false
  1824. }
  1825. })
  1826. return canAddFlag;
  1827. }
  1828. const getRowReportVOList = (row)=>{
  1829. return (row.reportRespVOList || []).filter(item=>item.reportType !== PressureReportType['WORKINSTRUCTION'])
  1830. }
  1831. const filterReportType = (list: any[])=>{
  1832. return (list || []).filter(item=>item.reportType === PressureReportType['WORKINSTRUCTION'])
  1833. }
  1834. // 添加检验方案/查看检验方案按钮
  1835. const initEditOperationReportParams = JSON.parse(JSON.stringify(editOperationReportParams.value))
  1836. const addInspectionplanRef = ref<InstanceType<typeof AddInspectionplan>>()
  1837. const isEdit = ref<'add' | 'edit' | 'view'>('view')
  1838. const editInspectionplanParams = ref<Recordable>({
  1839. ...initEditOperationReportParams.value,
  1840. })
  1841. const AddInspectionplanDetailVisible = ref(false)
  1842. const inspectionplanDetail = ref({})
  1843. const handleUpdateInspectionplanDetail = (info) => {
  1844. console.log('handleUpdateInspectionplanDetail-info:', info )
  1845. editInspectionplanParams.value = {
  1846. ...editInspectionplanParams.value,
  1847. ...info
  1848. }
  1849. }
  1850. const handleRefreshInspectionplan= ()=>{
  1851. // 重新获取审核列表数据
  1852. operationReportPageNo.value = 1
  1853. handleGetOperationReportAuditList()
  1854. }
  1855. const handleAddInspectionplanReport = async () => {
  1856. try {
  1857. if (!isCanAddFlag()){
  1858. return
  1859. }
  1860. // 查询检验方案模板数据
  1861. const options = ref<any[]>([])
  1862. const params = { type: '6',reportType : 600 }
  1863. const response = await getPressureReportTemplateListNoLimit({...params, pageNo: 1, pageSize: 100, status: 200})
  1864. options.value = response?.data?.list || response?.list || response || []
  1865. const newParams = {
  1866. options: options.value.map(item => ({
  1867. ...item,
  1868. label: item.tbName,
  1869. value: item.id
  1870. })),
  1871. formData: {
  1872. orderId: taskOrderDetail.value.id,
  1873. },
  1874. equipCount: unref(selectedEquips).length
  1875. }
  1876. // 添加检验方案逻辑
  1877. addInspectionplanRef.value?.open(newParams, '添加检验方案')
  1878. } catch (error) {
  1879. // 处理接口错误
  1880. ElMessage({
  1881. type: 'error',
  1882. message: 'Failed to load options'
  1883. });
  1884. console.error('API error:', error);
  1885. }
  1886. }
  1887. const getCheckItemFeeType = computed(() => {
  1888. return ({isAutoAmount, fee}) => {
  1889. if(is(fee, 'Number')) return fee
  1890. else if(is(fee, 'Null') && isAutoAmount === '1') return '录入计算'
  1891. else return '无'
  1892. }
  1893. })
  1894. const newHandleOperationReport = async (row, type: 'add' | 'edit' | 'view' | '' = '') => {
  1895. if(row.reportType === PressureReportType.MAINQUESTION){
  1896. return handleMainquestionAddReport(row.reportType, type, row)
  1897. }
  1898. // 如果是检验方案走检验方案的逻辑
  1899. if(row.reportType === PressureReportType['INSPECTIONPLAN']) {
  1900. // 检验方案
  1901. editInspectionplanParams.value = {
  1902. ...editInspectionplanParams.value,
  1903. reportId: row.id,
  1904. templateId: row.templateId,
  1905. orderId: taskOrderDetail.value.id,
  1906. }
  1907. inspectionplanDetail.value = row
  1908. if(!row.status){
  1909. // const templateInitJSON = await getPressureReportTemplateMockJSON( {taskOrderNo: props.taskOrder.orderNo,
  1910. // templateId: row.templateId})
  1911. // editInspectionplanParams.value.prepareJson = templateInitJSON
  1912. }
  1913. isEdit.value = type ? type : !row.status ? 'add' : 'edit'
  1914. AddInspectionplanDetailVisible.value = true
  1915. return
  1916. }
  1917. //作业指导书 选择的是模板,则直接通过葡萄城进行查看预览
  1918. if(row.reportType === PressureReportType['WORKINSTRUCTION']) {
  1919. return handleWorkBookDetail(row,type !== 'view')
  1920. }
  1921. // 查看文件详情的pdf
  1922. showDocPdfDialog.value = true
  1923. checkRowReport.value = row
  1924. showDesigner.value = !!row.templateId
  1925. }
  1926. // 作业指导书查看详情/编辑
  1927. const handleWorkBookDetail = (row, isEdit = false)=>{
  1928. //isCustomFileUrl.value = !row.templateId
  1929. editOperationReportTypeTitle.value = PressureReportTypeMap[row.reportType]
  1930. editOperationReportParams.value = {
  1931. ...editOperationReportParams.value,
  1932. reportId: row.id,
  1933. templateId: row.templateId,
  1934. orderId: taskOrderDetail.value.id,
  1935. prepareJson: row.prepareJson
  1936. }
  1937. isWorkBookEdit.value = isEdit
  1938. editWorkBookReportVisible.value = true
  1939. }
  1940. /***** 费用计算 *****/
  1941. const calcEquipmentId = ref('')
  1942. const calcTemplateInfo = ref({})
  1943. const showCalcCheckItemFeeDialog = ref(false)
  1944. const handleInputCalcField = async (equipId, item) => {
  1945. try {
  1946. calcTemplateInfo.value = item
  1947. calcEquipmentId.value = equipId
  1948. showCalcCheckItemFeeDialog.value = true
  1949. } catch (error) {
  1950. ElMessage.error('录入费用出错啦!')
  1951. console.error('录入费用出错啦!', error)
  1952. }
  1953. }
  1954. const handleSaveCalcFee = async (templateInfo) => {
  1955. // 更新检验项目的费用
  1956. const updateRes = await BoilerTaskOrderApi.updateCheckItemFee({id: templateInfo.id, fee: templateInfo.fee, feeCalculateJson: templateInfo.feeCalculateJson })
  1957. if(updateRes) {
  1958. emit('refresh')
  1959. ElMessage.success('费用已更新')
  1960. }
  1961. }
  1962. /***** 费用计算 end *****/
  1963. /*
  1964. * 添加重大问题线索
  1965. * */
  1966. const handleMainquestionAddReport = async (reportType, type: 'add' | 'edit' | 'view', row?: Recordable) => {
  1967. if (!reportType) return ElMessage.error('未知的报告类型')
  1968. if (!row && unref(selectedEquips).length !== 1) return ElMessage.error('请选择一台设备')
  1969. if (type !== 'view' && !isCanAddFlag(row)){
  1970. return
  1971. }
  1972. isAddMainquestion.value = type
  1973. console.log('isAddMainquestion:log', isAddMainquestion.value)
  1974. mainReportId.value = row ? row.id : ''
  1975. mainOrderItemId.value = row ? row.orderItemId : unref(selectedEquips)[0].mainID
  1976. curMainquestionEquipmentRow.value = row ? {...row} : unref(selectedEquips)[0]
  1977. // 校验审核列表是否已经存在
  1978. const existingAudit = supportingDocsAuditDataList.value.find(item => item.reportType === reportType && item.orderItemId === curMainquestionEquipmentRow.value.mainID)
  1979. if (existingAudit) {
  1980. ElMessage.error('该设备已存在该类型的报告')
  1981. return
  1982. }
  1983. if (type == 'add'){
  1984. const confirmed = await ElMessageBox.confirm('是否确定添加重大问题线索?', '添加重大问题线索提示', {
  1985. confirmButtonText: '确定',
  1986. cancelButtonText: '取消',
  1987. type: 'warning'
  1988. }).catch(() => false);
  1989. if (!confirmed) {
  1990. return;
  1991. }
  1992. }
  1993. handleServiceOrder(400)
  1994. }
  1995. const handleSuccessInspectionplan = async (info) => {
  1996. const firstOrderItem = unref(taskOrderDetail).orderItems[0] || {}
  1997. const params: Recordable = {
  1998. taskOrderNo: props.taskOrder.orderNo,
  1999. templateId: info.templateId,
  2000. }
  2001. if (firstOrderItem.equipCode) {
  2002. params.equipCode = firstOrderItem.equipCode
  2003. }
  2004. try {
  2005. // 1.获取选中模板配置信息
  2006. //const templateInitJSON = await getPressureReportTemplateMockJSON(params)
  2007. const templateInitJSON = null;
  2008. const defaultUser: Record<string, any> = {
  2009. prepareName: unref(userInfo)?.nickname,
  2010. prepareDate: dayjs().format('YYYY年MM月DD')
  2011. }
  2012. const prepareJson = templateInitJSON ? {...JSON.parse(templateInitJSON), ...defaultUser} : defaultUser
  2013. // 2.组装参数, 生成新的检验方案记录,
  2014. const addParams = {
  2015. orderId: taskOrderDetail.value.id,
  2016. templateId: info.templateId,
  2017. prepareJson: JSON.stringify(prepareJson),
  2018. prepareId: unref(userInfo)?.id,
  2019. prepareName: unref(userInfo)?.nickname,
  2020. orderItemIds: selectedEquips.value.map(item => item.mainID),
  2021. reportName: info.reportName,
  2022. }
  2023. const newReportId = await BoilerTaskOrderApi.addMajorIssues(addParams)
  2024. editInspectionplanParams.value = {
  2025. reportId: newReportId,
  2026. templateId: info.templateId,
  2027. orderId: taskOrderDetail.value.id,
  2028. // prepareJson: templateInitJSON ? JSON.parse(templateInitJSON) : ''
  2029. prepareJson: JSON.stringify(prepareJson),
  2030. }
  2031. isEdit.value = 'add'
  2032. AddInspectionplanDetailVisible.value = true
  2033. } catch (error) {
  2034. ElMessage.error('获取模板失败')
  2035. }
  2036. }
  2037. const handleUpdateServiceRecordList = ()=>{
  2038. isAddMainquestion.value = 'view'
  2039. emit('refresh');
  2040. }
  2041. const showViewMainquestionBtn = (row: Recordable)=>{
  2042. return supportingDocsAuditDataList.value.some(item => item.reportType === PressureReportType.MAINQUESTION && item.orderItemId === row.mainID)
  2043. }
  2044. const handleViewMainquestionReport = (row: Recordable)=>{
  2045. if(!showViewMainquestionBtn(row)) return ElMessage.error('该设备不存在该类型的报告')
  2046. const checkAuditRow = unref(supportingDocsAuditDataList).find(item => item.reportType === PressureReportType.MAINQUESTION && item.orderItemId === row.mainID)
  2047. newHandleOperationReport(checkAuditRow, 'view')
  2048. }
  2049. const handleLookSecurityCheck = async () => {
  2050. showSavetyCheckRecordVersions.value = true
  2051. await fetchSafetyCheckRecordPage()
  2052. }
  2053. //添加作业指导书
  2054. // 记录当前的报告类型相关信息
  2055. const addBookAndCheckSchemeRef = ref<InstanceType<typeof AddBookAndCheckScheme>>()
  2056. const curReportType = ref()
  2057. const editWorkBookReportVisible = ref(false)
  2058. const curReportTypeInfo = reactive({
  2059. reportType: '',
  2060. data: {}
  2061. })
  2062. const handleAddReport = async (reportType, row?: Recordable) => {
  2063. if (!isCanAddFlag(row)){
  2064. return
  2065. }
  2066. // 更新记录操作行信息
  2067. curReportTypeInfo.reportType = reportType
  2068. curReportTypeInfo.data = {...row}
  2069. // 创建一个带ElSelect组件的弹窗
  2070. const dialogSelectedValue = ref<string | number>('')
  2071. const createElSelectFormDialog = (options, label) => {
  2072. return defineComponent({
  2073. setup() {
  2074. return () => h('div', [
  2075. h('p', { style: 'margin-bottom: 6px' }, label),
  2076. h(ElSelect, {
  2077. modelValue: dialogSelectedValue.value,
  2078. 'onUpdate:modelValue': (value: string) => {
  2079. dialogSelectedValue.value = value;
  2080. },
  2081. placeholder: '请选择' + label,
  2082. style: 'width: 100%'
  2083. }, options.map(option =>
  2084. h(ElOption, {
  2085. key: option.id,
  2086. label: option.name,
  2087. value: option.id
  2088. })
  2089. ))
  2090. ]);
  2091. }
  2092. });
  2093. }
  2094. try {
  2095. if(!reportType) {
  2096. ElMessage.error('未知的报告类型')
  2097. return
  2098. }
  2099. // 获取下拉选择框的options数据
  2100. const options = ref<any[]>([])
  2101. const params = {}
  2102. switch (reportType) {
  2103. // case PressureReportType['MAINQUESTION']:
  2104. // params['classId'] = 'd799cf8309fa17df5bb87766fc10e00b'
  2105. // break
  2106. // case PressureReportType['INSPECTIONPLAN']:
  2107. // // 检验方案
  2108. // params['type'] = '6'
  2109. // break
  2110. case PressureReportType['WORKINSTRUCTION']:
  2111. // 作业指导书
  2112. params['reportType'] = '700'
  2113. break
  2114. default:
  2115. return
  2116. }
  2117. // 获取指定项目类型的报告
  2118. const response = await getPressureReportTemplateListNoLimit({...params, pageNo: 1, pageSize: 100, status: 200})
  2119. options.value = response?.data?.list || response?.list || response || []
  2120. if([PressureReportType['INSPECTIONPLAN'], PressureReportType['WORKINSTRUCTION']].includes(reportType)) {
  2121. curReportType.value = reportType
  2122. // 检验方案 & 作业指导书 调整修改逻辑其他的保持不变
  2123. const newParams = {
  2124. title: PressureReportTypeMap[reportType],
  2125. options: options.value.map(item => ({
  2126. ...item,
  2127. label: item.tbName,
  2128. value: item.id
  2129. })),
  2130. formData: {
  2131. ...row,
  2132. orderId: taskOrderDetail.value.id,
  2133. // templateId: dialogSelectedValue.value,
  2134. }
  2135. }
  2136. // 添加检验方案逻辑
  2137. // if(reportType === PressureReportType['INSPECTIONPLAN']) {
  2138. // addInspectionplanRef.value?.open(newParams, '添加检验方案')
  2139. // return
  2140. // }
  2141. addBookAndCheckSchemeRef.value?.open(newParams, reportType)
  2142. return
  2143. }
  2144. // 4. 显示自定义弹窗
  2145. ElMessageBox({
  2146. title: '关联项目模板',
  2147. message: h(createElSelectFormDialog(options.value, '项目模板')),
  2148. confirmButtonText: '确定',
  2149. cancelButtonText: '取消',
  2150. showCancelButton: true,
  2151. customClass: 'customPromptStyle',
  2152. beforeClose: (action: Action, instance, done) => {
  2153. if((dialogSelectedValue.value && action === 'confirm') || action === 'cancel') {
  2154. done()
  2155. } else {
  2156. ElMessage.error('请选择项目模板')
  2157. }
  2158. }
  2159. }).then(async () => {
  2160. if(dialogSelectedValue.value) {
  2161. if (params['type'] == '700') {
  2162. // 这里去打开模板
  2163. editOperationReportVisible.value = true
  2164. editOperationReportTypeTitle.value = PressureReportTypeMap[reportType]
  2165. editOperationReportParams.value = {
  2166. ...editOperationReportParams.value,
  2167. templateId: dialogSelectedValue.value,
  2168. orderId: taskOrderDetail.value.id,
  2169. }
  2170. dialogSelectedValue.value = ''
  2171. }
  2172. }
  2173. }).catch((error) => {
  2174. dialogSelectedValue.value = ''
  2175. });
  2176. } catch (error) {
  2177. // 处理接口错误
  2178. ElMessage({
  2179. type: 'error',
  2180. message: 'Failed to load options'
  2181. });
  2182. console.error('API error:', error);
  2183. }
  2184. }
  2185. // 添加作业指导书
  2186. const handleSuccessReport = async (info) => {
  2187. const reportList = filterReportType(info.reportRespVOList);
  2188. const templateIds = (reportList || []).filter(item=>item.templateId === info.templateId)
  2189. if (templateIds.length > 0){
  2190. ElMessage.error('该设备已存在该作业指导书')
  2191. return
  2192. }
  2193. if(!info) return handleEditOperationReportList()
  2194. // 如果选择的是模板,则还是走之前的逻辑,打开葡萄城进行编辑提交
  2195. if(info?.addType === '2' && info.id){
  2196. // 这里去打开模板
  2197. editOperationReportTypeTitle.value = PressureReportTypeMap[unref(curReportType)]
  2198. editOperationReportParams.value = {
  2199. ...editOperationReportParams.value,
  2200. templateId: info.templateId,
  2201. orderId: taskOrderDetail.value.id,
  2202. orderItemId: info.mainID,
  2203. // 操作指导书,初始化编制人和编制时间
  2204. // prepareJson: JSON.stringify({
  2205. // prepareName: unref(userInfo)?.nickname,
  2206. // prepareDate: dayjs().format('YYYY年MM月DD'),
  2207. // })
  2208. }
  2209. isWorkBookEdit.value = true
  2210. //添加操作指导书
  2211. if (!editOperationReportParams.value.reportId) {
  2212. // 初次编辑模板 需要添加报告
  2213. // newReportId 返回的是reportId
  2214. const params: Recordable = {
  2215. orderId: editOperationReportParams.value.orderId,
  2216. templateId: editOperationReportParams.value.templateId,
  2217. prepareId: unref(userInfo)?.id,
  2218. prepareName: unref(userInfo)?.nickname,
  2219. orderItemId: editOperationReportParams.value.orderItemId
  2220. }
  2221. editOperationReportParams.value.reportId = await BoilerTaskOrderApi.addMajorIssues(params)
  2222. }
  2223. editWorkBookReportVisible.value = true
  2224. }
  2225. }
  2226. const handleEditOperationReportList = () => {
  2227. // 重新获取列表数据
  2228. // operationReportPageNo.value = 1
  2229. // handleGetOperationReportAuditList()
  2230. // editOperationReportParams.value = initEditOperationReportParams.value
  2231. emit('refresh');
  2232. }
  2233. const getTypeColor = (status: string | number) => {
  2234. const statusMap = {
  2235. [PressureTaskOrderTaskStatus.WAIT_CONFIRM]: 'primary',
  2236. [PressureTaskOrderTaskStatus.CANCELLED]: 'info',
  2237. [PressureTaskOrderTaskStatus.AUDITING_EDIT]: 'warning',
  2238. [PressureTaskOrderTaskStatus.AUDITING_CANCEL]: 'warning',
  2239. [PressureTaskOrderTaskStatus.AUDITING_TIME]: 'warning',
  2240. [PressureTaskOrderTaskStatus.CONFIRMED]: 'success',
  2241. [PressureTaskOrderTaskStatus.RECORD_INPUT]: 'warning',
  2242. [PressureTaskOrderTaskStatus.RECORD_CHECK]: 'warning',
  2243. [PressureTaskOrderTaskStatus.REPORT_INPUT]: 'warning',
  2244. [PressureTaskOrderTaskStatus.REPORT_AUDIT]: 'warning',
  2245. [PressureTaskOrderTaskStatus.REPORT_APPROVE]: 'warning',
  2246. [PressureTaskOrderTaskStatus.REPORT_END]: 'primary'
  2247. };
  2248. return statusMap[status] || 'info';
  2249. }
  2250. const isCustomFileUrl = ref(false)
  2251. const handleResubmitDocs = async (row) => {
  2252. if(row.reportType === PressureReportType.MAINQUESTION){
  2253. return handleMainquestionAddReport(row.reportType, 'edit', row)
  2254. }
  2255. // 如果是检验方案走检验方案的逻辑
  2256. if(row.reportType === PressureReportType['INSPECTIONPLAN']) {
  2257. // 检验方案
  2258. editInspectionplanParams.value = {
  2259. reportId: row.id,
  2260. templateId: row.templateId,
  2261. orderId: taskOrderDetail.value.id,
  2262. prepareJson: row.prepareJson || ''
  2263. }
  2264. inspectionplanDetail.value = row
  2265. isEdit.value = 'edit'
  2266. AddInspectionplanDetailVisible.value = true
  2267. return
  2268. }
  2269. isCustomFileUrl.value = !row.templateId
  2270. // 重新提交
  2271. editOperationReportTypeTitle.value = PressureReportTypeMap[row.reportType]
  2272. editOperationReportParams.value = {
  2273. ...editOperationReportParams.value,
  2274. reportId: row.id,
  2275. templateId: row.templateId,
  2276. orderId: taskOrderDetail.value.id,
  2277. prepareJson: row.prepareJson
  2278. }
  2279. // 作业指导书 重新提交审批
  2280. if(row.reportType === PressureReportType['WORKINSTRUCTION']) {
  2281. return handleWorkBookDetail(row, true)
  2282. }
  2283. editOperationReportVisible.value = true
  2284. }
  2285. const handleCancelDocs = async (item) => {
  2286. // 作废项目
  2287. try {
  2288. const { value: voidReason } = await ElMessageBox.prompt(
  2289. `确定要作废项目 ${item.reportName} 吗?`,
  2290. '作废项目',
  2291. {
  2292. confirmButtonText: '确认作废',
  2293. cancelButtonText: '取消',
  2294. inputPlaceholder: '请输入作废原因',
  2295. inputType: 'textarea',
  2296. inputValidator: (value: string) => {
  2297. if (!value || !value.trim()) {
  2298. return '作废原因不能为空'
  2299. }
  2300. if (value.trim().length < 5) {
  2301. return '作废原因至少需要5个字符'
  2302. }
  2303. if (value.trim().length > 200) {
  2304. return '作废原因不能超过200个字符'
  2305. }
  2306. return true
  2307. },
  2308. inputErrorMessage: '请输入有效的作废原因'
  2309. }
  2310. )
  2311. if (voidReason && voidReason.trim()) {
  2312. const params: Recordable = {
  2313. id: item.id,
  2314. reportType: item.reportType,
  2315. reason: voidReason.trim()
  2316. }
  2317. // 如果类型是检验方案/操作指导书作废,多传递一个isDelete字段
  2318. if([PressureReportType['INSPECTIONPLAN'], PressureReportType['WORKINSTRUCTION'], PressureReportType.MAINQUESTION].includes(item.reportType)) {
  2319. params.isDelete = true
  2320. }
  2321. await BoilerTaskOrderApi.cancelReport(params)
  2322. ElMessage.success(`成功作废项目 ${item.reportName}`)
  2323. handleGetOperationReportAuditList()
  2324. }
  2325. } catch (error: any) {
  2326. if (error !== 'cancel') {
  2327. console.error('作废项目失败:', error)
  2328. ElMessage.error('作废项目失败,请稍后重试')
  2329. }
  2330. }
  2331. }
  2332. </script>
  2333. <style lang="scss" scoped>
  2334. .loading-text {
  2335. text-align: center;
  2336. padding: 20px;
  2337. color: #909399;
  2338. }
  2339. :deep(.el-descriptions__label) {
  2340. width: 10%;
  2341. }
  2342. :deep(.el-descriptions__content) {
  2343. width: 20%;
  2344. }
  2345. .leader-tag {
  2346. display: inline-block;
  2347. width: 16px;
  2348. height: 16px;
  2349. line-height: 14px;
  2350. text-align: center;
  2351. border: 1px solid #4475d6;
  2352. font-size: 12px;
  2353. margin-right: 4px;
  2354. color: #4475d6;
  2355. }
  2356. .app-container { // Ensure this class is defined if not globally available
  2357. padding: 20px; // Example padding
  2358. }
  2359. // 操作按钮对齐样式
  2360. .operation-buttons {
  2361. display: flex;
  2362. justify-content: center;
  2363. align-items: center;
  2364. gap: 8px;
  2365. flex-wrap: wrap;
  2366. }
  2367. .custom-block.tip {
  2368. padding: 0 6px;
  2369. background-color: var(--block-warning-bg-color);
  2370. border-left: 5px solid var(--el-color-primary);
  2371. margin: 15px 0;
  2372. }
  2373. .el-row {
  2374. margin: 1px;
  2375. }
  2376. </style>