query.vue 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558
  1. <template>
  2. <div class="hc-layout-box">
  3. <div
  4. id="wbs-left-tree" :style="`width:${isWbsTreeShow ? leftWidth : 0}px; ${isWbsTreeShow ? '' : 'display: none'}`"
  5. class="hc-layout-left-box bg-white" :class="[isWbsTreeShow ? 'show' : '']"
  6. >
  7. <div class="hc-project-box">
  8. <div class="hc-project-icon-box">
  9. <HcIcon name="stack" />
  10. </div>
  11. <div class="project-name-box ml-2">
  12. <div class="project-alias">{{ projectInfo?.projectName }}</div>
  13. </div>
  14. </div>
  15. <div class="hc-tree-box">
  16. <div class="hc-search-tree-val">
  17. <el-input v-model="searchTreeVal" clearable block placeholder="请输入名称关键词检索" @keyup="searchTreeKeyUp">
  18. <template #suffix>
  19. <HcIcon name="search-2" ui="text-xl iscusor" @click="searchTreeClick" />
  20. </template>
  21. </el-input>
  22. </div>
  23. <div v-if="isShowLeft" id="hc-tree-scrollbar" v-loading="treeLoading" class="hc-tree-scrollbar" element-loading-text="获取数据中...">
  24. <el-scrollbar v-show="isSearchTree" class="scroll-bar-right-16">
  25. <HcDataTree
  26. :datas="searchTreeData"
  27. is-counts
  28. is-type
  29. :auto-expand-keys="treeAutoExpandKeys"
  30. default-expand-all
  31. @node-tap="wbsElTreeClick"
  32. />
  33. </el-scrollbar>
  34. <el-scrollbar v-show="!isSearchTree" class="scroll-bar-right-16">
  35. <HcLazyTree
  36. ref="wbstree"
  37. :auto-expand-keys="treeAutoExpandKeys"
  38. is-counts
  39. is-type
  40. @load="treeLoadNode"
  41. @node-tap="wbsElTreeClick"
  42. />
  43. </el-scrollbar>
  44. </div>
  45. </div>
  46. <div class="hc-tree-foot-tip-box">
  47. <div class="dot-view green">已审批</div>
  48. <div class="dot-view black">未填报</div>
  49. <div class="dot-view orange">已填报-待审批</div>
  50. <div class="dot-view blue">已填报-未上报</div>
  51. <div class="dot-view red">已隐藏</div>
  52. </div>
  53. <!-- 左右拖动 -->
  54. <div class="horizontal-drag-line" @mousedown="onmousedown" />
  55. </div>
  56. <div class="hc-layout-content-box">
  57. <hc-body padding="0px">
  58. <!--- 展开收缩树 -->
  59. <div class="hc-expansion-contraction-tree" @click="setWbsTreeShow">
  60. <HcIcon v-show="isWbsTreeShow" name="arrow-left-s" />
  61. <HcIcon v-show="!isWbsTreeShow" name="arrow-right-s" />
  62. </div>
  63. <HcNewCard padding>
  64. <template #header>
  65. <HcTooltip keys="query_report">
  66. <el-button :disabled="tableCheckedKeys.length <= 0" :loading="reportLoading" hc-btn color="#FF976A" style="color: white;" @click="reportModalClick">
  67. <HcIcon name="send-plane-2" />
  68. <span>上报</span>
  69. </el-button>
  70. </HcTooltip>
  71. <HcTooltip keys="query_download">
  72. <el-button
  73. v-if="!website.localModel"
  74. :disabled="tableCheckedKeys.length <= 0 || userInfo.user_id !== '1968964896450904066'" :loading="downloadLoading" hc-btn
  75. color="#A16222" @click="batchDownload"
  76. >
  77. <HcIcon name="download" />
  78. <span>下载</span>
  79. </el-button>
  80. <el-button
  81. v-else
  82. :disabled="tableCheckedKeys.length <= 0 " :loading="downloadLoading" hc-btn
  83. color="#A16222" @click="batchDownload"
  84. >
  85. <HcIcon name="download" />
  86. <span>下载</span>
  87. </el-button>
  88. </HcTooltip>
  89. <HcTooltip keys="query_print">
  90. <el-button
  91. :disabled="isCanDown || tableCheckedKeys.length <= 0" :loading="printLoading" hc-btn
  92. color="#A16222" @click="batchPrint"
  93. >
  94. <HcIcon name="printer" />
  95. <span>打印</span>
  96. </el-button>
  97. </HcTooltip>
  98. <HcTooltip keys="query_abolish">
  99. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn color="#567722" @click="batchAbolishClick">
  100. <HcIcon name="delete-bin-3" />
  101. <span>废除</span>
  102. </el-button>
  103. </HcTooltip>
  104. <HcTooltip keys="query_local_attestation">
  105. <el-button
  106. :disabled="tableCheckedKeys.length <= 0" :loading="localLoading" hc-btn
  107. color="#e03997" @click="batchLocal"
  108. >
  109. <HcIcon name="folder-download" />
  110. <span>本地验签</span>
  111. </el-button>
  112. </HcTooltip>
  113. <HcTooltip keys="query_online_attestation">
  114. <el-button
  115. :disabled="tableCheckedKeys.length <= 0" :loading="onlineLoading" hc-btn
  116. color="#e03997" @click="batchOnline"
  117. >
  118. <HcIcon name="cloud" />
  119. <span>在线验签</span>
  120. </el-button>
  121. </HcTooltip>
  122. <el-button :disabled="tableCheckedKeys.length <= 0" :loading="signLoading" hc-btn type="primary" @click="resignClick"> <HcIcon name="repeat" />re-sign</el-button>
  123. <HcTooltip keys="data-query-once-agin">
  124. <el-button
  125. v-if="userInfo.dept_id === '1536982621165592577'"
  126. :disabled="tableCheckedKeys.length <= 0 || userInfo.dept_id !== '1536982621165592577'"
  127. :loading="signLoading"
  128. hc-btn type="warning"
  129. @click="resignClick1"
  130. >
  131. <HcIcon name="repeat" />
  132. 一键电签
  133. </el-button>
  134. </HcTooltip>
  135. <HcTooltip keys="save_agin">
  136. <el-button
  137. :disabled="tableCheckedKeys.length <= 0" :loading="saveAginLoading" hc-btn
  138. color="#e03997" @click="saveAginClick"
  139. >
  140. <HcIcon name="save" />
  141. <span>save-again</span>
  142. </el-button>
  143. </HcTooltip>
  144. <HcTooltip keys="data-query-resign-title">
  145. <el-button
  146. :disabled="tableCheckedKeys.length <= 0"
  147. hc-btn
  148. color="#3F9EFF" style="color: white;" :loading="ruleModalSaveLoad" @click="resignTitleClick"
  149. >
  150. <HcIcon name="restart" />
  151. <span>重置题名</span>
  152. </el-button>
  153. </HcTooltip>
  154. </template>
  155. <template #search>
  156. <div class="flex items-center">
  157. <div class="w-40" :class="[searchForm.taskStatus ? 'hc-search-highlight' : '']">
  158. <el-select v-model="searchForm.taskStatus" clearable placeholder="流程状态">
  159. <el-option
  160. v-for="item in processStatusData" :key="item.value"
  161. :label="item.dictValue" :value="item.dictKey"
  162. />
  163. </el-select>
  164. </div>
  165. <div class="ml-2 w-32" :class="[searchForm.majorDateType ? 'hc-search-highlight' : '']">
  166. <el-select v-model="searchForm.majorDateType" clearable placeholder="资料类型">
  167. <el-option
  168. v-for="item in majorDataTypeOptions"
  169. :key="item.value"
  170. :label="item.label"
  171. :value="item.value"
  172. />
  173. </el-select>
  174. </div>
  175. <div class="ml-2 w-40" :class="[searchForm.fileUserIdAndName ? 'hc-search-highlight' : '']">
  176. <el-select v-model="searchForm.fileUserIdAndName" clearable placeholder="填报人">
  177. <el-option
  178. v-for="item in reportingPersonData" :key="item.value" :label="item.label"
  179. :value="item.value"
  180. />
  181. </el-select>
  182. </div>
  183. <div class="ml-2 w-40" :class="[searchForm.sourceType ? 'hc-search-highlight' : '']">
  184. <el-select v-model="searchForm.sourceType" clearable placeholder="文件类型">
  185. <el-option
  186. v-for="item in fileTypeData" :key="item.value" :label="item.dictValue"
  187. :value="item.dictKey"
  188. />
  189. </el-select>
  190. </div>
  191. <div class="ml-2 w-40" :class="[searchForm.waitingUserStatus ? 'hc-search-highlight' : '']">
  192. <el-select v-model="searchForm.waitingUserStatus" clearable placeholder="审批人状态">
  193. <el-option :value="1" label="未签字" />
  194. <el-option :value="2" label="已签字" />
  195. <el-option :value="3" label="已废除" />
  196. <el-option :value="999" label="签字异常" />
  197. </el-select>
  198. </div>
  199. <div class="ml-2 w-64" :class="[searchForm.betweenTime ? 'hc-search-highlight' : '']">
  200. <HcDatePicker :dates="betweenTime" clearable @change="betweenTimeUpdate" />
  201. </div>
  202. <div class="ml-2 w-60" :class="[searchForm.queryValue ? 'hc-search-highlight' : '']">
  203. <el-input
  204. v-model="searchForm.queryValue" clearable placeholder="请输入名称关键词检索"
  205. @keyup="keyUpEvent"
  206. />
  207. </div>
  208. <div class="ml-2">
  209. <el-button type="primary" @click="searchClick">
  210. <HcIcon name="search-2" />
  211. <span>搜索</span>
  212. </el-button>
  213. </div>
  214. </div>
  215. </template>
  216. <template #extra>
  217. <template v-if="contractInfo?.contractType === 2 || contractInfo?.contractType === 3">
  218. <HcNewSwitch :datas="contractTypeTab" :keys="contractTypeTabKey" size="default" @change="contractTypeTabChange" />
  219. </template>
  220. </template>
  221. <HcTable
  222. ref="tableListRef" :column="tableListColumn" :datas="tableListData" :loading="tableLoading"
  223. is-new :index-style="{ width: 60 }" is-check :check-style="{ width: 29 }"
  224. @selection-change="tableSelectionChange"
  225. >
  226. <template #taskStatusStr="{ row }">
  227. <el-tag
  228. :type="`${row.taskStatusStr === '已审批' ? 'success' : row.taskStatusStr === '待审批' ? 'warning' : row.taskStatusStr === '已废除' ? 'danger' : 'info'}`"
  229. class="mx-1" effect="dark"
  230. >
  231. {{ row.taskStatusStr }}
  232. </el-tag>
  233. </template>
  234. <template #name="{ row }">
  235. <div v-loading="row?.bussPreviewLoading" class="text-link" @click="tableRowName(row)" v-html="highlight(row?.name || '', searchForm.queryValue)" />
  236. </template>
  237. <template #fileUserIdAndName="{ row }">
  238. <div v-if="row.fileUserIdAndName" v-html="highlight(`${row?.fileUserIdAndName}` || '', searchForm.fileUserIdAndName?.split('-')[1])" />
  239. </template>
  240. <template #waitingUserList="{ row }">
  241. <template v-for="item in row.waitingUserList">
  242. <el-tag
  243. v-if="item.waitingUserName"
  244. :key="item.waitingUserName"
  245. :type="`${item.status === 2 ? 'success' : item.status === 3 ? 'warning' : item.status === 999 ? 'danger' : 'info'}`"
  246. class="mx-1" effect="dark"
  247. >
  248. {{ item.waitingUserName }}
  249. </el-tag>
  250. </template>
  251. </template>
  252. </HcTable>
  253. <template #action>
  254. <div class="lr-dialog-footer">
  255. <div class="left">
  256. <span class="text-success">任务人员中:</span>
  257. <el-tag class="mx-1" effect="dark" type="info">未签字</el-tag>
  258. <el-tag class="mx-1" effect="dark" type="success">已签字</el-tag>
  259. <el-tag class="mx-1" effect="dark" type="warning">已废除</el-tag>
  260. <el-tag class="mx-1" effect="dark" type="danger">签字异常</el-tag>
  261. </div>
  262. <div class="right">
  263. <HcPages :pages="searchForm" @change="pageChange" />
  264. </div>
  265. </div>
  266. </template>
  267. </HcNewCard>
  268. </hc-body>
  269. </div>
  270. <!-- 批量上报审批 -->
  271. <HcReportModal
  272. :ids="reportIds"
  273. :node-id="primaryKeyId"
  274. :table-owner="contractTypeTabKey"
  275. :classify-type="classType"
  276. :contract-id="contractId"
  277. :flow-contract-id="nodeDataInfo?.contractId"
  278. :datas="reportDatas"
  279. :project-id="projectId"
  280. :show="showReportModal"
  281. :task-name="reportTaskName"
  282. :type-data="reportTypeData"
  283. :report-arr="reportArr"
  284. type="query"
  285. is-datas
  286. title="批量上报审批"
  287. url="informationWriteQuery/batchTask"
  288. @finish="showReportFinish"
  289. @hide="showReportModal = false"
  290. @tag-close="reportTaskTagClose"
  291. />
  292. <!-- 在线验签 -->
  293. <hc-new-drawer v-model="isOnlineVerifyDrawer" modal-class="hc-online-verify-drawer" to-id="app" @close="onlineVerifyDrawerClose">
  294. <hc-new-card>
  295. <template #header>
  296. <div class="online-verify-title">{{ onlineTitle }}</div>
  297. </template>
  298. <template #extra>
  299. <div class="online-verify-icon" @click="onlineVerifyDrawerClose">
  300. <HcIcon name="close-circle" />
  301. <span class="ml-1">关闭</span>
  302. </div>
  303. </template>
  304. <hc-body split padding="0px" :options="onlineVerifyOptions">
  305. <template #left>
  306. <hc-new-card>
  307. <HcPdf :src="onlineVerifyData.pdfUrl" />
  308. </hc-new-card>
  309. </template>
  310. <hc-new-card>
  311. <HcTable :column="cscTableColumn" :datas="cscTableData" is-new :index-style="{ width: 60 }" />
  312. </hc-new-card>
  313. </hc-body>
  314. </hc-new-card>
  315. </hc-new-drawer>
  316. <!-- 一键重签弹窗 -->
  317. <hc-new-dialog v-model="resignModal" title="一键重签" widths="38rem" :loading="signLoading" @close="cancelresign" @save="signClick">
  318. <div>
  319. 是否重新生成pdf:
  320. <el-radio-group v-model="resignModalRadio">
  321. <el-radio :value="0">否</el-radio>
  322. <el-radio :value="1">是</el-radio>
  323. </el-radio-group>
  324. </div>
  325. </hc-new-dialog>
  326. <!-- 一键重签弹窗1 -->
  327. <hc-new-dialog v-model="resignModal1" title="一键重签" widths="38rem" :loading="signLoading1" @close="cancelresign1" @save="signClick1">
  328. <div>
  329. <el-radio-group v-model="resignModalRadio1">
  330. <el-radio :value="0">全部电签</el-radio>
  331. <el-radio :value="1" :disabled="tableCheckedKeys.length > 1">部分电签</el-radio>
  332. </el-radio-group>
  333. </div>
  334. <div v-if="resignModalRadio1 === 1">
  335. <el-checkbox-group v-model="checkTaskUserIds">
  336. <el-checkbox v-for="item in tableCheckedKeys[0].waitingUserList" :key="item.id" :label="item.waitingUserName" :value="item.userId">
  337. <el-tag
  338. :type="`${item.status === 2 ? 'success' : item.status === 3 ? 'warning' : item.status === 999 ? 'danger' : 'info'}`"
  339. class="mx-1" effect="dark"
  340. >
  341. {{ item.waitingUserName }}
  342. </el-tag>
  343. </el-checkbox>
  344. </el-checkbox-group>
  345. </div>
  346. </hc-new-dialog>
  347. <!-- 重置文件题名弹窗 -->
  348. <hc-new-dialog v-model="resignTitleModal" title="重置题名" widths="38rem" :loading="resignTitleSaveLoad" @save="resignTitleSave">
  349. <div>
  350. 是否更改题名规则:
  351. <el-button type="primary" hc-btn size="small" @click="changeRuleClick">规则更改</el-button>
  352. </div>
  353. </hc-new-dialog>
  354. <!-- 规则修改弹窗 -->
  355. <hc-new-dialog v-model="ruleModal" title="更改重置题名题名规则" widths="88rem" :loading="ruleModalSaveLoad" @close="ruleModalClose" @save="ruleModalSave">
  356. <template #header>
  357. <div class="flex flex-col">
  358. <div class="mb-4 text-18px">
  359. <span>更改重置题名题名规则</span>
  360. </div>
  361. <div class="flex justify-between justify-items-center text-orange">
  362. <p>* 单条修改在表单下拉框选择规则,批量修改在右侧选规则点击【设置】统一更新所有规则</p>
  363. <p>* “修改后”仅为展示,【确认】后才会刷新文件题名</p>
  364. </div>
  365. </div>
  366. </template>
  367. <div class="flex items-center justify-between">
  368. <div>批量设置:</div>
  369. <el-select
  370. v-model="setValue"
  371. placeholder="请选择"
  372. multiple
  373. clearable
  374. class="custom-select flex-1"
  375. :popper-append-to-body="false"
  376. >
  377. <el-option
  378. v-for="item in nodeTypeData"
  379. :key="item.value"
  380. :label="item.label"
  381. :value="item.value"
  382. />
  383. </el-select>
  384. <el-button type="primary" hc-btn size="small" class="ml-2" :disabled="setValue.length === 0" @click="batchSetRule">设置</el-button>
  385. </div>
  386. <div style="position: relative; height: 440px" class="mt-2">
  387. <HcTable v-loading="ruleTableLoading" :column="ruleTableColumn" :datas="ruleTableData" :loading="ruleTableLoading">
  388. <template #rule="{ row }">
  389. <div class="flex items-center">
  390. <span class="text-red">*</span>
  391. <el-select
  392. v-model="row.rule"
  393. :class="{ 'error-border': !row.rule || row.rule.length === 0 }"
  394. placeholder="请选择"
  395. multiple
  396. clearable
  397. class="custom-select"
  398. :popper-append-to-body="false"
  399. @change="ruleChange(row)"
  400. >
  401. <el-option
  402. v-for="item in nodeTypeData"
  403. :key="item.value"
  404. :label="item.label"
  405. :value="item.value"
  406. />
  407. </el-select>
  408. </div>
  409. </template>
  410. </HcTable>
  411. </div>
  412. </hc-new-dialog>
  413. </div>
  414. </template>
  415. <script setup>
  416. import { onMounted, ref, watch } from 'vue'
  417. import { useAppStore } from '~src/store'
  418. import { getStoreValue, setStoreValue } from '~src/utils/storage'
  419. import { highlight } from '~src/utils/utils'
  420. import { arrToId, arrToKey, downloadBlob, getArrValue, getObjValue, isNullES, isString } from 'js-fast-way'
  421. import queryApi from '~api/data-fill/query'
  422. import { eVisaTaskCheckApi } from '~api/other'
  423. import { toPdfPage } from '~uti/btn-auth'
  424. import wbsApi from '~api/data-fill/wbs'
  425. import website from '~src/config'
  426. import { getDictionaryData } from '~uti/tools'
  427. import { getDictionary, userConfigSave } from '~api/other'
  428. import { useClick } from 'hc-vue3-ui'
  429. //变量
  430. const useAppState = useAppStore()
  431. const projectId = ref(useAppState.getProjectId)
  432. const contractId = ref(useAppState.getContractId)
  433. const projectInfo = ref(useAppState.getProjectInfo)
  434. const contractInfo = ref(useAppState.getContractInfo)
  435. const userInfo = ref(useAppState.getUserInfo)
  436. const isCollapse = ref(useAppState.getCollapse)
  437. const isLayout = ref(useAppState.isLayout)
  438. const isTemplateType = ref(useAppState.contractInfo?.templateType === 2)
  439. //变量
  440. const wbstree = ref(null)
  441. const wbstreeKey = ref(Math.random())
  442. //树搜索
  443. const isSearchTree = ref(false)
  444. const searchTreeHeight = ref()
  445. const searchTreeVal = ref('')
  446. //监听
  447. watch(() => [useAppState.getCollapse, searchTreeVal.value, useAppState.isLayout], ([Collapse, search, isLay]) => {
  448. isCollapse.value = Collapse
  449. isLayout.value = isLay || ''
  450. if (search.length === 0) {
  451. isSearchTree.value = false
  452. }
  453. })
  454. //是否禁用下载打印按钮
  455. const isCanDown = ref(false)
  456. //自动展开缓存
  457. const treeAutoExpandKeys = ref(getStoreValue('wbsTreeExpandKeys') || [])
  458. //渲染完成
  459. onMounted(() => {
  460. getFileUser()
  461. getReportNumber()
  462. getFirstTaskStatus()
  463. getDictBizClassify()
  464. getMajorDataTypeOptions()
  465. isCanDown.value = !website.localModel
  466. const treeWidth = useAppState.getTreeWidth
  467. leftWidth.value = isNullES(treeWidth) || treeWidth <= 0 ? 440 : treeWidth
  468. })
  469. //获取
  470. const majorDataTypeOptions = ref([])
  471. const getMajorDataTypeOptions = async () => {
  472. majorDataTypeOptions.value = (await getDictionaryData('major_data_type', false)).filter(item => item.value !== 0)
  473. }
  474. const searchTreeData = ref([])
  475. //回车
  476. const treeLoading = ref(true)
  477. const getSearchTreeData = async () => {
  478. treeLoading.value = true
  479. const { error, code, data } = await queryApi.getTreeNodeByQueryValueAndContractId({
  480. contractId: contractId.value,
  481. queryValue: searchTreeVal.value,
  482. tableOwner:contractTypeTabKey.value,
  483. })
  484. //判断状态
  485. if (!error && code === 200) {
  486. let treedata = getArrValue(data)
  487. searchTreeData.value = treedata
  488. treeLoading.value = false
  489. } else {
  490. treeLoading.value = false
  491. searchTreeData.value = []
  492. }
  493. }
  494. //回车
  495. const searchTreeKeyUp = (e) => {
  496. if (e.key === 'Enter') {
  497. searchTreeClick()
  498. }
  499. }
  500. const searchTreeClick = async () => {
  501. if (searchTreeVal.value) {
  502. searchTreeHeight.value = document.getElementById('hc-tree-scrollbar').offsetHeight
  503. isSearchTree.value = true
  504. //treeLoading.value = true
  505. getSearchTreeData().then()
  506. } else {
  507. isSearchTree.value = false
  508. }
  509. }
  510. //树相关的变量
  511. const primaryKeyId = ref('')
  512. const nodeItemInfo = ref({})
  513. const nodeDataInfo = ref({})
  514. //懒加载的数据
  515. const treeLoadNode = async ({ node, item, level }, resolve) => {
  516. let contractIdRelation = '', parentId = '', primaryKeyId = ''
  517. if (level !== 0) {
  518. const nodeData = getObjValue(item)
  519. contractIdRelation = nodeData?.contractIdRelation || ''
  520. parentId = contractIdRelation ? nodeData?.primaryKeyId : nodeData?.id
  521. primaryKeyId = nodeData?.id || ''
  522. }
  523. //获取数据
  524. const { data } = await queryApi.queryWbsTreeData({
  525. contractId: contractId.value || '',
  526. contractIdRelation,
  527. primaryKeyId,
  528. parentId,
  529. // classifyType: contractTypeTabKey.value,
  530. classifyType: classType.value,
  531. tableOwner:contractTypeTabKey.value,
  532. dataTime:new Date(),
  533. })
  534. resolve(getArrValue(data))
  535. treeLoading.value = false
  536. }
  537. //树被点击
  538. const wbsElTreeClick = ({ node, data, keys }) => {
  539. nodeItemInfo.value = node
  540. nodeDataInfo.value = data
  541. primaryKeyId.value = data['primaryKeyId'] || ''
  542. //缓存自动展开
  543. treeAutoExpandKeys.value = keys
  544. setStoreValue('wbsTreeExpandKeys', keys)
  545. //改变搜索表单数据
  546. searchForm.value.wbsId = data['primaryKeyId']
  547. //只有监理、指挥合同段才传contractIdRelation
  548. if (contractInfo.value?.contractType === 2 || contractInfo.value?.contractType === 3) {
  549. searchForm.value.contractIdRelation = data['contractIdRelation']
  550. } else {
  551. searchForm.value.contractIdRelation = ''
  552. }
  553. searchForm.value.current = 1
  554. getTableData().then(()=>{
  555. getFileUser()
  556. })
  557. }
  558. //搜索条件
  559. const processStatusData = ref([]) //流程状态
  560. const reportingPersonData = ref([]) //填报人
  561. const fileTypeData = ref([]) //文件类型
  562. const reportBatchData = ref([]) //上报批次
  563. /**
  564. * 获取所有填报人信息
  565. *
  566. * 根据当前选中的节点信息,调用API获取该节点下的所有填报人员数据,
  567. * 并将结果格式化为选择器可用的选项数组
  568. *
  569. * @async
  570. * @returns {Promise<void>} 无返回值,但会更新 reportingPersonData 响应式变量
  571. */
  572. const getFileUser = async () => {
  573. const info = nodeDataInfo.value
  574. // if (!info || !info?.contractIdRelation) {
  575. // window.$message?.warning('请先点击左侧节点')
  576. // return
  577. // }
  578. const { error, code, data } = await queryApi.getFileUser({
  579. contractId: contractId.value,
  580. contractIdRelation: contractInfo.value?.contractType === 2 ? info?.contractIdRelation : contractId.value,
  581. })
  582. //判断状态
  583. if (!error && code === 200) {
  584. let res = getArrValue(data), userArr = []
  585. res.forEach(item => {
  586. userArr.push({ label: item['userName'], value: `${item['userId']}-${item['userName']}` })
  587. })
  588. reportingPersonData.value = userArr
  589. } else {
  590. reportingPersonData.value = []
  591. }
  592. }
  593. //获取上报批次
  594. const getReportNumber = async () => {
  595. const { error, code, data } = await queryApi.getReportNumber({
  596. contractId: contractId.value,
  597. projectId: projectId.value,
  598. })
  599. //判断状态
  600. if (!error && code === 200) {
  601. reportBatchData.value = getArrValue(data)
  602. } else {
  603. reportBatchData.value = []
  604. }
  605. }
  606. //获取流程状态
  607. const getFirstTaskStatus = async () => {
  608. const { error, code, data } = await queryApi.getFirstTaskStatus()
  609. //判断状态
  610. if (!error && code === 200) {
  611. processStatusData.value = getArrValue(data)
  612. } else {
  613. processStatusData.value = []
  614. }
  615. }
  616. //获取流程状态分类和文件类型分类
  617. const getDictBizClassify = async () => {
  618. const { error, code, data } = await queryApi.getDictBizClassify({
  619. contractId: contractId.value,
  620. code: 'fileType',
  621. })
  622. //判断状态
  623. if (!error && code === 200) {
  624. fileTypeData.value = getArrValue(data)
  625. } else {
  626. fileTypeData.value = []
  627. }
  628. }
  629. //搜索表单
  630. const searchForm = ref({
  631. taskStatus: null, fileUserIdAndName: null, sourceType: null, reportNumber: null, betweenTime: '',
  632. queryValue: '', contractIdRelation: null, wbsId: null, current: 1, size: 20, total: 0, majorDateType: null,
  633. waitingUserStatus: null,
  634. })
  635. //结构类型tab数据和相关处理
  636. // const contractTypeTabKey = ref('1')
  637. const contractTypeTabKey = ref(contractInfo.value?.contractType === 2 ? '2' : '1')
  638. //加载树需要的classType由合同段获取
  639. const classType = ref(contractInfo.value?.contractType === 2 ? '2' : '1')
  640. const contractTypeTab = ref([
  641. { key: '1', name: '施工数据' },
  642. { key: '2', name: '监理数据' },
  643. ])
  644. //是否显示左边树
  645. const isShowLeft = ref(true)
  646. const contractTypeTabChange = (item) => {
  647. contractTypeTabKey.value = item?.key
  648. //重新加载左边树
  649. isShowLeft.value = false
  650. setTimeout(()=>{
  651. isShowLeft.value = true
  652. }, 500)
  653. searchClick()
  654. }
  655. //获取合同段类型
  656. // const getContractTypeKey = () => {
  657. // const { contractType } = contractInfo.value;
  658. // if (contractType === 2 || contractType === 3) {
  659. // return contractTypeTabKey.value ?? '1'
  660. // } else {
  661. // return null
  662. // }
  663. // }
  664. //日期时间被选择
  665. const betweenTime = ref(null)
  666. const betweenTimeUpdate = ({ arr, query }) => {
  667. betweenTime.value = arr
  668. searchForm.value.betweenTime = query
  669. }
  670. //回车搜索
  671. const keyUpEvent = (e) => {
  672. if (e.key === 'Enter') {
  673. searchForm.value.current = 1
  674. if (searchForm.value?.queryValue) {
  675. searchForm.value.queryValue = searchForm.value.queryValue.trim()
  676. }
  677. getTableData()
  678. }
  679. }
  680. //搜索
  681. const searchClick = () => {
  682. searchForm.value.current = 1
  683. if (searchForm.value?.queryValue) {
  684. searchForm.value.queryValue = searchForm.value.queryValue.trim()
  685. }
  686. wbstreeKey.value = Math.random()
  687. getTableData()
  688. // wbstree.value.resetNode().then((red)=>{
  689. // if(red){
  690. // getTableData()
  691. // }
  692. // })
  693. }
  694. //分页被点击
  695. const pageChange = ({ current, size }) => {
  696. searchForm.value.current = current
  697. searchForm.value.size = size
  698. getTableData()
  699. }
  700. //获取数据
  701. const tableListRef = ref(null)
  702. const tableLoading = ref(false)
  703. const tableListColumn = ref([
  704. { key: 'name', name: '文件名称' },
  705. // { key: 'startTime', name: '开始时间', width: 140, align: 'center' },
  706. { key: 'taskStatusStr', name: '流程状态', width: 100, align: 'center' },
  707. { key: 'reportNumber', name: '上报批次', width: 80, align: 'center' },
  708. { key: 'fileUserIdAndName', name: '填报人', width: 190, align: 'center' },
  709. { key: 'waitingUserList', name: '任务人', align: 'center' },
  710. ])
  711. const tableListData = ref([])
  712. const getTableData = async () => {
  713. if (searchForm.value.wbsId) {
  714. tableListRef.value?.clearSelection()
  715. tableCheckedKeys.value = []
  716. tableLoading.value = true
  717. // const classifyType = getContractTypeKey();
  718. const { error, code, data } = await queryApi.getPageData({
  719. projectId: projectId.value,
  720. contractId: contractId.value,
  721. ...searchForm.value,
  722. classifyType: contractTypeTabKey.value,
  723. })
  724. //处理数据
  725. tableLoading.value = false
  726. if (!error && code === 200) {
  727. tableListData.value = getArrValue(data['records'])
  728. searchForm.value.total = data.total || 0
  729. } else {
  730. // window.$message?.error(msg)
  731. tableListData.value = []
  732. searchForm.value.total = 0
  733. }
  734. } else {
  735. window?.$message?.warning('请先选择一个树节点')
  736. }
  737. }
  738. //多选
  739. const tableCheckedKeys = ref([])
  740. const tableSelectionChange = (rows) => {
  741. tableCheckedKeys.value = rows.filter((item) => {
  742. return (item ?? '') !== ''
  743. })
  744. }
  745. //名称被点击
  746. const tableRowName = (row) => {
  747. bussPreview(row)
  748. }
  749. //多表预览
  750. const bussPreview = async (row) => {
  751. const info = nodeDataInfo.value
  752. row.bussPreviewLoading = true
  753. const { error, code, data } = await wbsApi.getBussPdfs({
  754. nodeId: row?.wbsId || '',
  755. classify: contractTypeTabKey.value,
  756. projectId: projectId.value,
  757. // contractId: contractId.value
  758. contractId: contractInfo.value?.contractType == 2 ? info?.contractIdRelation : contractId.value,
  759. })
  760. row.bussPreviewLoading = false
  761. if (!error && code === 200) {
  762. // row.name会存在乱码,所以用id代替
  763. toPdfPage(data, row.id, row.id)
  764. // toPdfPage(data)
  765. //window.open(data, '_blank')
  766. } else {
  767. window.$message?.warning('获取PDF失败')
  768. }
  769. }
  770. //上报
  771. const reportIds = ref('')
  772. const reportTaskName = ref('')
  773. const reportDatas = ref([])
  774. const reportTypeData = ref([])
  775. const showReportModal = ref(false)
  776. const reportLoading = ref(false)
  777. const reportArr = ref([])
  778. const reportModalClick = async () => {
  779. const rows = tableCheckedKeys.value
  780. //判断是否满足条件
  781. const result = rows.every(({ status }) => {
  782. return status === 0 || status === 3
  783. })
  784. //处理数据
  785. let newArr = []
  786. for (let i = 0; i < rows.length; i++) {
  787. newArr.push(rows[i]['wbsId'])
  788. }
  789. reportTypeData.value = newArr
  790. let newArr1 = []
  791. for (let i = 0; i < rows.length; i++) {
  792. newArr1.push(rows[i]['id'])
  793. }
  794. reportArr.value = newArr1
  795. //判断状态
  796. if (result) {
  797. reportLoading.value = true
  798. const taskCheck = await eVisaTaskCheckApi({
  799. projectId: projectId.value,
  800. contractId: contractId.value,
  801. })
  802. if (taskCheck) {
  803. //初始ID
  804. const row = getObjValue(rows[0])
  805. reportIds.value = arrToId(rows)
  806. //设置任务数据
  807. let reportDataArr = []
  808. rows.forEach(item => {
  809. reportDataArr.push({
  810. id: item?.id,
  811. name: item?.name,
  812. })
  813. })
  814. reportDatas.value = reportDataArr
  815. //设置任务名称
  816. reportTaskName.value = rows.length > 1 ? `${row.name}等${rows.length}个文件` : row.name
  817. reportLoading.value = false
  818. showReportModal.value = true
  819. } else {
  820. reportLoading.value = false
  821. }
  822. } else {
  823. window.$message?.warning('已上报的文件不能进行再次上报,若要重新上报,要先撤回之前的上报,再重新上报')
  824. }
  825. }
  826. //上报的审批内容移除
  827. const reportTaskTagClose = (index) => {
  828. const row = tableCheckedKeys.value[index]
  829. tableListRef.value?.toggleRowSelection(row, false)
  830. }
  831. //上报完成
  832. const showReportFinish = () => {
  833. showReportModal.value = false
  834. getTableData()
  835. }
  836. //下载
  837. const downloadLoading = ref(false)
  838. const batchDownload = async () => {
  839. const rows = tableCheckedKeys.value
  840. const ids = arrToId(rows)
  841. //批量下载
  842. downloadLoading.value = true
  843. const { error, disposition, res } = await queryApi.batchDownloadFileToZip({ ids: ids })
  844. //处理数据
  845. downloadLoading.value = false
  846. if (!error) {
  847. if (disposition) {
  848. downloadBlob(res, disposition)
  849. } else {
  850. window.$message?.error('数据异常')
  851. }
  852. }
  853. }
  854. //打印
  855. const printLoading = ref(false)
  856. const batchPrint = async () => {
  857. const rows = tableCheckedKeys.value
  858. const ids = arrToId(rows)
  859. //批量下载
  860. printLoading.value = true
  861. const { error, code, data } = await queryApi.batchPrint({ ids: ids })
  862. //处理数据
  863. printLoading.value = false
  864. const res = isString(data) ? data ?? '' : ''
  865. if (!error && code === 200 && res) {
  866. toPdfPage(res)
  867. //window.open(res, '_blank')
  868. }
  869. }
  870. //废除
  871. const batchAbolishClick = () => {
  872. const rows = tableCheckedKeys.value
  873. //判断是否满足条件
  874. const result = rows.every(({ status }) => {
  875. return status !== 0 && status !== 3
  876. })
  877. //判断状态
  878. if (result) {
  879. //拼接ID
  880. const ids = arrToId(rows)
  881. window?.$messageBox?.alert('是否废除勾选的已上报文件?', '废除文件', {
  882. showCancelButton: true,
  883. confirmButtonText: '确定废除',
  884. cancelButtonText: '取消',
  885. callback: (action) => {
  886. if (action === 'confirm') {
  887. batchAbolishSave(ids)
  888. }
  889. },
  890. })
  891. } else {
  892. window.$message?.warning('未上报的文件不能废除')
  893. }
  894. }
  895. //废除勾选的已上报文件
  896. const batchAbolishSave = async (ids) => {
  897. const { error, code } = await queryApi.batchAbolish({ ids: ids, projectId:projectId.value, contractId:contractId.value })
  898. //处理数据
  899. if (!error && code === 200) {
  900. window.$message?.success('批量废除成功')
  901. tableCheckedKeys.value = []
  902. getTableData()
  903. }
  904. }
  905. //本地验签
  906. const localLoading = ref(false)
  907. const batchLocal = async () => {
  908. const rows = tableCheckedKeys.value
  909. //判断是否满足条件
  910. const result = rows.every(({ status }) => {
  911. return status === 2
  912. })
  913. //判断状态
  914. if (result) {
  915. const ids = arrToId(rows)
  916. //请求数据
  917. localLoading.value = true
  918. const { error, code, data, disposition, res } = await queryApi.localVerify({
  919. ids: ids,
  920. })
  921. //处理数据
  922. localLoading.value = false
  923. if (!error && code === 200) {
  924. if (disposition) {
  925. downloadBlob(res, disposition)
  926. } else {
  927. window.$message?.error('数据异常')
  928. }
  929. }
  930. } else {
  931. window.$message?.warning('存在未审批或未上报数据')
  932. }
  933. }
  934. //在线验签
  935. const onlineLoading = ref(false)
  936. const onlineVerifyData = ref({})
  937. const onlineTitle = ref('')
  938. const isOnlineVerifyDrawer = ref(false)
  939. const onlineVerifyOptions = {
  940. sizes: [50, 50],
  941. snapOffset: 0,
  942. minSize: ['10%', '80%'],
  943. }
  944. const batchOnline = async () => {
  945. const rows = tableCheckedKeys.value
  946. if (rows.length > 1) {
  947. window.$message?.warning('在线验签只能勾选一条数据进行验签')
  948. return
  949. }
  950. //判断是否满足条件
  951. const result = rows.every(({ status }) => {
  952. return status === 2
  953. })
  954. //判断状态
  955. if (!result) {
  956. window.$message?.warning('存在未审批或未上报数据')
  957. return
  958. }
  959. //发起请求
  960. onlineTitle.value = rows[0]?.name
  961. const ids = arrToId(rows)
  962. onlineLoading.value = true
  963. const { error, code, msg, data } = await queryApi.onlineVerify({
  964. ids: ids,
  965. })
  966. //处理数据
  967. onlineLoading.value = false
  968. if (!error && code === 200) {
  969. onlineVerifyData.value = getObjValue(data)
  970. cscTableData.value = getArrValue(data['certBeanVOList'])
  971. isOnlineVerifyDrawer.value = true
  972. } else {
  973. onlineVerifyData.value = {}
  974. window.$message?.error(msg ?? '操作失败')
  975. }
  976. }
  977. //签名信息
  978. const cscTableColumn = [
  979. { key:'dn', name: '签名者', width: 300 },
  980. { key:'time', name: '签名时间', width: 200 },
  981. { key:'result', name: '验签结果' },
  982. ]
  983. const cscTableData = ref([])
  984. //在线验签抽屉被关闭
  985. const onlineVerifyDrawerClose = () => {
  986. isOnlineVerifyDrawer.value = false
  987. onlineLoading.value = false
  988. }
  989. //树展开和收起
  990. const isWbsTreeShow = ref(true)
  991. const setWbsTreeShow = () => {
  992. isWbsTreeShow.value = !isWbsTreeShow.value
  993. }
  994. //左右拖动,改变树形结构宽度
  995. const leftWidth = ref(300)
  996. //更新配置
  997. watch(
  998. () => leftWidth.value,
  999. (diffVal) => {
  1000. setUserConfig(diffVal)
  1001. },
  1002. )
  1003. const setUserConfig = async (data) => {
  1004. await useClick()
  1005. useAppState.setTreeWidth(data)
  1006. await userConfigSave({ treeWidth: data })
  1007. }
  1008. const onmousedown = () => {
  1009. let leftNum = 0
  1010. if (isLayout.value === 'no') {
  1011. leftNum = 0
  1012. } else {
  1013. leftNum = isCollapse.value ? 142 : 272
  1014. }
  1015. document.onmousemove = (ve) => {
  1016. let diffVal = ve.clientX - leftNum
  1017. if (diffVal >= 310 && diffVal <= 900) {
  1018. leftWidth.value = diffVal
  1019. }
  1020. }
  1021. document.onmouseup = () => {
  1022. document.onmousemove = null
  1023. document.onmouseup = null
  1024. }
  1025. }
  1026. const allElementsNotEmpty = (str)=> {
  1027. // 使用split将字符串分割成字符数组
  1028. // 使用every方法判断每个元素是否不为空字符串
  1029. return str.split('').every(char => char !== '')
  1030. }
  1031. //一键重签
  1032. const signLoading = ref(false)
  1033. const resignModal = ref(false)
  1034. const resignModalRadio = ref(0)
  1035. const resignClick = async ()=>{
  1036. const rows = tableCheckedKeys.value
  1037. if (rows.length <= 0) {
  1038. window.$message?.warning('只能操作待审批和已审批数据')
  1039. return
  1040. }
  1041. resignModal.value = true
  1042. }
  1043. const signClick = async () => {
  1044. const rows = tableCheckedKeys.value
  1045. //获取任务id
  1046. const taskIds = arrToKey(rows, 'taskId')
  1047. const idsArr = taskIds.split(',')
  1048. let isCan = idsArr.some(ele=>!ele)
  1049. if (isCan) {
  1050. window.$message?.warning('参数异常,暂不支持该操作')
  1051. return
  1052. }
  1053. //发起请求
  1054. signLoading.value = true
  1055. const { error, code, msg } = await queryApi.reSigningEVisa({
  1056. contractId: contractId.value,
  1057. projectId: projectId.value,
  1058. taskIds: taskIds,
  1059. classifyType: contractTypeTabKey.value,
  1060. type:resignModalRadio.value,
  1061. })
  1062. //处理数据
  1063. signLoading.value = false
  1064. if (!error && code === 200) {
  1065. window.$message?.success(msg ?? '提交成功,请请耐心等待重签,可继续操作其它的功能。')
  1066. getTableData().then()
  1067. } else {
  1068. window.$message?.error(msg ?? '操作失败')
  1069. }
  1070. resignModal.value = false
  1071. }
  1072. const cancelresign = ()=>{
  1073. resignModalRadio.value = 0
  1074. resignModal.value = false
  1075. }
  1076. //重新验签
  1077. const saveAginClick = async ()=>{
  1078. const rows = tableCheckedKeys.value
  1079. const taskIds = rows.map(row => row.taskId)
  1080. if (taskIds.some(id => id)) {
  1081. window.$message?.warning('只能操作未上报的数据')
  1082. return
  1083. }
  1084. const objArr = rows.map(row => ({
  1085. id: row.id,
  1086. wbsId: row.wbsId,
  1087. projectId: projectId.value,
  1088. contractId: contractId.value,
  1089. }))
  1090. saveAginLoading.value = true
  1091. const { error, code, msg } = await queryApi.reSigningEVisaStatus0(objArr)
  1092. //处理数据
  1093. saveAginLoading.value = false
  1094. if (!error && code === 200) {
  1095. window.$message?.success(msg ?? '提交成功,请请耐心等待重签,可继续操作其它的功能。')
  1096. getTableData().then()
  1097. } else {
  1098. window.$message?.error(msg ?? '操作失败')
  1099. }
  1100. }
  1101. const saveAginLoading = ref(false)
  1102. //重置文件题名
  1103. const resignTitleModal = ref(false)
  1104. const resignTitleClick = async ()=>{
  1105. // resignTitleModal.value = true
  1106. if (isTemplateType.value) {
  1107. resignTitleModal.value = true
  1108. } else {
  1109. resignTitleSave()
  1110. }
  1111. }
  1112. const resignTitleSave = async ()=>{
  1113. const rows = tableCheckedKeys.value
  1114. let arr = []
  1115. rows.forEach(item=>{
  1116. arr.push({
  1117. id:item.id,
  1118. nodeName:'',
  1119. nameRule:'',
  1120. })
  1121. })
  1122. ruleModalSaveLoad.value = true
  1123. const { error, code, msg, data } = await queryApi.flushQueryName({
  1124. type:1,
  1125. list:arr,
  1126. })
  1127. //处理数据
  1128. ruleModalSaveLoad.value = false
  1129. if (!error && code === 200) {
  1130. window.$message?.success(msg)
  1131. resignTitleModal.value = false
  1132. getTableData().then()
  1133. } else {
  1134. window.$message?.error(msg || '操作失败')
  1135. }
  1136. }
  1137. const resignTitleSaveLoad = ref(false)
  1138. //规则更改
  1139. const changeRuleClick = async ()=>{
  1140. await getWbsNodeTypeApi()
  1141. ruleModal.value = true
  1142. ruleTableData.value = []
  1143. let arr = tableCheckedKeys.value.map(item=>{
  1144. return {
  1145. wbsId:item.wbsId,
  1146. projectId:projectId.value,
  1147. id:item.id,
  1148. }
  1149. })
  1150. let arr1 = await getRuleListData(arr)
  1151. ruleTableData.value = arr1
  1152. for (let i = 0; i < ruleTableData.value.length; i++) {
  1153. const currentItem = ruleTableData.value[i]
  1154. const matchedItem = tableCheckedKeys.value.find(item => item.wbsId === currentItem.wbsId)
  1155. if (matchedItem) {
  1156. currentItem.name = matchedItem.name
  1157. currentItem.id = matchedItem.id
  1158. }
  1159. }
  1160. // ruleTableData.value = arr
  1161. }
  1162. const ruleModal = ref(false)
  1163. const ruleModalSaveLoad = ref(false)
  1164. const ruleModalClose = ()=>{
  1165. ruleModal.value = false
  1166. setValue.value = []
  1167. }
  1168. const ruleModalSave = async ()=>{
  1169. let isCanSave = ruleTableData.value.every(row => row.rule && row.rule.length > 0)
  1170. if (!isCanSave) {
  1171. window.$message.warning('请选择题名规规则')
  1172. return
  1173. }
  1174. let arr = []
  1175. ruleTableData.value.forEach(item=>{
  1176. arr.push({
  1177. id:item.id,
  1178. nodeName:item.newNodeName,
  1179. nameRule:item.rule.join('-'),
  1180. })
  1181. })
  1182. ruleModalSaveLoad.value = true
  1183. const { error, code, msg, data } = await queryApi.flushQueryName({
  1184. type:2,
  1185. list:arr,
  1186. })
  1187. //处理数据
  1188. ruleModalSaveLoad.value = false
  1189. if (!error && code === 200) {
  1190. window.$message?.success(msg)
  1191. getTableData().then()
  1192. ruleModalClose()
  1193. resignTitleModal.value = false
  1194. }
  1195. }
  1196. const setValue = ref('')
  1197. const ruleTableColumn = ref([
  1198. { key: 'name', name: '文件题名' },
  1199. { key: 'newNodeName', name: '修改后' },
  1200. { key: 'rule', name: '题名规则' },
  1201. ])
  1202. const ruleTableData = ref([])
  1203. const batchSetRule = async ()=>{
  1204. if (setValue.value.length === 0) {
  1205. window.$message.warning('请选择题名规则')
  1206. return
  1207. }
  1208. ruleTableData.value.forEach( (ele)=>{
  1209. ele.rule = setValue.value
  1210. let matchedItems = [] // 存储匹配的项
  1211. if (ele.rule.length > 0) {
  1212. // 1. 找出所有匹配的项
  1213. matchedItems = nodeTypeData.value.filter(dataItem =>
  1214. ele.rule.includes(dataItem.value),
  1215. )
  1216. // 2. 按原始 sort 排序
  1217. matchedItems.sort((a, b) => a.sort - b.sort)
  1218. // 3. 更新 ele.rule 为排序后的 value 数组
  1219. ele.rule = matchedItems.map(item => item.value)
  1220. }
  1221. })
  1222. let arr = []
  1223. ruleTableData.value.forEach((item)=>{
  1224. arr.push({
  1225. wbsId:item.wbsId,
  1226. nameRule:item.rule.join('-'),
  1227. id:item.id,
  1228. })
  1229. })
  1230. let afterArr = await getRuleValue(arr)
  1231. for (let i = 0; i < ruleTableData.value.length; i++) {
  1232. const currentItem = ruleTableData.value[i]
  1233. const matchedItem = afterArr.find(item => item.wbsId === currentItem.wbsId)
  1234. if (matchedItem) {
  1235. currentItem.newNodeName = matchedItem.newNodeName
  1236. }
  1237. }
  1238. }
  1239. const ruleChange = async (ele) => {
  1240. let str = ''
  1241. let matchedItems = [] // 存储匹配的项
  1242. if (ele.rule.length > 0) {
  1243. // 1. 找出所有匹配的项
  1244. matchedItems = nodeTypeData.value.filter(dataItem =>
  1245. ele.rule.includes(dataItem.value),
  1246. )
  1247. // 2. 按原始 sort 排序
  1248. matchedItems.sort((a, b) => a.sort - b.sort)
  1249. // 3. 更新 ele.rule 为排序后的 value 数组
  1250. ele.rule = matchedItems.map(item => item.value)
  1251. // 4. 生成连接字符串
  1252. str = ele.rule.join('-')
  1253. }
  1254. // 5. 调用API
  1255. let arr = [{
  1256. wbsId: ele.wbsId,
  1257. nameRule: str,
  1258. projectId: projectId.value,
  1259. id:ele.id,
  1260. }]
  1261. let afterArr = await getRuleValue(arr)
  1262. ele.newNodeName = afterArr[0].newNodeName
  1263. }
  1264. const getRuleLoad = ref(false)
  1265. const ruleTableLoading = ref(false)
  1266. const getRuleListData = async (arr) => {
  1267. ruleTableLoading.value = true
  1268. const { error, code, msg, data } = await queryApi.getNameRuleList(arr)
  1269. //处理数据
  1270. ruleTableLoading.value = false
  1271. if (!error && code === 200) {
  1272. return data || ''
  1273. } else {
  1274. return ''
  1275. }
  1276. }
  1277. const getRuleValue = async (arr) => {
  1278. // 检查 arr 中每一项的 nameRule 是否有值
  1279. const hasInvalidItem = arr.some(item => !item.nameRule || item.nameRule.length === 0)
  1280. if (hasInvalidItem) {
  1281. window.$message.warning('请选择题名规则')
  1282. return
  1283. }
  1284. getRuleLoad.value = true
  1285. const { error, code, msg, data } = await queryApi.previewNodeName(arr)
  1286. //处理数据
  1287. getRuleLoad.value = false
  1288. if (!error && code === 200) {
  1289. return data || ''
  1290. } else {
  1291. return ''
  1292. }
  1293. }
  1294. //获取节点类型
  1295. const nodeTypeData = ref([])
  1296. const getWbsNodeTypeApi = async () => {
  1297. const { data } = await getDictionary({
  1298. code: 'name_rule',
  1299. })
  1300. //处理数据
  1301. let newArr = []
  1302. const newData = getArrValue(data)
  1303. for (let i = 0; i < newData.length; i++) {
  1304. newArr.push({
  1305. label: newData[i]['dictValue'],
  1306. value:newData[i]['dictKey'],
  1307. })
  1308. }
  1309. nodeTypeData.value = newArr
  1310. }
  1311. //一键重签1
  1312. const resignModal1 = ref(false)
  1313. const resignModalRadio1 = ref(0)
  1314. const resignClick1 = ()=>{
  1315. const rows = tableCheckedKeys.value
  1316. if (rows.length <= 0) {
  1317. window.$message?.warning('只能操作待审批和已审批数据')
  1318. return
  1319. }
  1320. //获取任务id
  1321. const taskIds = arrToKey(rows, 'taskId')
  1322. const idsArr = taskIds.split(',')
  1323. let isCan = idsArr.some(ele=>!ele)
  1324. if (isCan) {
  1325. window.$message?.warning('只能操作待审批和已审批数据')
  1326. return
  1327. }
  1328. resignModal1.value = true
  1329. }
  1330. const signLoading1 = ref(false)
  1331. const cancelresign1 = ()=>{
  1332. resignModalRadio1.value = 0
  1333. resignModal1.value = false
  1334. checkTaskUserIds.value = []
  1335. }
  1336. const signClick1 = async () => {
  1337. const rows = tableCheckedKeys.value
  1338. //获取任务id
  1339. const ids = arrToId(rows)
  1340. if (resignModalRadio1.value === 1) {
  1341. if (checkTaskUserIds.value.length === 0) {
  1342. return window.$message?.warning('请选择用户')
  1343. }
  1344. } else {
  1345. checkTaskUserIds.value = []
  1346. }
  1347. //发起请求
  1348. signLoading1.value = true
  1349. const { error, code, msg } = await queryApi.reSigningEVisa1({
  1350. userIds: checkTaskUserIds.value.length === 1 ? checkTaskUserIds.value[0] : checkTaskUserIds.value.join(','),
  1351. ids: ids,
  1352. })
  1353. //处理数据
  1354. signLoading1.value = false
  1355. if (!error && code === 200) {
  1356. window.$message?.success(msg ?? '提交成功,请请耐心等待重签,可继续操作其它的功能。')
  1357. cancelresign1()
  1358. getTableData().then()
  1359. }
  1360. }
  1361. const checkTaskUserIds = ref([])
  1362. </script>
  1363. <style lang="scss" scoped>
  1364. @import "../../styles/data-fill/query.scss";
  1365. .error-border {
  1366. border: 1px solid red;
  1367. }
  1368. .iscusor {
  1369. cursor: pointer;
  1370. }
  1371. .bg-primary-color {
  1372. background-color: var(--el-color-primary) ;
  1373. }
  1374. </style>
  1375. <style lang="scss">
  1376. .hc-online-verify-drawer .el-card.hc-new-card-box {
  1377. .hc-card-header-box {
  1378. .online-verify-title {
  1379. font-size: 20px;
  1380. }
  1381. .online-verify-icon {
  1382. display: flex;
  1383. align-items: center;
  1384. cursor: pointer;
  1385. color: #5a5959;
  1386. i {
  1387. font-size: 18px;
  1388. }
  1389. &:hover {
  1390. color: var(--el-color-primary);
  1391. }
  1392. }
  1393. }
  1394. }
  1395. .custom-select{
  1396. .el-select__wrapper {
  1397. height: 32px;
  1398. overflow-y: hidden;
  1399. }
  1400. .el-select__selection.is-near {
  1401. height: 32px;
  1402. overflow-y: hidden;
  1403. overflow-x: hidden;
  1404. flex-wrap: nowrap;
  1405. }
  1406. }
  1407. </style>