query.vue 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  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. :disabled="isCanDown || tableCheckedKeys.length <= 0" :loading="downloadLoading" hc-btn
  74. color="#A16222" @click="batchDownload"
  75. >
  76. <HcIcon name="download" />
  77. <span>下载</span>
  78. </el-button>
  79. </HcTooltip>
  80. <HcTooltip keys="query_print">
  81. <el-button
  82. :disabled="isCanDown || tableCheckedKeys.length <= 0" :loading="printLoading" hc-btn
  83. color="#A16222" @click="batchPrint"
  84. >
  85. <HcIcon name="printer" />
  86. <span>打印</span>
  87. </el-button>
  88. </HcTooltip>
  89. <HcTooltip keys="query_abolish">
  90. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn color="#567722" @click="batchAbolishClick">
  91. <HcIcon name="delete-bin-3" />
  92. <span>废除</span>
  93. </el-button>
  94. </HcTooltip>
  95. <HcTooltip keys="query_local_attestation">
  96. <el-button
  97. :disabled="tableCheckedKeys.length <= 0" :loading="localLoading" hc-btn
  98. color="#e03997" @click="batchLocal"
  99. >
  100. <HcIcon name="folder-download" />
  101. <span>本地验签</span>
  102. </el-button>
  103. </HcTooltip>
  104. <HcTooltip keys="query_online_attestation">
  105. <el-button
  106. :disabled="tableCheckedKeys.length <= 0" :loading="onlineLoading" hc-btn
  107. color="#e03997" @click="batchOnline"
  108. >
  109. <HcIcon name="cloud" />
  110. <span>在线验签</span>
  111. </el-button>
  112. </HcTooltip>
  113. <el-button :disabled="tableCheckedKeys.length <= 0" :loading="signLoading" hc-btn type="primary" @click="resignClick"> <HcIcon name="repeat" />re-sign</el-button>
  114. <HcTooltip keys="save_agin">
  115. <el-button
  116. :disabled="tableCheckedKeys.length <= 0" :loading="saveAginLoading" hc-btn
  117. color="#e03997" @click="saveAginClick"
  118. >
  119. <HcIcon name="save" />
  120. <span>save-again</span>
  121. </el-button>
  122. </HcTooltip>
  123. </template>
  124. <template #search>
  125. <div class="flex items-center">
  126. <div class="w-40">
  127. <el-select v-model="searchForm.taskStatus" clearable placeholder="流程状态">
  128. <el-option
  129. v-for="item in processStatusData" :key="item.value"
  130. :label="item.dictValue" :value="item.dictKey"
  131. />
  132. </el-select>
  133. </div>
  134. <div class="ml-2 w-32">
  135. <el-select v-model="searchForm.majorDateType" clearable placeholder="资料类型">
  136. <el-option
  137. v-for="item in majorDataTypeOptions"
  138. :key="item.value"
  139. :label="item.label"
  140. :value="item.value"
  141. />
  142. </el-select>
  143. </div>
  144. <div class="ml-2 w-40">
  145. <el-select v-model="searchForm.fileUserIdAndName" clearable placeholder="填报人">
  146. <el-option
  147. v-for="item in reportingPersonData" :key="item.value" :label="item.label"
  148. :value="item.value"
  149. />
  150. </el-select>
  151. </div>
  152. <div class="ml-2 w-40">
  153. <el-select v-model="searchForm.sourceType" clearable placeholder="文件类型">
  154. <el-option
  155. v-for="item in fileTypeData" :key="item.value" :label="item.dictValue"
  156. :value="item.dictKey"
  157. />
  158. </el-select>
  159. </div>
  160. <div class="ml-2 w-40">
  161. <el-select v-model="searchForm.waitingUserStatus" clearable placeholder="审批人状态">
  162. <el-option :value="1" label="未签字" />
  163. <el-option :value="2" label="已签字" />
  164. <el-option :value="3" label="已废除" />
  165. <el-option :value="999" label="签字异常" />
  166. </el-select>
  167. </div>
  168. <div class="ml-2 w-64">
  169. <HcDatePicker :dates="betweenTime" clearable @change="betweenTimeUpdate" />
  170. </div>
  171. <div class="ml-2 w-60">
  172. <el-input
  173. v-model="searchForm.queryValue" clearable placeholder="请输入名称关键词检索"
  174. @keyup="keyUpEvent"
  175. />
  176. </div>
  177. <div class="ml-2">
  178. <el-button type="primary" @click="searchClick">
  179. <HcIcon name="search-2" />
  180. <span>搜索</span>
  181. </el-button>
  182. </div>
  183. </div>
  184. </template>
  185. <template #extra>
  186. <template v-if="contractInfo?.contractType === 2 || contractInfo?.contractType === 3">
  187. <HcNewSwitch :datas="contractTypeTab" :keys="contractTypeTabKey" size="default" @change="contractTypeTabChange" />
  188. </template>
  189. </template>
  190. <HcTable
  191. ref="tableListRef" :column="tableListColumn" :datas="tableListData" :loading="tableLoading"
  192. is-new :index-style="{ width: 60 }" is-check :check-style="{ width: 29 }"
  193. @selection-change="tableSelectionChange"
  194. >
  195. <template #name="{ row }">
  196. <span v-loading="row?.bussPreviewLoading" class="text-link" @click="tableRowName(row)">{{ row?.name }}</span>
  197. </template>
  198. <template #waitingUserList="{ row }">
  199. <template v-for="item in row.waitingUserList">
  200. <el-tag
  201. v-if="item.waitingUserName"
  202. :key="item.waitingUserName"
  203. :type="`${item.status === 2 ? 'success' : item.status === 3 ? 'warning' : item.status === 999 ? 'danger' : 'info'}`"
  204. class="mx-1" effect="dark"
  205. >
  206. {{ item.waitingUserName }}
  207. </el-tag>
  208. </template>
  209. </template>
  210. </HcTable>
  211. <template #action>
  212. <div class="lr-dialog-footer">
  213. <div class="left">
  214. <span class="text-success">任务人员中:</span>
  215. <el-tag class="mx-1" effect="dark" type="info">未签字</el-tag>
  216. <el-tag class="mx-1" effect="dark" type="success">已签字</el-tag>
  217. <el-tag class="mx-1" effect="dark" type="warning">已废除</el-tag>
  218. <el-tag class="mx-1" effect="dark" type="danger">签字异常</el-tag>
  219. </div>
  220. <div class="right">
  221. <HcPages :pages="searchForm" @change="pageChange" />
  222. </div>
  223. </div>
  224. </template>
  225. </HcNewCard>
  226. </hc-body>
  227. </div>
  228. <!-- 批量上报审批 -->
  229. <HcReportModal
  230. :ids="reportIds"
  231. :node-id="primaryKeyId"
  232. :table-owner="contractTypeTabKey"
  233. :classify-type="classType"
  234. :contract-id="contractId"
  235. :datas="reportDatas"
  236. :project-id="projectId"
  237. :show="showReportModal"
  238. :task-name="reportTaskName"
  239. :type-data="reportTypeData"
  240. :report-arr="reportArr"
  241. type="query"
  242. is-datas
  243. title="批量上报审批"
  244. url="informationWriteQuery/batchTask"
  245. @finish="showReportFinish"
  246. @hide="showReportModal = false"
  247. @tag-close="reportTaskTagClose"
  248. />
  249. <!-- 在线验签 -->
  250. <hc-new-drawer v-model="isOnlineVerifyDrawer" modal-class="hc-online-verify-drawer" to-id="app" @close="onlineVerifyDrawerClose">
  251. <hc-new-card>
  252. <template #header>
  253. <div class="online-verify-title">{{ onlineTitle }}</div>
  254. </template>
  255. <template #extra>
  256. <div class="online-verify-icon" @click="onlineVerifyDrawerClose">
  257. <HcIcon name="close-circle" />
  258. <span class="ml-1">关闭</span>
  259. </div>
  260. </template>
  261. <hc-body split padding="0px" :options="onlineVerifyOptions">
  262. <template #left>
  263. <hc-new-card>
  264. <HcPdf :src="onlineVerifyData.pdfUrl" />
  265. </hc-new-card>
  266. </template>
  267. <hc-new-card>
  268. <HcTable :column="cscTableColumn" :datas="cscTableData" is-new :index-style="{ width: 60 }" />
  269. </hc-new-card>
  270. </hc-body>
  271. </hc-new-card>
  272. </hc-new-drawer>
  273. <!-- 一键重签弹窗 -->
  274. <hc-new-dialog v-model="resignModal" title="一键重签" widths="38rem" :loading="signLoading" @close="cancelresign" @save="signClick">
  275. <div>
  276. 是否重新生成pdf:
  277. <el-radio-group v-model="resignModalRadio">
  278. <el-radio :value="0">否</el-radio>
  279. <el-radio :value="1">是</el-radio>
  280. </el-radio-group>
  281. </div>
  282. </hc-new-dialog>
  283. </div>
  284. </template>
  285. <script setup>
  286. import { onMounted, ref, watch } from 'vue'
  287. import { useAppStore } from '~src/store'
  288. import { getStoreValue, setStoreValue } from '~src/utils/storage'
  289. import { arrToId, arrToKey, downloadBlob, getArrValue, getObjValue, isString } from 'js-fast-way'
  290. import queryApi from '~api/data-fill/query'
  291. import { eVisaTaskCheckApi } from '~api/other'
  292. import { toPdfPage } from '~uti/btn-auth'
  293. import wbsApi from '~api/data-fill/wbs'
  294. import website from '~src/config'
  295. import { getDictionaryData } from '~uti/tools'
  296. //变量
  297. const useAppState = useAppStore()
  298. const projectId = ref(useAppState.getProjectId)
  299. const contractId = ref(useAppState.getContractId)
  300. const projectInfo = ref(useAppState.getProjectInfo)
  301. const contractInfo = ref(useAppState.getContractInfo)
  302. const isCollapse = ref(useAppState.getCollapse)
  303. const isLayout = ref(useAppState.isLayout)
  304. //变量
  305. const wbstree = ref(null)
  306. const wbstreeKey = ref(Math.random())
  307. //树搜索
  308. const isSearchTree = ref(false)
  309. const searchTreeHeight = ref()
  310. const searchTreeVal = ref('')
  311. //监听
  312. watch(() => [useAppState.getCollapse, searchTreeVal.value, useAppState.isLayout], ([Collapse, search, isLay]) => {
  313. isCollapse.value = Collapse
  314. isLayout.value = isLay || ''
  315. if (search.length == 0) {
  316. isSearchTree.value = false
  317. }
  318. })
  319. //是否禁用下载打印按钮
  320. const isCanDown = ref(false)
  321. //自动展开缓存
  322. const treeAutoExpandKeys = ref(getStoreValue('wbsTreeExpandKeys') || [])
  323. //渲染完成
  324. onMounted(() => {
  325. getFileUser()
  326. getReportNumber()
  327. getFirstTaskStatus()
  328. getDictBizClassify()
  329. getMajorDataTypeOptions()
  330. isCanDown.value = !website.localModel
  331. })
  332. //获取
  333. const majorDataTypeOptions = ref([])
  334. const getMajorDataTypeOptions = async () => {
  335. majorDataTypeOptions.value = (await getDictionaryData('major_data_type', false)).filter(item => item.value !== 0)
  336. }
  337. const searchTreeData = ref([])
  338. //回车
  339. const treeLoading = ref(true)
  340. const getSearchTreeData = async () => {
  341. treeLoading.value = true
  342. const { error, code, data } = await queryApi.getTreeNodeByQueryValueAndContractId({
  343. contractId: contractId.value,
  344. queryValue: searchTreeVal.value,
  345. tableOwner:contractTypeTabKey.value,
  346. })
  347. //判断状态
  348. if (!error && code === 200) {
  349. let treedata = getArrValue(data)
  350. searchTreeData.value = treedata
  351. treeLoading.value = false
  352. } else {
  353. treeLoading.value = false
  354. searchTreeData.value = []
  355. }
  356. }
  357. //回车
  358. const searchTreeKeyUp = (e) => {
  359. if (e.key === 'Enter') {
  360. searchTreeClick()
  361. }
  362. }
  363. const searchTreeClick = async () => {
  364. if (searchTreeVal.value) {
  365. searchTreeHeight.value = document.getElementById('hc-tree-scrollbar').offsetHeight
  366. isSearchTree.value = true
  367. //treeLoading.value = true
  368. getSearchTreeData().then()
  369. } else {
  370. isSearchTree.value = false
  371. }
  372. }
  373. //树相关的变量
  374. const primaryKeyId = ref('')
  375. const nodeItemInfo = ref({})
  376. const nodeDataInfo = ref({})
  377. //懒加载的数据
  378. const treeLoadNode = async ({ node, item, level }, resolve) => {
  379. let contractIdRelation = '', parentId = '', primaryKeyId = ''
  380. if (level !== 0) {
  381. const nodeData = getObjValue(item)
  382. contractIdRelation = nodeData?.contractIdRelation || ''
  383. parentId = contractIdRelation ? nodeData?.primaryKeyId : nodeData?.id
  384. primaryKeyId = nodeData?.id || ''
  385. }
  386. //获取数据
  387. const { data } = await queryApi.queryWbsTreeData({
  388. contractId: contractId.value || '',
  389. contractIdRelation,
  390. primaryKeyId,
  391. parentId,
  392. // classifyType: contractTypeTabKey.value,
  393. classifyType: classType.value,
  394. tableOwner:contractTypeTabKey.value,
  395. dataTime:new Date(),
  396. })
  397. resolve(getArrValue(data))
  398. treeLoading.value = false
  399. }
  400. //树被点击
  401. const wbsElTreeClick = ({ node, data, keys }) => {
  402. nodeItemInfo.value = node
  403. nodeDataInfo.value = data
  404. primaryKeyId.value = data['primaryKeyId'] || ''
  405. //缓存自动展开
  406. treeAutoExpandKeys.value = keys
  407. setStoreValue('wbsTreeExpandKeys', keys)
  408. //改变搜索表单数据
  409. searchForm.value.wbsId = data['primaryKeyId']
  410. //只有监理、指挥合同段才传contractIdRelation
  411. if (contractInfo.value?.contractType == 2 || contractInfo.value?.contractType == 3) {
  412. searchForm.value.contractIdRelation = data['contractIdRelation']
  413. } else {
  414. searchForm.value.contractIdRelation = ''
  415. }
  416. searchForm.value.current = 1
  417. getFileUser()
  418. getTableData()
  419. }
  420. //搜索条件
  421. const processStatusData = ref([]) //流程状态
  422. const reportingPersonData = ref([]) //填报人
  423. const fileTypeData = ref([]) //文件类型
  424. const reportBatchData = ref([]) //上报批次
  425. //获取所有填报人
  426. const getFileUser = async () => {
  427. const info = nodeDataInfo.value
  428. if (!info || !info?.contractIdRelation) {
  429. window.$message?.warning('请先点击左侧节点')
  430. return
  431. }
  432. const { error, code, data } = await queryApi.getFileUser({
  433. contractId: contractId.value,
  434. contractIdRelation: contractInfo.value?.contractType === 2 ? info?.contractIdRelation : contractId.value,
  435. })
  436. //判断状态
  437. if (!error && code === 200) {
  438. let res = getArrValue(data), userArr = []
  439. res.forEach(item => {
  440. userArr.push({ label: item['userName'], value: `${item['userId']}-${item['userName']}` })
  441. })
  442. reportingPersonData.value = userArr
  443. } else {
  444. reportingPersonData.value = []
  445. }
  446. }
  447. //获取上报批次
  448. const getReportNumber = async () => {
  449. const { error, code, data } = await queryApi.getReportNumber({
  450. contractId: contractId.value,
  451. projectId: projectId.value,
  452. })
  453. //判断状态
  454. if (!error && code === 200) {
  455. reportBatchData.value = getArrValue(data)
  456. } else {
  457. reportBatchData.value = []
  458. }
  459. }
  460. //获取流程状态
  461. const getFirstTaskStatus = async () => {
  462. const { error, code, data } = await queryApi.getFirstTaskStatus()
  463. //判断状态
  464. if (!error && code === 200) {
  465. processStatusData.value = getArrValue(data)
  466. } else {
  467. processStatusData.value = []
  468. }
  469. }
  470. //获取流程状态分类和文件类型分类
  471. const getDictBizClassify = async () => {
  472. const { error, code, data } = await queryApi.getDictBizClassify({
  473. contractId: contractId.value,
  474. code: 'fileType',
  475. })
  476. //判断状态
  477. if (!error && code === 200) {
  478. fileTypeData.value = getArrValue(data)
  479. } else {
  480. fileTypeData.value = []
  481. }
  482. }
  483. //搜索表单
  484. const searchForm = ref({
  485. taskStatus: null, fileUserIdAndName: null, sourceType: null, reportNumber: null, betweenTime: null,
  486. queryValue: null, contractIdRelation: null, wbsId: null, current: 1, size: 20, total: 0, majorDateType:'',
  487. waitingUserStatus:'',
  488. })
  489. //结构类型tab数据和相关处理
  490. // const contractTypeTabKey = ref('1')
  491. const contractTypeTabKey = ref(contractInfo.value?.contractType === 2 ? '2' : '1')
  492. //加载树需要的classType由合同段获取
  493. const classType = ref(contractInfo.value?.contractType === 2 ? '2' : '1')
  494. const contractTypeTab = ref([
  495. { key: '1', name: '施工数据' },
  496. { key: '2', name: '监理数据' },
  497. ])
  498. //是否显示左边树
  499. const isShowLeft = ref(true)
  500. const contractTypeTabChange = (item) => {
  501. contractTypeTabKey.value = item?.key
  502. //重新加载左边树
  503. isShowLeft.value = false
  504. setTimeout(()=>{
  505. isShowLeft.value = true
  506. }, 500)
  507. searchClick()
  508. }
  509. //获取合同段类型
  510. // const getContractTypeKey = () => {
  511. // const { contractType } = contractInfo.value;
  512. // if (contractType === 2 || contractType === 3) {
  513. // return contractTypeTabKey.value ?? '1'
  514. // } else {
  515. // return null
  516. // }
  517. // }
  518. //日期时间被选择
  519. const betweenTime = ref(null)
  520. const betweenTimeUpdate = ({ arr, query }) => {
  521. betweenTime.value = arr
  522. searchForm.value.betweenTime = query
  523. }
  524. //回车搜索
  525. const keyUpEvent = (e) => {
  526. if (e.key === 'Enter') {
  527. searchForm.value.current = 1
  528. if (searchForm.value?.queryValue) {
  529. searchForm.value.queryValue = searchForm.value.queryValue.trim()
  530. }
  531. getTableData()
  532. }
  533. }
  534. //搜索
  535. const searchClick = () => {
  536. searchForm.value.current = 1
  537. if (searchForm.value?.queryValue) {
  538. searchForm.value.queryValue = searchForm.value.queryValue.trim()
  539. }
  540. wbstreeKey.value = Math.random()
  541. getTableData()
  542. // wbstree.value.resetNode().then((red)=>{
  543. // if(red){
  544. // getTableData()
  545. // }
  546. // })
  547. }
  548. //分页被点击
  549. const pageChange = ({ current, size }) => {
  550. searchForm.value.current = current
  551. searchForm.value.size = size
  552. getTableData()
  553. }
  554. //获取数据
  555. const tableListRef = ref(null)
  556. const tableLoading = ref(false)
  557. const tableListColumn = ref([
  558. { key: 'name', name: '文件名称' },
  559. // { key: 'startTime', name: '开始时间', width: 140, align: 'center' },
  560. { key: 'taskStatusStr', name: '流程状态', width: 100, align: 'center' },
  561. { key: 'reportNumber', name: '上报批次', width: 80, align: 'center' },
  562. { key: 'fileUserIdAndName', name: '填报人', width: 190, align: 'center' },
  563. { key: 'waitingUserList', name: '任务人', width: 100, align: 'center' },
  564. //{ key: 'evisaFailedInfo', name: '电签失败原因' },
  565. ])
  566. const tableListData = ref([])
  567. const getTableData = async () => {
  568. if (searchForm.value.wbsId) {
  569. tableListRef.value?.clearSelection()
  570. tableCheckedKeys.value = []
  571. tableLoading.value = true
  572. // const classifyType = getContractTypeKey();
  573. const { error, code, data, msg } = await queryApi.getPageData({
  574. projectId: projectId.value,
  575. contractId: contractId.value,
  576. ...searchForm.value,
  577. classifyType: contractTypeTabKey.value,
  578. })
  579. //处理数据
  580. tableLoading.value = false
  581. if (!error && code === 200) {
  582. tableListData.value = getArrValue(data['records'])
  583. searchForm.value.total = data.total || 0
  584. } else {
  585. // window.$message?.error(msg)
  586. tableListData.value = []
  587. searchForm.value.total = 0
  588. }
  589. } else {
  590. window?.$message?.warning('请先选择一个树节点')
  591. }
  592. }
  593. //多选
  594. const tableCheckedKeys = ref([])
  595. const tableSelectionChange = (rows) => {
  596. tableCheckedKeys.value = rows.filter((item) => {
  597. return (item ?? '') !== ''
  598. })
  599. }
  600. //名称被点击
  601. const tableRowName = (row) => {
  602. //如果 evisaPdfUrl 不为空,使用evisaPdfUrl,反之使用pdfUrl
  603. // if (row['evisaPdfUrl']) {
  604. // toPdfPage(row['evisaPdfUrl'])
  605. // //window.open(row['evisaPdfUrl'], '_blank')
  606. // } else if (row['pdfUrl']) {
  607. // toPdfPage(row['pdfUrl'])
  608. // //window.open(row['pdfUrl'], '_blank')
  609. // } else {
  610. // window.$message?.warning('文件不存在')
  611. // }
  612. bussPreview(row)
  613. }
  614. //多表预览
  615. const bussPreview = async (row) => {
  616. const info = nodeDataInfo.value
  617. row.bussPreviewLoading = true
  618. const { error, code, data } = await wbsApi.getBussPdfs({
  619. nodeId: row?.wbsId || '',
  620. classify: contractTypeTabKey.value,
  621. projectId: projectId.value,
  622. // contractId: contractId.value
  623. contractId: contractInfo.value?.contractType == 2 ? info?.contractIdRelation : contractId.value,
  624. })
  625. row.bussPreviewLoading = false
  626. if (!error && code === 200) {
  627. toPdfPage(data)
  628. //window.open(data, '_blank')
  629. } else {
  630. window.$message?.warning('获取PDF失败')
  631. }
  632. }
  633. //上报
  634. const reportIds = ref('')
  635. const reportTaskName = ref('')
  636. const reportDatas = ref([])
  637. const reportTypeData = ref([])
  638. const showReportModal = ref(false)
  639. const reportLoading = ref(false)
  640. const reportArr = ref([])
  641. const reportModalClick = async () => {
  642. const rows = tableCheckedKeys.value
  643. //判断是否满足条件
  644. const result = rows.every(({ status }) => {
  645. return status === 0 || status === 3
  646. })
  647. //处理数据
  648. let newArr = []
  649. for (let i = 0; i < rows.length; i++) {
  650. newArr.push(rows[i]['wbsId'])
  651. }
  652. reportTypeData.value = newArr
  653. let newArr1 = []
  654. for (let i = 0; i < rows.length; i++) {
  655. newArr1.push(rows[i]['id'])
  656. }
  657. reportArr.value = newArr1
  658. //判断状态
  659. if (result) {
  660. reportLoading.value = true
  661. const taskCheck = await eVisaTaskCheckApi({
  662. projectId: projectId.value,
  663. contractId: contractId.value,
  664. })
  665. if (taskCheck) {
  666. //初始ID
  667. const row = getObjValue(rows[0])
  668. reportIds.value = arrToId(rows)
  669. //设置任务数据
  670. let reportDataArr = []
  671. rows.forEach(item => {
  672. reportDataArr.push({
  673. id: item?.id,
  674. name: item?.name,
  675. })
  676. })
  677. reportDatas.value = reportDataArr
  678. //设置任务名称
  679. reportTaskName.value = rows.length > 1 ? `${row.name}等${rows.length}个文件` : row.name
  680. reportLoading.value = false
  681. showReportModal.value = true
  682. } else {
  683. reportLoading.value = false
  684. }
  685. } else {
  686. window.$message?.warning('已上报的文件不能进行再次上报,若要重新上报,要先撤回之前的上报,再重新上报')
  687. }
  688. }
  689. //上报的审批内容移除
  690. const reportTaskTagClose = (index) => {
  691. const row = tableCheckedKeys.value[index]
  692. tableListRef.value?.toggleRowSelection(row, false)
  693. }
  694. //上报完成
  695. const showReportFinish = () => {
  696. showReportModal.value = false
  697. getTableData()
  698. }
  699. //下载
  700. const downloadLoading = ref(false)
  701. const batchDownload = async () => {
  702. const rows = tableCheckedKeys.value
  703. const ids = arrToId(rows)
  704. //批量下载
  705. downloadLoading.value = true
  706. const { error, disposition, res } = await queryApi.batchDownloadFileToZip({ ids: ids })
  707. //处理数据
  708. downloadLoading.value = false
  709. if (!error) {
  710. if (disposition) {
  711. downloadBlob(res, disposition)
  712. } else {
  713. window.$message?.error('数据异常')
  714. }
  715. }
  716. }
  717. //打印
  718. const printLoading = ref(false)
  719. const batchPrint = async () => {
  720. const rows = tableCheckedKeys.value
  721. const ids = arrToId(rows)
  722. //批量下载
  723. printLoading.value = true
  724. const { error, code, data } = await queryApi.batchPrint({ ids: ids })
  725. //处理数据
  726. printLoading.value = false
  727. const res = isString(data) ? data ?? '' : ''
  728. if (!error && code === 200 && res) {
  729. toPdfPage(res)
  730. //window.open(res, '_blank')
  731. }
  732. }
  733. //废除
  734. const batchAbolishClick = () => {
  735. const rows = tableCheckedKeys.value
  736. //判断是否满足条件
  737. const result = rows.every(({ status }) => {
  738. return status !== 0 && status !== 3
  739. })
  740. //判断状态
  741. if (result) {
  742. //拼接ID
  743. const ids = arrToId(rows)
  744. window?.$messageBox?.alert('是否废除勾选的已上报文件?', '废除文件', {
  745. showCancelButton: true,
  746. confirmButtonText: '确定废除',
  747. cancelButtonText: '取消',
  748. callback: (action) => {
  749. if (action === 'confirm') {
  750. batchAbolishSave(ids)
  751. }
  752. },
  753. })
  754. } else {
  755. window.$message?.warning('未上报的文件不能废除')
  756. }
  757. }
  758. //废除勾选的已上报文件
  759. const batchAbolishSave = async (ids) => {
  760. const { error, code } = await queryApi.batchAbolish({ ids: ids, projectId:projectId.value, contractId:contractId.value })
  761. //处理数据
  762. if (!error && code === 200) {
  763. window.$message?.success('批量废除成功')
  764. tableCheckedKeys.value = []
  765. getTableData()
  766. }
  767. }
  768. //本地验签
  769. const localLoading = ref(false)
  770. const batchLocal = async () => {
  771. const rows = tableCheckedKeys.value
  772. //判断是否满足条件
  773. const result = rows.every(({ status }) => {
  774. return status === 2
  775. })
  776. //判断状态
  777. if (result) {
  778. const ids = arrToId(rows)
  779. //请求数据
  780. localLoading.value = true
  781. const { error, code, data, disposition, res } = await queryApi.localVerify({
  782. ids: ids,
  783. })
  784. //处理数据
  785. localLoading.value = false
  786. if (!error && code === 200) {
  787. if (disposition) {
  788. downloadBlob(res, disposition)
  789. } else {
  790. window.$message?.error('数据异常')
  791. }
  792. }
  793. } else {
  794. window.$message?.warning('存在未审批或未上报数据')
  795. }
  796. }
  797. //在线验签
  798. const onlineLoading = ref(false)
  799. const onlineVerifyData = ref({})
  800. const onlineTitle = ref('')
  801. const isOnlineVerifyDrawer = ref(false)
  802. const onlineVerifyOptions = {
  803. sizes: [50, 50],
  804. snapOffset: 0,
  805. minSize: ['10%', '80%'],
  806. }
  807. const batchOnline = async () => {
  808. const rows = tableCheckedKeys.value
  809. if (rows.length > 1) {
  810. window.$message?.warning('在线验签只能勾选一条数据进行验签')
  811. return
  812. }
  813. //判断是否满足条件
  814. const result = rows.every(({ status }) => {
  815. return status === 2
  816. })
  817. //判断状态
  818. if (!result) {
  819. window.$message?.warning('存在未审批或未上报数据')
  820. return
  821. }
  822. //发起请求
  823. onlineTitle.value = rows[0]?.name
  824. const ids = arrToId(rows)
  825. onlineLoading.value = true
  826. const { error, code, msg, data } = await queryApi.onlineVerify({
  827. ids: ids,
  828. })
  829. //处理数据
  830. onlineLoading.value = false
  831. if (!error && code === 200) {
  832. onlineVerifyData.value = getObjValue(data)
  833. cscTableData.value = getArrValue(data['certBeanVOList'])
  834. isOnlineVerifyDrawer.value = true
  835. } else {
  836. onlineVerifyData.value = {}
  837. window.$message?.error(msg ?? '操作失败')
  838. }
  839. }
  840. //签名信息
  841. const cscTableColumn = [
  842. { key:'dn', name: '签名者', width: 300 },
  843. { key:'time', name: '签名时间', width: 200 },
  844. { key:'result', name: '验签结果' },
  845. ]
  846. const cscTableData = ref([])
  847. //在线验签抽屉被关闭
  848. const onlineVerifyDrawerClose = () => {
  849. isOnlineVerifyDrawer.value = false
  850. onlineLoading.value = false
  851. }
  852. //树展开和收起
  853. const isWbsTreeShow = ref(true)
  854. const setWbsTreeShow = () => {
  855. isWbsTreeShow.value = !isWbsTreeShow.value
  856. }
  857. //左右拖动,改变树形结构宽度
  858. const leftWidth = ref(300)
  859. const onmousedown = () => {
  860. let leftNum = 0
  861. if (isLayout.value === 'no') {
  862. leftNum = 0
  863. } else {
  864. leftNum = isCollapse.value ? 142 : 272
  865. }
  866. document.onmousemove = (ve) => {
  867. let diffVal = ve.clientX - leftNum
  868. if (diffVal >= 310 && diffVal <= 900) {
  869. leftWidth.value = diffVal
  870. }
  871. }
  872. document.onmouseup = () => {
  873. document.onmousemove = null
  874. document.onmouseup = null
  875. }
  876. }
  877. const allElementsNotEmpty = (str)=> {
  878. // 使用split将字符串分割成字符数组
  879. // 使用every方法判断每个元素是否不为空字符串
  880. return str.split('').every(char => char !== '')
  881. }
  882. //一键重签
  883. const signLoading = ref(false)
  884. const resignModal = ref(false)
  885. const resignModalRadio = ref(0)
  886. const resignClick = async ()=>{
  887. const rows = tableCheckedKeys.value
  888. if (rows.length <= 0) {
  889. window.$message?.warning('请先勾选已审批的数据')
  890. return
  891. }
  892. //判断是否满足条件 //一键重迁 全部放开
  893. /*const result = rows.every(({ status }) => {
  894. if(status ===1 || status ===2){
  895. return true;
  896. }else{
  897. return false;
  898. }
  899. })
  900. //判断状态
  901. if (!result) {
  902. window.$message?.warning('只能勾选已审批的数据')
  903. return
  904. }*/
  905. resignModal.value = true
  906. }
  907. const signClick = async () => {
  908. const rows = tableCheckedKeys.value
  909. //获取任务id
  910. const taskIds = arrToKey(rows, 'taskId')
  911. const idsArr = taskIds.split(',')
  912. let isCan = idsArr.some(ele=>!ele)
  913. if (isCan) {
  914. window.$message?.warning('参数异常,暂不支持该操作')
  915. return
  916. }
  917. //发起请求
  918. signLoading.value = true
  919. const { error, code, msg } = await queryApi.reSigningEVisa({
  920. contractId: contractId.value,
  921. projectId: projectId.value,
  922. taskIds: taskIds,
  923. classifyType: contractTypeTabKey.value,
  924. type:resignModalRadio.value,
  925. })
  926. //处理数据
  927. signLoading.value = false
  928. if (!error && code === 200) {
  929. window.$message?.success(msg ?? '提交成功,请请耐心等待重签,可继续操作其它的功能。')
  930. getTableData().then()
  931. } else {
  932. window.$message?.error(msg ?? '操作失败')
  933. }
  934. resignModal.value = false
  935. }
  936. const cancelresign = ()=>{
  937. resignModalRadio.value = 0
  938. resignModal.value = false
  939. }
  940. //重新验签
  941. const saveAginClick = async ()=>{
  942. const rows = tableCheckedKeys.value
  943. const taskIds = rows.map(row => row.taskId)
  944. if (taskIds.some(id => id)) {
  945. window.$message?.warning('存在taskId,不能点击该按钮')
  946. return
  947. }
  948. const objArr = rows.map(row => ({
  949. id: row.id,
  950. wbsId: row.wbsId,
  951. projectId: projectId.value,
  952. contractId: contractId.value,
  953. }))
  954. saveAginLoading.value = true
  955. const { error, code, msg } = await queryApi.reSigningEVisaStatus0(objArr)
  956. //处理数据
  957. saveAginLoading.value = false
  958. if (!error && code === 200) {
  959. window.$message?.success(msg ?? '提交成功,请请耐心等待重签,可继续操作其它的功能。')
  960. getTableData().then()
  961. } else {
  962. window.$message?.error(msg ?? '操作失败')
  963. }
  964. }
  965. const saveAginLoading = ref(false)
  966. </script>
  967. <style lang="scss" scoped>
  968. @import "../../styles/data-fill/query.scss";
  969. .iscusor {
  970. cursor: pointer;
  971. }
  972. </style>
  973. <style lang="scss">
  974. .hc-online-verify-drawer .el-card.hc-new-card-box {
  975. .hc-card-header-box {
  976. .online-verify-title {
  977. font-size: 20px;
  978. }
  979. .online-verify-icon {
  980. display: flex;
  981. align-items: center;
  982. cursor: pointer;
  983. color: #5a5959;
  984. i {
  985. font-size: 18px;
  986. }
  987. &:hover {
  988. color: var(--el-color-primary);
  989. }
  990. }
  991. }
  992. }
  993. </style>