project-scanning.vue 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. <template>
  2. <div class="hc-layout-box">
  3. <div :style="`width:${leftWidth}px;`" class="hc-layout-left-box">
  4. <div class="hc-project-box">
  5. <div class="hc-project-icon-box">
  6. <HcIcon name="stack" />
  7. </div>
  8. <div class="ml-2 project-name-box">
  9. <span class="text-xl text-cut project-alias">{{ projectInfo.projectAlias }}</span>
  10. <div class="text-xs text-cut project-name">{{ projectInfo.name }}</div>
  11. </div>
  12. </div>
  13. <div class="hc-tree-box">
  14. <el-scrollbar>
  15. <ProjectTree :auto-expand-keys="TreeAutoExpandKeys" :datas="ElTreeData" @nodeTap="nodeElTreeClick" />
  16. </el-scrollbar>
  17. </div>
  18. <!-- 左右拖动 -->
  19. <div class="horizontal-drag-line" @mousedown="onmousedown" />
  20. </div>
  21. <div class="hc-layout-content-box">
  22. <HcCard :scrollbar="false" action-size="lg">
  23. <template #header>
  24. <HcTooltip keys="project-scanning-upload">
  25. <el-button :disabled="!nodeIds" hc-btn type="primary" @click="uploadModalClick">
  26. <HcIcon name="add-circle" />
  27. <span>上传文件</span>
  28. </el-button>
  29. </HcTooltip>
  30. <HcTooltip keys="project-scanning-download">
  31. <el-button
  32. :disabled="tableCheckedKeys.length <= 0" :loading="batchDownloadLoading" hc-btn
  33. @click="batchDownload"
  34. >
  35. <HcIcon name="download" />
  36. <span>批量下载</span>
  37. </el-button>
  38. </HcTooltip>
  39. <HcTooltip keys="project-scanning-report">
  40. <el-button
  41. :disabled="tableCheckedKeys.length <= 0" :loading="reportLoading" hc-btn
  42. @click="reportModalClick"
  43. >
  44. <HcIcon name="send-plane-2" />
  45. <span>批量上报</span>
  46. </el-button>
  47. </HcTooltip>
  48. <HcTooltip keys="project-scanning-attest">
  49. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn @click="certificationModalClick">
  50. <HcIcon name="vip-diamond" />
  51. <span>批量认证</span>
  52. </el-button>
  53. </HcTooltip>
  54. <HcTooltip keys="project-scanning-del">
  55. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn @click="batchDel">
  56. <HcIcon name="delete-bin-2" />
  57. <span>批量删除</span>
  58. </el-button>
  59. </HcTooltip>
  60. <HcTooltip keys="project-scanning-edit">
  61. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn @click="batchEditClick">
  62. <HcIcon name="draft" />
  63. <span>批量编辑</span>
  64. </el-button>
  65. </HcTooltip>
  66. <HcTooltip keys="project-scanning-abolish">
  67. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn @click="batchAbolishClick">
  68. <HcIcon name="delete-bin-3" />
  69. <span>批量废除</span>
  70. </el-button>
  71. </HcTooltip>
  72. </template>
  73. <template #search>
  74. <div class="w-32">
  75. <el-select v-model="searchForm.isApprovalValue" clearable placeholder="审批状态">
  76. <el-option
  77. v-for="item in approvalData" :label="item.dictValue"
  78. :value="item.dictKey"
  79. />
  80. </el-select>
  81. </div>
  82. <div class="w-32 ml-4">
  83. <el-select v-model="searchForm.isCertificationValue" clearable placeholder="认证状态">
  84. <el-option
  85. v-for="item in certificationType" :label="item.dictValue"
  86. :value="item.dictKey"
  87. />
  88. </el-select>
  89. </div>
  90. <div class="w-64 ml-3">
  91. <el-input
  92. v-model="searchForm.queryValue" clearable placeholder="请输入文件名、责任者进行搜索"
  93. @keyup="keyUpEvent"
  94. />
  95. </div>
  96. <div class="ml-2">
  97. <el-button type="primary" @click="searchClick">
  98. <HcIcon name="search-2" />
  99. <span>搜索</span>
  100. </el-button>
  101. </div>
  102. </template>
  103. <HcTable
  104. ref="tableListRef" :column="tableListColumn" :datas="tableListData" :loading="tableLoading"
  105. is-check @selection-change="tableSelectionChange"
  106. >
  107. <template #fileName="{ row }">
  108. <span class="text-link" @click="tablePreview(row)">{{ row?.fileName }}</span>
  109. </template>
  110. <template #isApprovalValue="{ row }">
  111. <el-tag
  112. v-if="row.isApprovalValue"
  113. :type="`${row.status === 2 ? 'success' : row.status === 0 ? 'warning' : row.status === 1 ? 'danger' : 'info'}`"
  114. class="mx-1" effect="dark"
  115. >
  116. {{ row.isApprovalValue }}
  117. </el-tag>
  118. </template>
  119. </HcTable>
  120. <template #action>
  121. <HcPages :pages="searchForm" @change="pageChange" />
  122. </template>
  123. </HcCard>
  124. </div>
  125. <!-- 新增编辑文件 -->
  126. <el-dialog v-model="showUploadModal" class="hc-modal-border hc-modal-table" title="上传工程文件" width="80vw">
  127. <HcTable
  128. :column="tableUploadColumn" :datas="tableUploadData" :loading="uploadSaveLoading"
  129. ui="hc-form-table"
  130. >
  131. <template #fileNumber="{ row }">
  132. <el-input
  133. v-model="row.fileNumber" :class="row.isFileNumber ? 'is-error' : ''"
  134. @input="tableInput($event, row, 'isFileNumber')"
  135. />
  136. </template>
  137. <template #fileName="{ row }">
  138. <el-input
  139. v-model="row.fileName" :class="row.isFileName ? 'is-error' : ''"
  140. @input="tableInput($event, row, 'isFileName')"
  141. />
  142. </template>
  143. <template #fileTime="{ row }">
  144. <el-date-picker
  145. v-model="row.fileTime" :clearable="false" format="YYYY/MM/DD" type="date"
  146. value-format="YYYY-MM-DD"
  147. />
  148. </template>
  149. <template v-if="isBuiltDrawing === 1" #sheetType="{ row }">
  150. <el-select v-model="row.sheetType">
  151. <el-option
  152. v-for="item in sheetType" :key="item.dictKey" :label="item.dictValue"
  153. :value="item.dictKey"
  154. />
  155. </el-select>
  156. </template>
  157. <template v-if="isBuiltDrawing === 1" #sheetSource="{ row }">
  158. <el-select v-model="row.sheetSource">
  159. <el-option
  160. v-for="item in sheetSourceType" :key="item.dictKey" :label="item.dictValue"
  161. :value="item.dictKey"
  162. />
  163. </el-select>
  164. </template>
  165. <template v-if="isBuiltDrawing === 1" #drawingNo="{ row }">
  166. <el-input v-model="row.drawingNo" />
  167. </template>
  168. <template v-if="isBuiltDrawing === 1" #citeChangeNumber="{ row }">
  169. <el-input v-model="row.citeChangeNumber" />
  170. </template>
  171. <template #isApproval="{ row }">
  172. <el-select v-model="row.isApproval">
  173. <el-option
  174. v-for="item in whetherData" :key="item.value" :label="item.label"
  175. :value="item.value"
  176. />
  177. </el-select>
  178. </template>
  179. <template #isNeedCertification="{ row }">
  180. <el-select v-model="row.isNeedCertification">
  181. <el-option
  182. v-for="item in whetherData" :key="item.value" :label="item.label"
  183. :value="item.value"
  184. />
  185. </el-select>
  186. </template>
  187. <template #dutyUser="{ row }">
  188. <el-input v-model="row.dutyUser" />
  189. </template>
  190. <template #action="{ row, index }">
  191. <HcFileUpload1
  192. v-if="row.id" @change="newUploadsChange($event, row)"
  193. @progress="newUploadsProgress($event, row)"
  194. >
  195. <el-button :loading="row.newBtnLoading" plain size="small" type="primary">
  196. 上传新文件
  197. </el-button>
  198. </HcFileUpload1>
  199. <el-button
  200. :loading="row.delBtnLoading" plain size="small" type="danger"
  201. @click="delUploadData(row, index)"
  202. >
  203. 删除
  204. </el-button>
  205. </template>
  206. </HcTable>
  207. <template #footer>
  208. <div class="lr-dialog-footer">
  209. <div class="left flex items-center">
  210. <HcFileUpload @change="uploadsChange" @progress="uploadsProgress">
  211. <el-button :disabled="uploadSaveLoading" :loading="uploadsLoading" hc-btn type="primary">
  212. <HcIcon name="add-circle" />
  213. <span>新增上传</span>
  214. </el-button>
  215. </HcFileUpload>
  216. </div>
  217. <div class="right">
  218. <el-button size="large" @click="batchUploadCancel">
  219. <HcIcon name="close" />
  220. <span>取消</span>
  221. </el-button>
  222. <el-button
  223. :disabled="uploadsLoading" :loading="uploadSaveLoading" hc-btn type="primary"
  224. @click="batchUploadSave"
  225. >
  226. <HcIcon name="save" />
  227. <span>提交保存</span>
  228. </el-button>
  229. </div>
  230. </div>
  231. </template>
  232. </el-dialog>
  233. <!-- 批量上报审批 -->
  234. <HcReportModal
  235. :contract-id="contractId"
  236. :datas="reportDatas"
  237. :ids="reportIds"
  238. :project-id="projectId"
  239. :show="showReportModal"
  240. :task-name="reportTaskName"
  241. is-datas
  242. title="批量上报审批"
  243. url="archiveFile/batchApproval2"
  244. @finish="showReportFinish"
  245. @hide="showReportModal = false"
  246. @tagClose="reportTaskTagClose"
  247. />
  248. <!-- 批量认证 -->
  249. <el-dialog
  250. v-model="showCertificationModal" class="hc-modal-border hc-modal-table" title="批量认证"
  251. width="80vw"
  252. >
  253. <div class="hc-card-body-flex">
  254. <div class="flex-table">
  255. <HcTable :column="CertColumns" :datas="CertData" ui="hc-form-table" @row-click="CertRowClick">
  256. <template #action="{ row, index }">
  257. <el-button plain size="small" type="primary" @click.stop="CertRowClick2(row)">
  258. 预览
  259. </el-button>
  260. </template>
  261. </HcTable>
  262. </div>
  263. <div v-if="CertPdf" class="flex-iframe">
  264. <iframe :src="CertPdf" allow="display-capture" frameborder="1" height="100%" width="100%" />
  265. </div>
  266. <div v-else class="flex-iframe hc-no-table-form">
  267. <div class="table-form-no">
  268. <img :src="notableform" alt="">
  269. <div class="desc">暂无 PDF 数据</div>
  270. </div>
  271. </div>
  272. </div>
  273. <template #footer>
  274. <div class="dialog-footer">
  275. <el-button size="large" @click="showCertificationModal = false">
  276. <HcIcon name="close" />
  277. <span>取消</span>
  278. </el-button>
  279. <el-button :loading="CertLoading" hc-btn type="primary" @click="CertClick">
  280. <HcIcon name="save" />
  281. <span>确认认证</span>
  282. </el-button>
  283. </div>
  284. </template>
  285. </el-dialog>
  286. </div>
  287. </template>
  288. <script setup>
  289. import { onMounted, ref, watch } from 'vue'
  290. import { useAppStore } from '~src/store'
  291. import { useRoute, useRouter } from 'vue-router'
  292. import ProjectTree from './components/ProjectTree.vue'
  293. import HcFileUpload from './components/HcFileUpload.vue'
  294. import HcFileUpload1 from './components/HcFileUpload1.vue'
  295. import { getStoreValue, setStoreValue } from '~src/utils/storage'
  296. import projectScanningApi from '~api/other-file/projectScanning'
  297. import notableform from '~src/assets/view/notableform.svg'
  298. import { arrToId, deepClone, downloadBlob, getArrValue } from 'js-fast-way'
  299. import { eVisaTaskCheckApi } from '~api/other'
  300. import tasksDataApi from '~api/tasks/data'
  301. import ossApi from '~api/oss'
  302. import dayjs from 'dayjs'
  303. import { delMessageV2 } from '~com/message/index.js'
  304. //变量
  305. const router = useRouter()
  306. const useRoutes = useRoute()
  307. const useAppState = useAppStore()
  308. const projectId = ref(useAppState.getProjectId)
  309. const contractId = ref(useAppState.getContractId)
  310. const projectInfo = ref(useAppState.getProjectInfo)
  311. const isCollapse = ref(useAppState.getCollapse)
  312. //监听
  313. watch(() => [
  314. useAppState.getCollapse,
  315. ], ([Collapse]) => {
  316. isCollapse.value = Collapse
  317. })
  318. //自动展开缓存
  319. const TreeAutoExpandKeys = ref(getStoreValue('scanningTreeExpandKeys') || [])
  320. const dayDate = ref('')
  321. //渲染完成
  322. onMounted(() => {
  323. getClassIfyList()
  324. firstTaskStatus()
  325. certificationStatus()
  326. dayDate.value = dayjs(new Date()).format('YYYY-MM-DD')
  327. })
  328. //获取树的数据
  329. const ElTreeData = ref([])
  330. const getClassIfyList = async () => {
  331. const { error, code, data } = await projectScanningApi.getClassIfyList({
  332. projectId: projectId.value,
  333. contractId: contractId.value,
  334. })
  335. //处理数据
  336. if (!error && code === 200) {
  337. ElTreeData.value = getArrValue(data)
  338. } else {
  339. ElTreeData.value = []
  340. }
  341. }
  342. //项目树被点击
  343. const treeNodeInfo = ref({})
  344. const treeDataInfo = ref({})
  345. const nodeIds = ref('')
  346. const isStorageNode = ref(0)
  347. const isBuiltDrawing = ref(0)
  348. const nodeElTreeClick = ({ node, data, keys, key }) => {
  349. treeNodeInfo.value = node
  350. treeDataInfo.value = data
  351. //设置变量
  352. nodeIds.value = key || ''
  353. isStorageNode.value = data['isStorageNode'] || 0
  354. isBuiltDrawing.value = data['isBuiltDrawing'] || 0
  355. //设置搜索数据
  356. searchForm.value.current = 1
  357. searchForm.value.nodeIds = key || ''
  358. setTableColumns()
  359. getTableData()
  360. //缓存展开的节点
  361. setStoreValue('scanningTreeExpandKeys', keys)
  362. }
  363. //获取任务类型
  364. const approvalData = ref([])
  365. const firstTaskStatus = async () => {
  366. const { error, code, data } = await tasksDataApi.queryTaskTypeStatus({
  367. typeOrStatus: 'first_task_status',
  368. })
  369. //处理数据
  370. if (!error && code === 200) {
  371. approvalData.value = getArrValue(data)
  372. } else {
  373. approvalData.value = []
  374. }
  375. }
  376. //获取认证状态
  377. const certificationType = ref([])
  378. const certificationStatus = async () => {
  379. const { error, code, data } = await tasksDataApi.queryTaskTypeStatus({
  380. typeOrStatus: 'certification_status',
  381. })
  382. //处理数据
  383. if (!error && code === 200) {
  384. certificationType.value = getArrValue(data)
  385. } else {
  386. certificationType.value = []
  387. }
  388. }
  389. //获取图幅类型
  390. const sheetType = ref([])
  391. const sheetTypeStatus = async () => {
  392. const { error, code, data } = await tasksDataApi.queryTaskTypeStatus({
  393. typeOrStatus: 'sheet_type',
  394. })
  395. //处理数据
  396. if (!error && code === 200) {
  397. sheetType.value = getArrValue(data)
  398. } else {
  399. sheetType.value = []
  400. }
  401. }
  402. //获取图表来源
  403. const sheetSourceType = ref([])
  404. const sheetSourceStatus = async () => {
  405. const { error, code, data } = await tasksDataApi.queryTaskTypeStatus({
  406. typeOrStatus: 'sheet_source',
  407. })
  408. //处理数据
  409. if (!error && code === 200) {
  410. sheetSourceType.value = getArrValue(data)
  411. } else {
  412. sheetSourceType.value = []
  413. }
  414. }
  415. //搜索表单
  416. const searchForm = ref({
  417. nodeIds: '', isApprovalValue: null, isCertificationValue: null, queryValue: null,
  418. current: 1, size: 20, total: 0,
  419. })
  420. //回车搜索
  421. const keyUpEvent = (e) => {
  422. if (e.key === 'Enter') {
  423. searchClick()
  424. }
  425. }
  426. //搜索
  427. const searchClick = () => {
  428. if (nodeIds.value) {
  429. searchForm.value.current = 1
  430. getTableData()
  431. } else {
  432. window?.$message?.warning('请先在左边选择一个树节点')
  433. }
  434. }
  435. //分页被点击
  436. const pageChange = ({ current, size }) => {
  437. searchForm.value.current = current
  438. searchForm.value.size = size
  439. getTableData()
  440. }
  441. //设置表头
  442. const tableListColumn = ref([
  443. { key: 'fileNumber', name: '文件编号', width: 160 },
  444. { key: 'fileName', name: '文件名称' },
  445. { key: 'filePage', name: '文件页数', width: 120 },
  446. { key: 'isCertificationValue', name: '认证状态', width: 160 },
  447. { key: 'isApprovalValue', name: '状态', width: 160 },
  448. { key: 'fileTime', name: '文件时间', width: 160 },
  449. { key: 'dutyUser', name: '责任者', width: 160 },
  450. ])
  451. const setTableColumns = () => {
  452. if (isBuiltDrawing.value === 1) {
  453. tableListColumn.value = [
  454. { key: 'fileNumber', name: '文件编号', width: 160 },
  455. { key: 'fileName', name: '文件名称' },
  456. { key: 'filePage', name: '文件页数', width: 120 },
  457. { key: 'sheetType', name: '图幅' },
  458. { key: 'sheetSourceValue', name: '图表来源' },
  459. { key: 'drawingNo', name: '图号' },
  460. { key: 'citeChangeNumber', name: '引用变更令编号' },
  461. { key: 'isCertificationValue', name: '认证状态', width: 160 },
  462. { key: 'isApprovalValue', name: '状态', width: 160 },
  463. { key: 'fileTime', name: '文件时间', width: 160 },
  464. { key: 'dutyUser', name: '责任者', width: 160 },
  465. ]
  466. sheetTypeStatus()
  467. sheetSourceStatus()
  468. } else {
  469. tableListColumn.value = [
  470. { key: 'fileNumber', name: '文件编号', width: 160 },
  471. { key: 'fileName', name: '文件名称' },
  472. { key: 'filePage', name: '文件页数', width: 120 },
  473. { key: 'isCertificationValue', name: '认证状态', width: 160 },
  474. { key: 'isApprovalValue', name: '状态', width: 160 },
  475. { key: 'fileTime', name: '文件时间', width: 160 },
  476. { key: 'dutyUser', name: '责任者', width: 160 },
  477. ]
  478. }
  479. }
  480. //获取数据
  481. const tableLoading = ref(false)
  482. const tableListData = ref([])
  483. const getTableData = async () => {
  484. tableLoading.value = true
  485. const { error, code, data } = await projectScanningApi.getarchiveFilePage({
  486. ...searchForm.value,
  487. projectId: projectId.value,
  488. contractId: contractId.value,
  489. })
  490. //判断状态
  491. tableLoading.value = false
  492. if (!error && code === 200) {
  493. tableListData.value = getArrValue(data['records'])
  494. searchForm.value.total = data['total'] || 0
  495. } else {
  496. tableListData.value = []
  497. searchForm.value.total = 0
  498. }
  499. }
  500. //多选
  501. const tableListRef = ref(null)
  502. const tableCheckedKeys = ref([])
  503. const tableSelectionChange = (rows) => {
  504. tableCheckedKeys.value = rows.filter((item) => {
  505. return (item ?? '') !== ''
  506. })
  507. }
  508. //文件名称被点击
  509. const tablePreview = (row) => {
  510. const pdfUrl = row['pdfFileUrl'] || ''
  511. const evisaFile = row['evisaFile'] || ''
  512. if (evisaFile) {
  513. window.open(evisaFile, '_blank')
  514. } else if (pdfUrl) {
  515. window.open(pdfUrl, '_blank')
  516. } else {
  517. window.$message?.warning('该数据暂无PDF')
  518. }
  519. }
  520. //新增文件
  521. const tableUploadType = ref('add')
  522. const showUploadModal = ref(false)
  523. const uploadModalClick = () => {
  524. if (nodeIds.value && isStorageNode.value === 1) {
  525. tableUploadType.value = 'add'
  526. setTableUploadColumn()
  527. uploadSaveLoading.value = false
  528. tableUploadData.value = []
  529. showUploadModal.value = true
  530. } else {
  531. window?.$message?.warning('请先选择一个子节点')
  532. }
  533. }
  534. //设置文件表头
  535. const tableUploadColumn = ref([
  536. { key: 'fileNumber', name: '文件编号' },
  537. { key: 'fileName', name: '文件名称' },
  538. { key: 'fileTime', name: '文件时间' },
  539. { key: 'isApproval', name: '是否需要审批' },
  540. { key: 'isNeedCertification', name: '是否需要认证' },
  541. { key: 'dutyUser', name: '责任者' },
  542. { key: 'action', name: '操作', width: 180 },
  543. ])
  544. const setTableUploadColumn = () => {
  545. if (isBuiltDrawing.value === 1) {
  546. tableUploadColumn.value = [
  547. { key: 'fileNumber', name: '文件编号' },
  548. { key: 'fileName', name: '文件名称' },
  549. { key: 'fileTime', name: '文件时间' },
  550. { key: 'sheetType', name: '图幅' },
  551. { key: 'sheetSource', name: '图表来源' },
  552. { key: 'drawingNo', name: '图号' },
  553. { key: 'citeChangeNumber', name: '引用变更令编号' },
  554. { key: 'isApproval', name: '是否需要审批' },
  555. { key: 'isNeedCertification', name: '是否需要认证' },
  556. { key: 'dutyUser', name: '责任者' },
  557. { key: 'action', name: '操作', width: 180 },
  558. ]
  559. } else {
  560. tableUploadColumn.value = [
  561. { key: 'fileNumber', name: '文件编号' },
  562. { key: 'fileName', name: '文件名称' },
  563. { key: 'fileTime', name: '文件时间' },
  564. { key: 'isApproval', name: '是否需要审批' },
  565. { key: 'isNeedCertification', name: '是否需要认证' },
  566. { key: 'dutyUser', name: '责任者' },
  567. { key: 'action', name: '操作', width: 180 },
  568. ]
  569. }
  570. }
  571. const tableUploadData = ref([])
  572. //上传的文件结果
  573. const uploadsChange = ({ fileList }) => {
  574. let newArr = []
  575. const sheet = sheetType.value, source = sheetSourceType.value
  576. for (let i = 0; i < fileList.length; i++) {
  577. const item = fileList[i]
  578. let name = item['originalName'] || ''
  579. let fileName = name.substring(0, name.lastIndexOf('.'))
  580. newArr.push({
  581. projectId: projectId.value,
  582. contractId: contractId.value,
  583. nodeId: nodeIds.value,
  584. fileNumber: '',
  585. fileName: fileName,
  586. ossFileName: item?.name || '',
  587. fileTime: dayDate.value,
  588. fileUrl: item?.link || '',
  589. sheetType: sheet.length > 0 ? sheet[0]['dictKey'] || '' : '',
  590. sheetSource: source.length > 0 ? source[0]['dictKey'] || '' : '',
  591. drawingNo: '',
  592. citeChangeNumber: '',
  593. isApproval: 0,
  594. isNeedCertification: 0,
  595. dutyUser: '',
  596. pdfFileUrl: item?.pdfUrl || '',
  597. filePage: item?.page || '',
  598. })
  599. }
  600. tableUploadData.value = newArr
  601. }
  602. //上传进度
  603. const uploadsLoading = ref(false)
  604. const uploadsProgress = (val) => {
  605. uploadsLoading.value = val
  606. }
  607. //表单下拉数据
  608. const whetherData = ref([{ label: '不需要', value: 0 }, { label: '需要', value: 1 }])
  609. //输入框验证
  610. const tableInput = (val, row, isv) => {
  611. if (val) {
  612. row[isv] = false
  613. } else {
  614. row[isv] = true
  615. }
  616. }
  617. //上传新文件
  618. const newUploadsChange = ({ fileList }, row) => {
  619. if (fileList.length > 0) {
  620. const item = fileList[0]
  621. const name = item['originalName'] || ''
  622. const fileName = name.substring(0, name.lastIndexOf('.'))
  623. //更新数据
  624. row.fileName = fileName
  625. row.ossFileName = item?.name || ''
  626. row.fileUrl = item?.link || ''
  627. row.pdfFileUrl = item?.pdfUrl || ''
  628. row.filePage = item?.page || ''
  629. }
  630. }
  631. const newUploadsProgress = (val, row) => {
  632. row.newBtnLoading = val
  633. }
  634. //删除
  635. const delUploadData = async (row, index) => {
  636. if (row['ossFileName']) {
  637. row['delBtnLoading'] = true
  638. await ossApi.removeFile({ fileName: row['ossFileName'] })
  639. row['delBtnLoading'] = false
  640. tableUploadData.value.splice(index, 1)
  641. } else {
  642. tableUploadData.value.splice(index, 1)
  643. }
  644. }
  645. //批量上传保存
  646. const uploadSaveLoading = ref(false)
  647. const batchUploadSave = async () => {
  648. const rows = tableUploadData.value
  649. if (rows.length > 0) {
  650. //验证表单数据
  651. uploadSaveLoading.value = true
  652. let isTableRows = false
  653. for (let i = 0; i < rows.length; i++) {
  654. if (!rows[i]['fileNumber']) {
  655. rows[i]['isFileNumber'] = true
  656. isTableRows = true
  657. } else if (!rows[i]['fileName']) {
  658. rows[i]['isFileName'] = true
  659. isTableRows = true
  660. }
  661. }
  662. //判断数据
  663. if (isTableRows) {
  664. uploadSaveLoading.value = false
  665. window.$message?.warning('请先完善表单信息')
  666. } else {
  667. if (tableUploadType.value === 'add') {
  668. await batchUploadSaveApi(rows)
  669. } else {
  670. await batchEditSaveApi(rows)
  671. }
  672. }
  673. } else {
  674. window.$message?.warning('请先上传文件')
  675. }
  676. }
  677. //确认上传保存
  678. const batchUploadSaveApi = async (rows) => {
  679. uploadSaveLoading.value = true
  680. const { error, code } = await projectScanningApi.batchUploadSave({
  681. list: rows,
  682. }, false)
  683. //判断状态
  684. uploadSaveLoading.value = false
  685. if (!error && code === 200) {
  686. window.$message?.success('保存成功')
  687. batchUploadCancel()
  688. getTableData()
  689. } else {
  690. window.$message?.error('保存失败')
  691. }
  692. }
  693. //取消上传
  694. const batchUploadCancel = () => {
  695. tableUploadData.value = []
  696. uploadSaveLoading.value = false
  697. uploadsLoading.value = false
  698. showUploadModal.value = false
  699. }
  700. //批量编辑
  701. const batchEditClick = () => {
  702. const rows = deepClone(tableCheckedKeys.value)
  703. //判断是否满足条件
  704. const result = rows.every(({ status }) => {
  705. return status !== 1 && status !== 2
  706. })
  707. console.log(rows)
  708. //判断状态
  709. if (result) {
  710. tableUploadType.value = 'edit'
  711. setTableUploadColumn()
  712. uploadSaveLoading.value = false
  713. tableUploadData.value = rows
  714. showUploadModal.value = true
  715. } else {
  716. window.$message?.warning('已上报或已审批的文件不能编辑')
  717. }
  718. }
  719. //确认编辑上传保存
  720. const batchEditSaveApi = async (rows) => {
  721. uploadSaveLoading.value = true
  722. const { error, code } = await projectScanningApi.batchEditSave({
  723. list: rows,
  724. }, false)
  725. //判断状态
  726. uploadSaveLoading.value = false
  727. if (!error && code === 200) {
  728. window.$message?.success('保存成功')
  729. batchUploadCancel()
  730. getTableData()
  731. } else {
  732. window.$message?.error('保存失败')
  733. }
  734. }
  735. //批量下载
  736. const batchDownloadLoading = ref(false)
  737. const batchDownload = async () => {
  738. const rows = deepClone(tableCheckedKeys.value)
  739. const ids = arrToId(rows)
  740. //批量下载
  741. batchDownloadLoading.value = true
  742. const { error, disposition, res } = await projectScanningApi.batchDownloadFileToZip({ ids: ids })
  743. //处理数据
  744. batchDownloadLoading.value = false
  745. if (!error) {
  746. if (disposition) {
  747. downloadBlob(res, disposition)
  748. } else {
  749. window.$message?.error('数据异常')
  750. }
  751. }
  752. }
  753. //批量上报
  754. const reportIds = ref('')
  755. const reportTaskName = ref('')
  756. const reportDatas = ref([])
  757. const showReportModal = ref(false)
  758. const reportLoading = ref(false)
  759. const reportModalClick = async () => {
  760. const rows = tableCheckedKeys.value
  761. const result = rows.every(({ status }) => {
  762. return status === 0 //isApproval !== 1 && status !== 0 || isApproval === 1 && status !== 0
  763. })
  764. if (result) {
  765. reportLoading.value = true
  766. const taskCheck = await eVisaTaskCheckApi({
  767. projectId: projectId.value,
  768. contractId: contractId.value,
  769. })
  770. if (taskCheck) {
  771. reportIds.value = arrToId(rows)
  772. //设置任务数据
  773. let reportDataArr = []
  774. rows.forEach(item => {
  775. reportDataArr.push({
  776. id: item?.id,
  777. name: item?.fileName,
  778. })
  779. })
  780. reportDatas.value = reportDataArr
  781. //设置任务名称
  782. reportTaskName.value = rows.length > 1 ? `${rows[0].fileName}等${rows.length}个文件` : rows[0].fileName
  783. reportLoading.value = false
  784. showReportModal.value = true
  785. } else {
  786. reportLoading.value = false
  787. }
  788. } else {
  789. window.$message?.warning('已上报的文件不能进行再次上报,若要重新上报,要先撤回之前的上报,再重新上报')
  790. }
  791. }
  792. //上报的审批内容移除
  793. const reportTaskTagClose = (index) => {
  794. const row = tableCheckedKeys.value[index]
  795. tableListRef.value?.toggleRowSelection(row, false)
  796. }
  797. //上报完成
  798. const showReportFinish = () => {
  799. showReportModal.value = false
  800. getTableData()
  801. }
  802. //批量认证
  803. const CertData = ref([])
  804. const CertIds = ref([])
  805. const CertPdf = ref('')
  806. const CertColumns = [
  807. { key: 'fileName', name: '文件名称' },
  808. { key: 'action', name: '操作', width: 100 },
  809. ]
  810. //批量认证弹窗
  811. const showCertificationModal = ref(false)
  812. const certificationModalClick = () => {
  813. const rows = tableCheckedKeys.value
  814. const result = rows.every(({ isCertification }) => {
  815. return isCertification === 0
  816. })
  817. if (result) {
  818. CertData.value = rows
  819. CertIds.value = arrToId(rows)
  820. CertPdf.value = rows[0]?.pdfFileUrl || ''
  821. showCertificationModal.value = true
  822. } else {
  823. window.$message?.warning('已认证的文件不能再认证')
  824. }
  825. }
  826. //认证行被点击
  827. const CertRowClick = ({ row }) => {
  828. const pdfFileUrl = row?.pdfFileUrl || ''
  829. if (CertPdf.value !== pdfFileUrl) {
  830. CertPdf.value = pdfFileUrl
  831. }
  832. }
  833. //认证预览被点击
  834. const CertRowClick2 = ({ pdfFileUrl }) => {
  835. const pdfUrl = pdfFileUrl || ''
  836. if (CertPdf.value !== pdfUrl) {
  837. CertPdf.value = pdfUrl
  838. }
  839. }
  840. //确认认证
  841. const CertLoading = ref(false)
  842. const CertClick = async () => {
  843. CertLoading.value = true
  844. const { error, code } = await projectScanningApi.batchCertification({
  845. ids: CertIds.value.split(','),
  846. }, false)
  847. //判断状态
  848. CertLoading.value = false
  849. if (!error && code === 200) {
  850. window.$message?.success('认证成功')
  851. showCertificationModal.value = false
  852. getTableData()
  853. } else {
  854. window.$message?.error('认证失败')
  855. }
  856. }
  857. //批量删除
  858. const batchDel = () => {
  859. const rows = tableCheckedKeys.value
  860. const result = rows.every(({ status }) => {
  861. return status === 0
  862. })
  863. if (result) {
  864. const ids = arrToId(rows)
  865. delMessageV2(async (action, instance, done) => {
  866. if (action === 'confirm') {
  867. instance.confirmButtonLoading = true
  868. removeArchiveFile(ids)
  869. instance.confirmButtonLoading = false
  870. done()
  871. } else {
  872. done()
  873. }
  874. })
  875. } else {
  876. window.$message?.warning('已上报的文件需要先废除,才能执行删除')
  877. }
  878. }
  879. //确认批量删除
  880. const removeArchiveFile = async (ids) => {
  881. const { error, code } = await projectScanningApi.removeArchiveFile({
  882. ids: ids,
  883. }, false)
  884. //判断状态
  885. CertLoading.value = false
  886. if (!error && code === 200) {
  887. window.$message?.success('删除成功')
  888. getTableData()
  889. } else {
  890. window.$message?.error('删除失败')
  891. }
  892. }
  893. //批量废除
  894. const batchAbolishClick = () => {
  895. const rows = tableCheckedKeys.value
  896. const result = rows.every(({ status }) => {
  897. return status > 0
  898. })
  899. if (result) {
  900. const ids = arrToId(rows)
  901. window?.$messageBox?.alert('是否废除勾选的已上报文件?', '确认操作', {
  902. type: 'warning',
  903. showCancelButton: true,
  904. confirmButtonText: '确定废除',
  905. cancelButtonText: '取消',
  906. callback: (action) => {
  907. if (action === 'confirm') {
  908. batchAbolishSave(ids)
  909. }
  910. },
  911. })
  912. } else {
  913. window.$message?.warning('未上报的文件不能废除')
  914. }
  915. }
  916. //确认批量废除
  917. const batchAbolishSave = async (ids) => {
  918. const { error, code } = await projectScanningApi.batchAbolishSave({
  919. ids: ids,
  920. }, false)
  921. //判断状态
  922. if (!error && code === 200) {
  923. window.$message?.success('批量废除成功')
  924. getTableData()
  925. } else {
  926. window.$message?.error('批量废除失败')
  927. }
  928. }
  929. //左右拖动,改变树形结构宽度
  930. const leftWidth = ref(382)
  931. const onmousedown = () => {
  932. const leftNum = isCollapse.value ? 142 : 272
  933. document.onmousemove = (ve) => {
  934. const diffVal = ve.clientX - leftNum
  935. if (diffVal >= 310 && diffVal <= 900) {
  936. leftWidth.value = diffVal
  937. }
  938. }
  939. document.onmouseup = () => {
  940. document.onmousemove = null
  941. document.onmouseup = null
  942. }
  943. }
  944. </script>
  945. <style lang="scss" scoped>
  946. @import '../../styles/other-file/project-scanning.scss';
  947. </style>
  948. <style lang="scss">
  949. .el-table td.el-table__cell .hc-file-upload-box {
  950. display: inline-block;
  951. margin-right: 12px;
  952. }
  953. </style>