pipeDetail.vue 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941
  1. <template>
  2. <div class="app-container">
  3. <!-- 受检信息表单 -->
  4. <ContentWrap title="管道受检信息">
  5. <el-form :disabled="pageType === 'detail'" :model="formData" :rules="formRules" ref="formRef" label-width="120px" class="p-3">
  6. <div class="check-info-label-title">单位信息</div>
  7. <el-row class="form-group" :gutter="24">
  8. <el-col :span="8">
  9. <!-- 申请单位名称 unitName -->
  10. <el-form-item label="申请单位名称" prop="unitName" class="unit-form-item">
  11. <el-input v-if="useInputUnitName" v-model="formData.unitName.name" placeholder="请输入单位名称" />
  12. <CustomLargeListSelect
  13. v-else
  14. v-model:modelValue="formData.unitName"
  15. :fetchFunc="getUnitNewList"
  16. label-key="name"
  17. value-key="id"
  18. searchKeyProp="name"
  19. @change="handleChangeUnit"
  20. />
  21. <el-button type="primary" link @click="() => useInputUnitName = !useInputUnitName">{{useInputUnitName ? '选择单位' : '手动输入'}}</el-button>
  22. </el-form-item>
  23. </el-col>
  24. <el-col :span="8">
  25. <!-- 统一社会信用代码 socialCreditCode -->
  26. <el-form-item label="统一社会信用代码" prop="socialCreditCode" label-width="120px">
  27. <el-input v-model="formData.socialCreditCode" placeholder="请输入统一社会信用代码"/>
  28. </el-form-item>
  29. </el-col>
  30. <el-col :span="8">
  31. <!-- 申请单位地址 unitAddress -->
  32. <el-form-item label="申请单位地址" prop="unitAddress" label-width="120px">
  33. <el-input v-model="formData.unitAddress" placeholder="请输入申请单位地址"/>
  34. </el-form-item>
  35. </el-col>
  36. <el-col :span="8">
  37. <!-- 邮政编码 zipCode -->
  38. <el-form-item label="邮政编码" prop="zipCode">
  39. <el-input v-model="formData.zipCode" placeholder="请输入邮政编码" :maxlength="50"/>
  40. </el-form-item>
  41. </el-col>
  42. </el-row>
  43. <!-- <div class="check-info-label-title">使用单位</div> -->
  44. <el-row class="form-group" :gutter="24">
  45. <el-col :span="8">
  46. <!-- 使用单位名称 useUnitName -->
  47. <el-form-item label="使用单位名称" prop="useUnitName" class="unit-form-item">
  48. <el-input v-if="useInputUseUnitName" v-model="formData.useUnitName.name" placeholder="请输入使用单位名称" />
  49. <CustomLargeListSelect
  50. v-else
  51. v-model:modelValue="formData.useUnitName"
  52. :fetchFunc="getUnitNewList"
  53. label-key="name"
  54. value-key="id"
  55. searchKeyProp="name"
  56. @change="handleChangeUseUnit"
  57. />
  58. <el-button type="primary" link @click="() => useInputUseUnitName = !useInputUseUnitName">{{useInputUseUnitName ? '选择单位' : '手动输入'}}</el-button>
  59. </el-form-item>
  60. </el-col>
  61. <el-col :span="8">
  62. <!-- 统一社会信用代码 -->
  63. <el-form-item label="统一社会信用代码" prop="useUnitSocialCreditCode" label-width="120px">
  64. <el-input v-model="formData.useUnitSocialCreditCode" placeholder="请输入统一社会信用代码"/>
  65. </el-form-item>
  66. </el-col>
  67. <el-col :span="8">
  68. <!-- 使用单位地址 useUnitAddress -->
  69. <el-form-item label="使用单位地址" prop="useUnitAddress" label-width="120px">
  70. <el-input v-model="formData.useUnitAddress" placeholder="请输入使用单位地址"/>
  71. </el-form-item>
  72. </el-col>
  73. <el-col :span="8">
  74. <!-- 邮政编码 useUnitZipcode -->
  75. <el-form-item label="邮政编码" prop="useUnitZipcode">
  76. <el-input v-model="formData.useUnitZipcode" placeholder="请输入邮政编码"/>
  77. </el-form-item>
  78. </el-col>
  79. <el-col :span="8">
  80. <!-- 单位联系人 useUnitContact -->
  81. <el-form-item label="单位联系人" prop="useUnitContact" label-width="120px">
  82. <el-input v-model="formData.useUnitContact" placeholder="请输入单位联系人"/>
  83. </el-form-item>
  84. </el-col>
  85. <el-col :span="8">
  86. <!-- 联系人电话 useUnitPhone -->
  87. <el-form-item label="联系人电话" prop="useUnitPhone" label-width="120px">
  88. <el-input v-model="formData.useUnitPhone" placeholder="请输入联系人电话"/>
  89. </el-form-item>
  90. </el-col>
  91. </el-row>
  92. <div class="check-info-label-title">联系人信息</div>
  93. <el-row class="form-group" :gutter="24">
  94. <el-col :span="8">
  95. <!-- 约检联系人 unitContact -->
  96. <el-form-item label="约检联系人" prop="unitContact">
  97. <el-input v-model="formData.unitContact" placeholder="请输入约检联系人" :maxlength="50"/>
  98. </el-form-item>
  99. </el-col>
  100. <el-col :span="8">
  101. <!-- 约检联系人电话unitPhone -->
  102. <el-form-item label="联系人电话" prop="unitPhone" label-width="120px">
  103. <el-input v-model="formData.unitPhone" placeholder="请输入约检联系人电话" :maxlength="11"/>
  104. </el-form-item>
  105. </el-col>
  106. <el-col :span="8">
  107. <el-form-item label="联系人邮箱" prop="email" label-width="120px">
  108. <el-input v-model="formData.email" placeholder="请输入约检联系人邮箱" :maxlength="11"/>
  109. </el-form-item>
  110. </el-col>
  111. <el-col :span="8">
  112. <!-- 电子报告接收人 recipient -->
  113. <el-form-item label="电子报告接收人" prop="recipient" label-width="120px">
  114. <el-input v-model="formData.recipient" placeholder="请输入电子报告接收人" :maxlength="50"/>
  115. </el-form-item>
  116. </el-col>
  117. <el-col :span="8">
  118. <!-- 接收人电话 recipientPhone -->
  119. <el-form-item label="接收人电话" prop="recipientPhone">
  120. <el-input v-model="formData.recipientPhone" placeholder="请输入接收人电话" :maxlength="11"/>
  121. </el-form-item>
  122. </el-col>
  123. <el-col :span="8">
  124. <el-form-item label="接收人邮箱" prop="recipientEmail">
  125. <el-input v-model="formData.recipientEmail" placeholder="请输入接收人邮箱"/>
  126. </el-form-item>
  127. </el-col>
  128. <el-col :span="8">
  129. <el-form-item label="缴费联系人" prop="payerContactName" label-width="120px">
  130. <el-input v-model="formData.payerContactName" placeholder="请输入缴费联系人" :maxlength="50"/>
  131. </el-form-item>
  132. </el-col>
  133. <el-col :span="8">
  134. <!-- 接收人电话 recipientPhone -->
  135. <el-form-item label="缴费人电话" prop="payerContact">
  136. <el-input v-model="formData.payerContact" placeholder="请输入缴费人电话" :maxlength="11"/>
  137. </el-form-item>
  138. </el-col>
  139. <el-col :span="8">
  140. <el-form-item label="缴费人邮箱" prop="payerMail">
  141. <el-input v-model="formData.payerMail" placeholder="请输入缴费人邮箱"/>
  142. </el-form-item>
  143. </el-col>
  144. </el-row>
  145. <div class="check-info-label-title">受理信息</div>
  146. <el-row class="form-group" :gutter="24">
  147. <el-col :span="8">
  148. <!-- 检验部门 deptId -->
  149. <el-form-item label="检验部门" prop="deptId">
  150. <!-- <el-input v-model="formData.deptId" placeholder="请输入检验部门"/> -->
  151. <DeptSelect
  152. v-model="formData.deptId"
  153. placeholder="请选择部门"
  154. clearable
  155. />
  156. </el-form-item>
  157. </el-col>
  158. <el-col :span="8">
  159. <!-- 联系电话 deptPhone -->
  160. <el-form-item label="联系电话" prop="deptPhone" label-width="120px">
  161. <el-input v-model="formData.deptPhone" placeholder="请输入联系电话" :maxlength="20"/>
  162. </el-form-item>
  163. </el-col>
  164. <el-col :span="8">
  165. <!-- 约检时间 appointmentDate -->
  166. <el-form-item label="约检时间" prop="appointmentDate" label-width="120px">
  167. <el-date-picker
  168. v-model="formData.appointmentDate"
  169. type="date"
  170. value-format="YYYY-MM-DD"
  171. placeholder="请选择约检时间"
  172. :disabled-date="disabledDate"
  173. />
  174. </el-form-item>
  175. </el-col>
  176. <el-col :span="24">
  177. <!-- 检验员 teamList -->
  178. <el-form-item label="检验员" prop="teamList">
  179. <!-- <CheckerSelect-->
  180. <!-- ref="checkerSelectRef"-->
  181. <!-- v-model="selectedCheckers"-->
  182. <!-- :dept-id="userStore.getUser.deptId?.toString() || '1'"-->
  183. <!-- :disabled="false"-->
  184. <!-- :has-data="true"-->
  185. <!-- empty-text="暂无检验员数据"-->
  186. <!-- :multiple="true"-->
  187. <!-- @change="handleCheckerChange"-->
  188. <!-- />-->
  189. <div v-if="formattedCheckers.length > 0" class="selected-checkers">
  190. <el-tag
  191. v-for="checker in formattedCheckers"
  192. :key="checker.id"
  193. effect="plain"
  194. class="mr-8px mb-8px"
  195. >
  196. {{ checker.label }}
  197. </el-tag>
  198. </div>
  199. </el-form-item>
  200. </el-col>
  201. </el-row>
  202. <div class="check-info-label-title">异常信息</div>
  203. <el-row class="m-b-20px">
  204. <el-button v-if="!exceptionInfo.id" type="primary" @click="addExceptionInfo">添加异常单</el-button>
  205. <el-button v-else type="primary" @click="deleteExceptionInfo">删除异常单</el-button>
  206. </el-row>
  207. <el-row v-if="exceptionInfo.id" class="form-group" :gutter="24">
  208. <el-col :span="8">
  209. <el-form-item label="有效日期调整原因" prop="effectiveDateAdjustReason">
  210. <el-input v-model="exceptionInfo.effectiveDateAdjustReason" placeholder="请输入有效日期调整原因"/>
  211. </el-form-item>
  212. </el-col>
  213. <el-col :span="8">
  214. <el-form-item label="受理建议" prop="acceptSuggeston">
  215. <el-input v-model="exceptionInfo.acceptSuggeston" placeholder="请输入受理建议"/>
  216. </el-form-item>
  217. </el-col>
  218. <el-col :span="8">
  219. <el-form-item label="调整有效日期" prop="adjustEffectiveDate">
  220. <el-date-picker
  221. v-model="exceptionInfo.adjustEffectiveDate"
  222. type="date"
  223. value-format="YYYY-MM-DD"
  224. placeholder="请选择调整有效日期"
  225. />
  226. </el-form-item>
  227. </el-col>
  228. <el-col :span="12">
  229. <el-form-item label="情况说明" prop="descrition">
  230. <component :is="getExceptionItem('descrition', 'descritionAttach')" />
  231. </el-form-item>
  232. </el-col>
  233. <el-col :span="12">
  234. <el-form-item label="重启表" prop="restartTable">
  235. <component :is="getExceptionItem('restartTable', 'restartTableAttach')" />
  236. </el-form-item>
  237. </el-col>
  238. <el-col :span="12">
  239. <el-form-item label="指令书" prop="instrustionBook">
  240. <component :is="getExceptionItem('instrustionBook', 'instrustionBookAttach')" />
  241. </el-form-item>
  242. </el-col>
  243. <el-col :span="12">
  244. <el-form-item label="受理回执" prop="acceptReceipt">
  245. <component :is="getExceptionItem('acceptReceipt', 'acceptReceiptAttach')" />
  246. </el-form-item>
  247. </el-col>
  248. <el-col :span="12">
  249. <el-form-item label="其他" prop="other">
  250. <component :is="getExceptionItem('other', 'otherAttach')" />
  251. </el-form-item>
  252. </el-col>
  253. <el-col :span="12">
  254. <el-form-item label="提前检验申请函" prop="earlyCheckApply">
  255. <component :is="getExceptionItem('earlyCheckApply', 'earlyCheckApplyAttach')" />
  256. </el-form-item>
  257. </el-col>
  258. </el-row>
  259. <div class="check-info-label-title">检验收费</div>
  260. <el-row class="form-group" :gutter="24">
  261. <el-col :span="24">
  262. <!-- 定期检查&超年限检查 -->
  263. <el-form-item label="检验性质" prop="checkType" label-width="120px" v-if="orderDetail?.checkType">
  264. <span>{{ PressurePipeCheckTypeMap[orderDetail.checkType] }}</span>
  265. </el-form-item>
  266. <!-- 收费性质 feeNature -->
  267. <el-form-item prop="feeNature" >
  268. <template #label>
  269. <div class="flex flex-col text-right">
  270. <span>收费性质</span>
  271. <span>(行政事业收费)</span>
  272. </div>
  273. </template>
  274. <el-radio-group v-model="formData.feeNature">
  275. <el-radio v-for="(item, key) in PressureFeeNatureMap" :key="key" :value="key" :label="item"/>
  276. </el-radio-group>
  277. </el-form-item>
  278. </el-col>
  279. <el-col :span="24">
  280. <!-- 收费形式 feeType -->
  281. <el-form-item label="收费形式" prop="feeType">
  282. <el-radio-group v-model="formData.feeType">
  283. <el-radio label="100">非合同收费</el-radio>
  284. </el-radio-group>
  285. </el-form-item>
  286. </el-col>
  287. <el-col :span="24">
  288. <!-- 收费金额 actualAmount -->
  289. <!-- <el-form-item label="收费金额" prop="actualAmount" class="actualAmountFormItem">
  290. <el-input-number
  291. :controls="false"
  292. v-model="formData.actualAmount"
  293. placeholder="请输入收费金额"
  294. :min="0"
  295. />
  296. <div style="padding-left: 8px;">大写({{numberToChinese(formData.actualAmount)}})含税</div>
  297. </el-form-item>-->
  298. <div class="flex items-center gap-32 ml-40px text-14px">
  299. <span>应收法定金额: {{ formData.shouldAmount }}</span>
  300. <span>服务收费金额:{{ formData.serviceAmount }}</span>
  301. <span>免征费用: {{ formData.reduceFee }}</span>
  302. </div>
  303. </el-col>
  304. <!-- <el-col :span="24">
  305. &lt;!&ndash; 年度检查 &ndash;&gt;
  306. <el-form-item label="" prop="feeDate" label-width="30" v-if="orderDetail?.checkType == 200">
  307. <div class="feeDate_box">
  308. 甲方在本服务单签订之日起
  309. <el-input-number :controls="false" v-model="formData.feeDate" placeholder="请输入" :maxlength="50"/>
  310. 日内一次性支付。
  311. </div>
  312. </el-form-item>
  313. </el-col>-->
  314. </el-row>
  315. </el-form>
  316. </ContentWrap>
  317. <!-- 设备清单 -->
  318. <ContentWrap title="设备信息">
  319. <!-- 搜索工作栏 -->
  320. <el-form
  321. :model="equipQueryParams"
  322. ref="equipQueryFormRef"
  323. :disabled="pageType === 'detail'"
  324. :inline="true"
  325. label-width="80px"
  326. class="border-b border-gray-200 border-b-solid pb-4"
  327. >
  328. <!-- 基本信息查询部分 -->
  329. <div class="flex flex-wrap items-start gap-x-2">
  330. <!-- <el-form-item label="设备代码" prop="equipCode">-->
  331. <!-- <el-input-->
  332. <!-- v-model="equipQueryParams.equipCode"-->
  333. <!-- placeholder="请输入设备注册代码"-->
  334. <!-- clearable-->
  335. <!-- @keyup.enter="handleEquipQuery"-->
  336. <!-- class="!w-240px"-->
  337. <!-- />-->
  338. <!-- </el-form-item>-->
  339. <!-- <el-form-item label="出厂编号" prop="factoryCode">-->
  340. <!-- <el-input-->
  341. <!-- v-model="equipQueryParams.factoryCode"-->
  342. <!-- placeholder="请输入出厂编号"-->
  343. <!-- clearable-->
  344. <!-- @keyup.enter="handleEquipQuery"-->
  345. <!-- class="!w-240px"-->
  346. <!-- />-->
  347. <!-- </el-form-item>-->
  348. <el-form-item label="部门" prop="relateDepartment">
  349. <DeptSelect
  350. v-model="equipQueryParams.relateDepartment"
  351. placeholder="请选择部门"
  352. clearable
  353. class="!w-240px"
  354. />
  355. </el-form-item>
  356. <!-- <el-form-item label="运行状态" prop="status">
  357. <el-select
  358. v-model="equipQueryParams.status"
  359. placeholder="选择运行状态"
  360. clearable
  361. multiple
  362. collapse-tags
  363. collapse-tags-tooltip
  364. class="!w-240px"
  365. >
  366. <el-option
  367. v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_EQUIP_CONTAINER_STATUS)"
  368. :key="dict.value"
  369. :label="dict.label"
  370. :value="dict.value"
  371. />
  372. </el-select>
  373. </el-form-item> -->
  374. <el-form-item label="临检时间" prop="nextDate">
  375. <div class="flex items-center gap-x-2">
  376. <el-select v-model="datePickerType" class="!w-[90px]">
  377. <el-option label="时间段" value="daterange" />
  378. <el-option label="月份" value="month" />
  379. </el-select>
  380. <el-date-picker
  381. v-if="datePickerType === 'daterange'"
  382. v-model="daterange"
  383. type="daterange"
  384. value-format="YYYY-MM-DD"
  385. start-placeholder="开始日期"
  386. end-placeholder="结束日期"
  387. class="!w-[210px]"
  388. @change="handleDateChange"
  389. />
  390. <el-date-picker
  391. v-else
  392. v-model="month"
  393. type="month"
  394. value-format="YYYY-MM"
  395. placeholder="选择月份"
  396. class="!w-[140px]"
  397. @change="handleMonthChange"
  398. />
  399. </div>
  400. </el-form-item>
  401. </div>
  402. <!-- 区域和时间查询部分 -->
  403. <div class="flex flex-wrap items-start gap-x-2">
  404. <el-form-item label="区域" prop="equipDistrict">
  405. <AreaSelect
  406. v-model="equipQueryParams.equipDistrict"
  407. placeholder="请选择区域"
  408. class="!w-[240px]"
  409. multiple
  410. collapse-tags
  411. collapse-tags-tooltip
  412. :clearable="true"
  413. @clear="handleAreaClear"
  414. @change="handleAreaChange"
  415. />
  416. </el-form-item>
  417. <el-form-item label="街道" prop="equipStreet">
  418. <StreetSelect
  419. v-model="equipQueryParams.equipStreet"
  420. :district-ids="equipQueryParams.equipDistrict"
  421. placeholder="请选择街道"
  422. class="!w-[240px]"
  423. multiple
  424. collapse-tags
  425. collapse-tags-tooltip
  426. :clearable="true"
  427. @clear="handleStreetClear"
  428. @change="handleStreetChange"
  429. />
  430. </el-form-item>
  431. </div>
  432. <!-- 容器相关查询条件 -->
  433. <div class="">
  434. <el-form-item label="管道归类" prop="typeList" class="mb-2">
  435. <div class="flex items-center flex-1">
  436. <el-checkbox-group
  437. v-model="equipQueryParams.typeList"
  438. class="flex flex-wrap gap-2"
  439. >
  440. <el-checkbox
  441. v-for="dict in containerTypeOptions"
  442. :key="dict.value"
  443. :label="dict.label"
  444. :value="dict.value"
  445. />
  446. </el-checkbox-group>
  447. </div>
  448. </el-form-item>
  449. </div>
  450. <!-- 操作按钮 -->
  451. <div class="flex justify-center">
  452. <el-form-item class="!mb-0">
  453. <el-button @click="handleEquipQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
  454. <el-button @click="resetEquipQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
  455. <!-- 删除设备 -->
  456. <el-button type="danger" :disabled="selectedDetailRows.length === 0" @click="handleRejectEquip">
  457. <Icon icon="ep:failed" class="mr-5px" /> 拒绝约检
  458. </el-button>
  459. <el-button :disabled="orderDetail?.createAcceptOrder === true" type="primary" @click="handleAddEquip">
  460. <Icon icon="ep:plus" class="mr-5px" /> 添加设备
  461. </el-button>
  462. <el-button
  463. type="primary"
  464. @click="handleBatchEditFn"
  465. :disabled="selectedRows.length === 0"
  466. >
  467. <Icon icon="ep:edit" class="mr-5px" /> 批量修改约检联系人
  468. </el-button>
  469. </el-form-item>
  470. </div>
  471. </el-form>
  472. <!-- 设备列表 -->
  473. <el-table
  474. v-loading="loading"
  475. ref="tableRef"
  476. :data="equipList"
  477. stripe
  478. border
  479. @selection-change="handleSelectionChange"
  480. @sort-change="handleSortChange"
  481. :row-key="(row) => row.id"
  482. >
  483. <el-table-column type="selection" width="50" fixed="left"/>
  484. <el-table-column type="expand" width="1">
  485. <template #default="props">
  486. <div class="ml-15px mr-15px">
  487. <el-table :data="props.row.detailSaveReqVOS" border
  488. :header-cell-style="{background: '#f5f7fa', color: '#606266'}"
  489. :ref="(el) => setDetailTableRef(el, props.row.id)"
  490. @selection-change="(selection) => handleDetailSelectionChange(selection, props.row)"
  491. >
  492. <el-table-column type="selection" width="50" fixed="left"/>
  493. <el-table-column type="index" label="序号" width="60" align="center" :index="indexMethod1" />
  494. <el-table-column label="管道编号" prop="pipeNo" align="center" min-width="100" />
  495. <el-table-column label="注册代码" prop="equipCode" align="center" min-width="120" />
  496. <el-table-column label="管道名称" prop="pipeName" align="center" min-width="150" />
  497. <el-table-column label="管道级别" prop="pipeLevel" align="center" min-width="80" />
  498. <el-table-column label="规格" align="center" min-width="180">
  499. <el-table-column label="公称直径mm" prop="nominalDiameter" align="center" min-width="80" />
  500. <el-table-column label="公称壁厚mm" prop="nominalWallThickness" align="center" min-width="80" />
  501. <el-table-column label="管道长度m" prop="pipeLength" align="center" min-width="80" />
  502. </el-table-column>
  503. <el-table-column label="管道材质" prop="pipeMaterial" align="center" min-width="100" />
  504. <el-table-column label="材料标准" prop="materialStandard" align="center" min-width="100" />
  505. <el-table-column label="设计 / 允许 (监控) 工作条件" align="center" min-width="300">
  506. <el-table-column label="压力MPa" prop="designPressure" align="center" min-width="100" />
  507. <el-table-column label="温度℃" prop="designTemperature" align="center" min-width="100" />
  508. <el-table-column label="介质" prop="pipeMedium" align="center" min-width="100" />
  509. </el-table-column>
  510. <el-table-column label="焊口数量" prop="weldCount" align="center" min-width="80" />
  511. <el-table-column label="起止点" prop="startEndPoint" align="center" min-width="200" />
  512. <el-table-column label="安全状况等级" prop="safetyStatusLevel" align="center" min-width="100" />
  513. </el-table>
  514. </div>
  515. </template>
  516. </el-table-column>
  517. <el-table-column type="index" label="序号" width="60" align="center" :index="indexMethod" />
  518. <el-table-column
  519. label="工程号"
  520. align="center"
  521. prop="projectNo"
  522. min-width="120"
  523. >
  524. <template #default="{ row }">
  525. <div
  526. v-if="row.projectNo"
  527. class="cursor-pointer"
  528. @click="toggleExpand(row)"
  529. >
  530. <div class="flex items-center justify-center gap-1 schedule-link">
  531. <span class="text-xs color-blue">{{row.projectNo}}</span>
  532. </div>
  533. </div>
  534. </template>
  535. </el-table-column>
  536. <el-table-column label="工程名称"
  537. align="center"
  538. prop="projectName"
  539. min-width="120"
  540. show-overflow-tooltip
  541. />
  542. <!-- 区域 -->
  543. <el-table-column
  544. label="区域/街道"
  545. align="center"
  546. prop="pipeStreet"
  547. min-width="120"
  548. show-overflow-tooltip
  549. >
  550. <template #default="{ row }">
  551. <span class="text-xs">{{ row.equipStreetName ?? row.equipDistrictName}}</span>
  552. </template>
  553. </el-table-column>
  554. <!-- 管道类别 -->
  555. <el-table-column label="管道类别" align="center" prop="pipeCategory">
  556. <template #default="scope">
  557. {{ containerTypeOptions.find(i => i.value == scope.row.pipeCategory)?.label }}
  558. </template>
  559. </el-table-column>
  560. <el-table-column
  561. label="约检联系人"
  562. align="center"
  563. prop="contact"
  564. min-width="120"
  565. show-overflow-tooltip
  566. />
  567. <el-table-column
  568. label="约检联系人电话"
  569. align="center"
  570. prop="contactPhone"
  571. min-width="140"
  572. show-overflow-tooltip
  573. />
  574. </el-table>
  575. </ContentWrap>
  576. <!-- 设备清单 -->
  577. <ContentWrap title="备注">
  578. <el-row>
  579. <el-col :span="12">
  580. <el-form-item class="!mb-0" label="上次退回原因" prop="reason">
  581. <el-input type="textarea" :rows="4" v-model="formData.reason" readonly/>
  582. </el-form-item>
  583. </el-col>
  584. </el-row>
  585. </ContentWrap>
  586. <!-- 添加设备弹窗 -->
  587. <PipeAddEquipDialog
  588. v-model:visible="addEquipVisible"
  589. type="acceptOrder"
  590. :target-id="orderDetail?.id || ''"
  591. @success="handleAddEquipSuccess"
  592. :unit-code="orderDetail?.unitCode || ''"
  593. :unit-name="orderDetail?.unitName || ''"
  594. />
  595. <!-- 拒绝约检弹窗 -->
  596. <el-dialog
  597. v-model="rejectDialogVisible"
  598. title="拒绝约检"
  599. width="600px"
  600. destroy-on-close
  601. :close-on-click-modal="false"
  602. >
  603. <div class="mb-4">
  604. <div v-for="equip in selectedRows" :key="equip.id" class="mb-2">
  605. 设备注册代码:{{ equip.equipCode }}
  606. </div>
  607. </div>
  608. <div class="mb-4">
  609. 检验性质:{{ orderDetail?.checkType ? checkTypeMap[orderDetail.checkType] : '' }}
  610. </div>
  611. <div class="mb-4 flex flex-start items-center">
  612. <div class="!w-80px">拒绝原因:</div>
  613. <el-select v-model="rejectForm.reasonDict" placeholder="请选择拒绝原因" @change="() => {rejectForm.reason = ''}">
  614. <el-option
  615. v-for="dict in getStrDictOptions('refuseInspectedCategory')"
  616. :key="dict.value"
  617. :label="dict.label"
  618. :value="dict.value"
  619. />
  620. </el-select>
  621. </div>
  622. <div class="mb-4" v-if="rejectForm.reasonDict == '5'">
  623. <div class="mb-2">说明:</div>
  624. <el-input
  625. v-model="rejectForm.reason"
  626. type="textarea"
  627. :rows="4"
  628. placeholder="请输入"
  629. resize="none"
  630. />
  631. </div>
  632. <template #footer>
  633. <div class="flex justify-end items-center">
  634. <el-button type="primary" :loading="rejectLoading" @click="handleRejectConfirm(100)">上报市局</el-button>
  635. <!-- <el-button v-if="orderDetail.checkType === 100 || orderDetail.checkType === 300" type="primary" :loading="rejectLoading" @click="handleRejectConfirm(100)">上报市局</el-button>-->
  636. <!-- <el-button v-else type="primary" :loading="rejectLoading" @click="handleRejectConfirm(200)">上报拒检</el-button>-->
  637. <el-button type="warning" @click="handleRejectConfirm(300)">无需上报</el-button>
  638. <el-button @click="rejectDialogVisible = false">取消</el-button>
  639. </div>
  640. </template>
  641. </el-dialog>
  642. <!-- 页面底部按钮 -->
  643. <div class="flex justify-center pb-4 footer-btn-box">
  644. <el-button @click="handleClose">关闭</el-button>
  645. <el-button :disabled="pageType === 'detail'" type="primary" :loading="submitLoading" @click="handleGenerateAcceptance">
  646. 重新提交
  647. </el-button>
  648. <!-- <el-button type="primary" plain @click="handlePrintPDF">打印受理单PDF</el-button> -->
  649. </div>
  650. <PipeBatchEditForm ref="batchEditFormRef" @success="handleEquipQuery"/>
  651. <!-- <EquipContainerForm ref="EquipContainerFormRef" />-->
  652. <FileUploadModal ref="fileUploadModalRef" @success="handleFileUploadSuccess" />
  653. </div>
  654. </template>
  655. <script setup lang="tsx">
  656. import { ref, onMounted, computed, watch, unref } from 'vue'
  657. import { ElMessage, ElMessageBox } from 'element-plus'
  658. import { BoilerAcceptOrderApi } from '@/api/pressure2/boileracceptorder'
  659. import PipeBatchEditForm from '@/views/pressure2/planNew/components/PipeBatchEditForm.vue'
  660. import { BoilerAppointmentConfirmOrderEquipmentVO } from '@/api/pressure2/appointmentconfirmorder'
  661. import { type CheckerItem } from '@/views/pressure2/components/CheckerSelect'
  662. import dayjs from 'dayjs'
  663. import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
  664. import DeptSelect from '../../pressure2/planNew/components/DeptSelect.vue'
  665. import AreaSelect from '../../system/equipcontainer/components/AreaSelect.vue'
  666. import StreetSelect from '../../system/equipcontainer/components/StreetSelect.vue'
  667. import PipeAddEquipDialog from '../schedule/components/PipeAddEquipDialog.vue'
  668. import {formatArrayDate, formatDate} from '@/utils/formatTime'
  669. import { PressureBoilerCheckTypeMap, PressureFeeTypeMap, PressureSendTypeMap, PressureVehicleTypeMap, PressureAcceptTypeMap, PressureFeeNatureMap, PressureFeeNature, PressureBoilerCheckType} from '@/utils/constants'
  670. import { getUnitNewList, getUnitContacts } from '@/api/laboratory/unit'
  671. import EquipContainerForm from '@/components/EquipContainerForm/index.vue'
  672. import { numberToChinese } from '@/utils/formatter'
  673. import FileUploadModal from '@/views/pressure2/orderConfirm/components/ImportFile.vue'
  674. import { buildFileUrl } from '@/utils'
  675. import { useRoute } from 'vue-router'
  676. import { Icon } from '@/components/Icon'
  677. import { cloneDeep } from 'lodash-es'
  678. import {
  679. PipeEquipmentApi,
  680. PipeEquipmentDetailVO,
  681. PipeEquipmentVO
  682. } from "@/api/pressure2/pipeequipment";
  683. import {PipeAcceptOrderApi} from "@/api/pressure2/pipeacceptorder";
  684. import {PipeAppointmentConfirmOrderApi} from "@/api/pressure2/pipeappointmentconfirmorder";
  685. import {UserQualificationsApi} from "@/api/pressure2/userQualifications";
  686. import { useUserStore } from '@/store/modules/user'
  687. import {PressurePipeCheckTypeMap} from "../../../utils/constants";
  688. const route = useRoute()
  689. const userStore = useUserStore()
  690. const props = defineProps({
  691. visible: {
  692. type: Boolean,
  693. default: false
  694. },
  695. id: {
  696. type: String,
  697. default: ''
  698. },
  699. pageType: {
  700. type: String,
  701. default: ''
  702. }
  703. })
  704. const emit = defineEmits(['update:visible', 'success'])
  705. // const EquipContainerFormRef = ref<InstanceType<typeof EquipContainerForm>>()
  706. const orderDetail = ref()
  707. const batchEditFormRef = ref()
  708. const checkTypeMap = {
  709. [PressureBoilerCheckType.IN]: '内部检查',
  710. [PressureBoilerCheckType.OUT]: '外部检查',
  711. [PressureBoilerCheckType.PRESSURE]: '耐压检查'
  712. }
  713. const formData = ref<Record<string, any>>({
  714. appointmentDate: '',
  715. teamList: [] as string[],
  716. unitName: {
  717. name: '',
  718. id: ''
  719. },
  720. useUnitName: {
  721. name: '',
  722. id: ''
  723. },
  724. deptName: '',
  725. equipDistrict: undefined as number | undefined,
  726. equipDistrictName: '',
  727. equipStreet: '',
  728. equipStreetName: '',
  729. unitContact: '',
  730. unitContactDept: '',
  731. unitAddress: '',
  732. unitPhone: '',
  733. zipCode: '',
  734. mobile: '',
  735. remark: '',
  736. email: '',
  737. isAttach: false,
  738. sendType: '100',
  739. vehicle: '100',
  740. feeType: '100',
  741. acceptType: '100',
  742. actualAmount: 0,
  743. serviceAmount: 0,
  744. shouldAmount: 0,
  745. reduceFee: 0,
  746. planMaker: '',
  747. deptId: '',
  748. operator: '',
  749. areaDisplay: '',
  750. reason: '',
  751. socialCreditCode: '',
  752. recipient: '',
  753. recipientPhone: '',
  754. recipientEmail: '',
  755. useUnitSocialCreditCode: '',
  756. useUnitAddress: '',
  757. useUnitZipcode: '',
  758. useUnitContact: '',
  759. useUnitPhone: '',
  760. deptPhone: '',
  761. feeNature: '',
  762. feeDate: 0,
  763. })
  764. const userList = ref<any[]>([])
  765. // 检验员组件引用
  766. const checkerSelectRef = ref()
  767. // 选中的检验员对象列表
  768. const selectedCheckers = ref<CheckerItem[]>([])
  769. const loading = ref(false)
  770. const submitLoading = ref(false) // 提交按钮 loading
  771. // 记录每个区域下已选择的街道
  772. const areaStreetMap = ref(new Map<number, number[]>())
  773. // 设备查询相关
  774. const equipQueryParams = ref({
  775. pageNo: 1,
  776. pageSize: 50,
  777. equipDistrict: undefined as number[] | undefined,
  778. equipStreet: undefined as number[] | undefined,
  779. equipCode: '',
  780. factoryCode: '',
  781. relateDepartment: '',
  782. typeList: [] as string[],
  783. nextDate: [] as string[],
  784. useStatus: [] as string[],
  785. })
  786. const equipQueryFormRef = ref()
  787. const equipLoading = ref(false)
  788. const equipList = ref<BoilerAppointmentConfirmOrderEquipmentVO[]>([])
  789. // 选中的设备
  790. const selectedEquips = ref<BoilerAppointmentConfirmOrderEquipmentVO[]>([])
  791. const equipTotal = ref(0)
  792. const equipCategoryOptions = getStrDictOptions(DICT_TYPE.SYSTEM_EQUIP_CONTAINER_EQUIP_CATEGORY)
  793. const containerTypeOptions = getStrDictOptions(DICT_TYPE.PIPE_TYPE)
  794. const selectedRows = ref<BoilerAppointmentConfirmOrderEquipmentVO[]>([]) // 选中的行
  795. const selectedDetailRows = ref<PipeEquipmentDetailVO[]>([]) // 选中的行
  796. // 临检时间相关
  797. const datePickerType = ref<'daterange' | 'month'>('month')
  798. const daterange = ref<string[]>([])
  799. const month = ref<string>('')
  800. // 添加设备相关
  801. const addEquipVisible = ref(false)
  802. // 拒绝约检相关
  803. const rejectDialogVisible = ref(false)
  804. const rejectLoading = ref(false)
  805. const rejectForm = ref({
  806. reason: '',
  807. reasonDict: ''
  808. })
  809. const formRef = ref() // 表单引用
  810. const indexMethod = (index: number) => {
  811. return index + 1
  812. }
  813. const indexMethod1 = (index: number) => {
  814. return index + 1
  815. }
  816. /** 约检确认详情 */
  817. defineOptions({ name: 'OrderConfirmDetail' })
  818. // 表单验证规则
  819. const formRules = {
  820. // unitContact: [
  821. // { required: true, message: '请输入单位联系人', trigger: 'blur' }
  822. // ],
  823. // unitPhone: [
  824. // { required: true, message: '请输入单位联系电话', trigger: 'blur' },
  825. // ],
  826. // mobile: [
  827. // { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
  828. // ],
  829. email: [
  830. { pattern: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/, message: '请输入正确的邮箱', trigger: 'blur' }
  831. ],
  832. sendType: [
  833. { required: true, message: '请选择送达方式', trigger: 'blur' }
  834. ],
  835. // feeType: [
  836. // { required: true, message: '请选择收费类型', trigger: 'blur' }
  837. // ],
  838. acceptType: [
  839. { required: true, message: '请选择受理方式', trigger: 'blur' }
  840. ],
  841. vehicle: [
  842. { required: true, message: '请选择交通工具', trigger: 'blur' }
  843. ]
  844. }
  845. // 区域显示属性,与formData.areaDisplay分离
  846. const areaDisplay = computed(() => {
  847. const district = formData.value.equipDistrictName || ''
  848. const street = formData.value.equipStreetName || ''
  849. if (district && street) {
  850. return `${district}-${street}`
  851. }
  852. return district
  853. })
  854. type scheduleType = 'regular' | 'year' | ''
  855. const tableRef = ref()
  856. const currentEquip = ref<PipeEquipmentVO>()
  857. const currentCheckType = ref<scheduleType>('')
  858. // 存储所有子表引用的对象
  859. const detailTableRefs = ref<Record<string, any>>({})
  860. const setDetailTableRef = (el: any, parentId: string) => {
  861. if (el) {
  862. detailTableRefs.value[parentId] = el;
  863. }
  864. }
  865. const getDetailTableRef = (parentId: string) => {
  866. return detailTableRefs.value[parentId];
  867. }
  868. // 已展开行
  869. const expandRowKeys = ref<string[]>([])
  870. const expandRows = ref([])
  871. const toggleExpand = async (row: any) => {
  872. const key = row.id
  873. // 第一次点击展开,第二次点击同一行收起
  874. if (expandRowKeys.value.includes(key)) {
  875. expandRowKeys.value = expandRowKeys.value.filter((key) => key !== key)
  876. expandRows.value = expandRows.value.filter((row) => row.id !== key)
  877. selectedDetailRows.value = selectedDetailRows.value.filter((row) => row.pipeEquipmentId !== key)
  878. tableRef.value.toggleRowExpansion(row, false)
  879. tableRef.value.toggleRowSelection(row, false)
  880. } else {
  881. expandRowKeys.value.push(key)
  882. expandRows.value.push(row)
  883. tableRef.value.toggleRowExpansion(row, true)
  884. await PipeAcceptOrderApi.getPipeEquipmentDetailListByPipeEquipmentId(orderDetail.value.id,key).then((res) => {
  885. let find = equipList.value.find(item => item.id === key);
  886. find.detailSaveReqVOS = res.list
  887. })
  888. }
  889. }
  890. const handleDetailSelectionChange = (selection: any[], mainRow: any) => {
  891. selectedDetailRows.value = selectedDetailRows.value.filter((item) => item.equipPipeId !== mainRow.id)
  892. selectedDetailRows.value = [...selectedDetailRows.value.filter(row => !selection.some(sel => sel.id === row.id)), ...selection]
  893. // tableRef.value.toggleRowSelection(mainRow, true)
  894. // 如果子表有选中项,则自动选中主表行;否则取消选中主表行
  895. nextTick(() => {
  896. if (selection.length > 0) {
  897. // 子表有选中项,选中主表行
  898. tableRef.value.toggleRowSelection(mainRow, true);
  899. }else if (!selectedDetailRows.value.map(row => row.equipPipeId).includes(mainRow.id)){
  900. const currentlySelected = selectedRows.value.some(row => row.id === mainRow.id);
  901. if (currentlySelected && selection.length === 0) {
  902. // 只有当主行当前是选中状态且子表没有任何选中项时才取消主行选择
  903. tableRef.value.toggleRowSelection(mainRow,false);
  904. }
  905. }
  906. });
  907. }
  908. /** 表格选择框变化 */
  909. const handleSelectionChange = async (selection: BoilerAppointmentConfirmOrderEquipmentVO[]) => {
  910. // 计算取消选择的行
  911. const deselectedRows = selectedRows.value.filter(
  912. item => !selection.includes(item)
  913. );
  914. selectedRows.value = selection
  915. // 每一个勾选了主表的要找到对应的子表
  916. for (const item of selection) {
  917. // 如果没有子表,展开当前子表
  918. if (!expandRowKeys.value.includes(item.id)) {
  919. await toggleExpand(item)
  920. }
  921. // 如果没有勾选,勾选子表
  922. if (selectedDetailRows.value.findIndex(selectedDetailRow => selectedDetailRow.equipPipeId === item.id) === -1){
  923. getDetailTableRef(item.id)?.toggleAllSelection(true)
  924. }
  925. }
  926. deselectedRows.forEach(item => {
  927. getDetailTableRef(item.id)?.clearSelection()
  928. })
  929. }
  930. /** 处理表格排序 */
  931. const handleSortChange = ({ prop, order }) => {
  932. if (!prop || !order) {
  933. equipList.value.sort((a, b) => 0) // 重置排序
  934. return
  935. }
  936. equipList.value.sort((a, b) => {
  937. const aValue = a[prop] || ''
  938. const bValue = b[prop] || ''
  939. if (order === 'ascending') {
  940. return aValue > bValue ? 1 : -1
  941. } else {
  942. return aValue < bValue ? 1 : -1
  943. }
  944. })
  945. }
  946. // 获取约检详情
  947. const getDetail = async () => {
  948. const id = props.id as string
  949. if (!id) {
  950. ElMessage.warning('约检信息不存在')
  951. return
  952. }
  953. loading.value = true
  954. try {
  955. const res = await PipeAcceptOrderApi.getAcceptOrder(id)
  956. orderDetail.value = res
  957. let { payerContact, payerContactName, payerMail, email } = res;
  958. // 更新表单数据
  959. formData.value = {
  960. ...formData.value,
  961. appointmentDate: formatArrayDate(orderDetail.value?.appointmentDate || []),
  962. deptName: orderDetail.value?.deptName || '',
  963. equipDistrict: orderDetail.value?.equipDistrict ? Number(orderDetail.value.equipDistrict) : undefined,
  964. equipDistrictName: orderDetail.value?.equipDistrictName || '',
  965. unitContact: orderDetail.value?.unitContact || '',
  966. unitAddress: orderDetail.value?.unitAddress || '',
  967. unitPhone: orderDetail.value?.unitPhone || '',
  968. zipCode: orderDetail.value?.zipCode || '',
  969. mobile: orderDetail.value?.mobile || '',
  970. remark: orderDetail.value?.remark || '',
  971. email: orderDetail.value?.email || '',
  972. isAttach: orderDetail.value?.isAttach || false,
  973. sendType: String(orderDetail.value?.sendType) || '100',
  974. vehicle: String(orderDetail.value?.vehicle) || '100',
  975. feeType: String(orderDetail.value?.feeType) || '100',
  976. acceptType: String(orderDetail.value?.acceptType) || '100',
  977. actualAmount: orderDetail.value?.actualAmount || 0,
  978. serviceAmount: orderDetail.value?.serviceAmount || 0,
  979. shouldAmount: orderDetail.value?.shouldAmount || 0,
  980. reduceFee: orderDetail.value?.reduceFee || 0,
  981. deptId: orderDetail.value?.deptId || '',
  982. operator: orderDetail.value?.operator || '',
  983. equipStreetName: orderDetail.value?.equipStreetName || '',
  984. areaDisplay: areaDisplay.value,
  985. reason: orderDetail.value.reason,
  986. unitName: {
  987. name: orderDetail.value?.unitName || '',
  988. id: ''
  989. },
  990. useUnitName: {
  991. name: orderDetail.value?.useUnitName || '',
  992. id: ''
  993. },
  994. socialCreditCode: orderDetail.value?.socialCreditCode,
  995. recipient: orderDetail.value?.recipient,
  996. recipientPhone: orderDetail.value?.recipientPhone,
  997. recipientEmail: orderDetail.value?.recipientEmail,
  998. useUnitSocialCreditCode: orderDetail.value?.useUnitSocialCreditCode,
  999. useUnitAddress: orderDetail.value?.useUnitAddress,
  1000. useUnitZipcode: orderDetail.value?.useUnitZipcode,
  1001. useUnitContact: orderDetail.value?.useUnitContact,
  1002. useUnitPhone: orderDetail.value?.useUnitPhone,
  1003. deptPhone: orderDetail.value?.deptPhone,
  1004. feeNature: String(orderDetail.value?.feeNature),
  1005. feeDate: orderDetail.value?.feeDate || 0,
  1006. payerContact,
  1007. payerContactName,
  1008. payerMail,
  1009. }
  1010. // 更新异常单信息
  1011. const orderExceptionRespVO = res.orderExceptionRespVO
  1012. if(orderExceptionRespVO){
  1013. exceptionInfo.value = {
  1014. ...orderExceptionRespVO,
  1015. adjustEffectiveDate: orderExceptionRespVO.adjustEffectiveDate ? dayjs(orderExceptionRespVO.adjustEffectiveDate.join('-')).format('YYYY-MM-DD') : '',
  1016. }
  1017. }
  1018. userList.value = await UserQualificationsApi.getUserPipeAll()
  1019. // 获取检验员列表
  1020. const deptId = formData.value.deptId || userStore.getUser.deptId?.toString() || '1'
  1021. await nextTick()
  1022. checkerSelectRef.value?.getCheckerList(deptId)
  1023. const teamList = orderDetail.value?.teamList?.flatMap((team: any) => {
  1024. const teamMembers: any[] = []
  1025. // 处理组长
  1026. if (team.leaders && team.leaders.length > 0) {
  1027. team.leaders.forEach((leader: any) => {
  1028. if (leader) {
  1029. teamMembers.push({
  1030. memberId: leader.id,
  1031. groupTeamId: team.groupTeamId,
  1032. isLeader: true,
  1033. member: leader
  1034. })
  1035. }
  1036. })
  1037. }
  1038. // 处理组员
  1039. if (team.members && team.members.length > 0) {
  1040. team.members.forEach((member: any) => {
  1041. if (member) {
  1042. teamMembers.push({
  1043. memberId: member.id,
  1044. groupTeamId: team.groupTeamId,
  1045. isLeader: false,
  1046. member: member
  1047. })
  1048. }
  1049. })
  1050. }
  1051. return teamMembers
  1052. }) || []
  1053. if (teamList.length > 0) {
  1054. selectedCheckers.value = teamList
  1055. formData.value.teamList = teamList
  1056. }
  1057. } catch (error) {
  1058. console.error('获取计划详情失败:', error)
  1059. ElMessage.error('获取计划详情失败')
  1060. } finally {
  1061. loading.value = false
  1062. }
  1063. }
  1064. /** 处理检验员变化 */
  1065. const handleCheckerChange = (checkers: CheckerItem[]) => {
  1066. selectedCheckers.value = checkers
  1067. // 同步更新 formData.value.teamList
  1068. formData.value.teamList = checkers
  1069. }
  1070. const handleEquipQuery = async () => {
  1071. loading.value = true
  1072. try {
  1073. const params = {
  1074. pageNo: equipQueryParams.value.pageNo,
  1075. pageSize: equipQueryParams.value.pageSize,
  1076. orderId: orderDetail.value?.id,
  1077. equipCode: equipQueryParams.value.equipCode,
  1078. factoryCode: equipQueryParams.value.factoryCode,
  1079. relateDepartment: equipQueryParams.value.relateDepartment,
  1080. equipDistrict: equipQueryParams.value.equipDistrict,
  1081. equipStreet: equipQueryParams.value.equipStreet,
  1082. typeList: equipQueryParams.value.typeList || [],
  1083. nextDate: equipQueryParams.value.nextDate || [],
  1084. useStatus: equipQueryParams.value.useStatus || [],
  1085. }
  1086. expandRows.value.forEach(row => {
  1087. tableRef.value?.toggleRowExpansion(row, false)
  1088. })
  1089. // 清空展开行记录
  1090. expandRowKeys.value = []
  1091. expandRows.value = []
  1092. selectedRows.value = []
  1093. selectedDetailRows.value = []
  1094. // 移除空值
  1095. Object.keys(params).forEach(key => {
  1096. if (params[key] === '' || params[key] === undefined || params[key] === null) {
  1097. delete params[key]
  1098. }
  1099. // 处理空数组
  1100. if (Array.isArray(params[key]) && params[key].length === 0) {
  1101. delete params[key]
  1102. }
  1103. })
  1104. // 调用后端API获取数据
  1105. const res = await PipeAcceptOrderApi.getAcceptOrderEquipmentList(params)
  1106. equipList.value = res.list
  1107. equipTotal.value = res.total
  1108. } finally {
  1109. loading.value = false
  1110. }
  1111. }
  1112. // 页面加载时获取详情
  1113. onMounted(async () => {
  1114. await getDetail()
  1115. await handleEquipQuery()
  1116. })
  1117. /** 禁用日期 */
  1118. const disabledDate = (time: Date) => {
  1119. // 禁用过去的日期
  1120. return time.getTime() < dayjs().startOf('day').valueOf()
  1121. }
  1122. // const handleEquipCodeFn = (id?: number) => {
  1123. // EquipContainerFormRef.value.open(id)
  1124. // }
  1125. const resetEquipQuery = () => {
  1126. // 重置查询参数
  1127. equipQueryParams.value = {
  1128. pageNo: 1,
  1129. pageSize: 50,
  1130. equipDistrict: undefined,
  1131. equipStreet: undefined,
  1132. equipCode: '',
  1133. factoryCode: '',
  1134. relateDepartment: '',
  1135. typeList: [],
  1136. nextDate: [],
  1137. useStatus: [],
  1138. }
  1139. // 重置区域-街道映射
  1140. areaStreetMap.value.clear()
  1141. // 重置日期相关字段
  1142. daterange.value = []
  1143. month.value = ''
  1144. datePickerType.value = 'month'
  1145. // 重新查询数据
  1146. handleEquipQuery()
  1147. }
  1148. const handleEquipSelectionChange = (selection) => {
  1149. // 实现设备选择逻辑
  1150. selectedEquips.value = selection
  1151. }
  1152. const handleEquipSortChange = (sort) => {
  1153. // 实现设备排序逻辑
  1154. }
  1155. /** 处理区域变化 */
  1156. const handleAreaChange = (areas: number[]) => {
  1157. // 获取移除的区域(通过比较之前的区域列表和现在的区域列表)
  1158. const prevAreas = Array.from(areaStreetMap.value.keys())
  1159. const removedAreas = prevAreas.filter(area => !areas.includes(area))
  1160. // 移除取消选择的区域下的街道
  1161. if (removedAreas.length > 0) {
  1162. const currentStreets = equipQueryParams.value.equipStreet || []
  1163. removedAreas.forEach(areaId => {
  1164. const streetsToRemove = areaStreetMap.value.get(areaId) || []
  1165. // 从当前选中的街道中移除这些街道
  1166. equipQueryParams.value.equipStreet = currentStreets.filter(
  1167. streetId => !streetsToRemove.includes(streetId)
  1168. )
  1169. // 从映射中移除该区域
  1170. areaStreetMap.value.delete(areaId)
  1171. })
  1172. }
  1173. }
  1174. /** 处理区域清空 */
  1175. const handleAreaClear = () => {
  1176. // 清空所有选中的街道
  1177. equipQueryParams.value.equipStreet = []
  1178. // 清空区域-街道映射
  1179. areaStreetMap.value.clear()
  1180. }
  1181. /** 处理街道变化 */
  1182. const handleStreetChange = (streets: number[], areaId: number) => {
  1183. // 更新区域-街道映射
  1184. if (equipQueryParams.value.equipDistrict?.includes(areaId)) {
  1185. areaStreetMap.value.set(areaId, streets)
  1186. }
  1187. }
  1188. /** 处理街道清空 */
  1189. const handleStreetClear = () => {
  1190. // 清空所有区域下的街道选择
  1191. areaStreetMap.value.clear()
  1192. }
  1193. /** 处理日期范围变化 */
  1194. const handleDateChange = (val: [string, string] | null) => {
  1195. daterange.value = val || []
  1196. equipQueryParams.value.nextDate = val
  1197. ? [
  1198. dayjs(val[0]).startOf('day').format('YYYY-MM-DD HH:mm:ss'),
  1199. dayjs(val[1]).endOf('day').format('YYYY-MM-DD HH:mm:ss')
  1200. ]
  1201. : []
  1202. }
  1203. /** 处理月份变化 */
  1204. const handleMonthChange = (val: string | null) => {
  1205. if (!val) {
  1206. equipQueryParams.value.nextDate = []
  1207. return
  1208. }
  1209. const date = dayjs(val)
  1210. equipQueryParams.value.nextDate = [
  1211. date.startOf('month').format('YYYY-MM-DD HH:mm:ss'),
  1212. date.endOf('month').format('YYYY-MM-DD HH:mm:ss')
  1213. ]
  1214. month.value = val
  1215. }
  1216. // 监听日期类型变化
  1217. watch(datePickerType, (newVal) => {
  1218. // 清空日期相关字段
  1219. daterange.value = []
  1220. month.value = ''
  1221. equipQueryParams.value.nextDate = []
  1222. })
  1223. /** 拒绝约检 */
  1224. const handleRejectEquip = async () => {
  1225. if (selectedRows.value.length === 0 || selectedDetailRows.value.length === 0) {
  1226. ElMessage.warning('请选择要拒绝约检的设备')
  1227. return
  1228. }
  1229. rejectForm.value.reasonDict = ''
  1230. rejectForm.value.reason = ''
  1231. rejectDialogVisible.value = true
  1232. }
  1233. /** 处理批量修改 */
  1234. const handleBatchEditFn = () => {
  1235. if (selectedRows.value.length === 0) {
  1236. ElMessage.warning('请至少选择一条设备数据')
  1237. return
  1238. }
  1239. batchEditFormRef.value.open(selectedRows.value, '1')
  1240. }
  1241. /** 确认拒绝约检 */
  1242. const handleRejectConfirm = async (type) => {
  1243. if (!rejectForm.value.reasonDict) {
  1244. ElMessage.warning('请选择拒绝原因')
  1245. return
  1246. }
  1247. if (rejectForm.value.reasonDict == '5' && !rejectForm.value.reason) {
  1248. ElMessage.warning('请输入说明')
  1249. return
  1250. }
  1251. const equipIds = selectedRows.value.map(e => e.id)
  1252. const submitData = {
  1253. equipIds,
  1254. orderId: orderDetail.value?.id,
  1255. detailEquipRows: selectedDetailRows.value,
  1256. type,
  1257. reason: rejectForm.value.reason,
  1258. reasonDict: rejectForm.value.reasonDict,
  1259. }
  1260. let alertText = ''
  1261. switch(type) {
  1262. case 100:
  1263. alertText = '上报市局'
  1264. break
  1265. case 200:
  1266. alertText = '拒绝约检'
  1267. break
  1268. case 300:
  1269. alertText = '无需上报'
  1270. break
  1271. default:
  1272. alertText = ''
  1273. }
  1274. try {
  1275. // 调用api
  1276. const res = await PipeAcceptOrderApi.refuseAcceptOrder(submitData)
  1277. ElMessage.success(alertText + '操作成功')
  1278. // 提交成功后重置表单和关闭对话框
  1279. rejectForm.value.reason = ''
  1280. rejectForm.value.reasonDict = ''
  1281. rejectDialogVisible.value = false
  1282. handleEquipQuery() // 刷新设备列表
  1283. } catch (e) {
  1284. ElMessage.error(alertText + '操作失败')
  1285. }
  1286. }
  1287. /** 添加设备 */
  1288. const handleAddEquip = () => {
  1289. addEquipVisible.value = true
  1290. }
  1291. /** 添加设备成功 */
  1292. const handleAddEquipSuccess = (selectedEquips) => {
  1293. ElMessage.success('添加设备成功')
  1294. // 更新设备列表
  1295. handleEquipQuery()
  1296. }
  1297. /** 生成受理单 */
  1298. const handleGenerateAcceptance = () => {
  1299. console.log('开始验证表单', formRef.value)
  1300. // 表单验证
  1301. if (!formRef.value) {
  1302. ElMessage.warning('表单引用获取失败')
  1303. return
  1304. }
  1305. submitLoading.value = true
  1306. // 手动触发表单验证
  1307. formRef.value.validate((valid, fields) => {
  1308. if (!valid) {
  1309. ElMessage.warning('请完善必填信息')
  1310. console.log('验证失败的字段:', fields)
  1311. submitLoading.value = false
  1312. return
  1313. }
  1314. // 检查排期时间(检验员改为非必选,任务单阶段才必选)
  1315. if (!formData.value.appointmentDate) {
  1316. ElMessage.warning('请选择排期时间')
  1317. submitLoading.value = false
  1318. return
  1319. }
  1320. // 二次确认
  1321. ElMessageBox.confirm(
  1322. '确认重新提交受理单吗?',
  1323. '操作确认',
  1324. {
  1325. confirmButtonText: '确认',
  1326. cancelButtonText: '取消',
  1327. type: 'warning'
  1328. }
  1329. ).then(async () => {
  1330. if(exceptionInfo.value.id){
  1331. await handleSaveException()
  1332. }
  1333. // 确认后提交
  1334. submitAcceptance()
  1335. }).catch(() => {
  1336. // 用户取消操作
  1337. console.log('用户取消操作')
  1338. submitLoading.value = false
  1339. })
  1340. })
  1341. }
  1342. /** 提交受理单 */
  1343. const submitAcceptance = async () => {
  1344. try {
  1345. loading.value = true
  1346. // 组装提交数据
  1347. const submitData = {
  1348. id: orderDetail.value?.id,
  1349. ...formData.value,
  1350. appointmentDate: formData.value.appointmentDate,
  1351. unitName: orderDetail.value?.unitName?.name,
  1352. unitAddress: orderDetail.value?.unitAddress,
  1353. unitContact: formData.value.unitContact,
  1354. unitContactDept: formData.value.unitContactDept,
  1355. unitPhone: formData.value.unitPhone,
  1356. equipDistrict: orderDetail.value?.equipDistrict,
  1357. equipStreet: orderDetail.value?.equipStreet,
  1358. zipCode: formData.value.zipCode,
  1359. checkType: orderDetail.value?.checkType,
  1360. equipType: orderDetail.value?.equipType,
  1361. deptId: orderDetail.value?.deptId,
  1362. email: formData.value.email,
  1363. mobile: formData.value.mobile,
  1364. remark: formData.value.remark,
  1365. isAttach: formData.value.isAttach,
  1366. sendType: formData.value.sendType,
  1367. vehicle: formData.value.vehicle,
  1368. feeType: formData.value.feeType,
  1369. acceptType: formData.value.acceptType,
  1370. actualAmount: formData.value.actualAmount,
  1371. serviceAmount: formData.value.serviceAmount,
  1372. shouldAmount: formData.value.shouldAmount,
  1373. reduceFee: formData.value.reduceFee,
  1374. useUnitName: formData.value?.useUnitName?.name,
  1375. teamList: formData.value.teamList.reduce((acc: any[], item: any) => {
  1376. const existingGroup = acc.find(
  1377. group => group.groupTeamId === item.groupTeamId
  1378. );
  1379. if (existingGroup) {
  1380. // 避免重复添加相同的 userId,且不添加 leaderId
  1381. if (!item.isLeader && !existingGroup.userIds.includes(item.memberId)) {
  1382. existingGroup.userIds.push(item.memberId);
  1383. }
  1384. } else {
  1385. acc.push({
  1386. groupTeamId: item.groupTeamId,
  1387. leaderId: item.isLeader ? item.memberId : '',
  1388. userIds: item.isLeader ? [] : [item.memberId]
  1389. });
  1390. }
  1391. return acc;
  1392. }, [])
  1393. }
  1394. if(exceptionInfo.value.id){
  1395. submitData.boilerOrderExceptionSaveReqVO = cloneDeep({
  1396. ...exceptionInfo.value,
  1397. adjustEffectiveDate: unref(exceptionInfo).adjustEffectiveDate && unref(exceptionInfo).adjustEffectiveDate.split('-').map(item=>Number(item)),
  1398. })
  1399. }
  1400. // 调用API提交受理单
  1401. await PipeAcceptOrderApi.resubmitAcceptOrder(submitData)
  1402. emit('success')
  1403. ElMessage.success('提交成功')
  1404. handleClose()
  1405. } catch (error) {
  1406. console.error('提交失败:', error)
  1407. ElMessage.error('提交失败')
  1408. } finally {
  1409. loading.value = false
  1410. submitLoading.value = false
  1411. }
  1412. }
  1413. // 打印受理单
  1414. const handlePrintPDF = async () => {
  1415. const id = props.id as string
  1416. if(!id) return ElMessage.error('未找到受理单ID!')
  1417. try {
  1418. const pdfBlob = await BoilerAcceptOrderApi.printAcceptOrderPdf({id})
  1419. if(pdfBlob) {
  1420. const url = URL.createObjectURL(pdfBlob)
  1421. let a = document.createElement('a')
  1422. a.download = '受理单' + orderDetail.value?.acceptNo + '.pdf' //指定下载的文件名
  1423. a.href = url // URL对象
  1424. a.click() // 模拟点击
  1425. URL.revokeObjectURL(a.href) // 释放URL 对象
  1426. }
  1427. } catch (error) {
  1428. ElMessage.error('下载失败!')
  1429. }
  1430. }
  1431. // 手动输入单位
  1432. const useInputUseUnitName = ref(false)
  1433. const useInputUnitName = ref(false)
  1434. // 申请单位名称 change
  1435. const handleChangeUnit = async (unitInfo:any) => {
  1436. console.log('申请单位名称 change:', unitInfo)
  1437. formData.value.socialCreditCode = unitInfo.socialCreditCode;
  1438. formData.value.unitAddress = unitInfo.addr
  1439. formData.value.zipCode = unitInfo.post
  1440. // 获取单位默认联系人
  1441. const {list: unitDefaultContact} = await getUnitContacts({
  1442. pageNo: 1,
  1443. pageSize: 10,
  1444. unitId: unitInfo.id,
  1445. isDefault: '1'
  1446. })
  1447. if(unitDefaultContact && unitDefaultContact?.length > 0) {
  1448. formData.value.unitContact = unitDefaultContact[0].contactName
  1449. formData.value.unitPhone = unitDefaultContact[0].contactPhone
  1450. formData.value.recipient = unitDefaultContact[0].contactName
  1451. formData.value.recipientPhone = unitDefaultContact[0].contactPhone
  1452. }
  1453. }
  1454. // 使用单位名称 change
  1455. const handleChangeUseUnit = async (unitInfo:any) => {
  1456. console.log('使用单位名称 change:', unitInfo)
  1457. formData.value.useUnitSocialCreditCode = unitInfo.socialCreditCode;
  1458. formData.value.useUnitAddress = unitInfo.addr
  1459. formData.value.useUnitZipcode = unitInfo.post
  1460. // 获取单位默认联系人
  1461. const {list: unitDefaultContact} = await getUnitContacts({
  1462. pageNo: 1,
  1463. pageSize: 10,
  1464. unitId: unitInfo.id,
  1465. isDefault: '1'
  1466. })
  1467. if(unitDefaultContact && unitDefaultContact?.length > 0) {
  1468. formData.value.useUnitContact = unitDefaultContact[0].contactName
  1469. formData.value.useUnitPhone = unitDefaultContact[0].contactPhone
  1470. }
  1471. }
  1472. /** 关闭 */
  1473. const handleClose = () => {
  1474. emit('update:visible', false)
  1475. }
  1476. // 监听表单区域相关字段变化,更新areaDisplay
  1477. watch([() => formData.value.equipDistrictName, () => formData.value.equipStreetName], () => {
  1478. formData.value.areaDisplay = areaDisplay.value
  1479. })
  1480. const exceptionInfo = ref<Record<string, any>>({})
  1481. const getExceptionItem = (field: string, fieldAttr: string)=>{
  1482. const fileUrl = exceptionInfo.value[fieldAttr] && buildFileUrl(exceptionInfo.value[fieldAttr])
  1483. const fileName = exceptionInfo.value[field]
  1484. if(fileUrl) {
  1485. return (
  1486. <>
  1487. <div class="flex items-center w-full p-l-10px p-r-10px hover:bg-gray-100 rounded-6px">
  1488. {/* <el-tooltip content={fileName}> */}
  1489. <span class="flex-1 text-ellipsis overflow-hidden whitespace-nowrap">{fileName}</span>
  1490. {/* </el-tooltip> */}
  1491. <div class="ml-10px">
  1492. <el-link href={fileUrl} underline={false} download target="_blank" type="primary">下载</el-link>
  1493. </div>
  1494. <div class="ml-10px">
  1495. <el-button link type="danger" onClick={()=>handleRemove(field, fieldAttr)}>删除</el-button>
  1496. </div>
  1497. </div>
  1498. </>
  1499. )
  1500. } else {
  1501. return (
  1502. <el-button type="primary" onClick={()=>handleOpenFileUploadModal(field, fieldAttr)}>
  1503. <Icon icon="ep:upload-filled" />
  1504. <span>附件上传</span>
  1505. </el-button>
  1506. )
  1507. }
  1508. }
  1509. const addExceptionInfo = () => {
  1510. const orderId = orderDetail.value?.id || props.id;
  1511. if(!orderId) {
  1512. // ElMessage.error('请先保存订单')
  1513. return
  1514. }
  1515. PipeAppointmentConfirmOrderApi.createExceptionInfo({
  1516. orderId: orderDetail.value?.id || props.id,
  1517. orderType: 200,
  1518. }).then((res) => {
  1519. if(res) {
  1520. ElMessage.success('生成成功')
  1521. handleGetExceptionInfo(res)
  1522. }
  1523. }).catch((error)=>{
  1524. ElMessage.error(error)
  1525. })
  1526. }
  1527. const deleteExceptionInfo = () => {
  1528. ElMessageBox.confirm('确定删除异常单吗?', '提示', {
  1529. confirmButtonText: '确定',
  1530. cancelButtonText: '取消',
  1531. type: 'warning',
  1532. }).then(() => {
  1533. PipeAppointmentConfirmOrderApi.deleteExceptionInfo(exceptionInfo.value.id).then(res=>{
  1534. if(res) {
  1535. ElMessage.success('删除成功')
  1536. exceptionInfo.value = {}
  1537. }
  1538. })
  1539. }).catch(() => {
  1540. // 取消删除
  1541. });
  1542. }
  1543. // 更新异常信息
  1544. const handleSaveException=()=>{
  1545. return new Promise((resolve, reject)=>{
  1546. const { adjustEffectiveDate } = unref(exceptionInfo)
  1547. const params = {
  1548. ...exceptionInfo.value,
  1549. adjustEffectiveDate: adjustEffectiveDate && adjustEffectiveDate.split('-').map(item=>Number(item)),
  1550. }
  1551. PipeAppointmentConfirmOrderApi.updateExceptionInfo(params).then(res=>{
  1552. resolve(res)
  1553. }).catch((error)=>{
  1554. reject(error)
  1555. })
  1556. })
  1557. }
  1558. const getExceptionInfoList = () => {
  1559. PipeAppointmentConfirmOrderApi.getExceptionInfoList({
  1560. orderId: orderDetail.value?.id || props.id,
  1561. }).then(res=>{
  1562. console.log('getExceptionInfoList:',res)
  1563. })
  1564. }
  1565. const handleGetExceptionInfo = (id: string) => {
  1566. PipeAppointmentConfirmOrderApi.getExceptionInfo(id).then((res) => {
  1567. if(res) exceptionInfo.value = {
  1568. ...res,
  1569. adjustEffectiveDate: res.adjustEffectiveDate?.join('-')
  1570. }
  1571. }).catch((error)=>{
  1572. console.log(error, '-----error--->')
  1573. ElMessage.error(error)
  1574. })
  1575. }
  1576. const fileUploadModalRef = ref<InstanceType<typeof FileUploadModal>>();
  1577. const currentUploadMap = reactive({
  1578. field: '',
  1579. fieldAttr: '',
  1580. })
  1581. const handleOpenFileUploadModal = (type: string, attach: string) => {
  1582. currentUploadMap.field = type
  1583. currentUploadMap.fieldAttr = attach
  1584. fileUploadModalRef.value?.open()
  1585. }
  1586. const handleFileUploadSuccess = (fileInfo:{fileName: string, fileUrl: string}) => {
  1587. exceptionInfo.value[currentUploadMap.field] = fileInfo.fileName
  1588. exceptionInfo.value[currentUploadMap.fieldAttr] = fileInfo.fileUrl
  1589. console.log('handleFileUploadSuccess:', exceptionInfo.value)
  1590. }
  1591. const handleRemove = (type: string, attach: string) => {
  1592. exceptionInfo.value[type] = ''
  1593. exceptionInfo.value[attach] = ''
  1594. }
  1595. const formattedCheckers = computed(() => {
  1596. const teamList = formData.value.teamList
  1597. console.log("teamList",teamList)
  1598. if (!teamList || !Array.isArray(teamList) || teamList.length === 0) return []
  1599. const result: { id: string; label: string }[] = []
  1600. teamList.forEach((team: any, teamIndex: number) => {
  1601. if (team.isLeader) {
  1602. result.push({
  1603. id: `leader-${team.member.id || teamIndex}`,
  1604. label: `组长: ${team.member.nickname || ''}`
  1605. })
  1606. }else{
  1607. result.push({
  1608. id: `member-${team.member.id || teamIndex}`,
  1609. label: `${team.member.nickname || ''}`
  1610. })
  1611. }
  1612. })
  1613. return result
  1614. })
  1615. </script>
  1616. <style lang="scss" scoped>
  1617. .app-container {
  1618. position: absolute;
  1619. left: 0;
  1620. right: 0;
  1621. top: 0;
  1622. bottom: 0;
  1623. z-index: 1001;
  1624. overflow-y: auto;
  1625. background: #fff;
  1626. padding: 20px 20px 0;
  1627. }
  1628. .form-group {
  1629. &:not(:last-child) {
  1630. margin-bottom: 16px;
  1631. }
  1632. &-title {
  1633. color: #606266;
  1634. font-size: 13px;
  1635. font-weight: 500;
  1636. margin-bottom: 12px;
  1637. }
  1638. }
  1639. .check-info-label-title {
  1640. width: 100%;
  1641. line-height: 32px;
  1642. display: flex;
  1643. align-items: center;
  1644. margin-bottom: 12px;
  1645. &::before {
  1646. content: '';
  1647. display: inline-block;
  1648. width: 4px;
  1649. height: 16px;
  1650. background: var(--el-color-primary);
  1651. margin-right: 8px;
  1652. }
  1653. }
  1654. .feeDate_box {
  1655. color: #606266;
  1656. :deep(.el-input-number) {
  1657. width: 120px !important;
  1658. }
  1659. }
  1660. .unit-form-item {
  1661. :deep(.el-form-item__content) {
  1662. display: flex;
  1663. align-items: center;
  1664. flex-wrap: nowrap;
  1665. .el-button {
  1666. margin-left: 8px;
  1667. }
  1668. }
  1669. }
  1670. .unit-name {
  1671. display: flex;
  1672. align-items: center;
  1673. padding: 0 0 8px;
  1674. .label {
  1675. width: 90px;
  1676. color: #606266;
  1677. font-size: 13px;
  1678. text-align: right;
  1679. padding-right: 12px;
  1680. }
  1681. .value {
  1682. flex: 1;
  1683. font-size: 14px;
  1684. color: #303133;
  1685. }
  1686. }
  1687. :deep(.el-form) {
  1688. .el-form-item {
  1689. margin-bottom: 12px;
  1690. align-items: center;
  1691. &__label {
  1692. height: auto;
  1693. font-size: 13px;
  1694. line-height: 20px;
  1695. color: #606266;
  1696. padding-right: 8px;
  1697. }
  1698. .el-date-editor.el-input, .el-input-number {
  1699. width: 100%;
  1700. .el-input__inner {
  1701. text-align: left;
  1702. }
  1703. }
  1704. &.actualAmountFormItem {
  1705. .el-form-item__content {
  1706. display: flex;
  1707. .el-input-number {
  1708. width: 300px;
  1709. }
  1710. }
  1711. }
  1712. }
  1713. }
  1714. .selected-checkers {
  1715. display: inline-flex;
  1716. flex-wrap: wrap;
  1717. gap: 8px;
  1718. min-height: 32px;
  1719. padding: 4px 8px;
  1720. .el-tag {
  1721. margin: 0;
  1722. height: 24px;
  1723. line-height: 22px;
  1724. &:hover {
  1725. cursor: default;
  1726. }
  1727. }
  1728. }
  1729. .leader-tag {
  1730. display: inline-block;
  1731. width: 16px;
  1732. height: 16px;
  1733. line-height: 14px;
  1734. text-align: center;
  1735. border: 1px solid #4475d6;
  1736. font-size: 12px;
  1737. margin-right: 4px;
  1738. color: #4475d6;
  1739. }
  1740. .reject-dialog {
  1741. :deep(.el-dialog__header) {
  1742. margin: 0;
  1743. padding: 16px 20px;
  1744. border-bottom: 1px solid #dcdfe6;
  1745. }
  1746. :deep(.el-dialog__body) {
  1747. padding: 20px;
  1748. }
  1749. .reject-content {
  1750. .equip-list {
  1751. margin-bottom: 20px;
  1752. color: #606266;
  1753. line-height: 1.6;
  1754. }
  1755. .check-type {
  1756. color: #606266;
  1757. }
  1758. .reject-reason {
  1759. .reason-label {
  1760. color: #606266;
  1761. }
  1762. :deep(.el-textarea__inner) {
  1763. background-color: #f5f7fa;
  1764. border-color: #e4e7ed;
  1765. &:focus {
  1766. background-color: #fff;
  1767. }
  1768. }
  1769. }
  1770. }
  1771. .reject-footer {
  1772. margin-top: 20px;
  1773. display: flex;
  1774. align-items: center;
  1775. justify-content: space-between;
  1776. .time-tag {
  1777. :deep(.el-tag) {
  1778. height: 32px;
  1779. line-height: 30px;
  1780. font-size: 16px;
  1781. padding: 0 12px;
  1782. }
  1783. }
  1784. .action-buttons {
  1785. .el-button + .el-button {
  1786. margin-left: 12px;
  1787. }
  1788. }
  1789. }
  1790. }
  1791. .footer-btn-box {
  1792. position: sticky;
  1793. bottom: 0;
  1794. left: 0;
  1795. right: 0;
  1796. padding-top: 16px;
  1797. background-color: #fff;
  1798. z-index: 1002;
  1799. }
  1800. :deep(.el-table__expand-icon) {
  1801. display: none !important;
  1802. }
  1803. </style>