test.vue 56 KB

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