TaskOrderDetailDialog.vue 86 KB

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