query.vue 32 KB

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