query.vue 34 KB

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