TaskOrderDetailDialog.vue 90 KB

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