collection.vue 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830
  1. <template>
  2. <hc-body :loading="!isAppLoading" :project-nmae="projectInfo?.name" class="hc-file-collection-page" split>
  3. <template #tree>
  4. <HcTree
  5. ref="treeRef" :auto-expand-keys="treeAutoExpandKeys" :contract-id="contractId" :menus="ElTreeMenu"
  6. :project-id="projectId"
  7. @node-tap="projectTreeClick" @node-loading="treeNodeLoading" @menu-tap="ElTreeMenuClick"
  8. />
  9. </template>
  10. <hc-new-card>
  11. <template #header>
  12. <HcTooltip keys="file_collection_btn_upload_scanned_files">
  13. <el-button hc-btn type="primary" @click="uploadModalClick">上传扫描文件</el-button>
  14. </HcTooltip>
  15. <HcTooltip keys="file_collection_btn_sorting">
  16. <el-button hc-btn type="success" @click="sortingClick">分盒整理</el-button>
  17. </HcTooltip>
  18. <HcTooltip keys="file_collection_btn_download">
  19. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn>下载</el-button>
  20. </HcTooltip>
  21. <HcTooltip keys="file_collection_btn_certified">
  22. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn @click="certificationModalClick">认证</el-button>
  23. </HcTooltip>
  24. <HcTooltip keys="file_collection_btn_report">
  25. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn type="warning" @click="reportModalClick">上报</el-button>
  26. </HcTooltip>
  27. <HcTooltip keys="file_collection_btn_edit">
  28. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn @click="batchEditClick">编辑</el-button>
  29. </HcTooltip>
  30. <HcTooltip keys="file_collection_btn_repeal">
  31. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn @click="repealModalClick">废除</el-button>
  32. </HcTooltip>
  33. <HcTooltip keys="file_collection_btn_del">
  34. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn type="danger" @click="delModalClick">删除</el-button>
  35. </HcTooltip>
  36. <el-button :disabled="tableCheckedKeys.length <= 0" :loading="onlineLoading" color="#e03997" hc-btn @click="batchOnline">在线验签</el-button>
  37. </template>
  38. <template #extra>
  39. <HcTooltip keys="file_collection_btn_moves">
  40. <el-button color="#626aef" hc-btn @click="movesClick">跨目录移动</el-button>
  41. </HcTooltip>
  42. </template>
  43. <template #search>
  44. <div class="w-40">
  45. <el-select v-model="searchForm.isApprovalValue" clearable placeholder="审批状态">
  46. <el-option v-for="item in approvalStatus" :key="item.value" :label="item.label" :value="item.value" />
  47. </el-select>
  48. </div>
  49. <div class="ml-2 w-40">
  50. <el-select v-model="searchForm.isCertificationValue" clearable placeholder="认证状态">
  51. <el-option v-for="item in certifiedStatus" :key="item.value" :label="item.label" :value="item.value" />
  52. </el-select>
  53. </div>
  54. <div class="ml-2 w-64">
  55. <el-input v-model="searchForm.queryValue" clearable placeholder="请输入名称关键词检索" @keyup="keyUpEvent" />
  56. </div>
  57. <div class="ml-2">
  58. <el-button type="primary" @click="searchClick">搜索</el-button>
  59. </div>
  60. </template>
  61. <HcTable
  62. ref="tableRef" :check-style="{ width: 29 }" :column="tableColumn" :datas="tableData"
  63. :index-style="{ width: 80 }" :loading="tableLoading" is-check is-new
  64. @selection-change="tableSelection"
  65. >
  66. <template #table-column-header-num>
  67. <HcTooltip keys="file_collection_btn_sort">
  68. <span class="text-link text-lg" @click="tableSortClick">
  69. <HcIcon name="arrow-up-down" />
  70. </span>
  71. </HcTooltip>
  72. </template>
  73. <template #isApprovalValue="{ row }">
  74. <el-tag v-if="row?.isApprovalValue" :type="`${row.isApprovalValue === '已审批' ? 'success' : row.isApprovalValue === '待审批' ? 'warning' : row.isApprovalValue === '已废除' ? 'danger' : 'info'}`" class="mx-1" effect="dark">
  75. {{ row.isApprovalValue }}
  76. </el-tag>
  77. </template>
  78. <template #fileName="{ row }">
  79. <span class="text-link" @click="tableRowName(row)">{{ row?.fileName }}</span>
  80. </template>
  81. <template #sourceType="{ row }">
  82. <span>{{ row?.sourceType === 1 ? '原生' : '数字化' }}</span>
  83. </template>
  84. <template #fileTime="{ row }">
  85. <span>{{ getTableFileTime(row.fileTime) }}</span>
  86. </template>
  87. </HcTable>
  88. <template #action>
  89. <div class="lr-dialog-footer h-full">
  90. <div class="left hc-flex h-full text-14px">
  91. <span class="text">当前页的文件总页数:</span>
  92. <span>{{ fileTotalPage || 0 }}</span>
  93. </div>
  94. <div class="right">
  95. <HcPages :pages="searchForm" :sizes="[20, 50, 100, 200, 300, 500]" @change="pageChange" />
  96. </div>
  97. </div>
  98. </template>
  99. </hc-new-card>
  100. <!-- 预组卷整理 -->
  101. <hc-new-dialog v-model="sortingModal" is-row-footer is-table title="预组卷整理" widths="850px" @close="sortingModalClose">
  102. <div class="hc-sorting-modal-collapse">
  103. <el-collapse v-model="sortingActiveKey">
  104. <template v-for="(item, index) in sortingItemData" :key="index">
  105. <el-collapse-item :id="`item-${index}`" :name="`item-${index}`" disabled>
  106. <template #title>
  107. <div class="hc-collapse-item-header">
  108. <div class="item-index">盒{{ index + 1 }}</div>
  109. <el-divider direction="vertical" />
  110. <div class="item-input">
  111. <el-input
  112. v-model="item.boxName" :class="item.isName ? 'is-error' : ''"
  113. placeholder="请输入案卷题名"
  114. @change="tableIsInput($event, item, 'isName')"
  115. @input="tableIsInput($event, item, 'isName')"
  116. />
  117. </div>
  118. <el-divider direction="vertical" />
  119. <div class="item-action">
  120. <el-button type="primary" @click="sortingSelectFile(item, index)">选择文件</el-button>
  121. <el-button type="danger" @click="sortingDelData(item, index)">删除</el-button>
  122. </div>
  123. </div>
  124. </template>
  125. <HcTable
  126. ref="sorTableRef" :check-style="{ width: 29 }" :column="sortingTableColumn" :datas="item.list"
  127. :index-style="{ width: 60 }" :loading="sortingTableLoading" is-check is-new
  128. @selection-change="rows => sortingTableSelection(rows, item.list, index)"
  129. @single-select="singleCheck"
  130. >
  131. <template #name="{ row }">
  132. <span class="text-link">{{ row?.fileName }}</span>
  133. </template>
  134. </HcTable>
  135. </el-collapse-item>
  136. </template>
  137. </el-collapse>
  138. </div>
  139. <template #leftRowFooter>
  140. <el-button hc-btn type="primary" @click="addSortingModalClick">
  141. <HcIcon name="add" />
  142. <span>添加分盒</span>
  143. </el-button>
  144. </template>
  145. <template #rightRowFooter>
  146. <el-button hc-btn @click="sortingModalClose">
  147. <HcIcon name="close" />
  148. <span>取消</span>
  149. </el-button>
  150. <el-button :loading="sortingModalLoading" hc-btn type="primary" @click="sortingModalSave">
  151. <HcIcon name="check" />
  152. <span>确认</span>
  153. </el-button>
  154. </template>
  155. </hc-new-dialog>
  156. <!-- 预组卷整理 无数据 -->
  157. <hc-new-dialog v-model="sortingNoneModal" is-row-footer is-table title="预组卷整理" widths="850px" @close="sortingNoneModalClose">
  158. <div class="flex-center">
  159. <i class="el-icon" data-v-029747aa="" style="font-size: 200px;color:#81b337;cursor: pointer;" @click="toSortingModal">
  160. <svg data-v-029747aa="" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
  161. <path d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm-38.4 409.6H326.4a38.4 38.4 0 1 0 0 76.8h147.2v147.2a38.4 38.4 0 0 0 76.8 0V550.4h147.2a38.4 38.4 0 0 0 0-76.8H550.4V326.4a38.4 38.4 0 1 0-76.8 0v147.2z" fill="currentColor" />
  162. </svg>
  163. </i>
  164. <span>添加分盒</span>
  165. </div>
  166. </hc-new-dialog>
  167. <!-- 跨目录移动 -->
  168. <hc-new-dialog v-model="movesModal" :loading="movesModalLoading" is-table title="跨目录移动" widths="990px" @close="movesModalClose" @save="movesModalSave">
  169. <div class="hc-moves-transfer-box">
  170. <div class="hc-moves-transfer-panel">
  171. <div class="panel-header">
  172. <div class="panel-header-label">
  173. <el-checkbox v-model="movesCheckAll" :indeterminate="isIndeterminate" class="space size-xl" @change="handleCheckAllChange">
  174. 选择需要迁移的文件
  175. </el-checkbox>
  176. </div>
  177. <div class="panel-header-extra">{{ checkedMoves.length }}/{{ fileDatasList.length }}</div>
  178. </div>
  179. <div class="panel-body">
  180. <el-scrollbar v-loading="fileDatasListLoading">
  181. <el-checkbox-group v-model="checkedMoves" @change="handleCheckedMovesChange">
  182. <!-- <div v-for="item in fileDatasList" :key="item.id" class="hc-file-checkbox">
  183. <el-checkbox class="size-xl space" :label="item">
  184. {{ item.fileName }}
  185. </el-checkbox>
  186. </div> -->
  187. <recycle-scroller
  188. :buffer="1000" :item-size="110" :items="fileDatasList"
  189. :prerender="200" class="virtual-list" key-field="id"
  190. style="height: 900px"
  191. >
  192. <template #default="{ item, index }">
  193. <div :key="index">
  194. <el-checkbox :value="item" class="space mt-5 size-xl">{{ item.fileName }}</el-checkbox>
  195. </div>
  196. </template>
  197. </recycle-scroller>
  198. </el-checkbox-group>
  199. </el-scrollbar>
  200. </div>
  201. </div>
  202. <div class="hc-moves-transfer-buttons">
  203. <HcIcon name="arrow-right-double" style="font-size: 22px;" type="primary" />
  204. </div>
  205. <div class="hc-moves-transfer-panel">
  206. <div class="panel-header">选择移动目录</div>
  207. <div v-loading="treePanelLoading" class="panel-body">
  208. <el-scrollbar>
  209. <HcTree
  210. :contract-id="contractId" :is-show-menu="false" :project-id="projectId"
  211. :show-radio-fun="showRadioFun" id-prefix="hc-tree-moves-" is-radio
  212. @radio-change="radioChange" @node-loading="panelTreeLoading"
  213. />
  214. </el-scrollbar>
  215. </div>
  216. </div>
  217. </div>
  218. </hc-new-dialog>
  219. <!-- 调整排序 -->
  220. <hc-new-dialog v-model="sortModal" is-row-footer is-table title="调整排序" widths="80vw" @close="sortModalClose">
  221. <el-alert :closable="false" title="可拖动排序,也可在后面点击图标,切换排序" type="error" />
  222. <div class="hc-table-h">
  223. <HcTable
  224. :column="sortTableColumn" :datas="sortTableData" :index-style="{ width: 80 }"
  225. :loading="sortTableLoading"
  226. is-new is-row-drop quick-sort ui="hc-table-row-drop"
  227. @row-drop="sortTableRowDrop" @row-sort="sortTableRowDrop"
  228. >
  229. <template #action="{ index }">
  230. <span class="text-link text-xl" @click="upSortClick(index)">
  231. <HcIcon fill name="arrow-up" />
  232. </span>
  233. <span class="text-link ml-2 text-xl" @click="downSortClick(index)">
  234. <HcIcon fill name="arrow-down" />
  235. </span>
  236. </template>
  237. </HcTable>
  238. </div>
  239. <template #leftRowFooter>
  240. <el-button hc-btn @click="sortModalClose">
  241. <HcIcon name="close" />
  242. <span>取消</span>
  243. </el-button>
  244. <el-button :loading="sortModalLoading" hc-btn type="primary" @click="sortModalSave">
  245. <HcIcon name="check" />
  246. <span>确认</span>
  247. </el-button>
  248. </template>
  249. <template #rightRowFooter>
  250. <HcPages :pages="sortSearchForm" :sizes="[10, 20, 50, 100, 200, 300, 400, 500, 600]" @change="sortPageChange" />
  251. </template>
  252. </hc-new-dialog>
  253. <!-- 新增编辑文件 -->
  254. <hc-new-dialog v-model="showUploadModal" is-table title="上传工程文件" widths="90vw" @close="uploadModalClose">
  255. <HcTable
  256. :column="tableUploadColumn" :datas="tableUploadData" :index-style="{ width: 80 }"
  257. :loading="uploadSaveLoading"
  258. is-new is-sort ui="hc-form-table" @row-sort="tableUploadRowSort"
  259. >
  260. <template #fileNumber="{ row }">
  261. <!-- <el-input v-model="row.fileNumber" :class="row['isFileNumber'] ? 'is-error' : ''" @input="tableIsInput($event, row, 'isFileNumber')"/> -->
  262. <el-input v-model="row.fileNumber" />
  263. </template>
  264. <template #fileName="{ row }">
  265. <el-input v-model="row.fileName" :class="row.isFileName ? 'is-error' : ''" @input="tableIsInput($event, row, 'isFileName')" />
  266. </template>
  267. <template #fileTime="{ row }">
  268. <div class="relative w-full">
  269. <el-date-picker v-model="row.fileTime" class="w-full!" :clearable="false" format="YYYYMMDD" type="date" value-format="YYYYMMDD" />
  270. </div>
  271. <!-- <el-input v-model="row.fileTime" :class="row['isFileTime'] ? 'is-error' : ''" @input="tableIsInput($event, row, 'isFileTime')"/> -->
  272. </template>
  273. <template v-if="isBuiltDrawing === 2" #sheetType="{ row }">
  274. <el-select v-model="row.sheetType">
  275. <el-option v-for="item in sheetType" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
  276. </el-select>
  277. </template>
  278. <template v-if="isBuiltDrawing === 2" #sheetSource="{ row }">
  279. <el-select v-model="row.sheetSource">
  280. <el-option v-for="item in sheetSourceType" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
  281. </el-select>
  282. </template>
  283. <template v-if="isBuiltDrawing === 2" #drawingNo="{ row }">
  284. <el-input v-model="row.drawingNo" />
  285. </template>
  286. <template v-if="isBuiltDrawing === 2" #citeChangeNumber="{ row }">
  287. <el-input v-model="row.citeChangeNumber" />
  288. </template>
  289. <template #isApproval="{ row }">
  290. <el-select v-model="row.isApproval">
  291. <el-option v-for="item in whetherData" :key="item.value" :label="item.label" :value="item.value" />
  292. </el-select>
  293. </template>
  294. <template #isNeedCertification="{ row }">
  295. <el-select v-model="row.isNeedCertification">
  296. <el-option v-for="item in whetherData" :key="item.value" :label="item.label" :value="item.value" />
  297. </el-select>
  298. </template>
  299. <template #dutyUser="{ row }">
  300. <el-input v-model="row.dutyUser" />
  301. </template>
  302. <template #isElement="{ row }">
  303. <el-select v-model="row.isElement">
  304. <el-option :value="1" label="是" />
  305. <el-option :value="0" label="否" />
  306. </el-select>
  307. </template>
  308. <template #action="{ row, index }">
  309. <el-button v-if="tableUploadType === 'edit'" plain size="small" type="warning" @click="tableRowName(row)">查看文件</el-button>
  310. <el-button v-if="tableUploadType === 'edit'" :loading="row.newBtnLoading" plain size="small" type="primary" @click="substitutionClick(row)">替换</el-button>
  311. <el-button :loading="row.delBtnLoading" plain size="small" type="danger" @click="delUploadData(row, index)">删除</el-button>
  312. </template>
  313. </HcTable>
  314. <template #footer>
  315. <div class="lr-dialog-footer">
  316. <div class="left flex items-center">
  317. <el-button v-if="tableUploadType === 'add'" hc-btn type="primary" @click="uploadFileClick">
  318. <HcIcon name="add-circle" />
  319. <span>新增上传</span>
  320. </el-button>
  321. </div>
  322. <div class="right">
  323. <el-button size="large" :loading="uploadSaveLoading" @click="batchUploadCancel">
  324. <HcIcon name="close" />
  325. <span>取消</span>
  326. </el-button>
  327. <el-button :loading="uploadSaveLoading" hc-btn type="primary" @click="batchUploadSave">
  328. <HcIcon name="save" />
  329. <span>提交保存</span>
  330. </el-button>
  331. </div>
  332. </div>
  333. </template>
  334. </hc-new-dialog>
  335. <!-- 批量认证 -->
  336. <hc-new-dialog v-model="showCertificationModal" is-table title="批量认证" widths="80vw">
  337. <div class="hc-card-body-flex">
  338. <div class="flex-table">
  339. <HcTable
  340. :column="CertColumns" :datas="CertData" :index-style="{ width: 80 }"
  341. is-new ui="hc-form-table"
  342. @row-click="CertRowClick"
  343. >
  344. <template #action="{ row, index }">
  345. <el-button plain size="small" type="primary" @click.stop="CertRowClick2(row)">预览</el-button>
  346. </template>
  347. </HcTable>
  348. </div>
  349. <div v-if="CertPdf" class="flex-iframe">
  350. <iframe :src="CertPdf" allow="display-capture" frameborder="1" height="100%" width="100%" />
  351. </div>
  352. <div v-else class="flex-iframe hc-no-table-form">
  353. <div class="table-form-no">
  354. <img :src="notableform" alt="">
  355. <div class="desc">暂无 PDF 数据</div>
  356. </div>
  357. </div>
  358. </div>
  359. <template #footer>
  360. <div class="dialog-footer">
  361. <el-button size="large" @click="showCertificationModal = false">
  362. <HcIcon name="close" />
  363. <span>取消</span>
  364. </el-button>
  365. <el-button :loading="CertLoading" hc-btn type="primary" @click="CertClick">
  366. <HcIcon name="save" />
  367. <span>确认认证</span>
  368. </el-button>
  369. </div>
  370. </template>
  371. </hc-new-dialog>
  372. <!-- 批量编辑 -->
  373. <HcReport :data="reportData" :show="isReport" @finish="reportFinish" @hide="isReport = false" />
  374. <!-- 在线验签 -->
  375. <hc-new-drawer v-model="isOnlineVerifyDrawer" modal-class="hc-online-verify-drawer" to-id="app" @close="onlineVerifyDrawerClose">
  376. <hc-new-card>
  377. <template #header>
  378. <div class="online-verify-title">这是标题名称</div>
  379. </template>
  380. <template #extra>
  381. <div class="online-verify-icon" @click="onlineVerifyDrawerClose">
  382. <HcIcon name="close-circle" />
  383. <span class="ml-1">关闭</span>
  384. </div>
  385. </template>
  386. <hc-body :options="onlineVerifyOptions" padding="0px" split>
  387. <template #left>
  388. <hc-new-card>
  389. <HcPdf :src="onlineVerifyData.pdfUrl" />
  390. </hc-new-card>
  391. </template>
  392. <hc-new-card>
  393. <HcTable :column="cscTableColumn" :datas="cscTableData" :index-style="{ width: 60 }" is-new />
  394. </hc-new-card>
  395. </hc-body>
  396. </hc-new-card>
  397. </hc-new-drawer>
  398. </hc-body>
  399. </template>
  400. <script setup>
  401. import { useAppStore } from '~src/store'
  402. import { getStoreValue, setStoreValue } from '~src/utils/storage'
  403. import { computed, nextTick, onMounted, ref, watch } from 'vue'
  404. import HcTree from '~src/components/tree/hc-tree.vue'
  405. import HcReport from './components/HcReport.vue'
  406. import notableform from '~src/assets/view/notableform.svg'
  407. import { rowsToId } from '~uti/tools'
  408. import { HcDelMsg, HcUploadFileApi } from 'hc-vue3-ui'
  409. import archiveFileApi from '~api/archiveFile/archiveFile'
  410. import tasksFlowApi from '~api/tasks/flow'
  411. import { arrKeySort, arrToId, deepClone, getArrValue, getObjVal, isNullES } from 'js-fast-way'
  412. import tasksApi from '~api/tasks/data'
  413. import ossApi from '~api/oss'
  414. import { toPdfPage } from '~uti/btn-auth'
  415. //变量
  416. const useAppState = useAppStore()
  417. const projectId = ref(useAppState.getProjectId)
  418. const contractId = ref(useAppState.getContractId)
  419. const projectInfo = ref(useAppState.getProjectInfo)
  420. const isCollapse = ref(useAppState.getCollapse)
  421. //上传进度
  422. const uploadsLoading = ref(false)
  423. const treeRef = ref(null)
  424. //监听
  425. watch(() => [
  426. useAppState.getCollapse,
  427. ], ([Collapse]) => {
  428. isCollapse.value = Collapse
  429. })
  430. //监听
  431. watch(() => [useAppState.getProjectId, useAppState.getContractId, useAppState.getProjectInfo], ([pid, cid, info]) => {
  432. projectId.value = pid
  433. contractId.value = cid
  434. projectInfo.value = info
  435. }, { deep: true })
  436. //加载中
  437. const isAppLoading = computed(() => {
  438. return !isNullES(projectId.value) && !isNullES(contractId.value)
  439. })
  440. //监听变化
  441. watch(() => isAppLoading.value, (val) => {
  442. if (val) {
  443. treeLoading.value = true
  444. setTableColumns()
  445. }
  446. })
  447. //渲染完成
  448. onMounted(() => {
  449. if (isAppLoading.value) {
  450. treeLoading.value = true
  451. setTableColumns()
  452. }
  453. })
  454. //设置树菜单数据
  455. const ElTreeMenu = ref([
  456. { icon: 'add-circle', label: '新增', key: 'add' },
  457. { icon: 'draft', label: '编辑', key: 'edit' },
  458. { icon: 'delete-bin', label: '删除', key: 'del' },
  459. { icon: 'refresh', label: '目录同步', key: 'sync' },
  460. { icon: 'sort-asc', label: '排序', key: 'sort' },
  461. ])
  462. const dutyUser = ref('')
  463. //设置责任者
  464. const setdutyUser = async () => {
  465. const { error, code, data } = await archiveFileApi.getDutyUser({
  466. contractId: treecontractId.value,
  467. projectId: projectId.value,
  468. })
  469. if (!error && code === 200) {
  470. if (data?.contractType === 1) {
  471. dutyUser.value = data?.constructionUnitName || ''
  472. } else if (data?.contractType === 2) {
  473. dutyUser.value = data?.supervisionUnitName || ''
  474. } else if (data?.contractType === 3) {
  475. dutyUser.value = data?.contractorUnitName || ''
  476. }
  477. }
  478. }
  479. //打开文件选择框
  480. const uploadFileClick = () => {
  481. HcUploadFileApi({
  482. multiple: true,
  483. progress: () => {
  484. uploadsLoading.value = true
  485. },
  486. success: (file, res) => {
  487. uploadsChange(file.id, res.data)
  488. },
  489. error: (file) => {
  490. uploadsLoading.value = false
  491. window.$message.error(`${file.name} 上传失败`)
  492. },
  493. finish: () => {
  494. uploadsLoading.value = false
  495. window.$message.success('全部上传完成')
  496. },
  497. })
  498. }
  499. //替换文件
  500. const substitutionClick = (row) => {
  501. HcUploadFileApi({
  502. multiple: false,
  503. progress: () => {
  504. uploadsLoading.value = true
  505. },
  506. success: (_, { data }) => {
  507. //更新数据
  508. row.fileName = data?.originalName
  509. row.ossFileName = data?.name || ''
  510. row.fileUrl = data?.link || ''
  511. row.pdfFileUrl = data?.pdfUrl || ''
  512. row.filePage = data?.page || ''
  513. row.isUpdateUrl = 1
  514. uploadsLoading.value = false
  515. window.$message.success('上传成功')
  516. },
  517. error: (file) => {
  518. uploadsLoading.value = false
  519. window.$message.error(`${file.name} 上传失败`)
  520. },
  521. })
  522. }
  523. //树加载
  524. const treeLoading = ref(false)
  525. const treeNodeLoading = () => {
  526. treeLoading.value = false
  527. }
  528. const treePanelLoading = ref(false)
  529. const panelTreeLoading = () => {
  530. treePanelLoading.value = false
  531. }
  532. //审批状态
  533. const approvalStatus = ref([
  534. { label: '未上报', value: '0' },
  535. { label: '待审批', value: '1' },
  536. { label: '已审批', value: '2' },
  537. ])
  538. //认证状态
  539. const certifiedStatus = ref([
  540. { label: '已认证', value: '1' },
  541. { label: '未认证', value: '0' },
  542. ])
  543. //搜索表单
  544. const searchForm = ref({
  545. nodeIds: '',
  546. approval: null, certified: null, queryValue: null,
  547. current: 1, size: 20, total: 0,
  548. })
  549. //树相关的变量
  550. const isBuiltDrawing = ref(0)
  551. const isStorageNode = ref(0)
  552. const nodeIds = ref('')
  553. const treecontractId = ref('')
  554. //自动展开缓存
  555. const treeAutoExpandKeys = ref(getStoreValue('wbsTreeExpandKeys') || [])
  556. const projectTreeClick = ({ data, keys }) => {
  557. setStoreValue('wbsTreeExpandKeys', keys)
  558. treeAutoExpandKeys.value = keys || []
  559. nodeIds.value = data.id || ''
  560. isStorageNode.value = data['isStorageNode'] || 0
  561. treecontractId.value = data?.contractId || ''
  562. //设置搜索数据
  563. searchForm.value.current = 1
  564. searchForm.value.nodeIds = data.id || ''
  565. sortSearchForm.value.nodeIds = data.id || ''
  566. isBuiltDrawing.value = data.storageType
  567. getTableData()
  568. }
  569. //树菜单被点击
  570. const ElTreeMenuClick = async ({ data, keys }) => {
  571. // debugger
  572. setStoreValue('wbsTreeExpandKeys', keys)
  573. treeAutoExpandKeys.value = keys || []
  574. if (data?.extType === 2) {
  575. // 声像节点显示声像文件同步菜单
  576. ElTreeMenu.value = [
  577. { icon: 'add-circle', label: '新增', key: 'add' },
  578. { icon: 'draft', label: '编辑', key: 'edit' },
  579. { icon: 'delete-bin', label: '删除', key: 'del' },
  580. { icon: 'refresh', label: '目录同步', key: 'sync' },
  581. { icon: 'refresh', label: '文件同步', key: 'fileSync' },
  582. { icon: 'sort-asc', label: '排序', key: 'sort' },
  583. ]
  584. } else {
  585. if (data?.associationType === 3) {
  586. //声像
  587. ElTreeMenu.value = [
  588. { icon: 'add-circle', label: '新增', key: 'add' },
  589. { icon: 'draft', label: '编辑', key: 'edit' },
  590. { icon: 'delete-bin', label: '删除', key: 'del' },
  591. //{ icon: 'refresh', label: '目录同步', key: 'sync' },
  592. { icon: 'sort-asc', label: '排序', key: 'sort' },
  593. { icon: 'refresh', label: '声像文件同步', key: 'syncVocie' },
  594. ]
  595. } else if (data?.associationType === 6) {
  596. //日志
  597. ElTreeMenu.value = [
  598. { icon: 'add-circle', label: '新增', key: 'add' },
  599. { icon: 'draft', label: '编辑', key: 'edit' },
  600. { icon: 'delete-bin', label: '删除', key: 'del' },
  601. //{ icon: 'refresh', label: '目录同步', key: 'sync' },
  602. { icon: 'sort-asc', label: '排序', key: 'sort' },
  603. { icon: 'refresh', label: '日志文件同步', key: 'syncVocie' },
  604. ]
  605. } else if (data?.associationType === 2) {
  606. //试验
  607. ElTreeMenu.value = [
  608. { icon: 'add-circle', label: '新增', key: 'add' },
  609. { icon: 'draft', label: '编辑', key: 'edit' },
  610. { icon: 'delete-bin', label: '删除', key: 'del' },
  611. //{ icon: 'refresh', label: '目录同步', key: 'sync' },
  612. { icon: 'sort-asc', label: '排序', key: 'sort' },
  613. { icon: 'refresh', label: '试验文件同步', key: 'syncVocie' },
  614. ]
  615. } else {
  616. ElTreeMenu.value = [
  617. { icon: 'add-circle', label: '新增', key: 'add' },
  618. { icon: 'draft', label: '编辑', key: 'edit' },
  619. { icon: 'delete-bin', label: '删除', key: 'del' },
  620. { icon: 'refresh', label: '目录同步', key: 'sync' },
  621. { icon: 'sort-asc', label: '排序', key: 'sort' },
  622. ]
  623. }
  624. }
  625. }
  626. //回车搜索
  627. const keyUpEvent = (e) => {
  628. if (e.key === 'Enter') {
  629. searchForm.value.current = 1
  630. getTableData()
  631. }
  632. }
  633. //搜索
  634. const searchClick = () => {
  635. searchForm.value.current = 1
  636. getTableData()
  637. }
  638. //分页被点击
  639. const pageChange = ({ current, size }) => {
  640. searchForm.value.current = current
  641. searchForm.value.size = size
  642. getTableData()
  643. }
  644. //表格数据
  645. const tableRef = ref(null)
  646. const tableColumn = ref([])
  647. //设置表头
  648. const setTableColumns = () => {
  649. if (isBuiltDrawing.value === 1) {
  650. tableColumn.value = [
  651. { key: 'sourceType', name: '文件来源', width: 100 },
  652. { key: 'fileNumber', name: '文件编号', width: 100, autoWidth: true },
  653. { key: 'fileName', name: '文件名称' },
  654. { key: 'filePage', name: '文件页数', width: 120 },
  655. { key: 'sheetType', name: '图幅', width: 110 },
  656. { key: 'sheetSourceValue', name: '图表来源', width: 110 },
  657. { key: 'drawingNo', name: '图号', width: 110 },
  658. { key: 'citeChangeNumber', name: '引用变更令编号', width: 110 },
  659. { key: 'isCertificationValue', name: '认证状态', width: 100 },
  660. { key: 'isApprovalValue', name: '状态', width: 100 },
  661. { key: 'fileTime', name: '文件时间', width: 120, autoWidth: true },
  662. { key: 'dutyUser', name: '责任者', width: 140 },
  663. ]
  664. sheetTypeStatus()
  665. sheetSourceStatus()
  666. } else {
  667. tableColumn.value = [
  668. { key: 'sourceType', name: '文件来源', width: 100 },
  669. { key: 'fileNumber', name: '文件编号', width: 100, autoWidth: true },
  670. { key: 'fileName', name: '文件名称' },
  671. { key: 'filePage', name: '文件页数', width: 100 },
  672. { key: 'isCertificationValue', name: '认证状态', width: 100 },
  673. { key: 'isApprovalValue', name: '状态', width: 100 },
  674. { key: 'fileTime', name: '文件时间', width: 120, autoWidth: true },
  675. { key: 'dutyUser', name: '责任者', width: 140 },
  676. ]
  677. }
  678. }
  679. const tableData = ref([])
  680. //获取数据
  681. const tableLoading = ref(false)
  682. const getTableData = async () => {
  683. tableLoading.value = true
  684. fileTotalPage.value = 0
  685. const { error, code, data } = await archiveFileApi.getarchiveFilePage({
  686. ...searchForm.value,
  687. projectId: projectId.value,
  688. contractId: contractId.value,
  689. })
  690. tableLoading.value = false
  691. if (!error && code === 200) {
  692. tableData.value = getArrValue(data['records'])
  693. searchForm.value.total = data['total'] || 0
  694. } else {
  695. tableData.value = []
  696. searchForm.value.total = 0
  697. }
  698. getFileTotalPage()
  699. }
  700. //获取当前页的总页数
  701. const fileTotalPage = ref(0)
  702. const getFileTotalPage = () => {
  703. const arr = tableData.value
  704. if (arr.length <= 0) {
  705. fileTotalPage.value = 0
  706. return
  707. }
  708. //遍历数据
  709. let newPage = 0
  710. for (let i = 0; i < arr.length; i++) {
  711. newPage = newPage + Number(arr[i].filePage || 0)
  712. }
  713. fileTotalPage.value = newPage
  714. }
  715. //多选
  716. const tableCheckedKeys = ref([])
  717. const tableSelection = (rows) => {
  718. tableCheckedKeys.value = rows
  719. }
  720. //分盒整理
  721. const sortingModal = ref(false)
  722. const sortingClick = async () => {
  723. if (nodeIds.value && isStorageNode.value === 1) {
  724. const { error, code, data } = await archiveFileApi.getBoxNameAndBoxNumber({
  725. nodeId: nodeIds.value,
  726. })
  727. if (!error && code === 200) {
  728. if (data.length > 0) {
  729. sortingActiveKey.value = []
  730. sortingModal.value = true
  731. sortingItemData.value = getArrValue(data)
  732. sortingOldData.value = deepClone(sortingItemData.value)
  733. } else {
  734. console.log(1111111)
  735. sortingNoneModal.value = true
  736. }
  737. }
  738. } else {
  739. window?.$message?.warning('请先选择一个子节点')
  740. }
  741. }
  742. const sortingNoneModal = ref(false)//无数据显示的弹窗
  743. const toSortingModal = () => {
  744. sortingNoneModal.value = false
  745. sortingActiveKey.value = []
  746. sortingItemData.value = []
  747. sortingModal.value = true
  748. }
  749. const sortingNoneModalClose = () => {
  750. sortingNoneModal.value = false
  751. }
  752. const sortingItemData = ref([])
  753. const sortingOldData = ref([])//旧数据,用来对比是否修改名字
  754. //校验
  755. const tableIsInput = (val, row, key) => {
  756. //检测是否改过案卷名字
  757. if (key === 'isName') {
  758. row.isChange = true
  759. }
  760. row[key] = !val
  761. }
  762. const sortingActiveKey = ref([])
  763. const tableIndex = ref('')
  764. const sortingSelectFile = (row, index) => {
  765. tableIndex.value = index
  766. const key = `item-${index}`
  767. const indexNum = sortingActiveKey.value.indexOf(key)
  768. if (indexNum > -1) {
  769. sortingActiveKey.value.splice(indexNum, 1)
  770. } else {
  771. sortingActiveKey.value.push(key)
  772. if (!(row.list && row.list.length > 0)) {
  773. getSortingTableData(row, index)
  774. }
  775. }
  776. }
  777. //表格
  778. const sortingTableColumn = [
  779. { key: 'name', name: '文件名称' },
  780. ]
  781. //获取数据
  782. const sortingTableLoading = ref(false)
  783. const getSortingTableData = async (row, index) => {
  784. sortingTableLoading.value = true
  785. tableindex.value = index
  786. const { error, code, data } = await archiveFileApi.pageByBoxName({
  787. size: 99999,
  788. current: 1,
  789. projectId: projectId.value,
  790. contractId: contractId.value,
  791. nodeIds: nodeIds.value,
  792. boxName: row.boxName ? row.boxName : '',
  793. })
  794. sortingTableLoading.value = false
  795. if (!error && code === 200) {
  796. row.list = getArrValue(data['records'])
  797. setTableCheck(row, index).then()
  798. } else {
  799. row.list = []
  800. }
  801. }
  802. //表格ref
  803. const sorTableRef = ref([])
  804. const tableindex = ref('')
  805. //回显勾选
  806. const setTableCheck = async (row, index) => {
  807. if (row.ids) {
  808. const keys = row.ids.split(','), list = row.list
  809. for (let i = 0; i < list.length; i++) {
  810. const item = list[i]
  811. if (keys.indexOf(item.id) > -1) {
  812. item.checked = true
  813. await nextTick()
  814. // console.log(sorTableRef.value[index], 'sorTableRef.value[index]')
  815. sorTableRef.value[index].toggleRowSelection(item, true)
  816. }
  817. }
  818. }
  819. }
  820. //多选
  821. const checkList = ref([])
  822. const arrfliter = ref([])
  823. const singleCheck = async ({ row }) => {
  824. let isCheck = false
  825. let checkrow = JSON.parse(JSON.stringify(row))
  826. if (checkrow.checked === false || checkrow.checked === undefined) {
  827. if (checkList.value.length > 0) {
  828. let arr = checkList.value.filter(e => e.id === checkrow.id)
  829. if (arr.length > 0) {
  830. window.$message.warning('多个盒子不能选择同一份文件')
  831. await nextTick()
  832. sorTableRef.value[tableindex.value].toggleRowSelection(row, false)
  833. isCheck = true
  834. } else {
  835. isCheck = false
  836. row.tableindex = tableindex.value
  837. checkList.value.push(row)
  838. }
  839. } else {
  840. row.tableindex = tableindex.value
  841. checkList.value.push(row)
  842. }
  843. } else {
  844. let arr = checkList.value.filter(e => e.id === checkrow.id)
  845. if (isCheck === false && arr[0]?.checked === true || isCheck) {
  846. arrfliter.value = checkList.value.filter(e => e.id !== checkrow.id)
  847. } else {
  848. arrfliter.value = checkList.value
  849. }
  850. let newarr = []
  851. arrfliter.value.forEach((item) => {
  852. newarr.push(JSON.parse(JSON.stringify(item)))
  853. })
  854. checkList.value = newarr
  855. }
  856. }
  857. const sortingTableSelection = (rows, list, index) => {
  858. tableindex.value = index
  859. if (list) {
  860. list.forEach(element => {
  861. element.checked = false
  862. })
  863. }
  864. rows.forEach((element) => {
  865. element.checked = true
  866. })
  867. }
  868. //删除
  869. const sortingDelData = (row, index) => {
  870. sortingItemData.value.splice(index, 1)
  871. console.log(checkList.value, 'checkList.value')
  872. // checkList.value=[]
  873. //过滤掉当前选择的文件
  874. checkList.value = checkList.value.filter(e => e.tableindex !== index)
  875. if (row.boxNumber) {
  876. HcDelMsg(async (resolve) => {
  877. const { error, code } = await archiveFileApi.removeAllocation({
  878. boxName: row.boxName,
  879. boxNumber: row.boxNumber,
  880. })
  881. if (!error && code === 200) {
  882. window.$message?.success('删除成功!')
  883. sortingClick()
  884. }
  885. resolve() //关闭弹窗的回调
  886. })
  887. }
  888. }
  889. //添加分盒
  890. const addSortingModalClick = () => {
  891. console.log('添加分盒')
  892. sortingItemData.value.push({
  893. boxName: '',
  894. })
  895. }
  896. //确认保存
  897. const sortingModalLoading = ref(false)
  898. const sortingModalSave = async () => {
  899. sortingModalLoading.value = true
  900. //检测案卷名是否重复
  901. let nameRes = await checkNames()
  902. //console.log(nameRes)
  903. //return;
  904. for (let i = 0; i < nameRes.length; i++) {
  905. if (typeof nameRes[i].data == 'string') {
  906. window.$message?.error(nameRes[i].data + ',案卷名重复')
  907. sortingModalLoading.value = false
  908. return
  909. }
  910. }
  911. //组装数据
  912. let rows = []
  913. sortingItemData.value.forEach((item, index) => {
  914. let obj = {
  915. ids: '',
  916. boxName: item.boxName,
  917. boxNumber: index + 1,
  918. }
  919. let list = []
  920. if (item.list) {
  921. item.list.forEach((item2) => {
  922. if (item2.checked) {
  923. list.push(item2.id)
  924. }
  925. })
  926. obj.ids = list.join(',')
  927. } else {
  928. obj.ids = item.ids
  929. }
  930. rows.push(obj)
  931. })
  932. console.log(rows, 'rows')
  933. if (rows[0]?.ids) {
  934. const { error, code, data } = await archiveFileApi.allocation({
  935. list: rows,
  936. })
  937. if (!error && code === 200) {
  938. window.$message?.success('保存成功')
  939. sortingModal.value = false
  940. } else {
  941. window.$message?.error('保存失败')
  942. }
  943. } else {
  944. window.$message?.warning('空数据不能提交')
  945. }
  946. sortingModalLoading.value = false
  947. }
  948. const checkNames = () => {
  949. const arr = []
  950. sortingItemData.value.forEach((item) => {
  951. if (item.boxNumber) {
  952. if (item.isChange) {
  953. //是否修改过
  954. //对比旧的数据,是否相同
  955. for (let i = 0; i < sortingOldData.value.length; i++) {
  956. if (sortingOldData.value[i].boxNumber == item.boxNumber) {
  957. if (sortingOldData.value[i].boxName != item.boxName) {
  958. arr.push(
  959. archiveFileApi.getIsBoxName({
  960. boxName: item.boxName,
  961. }),
  962. )
  963. }
  964. return
  965. }
  966. }
  967. }
  968. } else {
  969. arr.push(
  970. archiveFileApi.getIsBoxName({
  971. boxName: item.boxName,
  972. }),
  973. )
  974. }
  975. })
  976. return Promise.all(arr)
  977. }
  978. //关闭
  979. const sortingModalClose = () => {
  980. sortingModal.value = false
  981. }
  982. //删除
  983. const delModalClick = () => {
  984. const rows = tableCheckedKeys.value
  985. //待审批,已审批都不能删除 豆海涛说,先取消限制
  986. /*const result = rows.some(({ isApprovalValue }) => {
  987. return isApprovalValue === '待审批' || isApprovalValue === '已审批'
  988. })
  989. if (result) {
  990. window.$message.warning('待审批或者已审批的文件都不能删除')
  991. return
  992. }
  993. if (rows.length <= 0) {
  994. window.$message?.error('请选择需要删除的数据')
  995. } else {
  996. HcDelMsg(async (resolve) => {
  997. const keys = arrToId(rows)
  998. const { error, code } = await archiveFileApi.removeFile({
  999. ids: keys,
  1000. })
  1001. if (!error && code === 200) {
  1002. window.$message?.success('删除成功!')
  1003. searchClick()
  1004. }
  1005. resolve() //关闭弹窗的回调
  1006. })
  1007. }*/
  1008. HcDelMsg(async (resolve) => {
  1009. const keys = arrToId(rows)
  1010. const { error, code } = await archiveFileApi.removeFile({
  1011. ids: keys,
  1012. })
  1013. if (!error && code === 200) {
  1014. window.$message?.success('删除成功!')
  1015. searchClick()
  1016. }
  1017. resolve() //关闭弹窗的回调
  1018. })
  1019. }
  1020. //废除
  1021. const repealModalClick = async () => {
  1022. const rows = tableCheckedKeys.value
  1023. if (rows.length <= 0) {
  1024. window.$message?.error('请选择需要废除的数据')
  1025. } else {
  1026. window?.$messageBox?.alert('请谨慎考虑后,确认是否需要废除?', '废除提醒', {
  1027. showCancelButton: true,
  1028. confirmButtonText: '确认废除',
  1029. cancelButtonText: '取消',
  1030. type: 'warning',
  1031. callback: async (action, instance, done) => {
  1032. if (action === 'confirm') {
  1033. instance.confirmButtonLoading = true
  1034. const keys = arrToId(rows)
  1035. const { error, code } = await tasksFlowApi.batchRepealTaskArchive({
  1036. ids: keys,
  1037. type: 1,
  1038. projectId: projectId.value,
  1039. contractId: contractId.value,
  1040. })
  1041. if (!error && code === 200) {
  1042. window.$message?.success('废除成功!')
  1043. searchClick()
  1044. }
  1045. instance.confirmButtonLoading = false
  1046. done()
  1047. } else {
  1048. done()
  1049. }
  1050. },
  1051. })
  1052. }
  1053. }
  1054. //跨目录移动
  1055. const movesModal = ref(false)
  1056. const movesClick = async () => {
  1057. movesModal.value = true
  1058. checkedMoves.value = []
  1059. movesCheckAll.value = false
  1060. treePanelLoading.value = true
  1061. fileDatasListLoading.value = true
  1062. const { error, code, data } = await archiveFileApi.getarchiveFilePage({
  1063. ...searchForm.value,
  1064. current: 1,
  1065. size: 50000,
  1066. projectId: projectId.value,
  1067. contractId: contractId.value,
  1068. })
  1069. fileDatasListLoading.value = false
  1070. if (!error && code === 200) {
  1071. fileDatasList.value = getArrValue(data['records'])
  1072. } else {
  1073. fileDatasList.value = []
  1074. }
  1075. }
  1076. //选择需要迁移的文件
  1077. const movesCheckAll = ref(false)
  1078. const isIndeterminate = ref(true)
  1079. const checkedMoves = ref([])
  1080. //左侧待迁移文件
  1081. const fileDatasList = ref([])
  1082. const fileDatasListLoading = ref(false)
  1083. //全选
  1084. const handleCheckAllChange = (val) => {
  1085. console.log(val, 'val')
  1086. const checked = fileDatasList.value
  1087. checkedMoves.value = val ? checked : []
  1088. isIndeterminate.value = false
  1089. }
  1090. //勾选
  1091. const handleCheckedMovesChange = (value) => {
  1092. const keys = fileDatasList.value
  1093. const checkedCount = value.length
  1094. movesCheckAll.value = checkedCount === keys.length
  1095. isIndeterminate.value = checkedCount > 0 && checkedCount < keys.length
  1096. }
  1097. //右侧radio
  1098. let radioNodeId = ''
  1099. const radioChange = (id) => {
  1100. //console.log(id)
  1101. radioNodeId = id
  1102. }
  1103. //只显示储存节点的单选
  1104. const showRadioFun = (data) => {
  1105. if (data.isStorageNode == 1) {
  1106. return true
  1107. } else {
  1108. return false
  1109. }
  1110. }
  1111. //保存
  1112. const movesModalLoading = ref(false)
  1113. const movesModalSave = async () => {
  1114. const keys = rowsToId(checkedMoves.value)
  1115. let ids = keys
  1116. if (checkedMoves.value.length < 1) {
  1117. window.$message?.warning('请勾选需要迁移的文件')
  1118. return
  1119. }
  1120. if (radioNodeId == '') {
  1121. window.$message?.warning('请选择要移动到的节点')
  1122. return
  1123. }
  1124. movesModalLoading.value = true
  1125. const { error, code, data } = await archiveFileApi.migrateFile({
  1126. ids: ids,
  1127. nodeId: radioNodeId,
  1128. })
  1129. movesModalLoading.value = false
  1130. if (!error && code === 200) {
  1131. window.$message?.success('保存成功')
  1132. movesModal.value = false
  1133. getTableData()
  1134. } else {
  1135. window.$message?.error('保存失败')
  1136. }
  1137. }
  1138. //关闭
  1139. const movesModalClose = () => {
  1140. movesModal.value = false
  1141. }
  1142. //表格排序
  1143. const sortModal = ref(false)
  1144. //显示
  1145. const tableSortClick = () => {
  1146. sortModal.value = true
  1147. getSortTableData()
  1148. }
  1149. //搜索表单
  1150. const sortSearchForm = ref({
  1151. nodeIds: '',
  1152. current: 1, size: 20, total: 0,
  1153. })
  1154. //分页被点击
  1155. const sortPageChange = ({ current, size }) => {
  1156. sortSearchForm.value.current = current
  1157. sortSearchForm.value.size = size
  1158. getSortTableData()
  1159. }
  1160. //表格数据
  1161. const sortTableColumn = ref([
  1162. { key: 'fileNumber', name: '文件编号', width: 160 },
  1163. { key: 'fileName', name: '文件名称' },
  1164. { key: 'fileTime', name: '文件时间', width: 120 },
  1165. { key: 'action', name: '排序', width: 90 },
  1166. ])
  1167. const sortTableData = ref([])
  1168. const sortTableLoading = ref(false)
  1169. const getSortTableData = async () => {
  1170. sortTableLoading.value = true
  1171. const { error, code, data } = await archiveFileApi.getarchiveFilePage({
  1172. ...sortSearchForm.value,
  1173. projectId: projectId.value,
  1174. contractId: contractId.value,
  1175. })
  1176. sortTableLoading.value = false
  1177. if (!error && code === 200) {
  1178. sortTableData.value = getArrValue(data['records'])
  1179. sortSearchForm.value.total = data['total'] || 0
  1180. } else {
  1181. sortTableData.value = []
  1182. sortSearchForm.value.total = 0
  1183. }
  1184. }
  1185. //拖动完成
  1186. const sortTableRowDrop = (rows) => {
  1187. sortTableData.value = [] // 先清空,否则排序会异常
  1188. nextTick(() => {
  1189. sortTableData.value = rows
  1190. })
  1191. }
  1192. //向下
  1193. const downSortClick = (index) => {
  1194. const indexs = index + 1
  1195. const data = sortTableData.value
  1196. if (indexs !== data.length) {
  1197. const tmp = data.splice(indexs, 1)
  1198. sortTableData.value.splice(index, 0, tmp[0])
  1199. } else {
  1200. window?.$message?.warning('已经处于置底,无法下移')
  1201. }
  1202. }
  1203. //向上
  1204. const upSortClick = (index) => {
  1205. const data = sortTableData.value || []
  1206. if (index !== 0) {
  1207. const tmp = data.splice(index - 1, 1)
  1208. sortTableData.value.splice(index, 0, tmp[0])
  1209. } else {
  1210. window?.$message?.warning('已经处于置顶,无法上移')
  1211. }
  1212. }
  1213. //保存
  1214. const sortModalLoading = ref(false)
  1215. const sortModalSave = async () => {
  1216. await batchEditSaveApi(sortTableData.value)
  1217. sortModal.value = false
  1218. }
  1219. //关闭
  1220. const sortModalClose = () => {
  1221. sortModal.value = false
  1222. }
  1223. //获取认证状态
  1224. const certificationType = ref([])
  1225. const certificationStatus = async () => {
  1226. const { error, code, data } = await tasksApi.queryTaskTypeStatus({
  1227. typeOrStatus: 'certification_status',
  1228. })
  1229. //处理数据
  1230. if (!error && code === 200) {
  1231. certificationType.value = getArrValue(data)
  1232. } else {
  1233. certificationType.value = []
  1234. }
  1235. }
  1236. //获取图幅类型
  1237. const sheetType = ref([])
  1238. const sheetTypeStatus = async () => {
  1239. console.log(1111111)
  1240. const { error, code, data } = await tasksApi.queryTaskTypeStatus({
  1241. typeOrStatus: 'sheet_type',
  1242. })
  1243. //处理数据
  1244. if (!error && code === 200) {
  1245. sheetType.value = getArrValue(data)
  1246. } else {
  1247. sheetType.value = []
  1248. }
  1249. }
  1250. //获取图表来源
  1251. const sheetSourceType = ref([])
  1252. const sheetSourceStatus = async () => {
  1253. const { error, code, data } = await tasksApi.queryTaskTypeStatus({
  1254. typeOrStatus: 'sheet_source',
  1255. })
  1256. //处理数据
  1257. if (!error && code === 200) {
  1258. sheetSourceType.value = getArrValue(data)
  1259. } else {
  1260. sheetSourceType.value = []
  1261. }
  1262. }
  1263. //新增文件
  1264. const tableUploadType = ref('add')
  1265. const showUploadModal = ref(false)
  1266. const uploadModalClick = () => {
  1267. if (nodeIds.value && isStorageNode.value === 1) {
  1268. tableUploadType.value = 'add'
  1269. setTableUploadColumn()
  1270. uploadSaveLoading.value = false
  1271. tableUploadData.value = []
  1272. showUploadModal.value = true
  1273. setdutyUser()
  1274. } else {
  1275. window?.$message?.warning('请先选择一个子节点')
  1276. }
  1277. }
  1278. const uploadModalClose = () => {
  1279. batchUploadCancel()
  1280. }
  1281. //设置文件表头
  1282. const tableUploadColumn = ref([
  1283. { key: 'fileNumber', name: '文件编号' },
  1284. { key: 'fileName', name: '文件名称' },
  1285. { key: 'fileTime', name: '文件时间' },
  1286. { key: 'isApproval', name: '是否需要审批', width: 80 },
  1287. { key: 'isNeedCertification', name: '是否需要认证', width: 80 },
  1288. { key: 'dutyUser', name: '责任者' },
  1289. { key: 'isElement', name: '是否四要素' },
  1290. { key: 'action', name: '操作', width: 220 },
  1291. ])
  1292. const setTableUploadColumn = () => {
  1293. const type = tableUploadType
  1294. if (isBuiltDrawing.value === 2) {
  1295. tableUploadColumn.value = [
  1296. { key: 'fileNumber', name: '文件编号', width: 200 },
  1297. { key: 'fileName', name: '文件名称', minWidth: 400 },
  1298. { key: 'fileTime', name: '文件时间', width: 140 },
  1299. { key: 'sheetType', name: '图幅', width: 100 },
  1300. { key: 'sheetSource', name: '图表来源', width: 100 },
  1301. { key: 'drawingNo', name: '图号', width: 140 },
  1302. { key: 'citeChangeNumber', name: '引用变更令编号', width: 140 },
  1303. { key: 'isApproval', name: '是否需要审批', width: 100 },
  1304. { key: 'isNeedCertification', name: '是否需要认证', width: 100 },
  1305. { key: 'dutyUser', name: '责任者', width: 160 },
  1306. { key: 'isElement', name: '是否四要素', width: 90 },
  1307. {
  1308. key: 'action', name: '操作',
  1309. width: type.value === 'edit' ? 220 : 70,
  1310. align: 'center', fixed: 'right',
  1311. },
  1312. ]
  1313. sheetTypeStatus()
  1314. sheetSourceStatus()
  1315. } else {
  1316. tableUploadColumn.value = [
  1317. { key: 'fileNumber', name: '文件编号', width: 200 },
  1318. { key: 'fileName', name: '文件名称' },
  1319. { key: 'fileTime', name: '文件时间', width: 140 },
  1320. { key: 'isApproval', name: '是否需要审批', width: 100 },
  1321. { key: 'isNeedCertification', name: '是否需要认证', width: 100 },
  1322. { key: 'dutyUser', name: '责任者', width: 160 },
  1323. { key: 'isElement', name: '是否四要素', width: 90 },
  1324. {
  1325. key: 'action', name: '操作',
  1326. width: type.value === 'edit' ? 220 : 70,
  1327. align: 'center', fixed: 'right',
  1328. },
  1329. ]
  1330. }
  1331. }
  1332. const tableUploadData = ref([])
  1333. //上传的文件结果
  1334. const uploadsChange = (fileId, item) => {
  1335. if (getObjVal(item)) {
  1336. let newArr = tableUploadData.value
  1337. const sheet = sheetType.value, source = sheetSourceType.value
  1338. let name = item['originalName'] || ''
  1339. let fileName = name.substring(0, name.lastIndexOf('.'))
  1340. newArr.push({
  1341. fileUploadId: fileId,
  1342. projectId: projectId.value,
  1343. contractId: contractId.value,
  1344. nodeId: nodeIds.value,
  1345. fileNumber: '',
  1346. fileName: fileName,
  1347. ossFileName: item?.name || '',
  1348. fileTime: null,
  1349. fileUrl: item?.link || '',
  1350. sheetType: sheet.length > 0 ? sheet[0]['dictKey'] || '' : '',
  1351. sheetSource: source.length > 0 ? source[0]['dictKey'] || '' : '',
  1352. drawingNo: '',
  1353. citeChangeNumber: '',
  1354. isApproval: 1,
  1355. isNeedCertification: 1,
  1356. dutyUser: dutyUser.value,
  1357. pdfFileUrl: item?.pdfUrl || '',
  1358. filePage: item?.page || '',
  1359. isElement: 0,
  1360. isUpdateUrl: 0,
  1361. fileSize: item?.fileSize,
  1362. })
  1363. //tableUploadData.value = newArr
  1364. tableUploadData.value = arrKeySort(newArr, 'fileUploadId')
  1365. } else {
  1366. console.log(item)
  1367. }
  1368. }
  1369. //表单下拉数据
  1370. const whetherData = ref([
  1371. { label: '不需要', value: 0 },
  1372. { label: '需要', value: 1 },
  1373. ])
  1374. //表格数据排序
  1375. const tableUploadRowSort = (arr) => {
  1376. tableUploadData.value = arr
  1377. }
  1378. //删除
  1379. const delUploadData = async (row, index) => {
  1380. if (row['ossFileName']) {
  1381. row['delBtnLoading'] = true
  1382. await ossApi.removeFile({ fileName: row['ossFileName'] })
  1383. row['delBtnLoading'] = false
  1384. tableUploadData.value.splice(index, 1)
  1385. } else {
  1386. tableUploadData.value.splice(index, 1)
  1387. }
  1388. }
  1389. //批量上传保存
  1390. const uploadSaveLoading = ref(false)
  1391. const batchUploadSave = async () => {
  1392. const rows = tableUploadData.value
  1393. if (rows.length > 0) {
  1394. //验证表单数据
  1395. uploadSaveLoading.value = true
  1396. let isTableRows = false
  1397. for (let i = 0; i < rows.length; i++) {
  1398. // if (!rows[i]['fileNumber']) {
  1399. // rows[i]['isFileNumber'] = true
  1400. // isTableRows = true
  1401. // } else if (!rows[i]['fileName']) {
  1402. // rows[i]['isFileName'] = true
  1403. // isTableRows = true
  1404. // }
  1405. // if (!rows[i]['fileTime']) {
  1406. // rows[i]['isFileTime'] = true
  1407. // isTableRows = true
  1408. // }
  1409. // else
  1410. if (!rows[i]['fileName']) {
  1411. rows[i]['isFileName'] = true
  1412. isTableRows = true
  1413. }
  1414. }
  1415. //判断数据
  1416. if (isTableRows) {
  1417. uploadSaveLoading.value = false
  1418. window.$message?.warning('请先完善表单信息')
  1419. } else {
  1420. if (tableUploadType.value === 'add') {
  1421. await batchUploadSaveApi(rows)
  1422. } else {
  1423. await batchEditSaveApi(rows)
  1424. }
  1425. }
  1426. } else {
  1427. window.$message?.warning('请先上传文件')
  1428. }
  1429. }
  1430. //确认上传保存
  1431. const batchUploadSaveApi = async (rows) => {
  1432. uploadSaveLoading.value = true
  1433. const { error, code } = await archiveFileApi.batchUploadSave({
  1434. list: rows,
  1435. }, false)
  1436. //判断状态
  1437. uploadSaveLoading.value = false
  1438. if (!error && code === 200) {
  1439. window.$message?.success('保存成功')
  1440. batchUploadCancel()
  1441. getTableData()
  1442. } else {
  1443. window.$message?.error('保存失败')
  1444. }
  1445. }
  1446. //取消上传
  1447. const batchUploadCancel = () => {
  1448. tableUploadData.value = []
  1449. uploadSaveLoading.value = false
  1450. uploadsLoading.value = false
  1451. showUploadModal.value = false
  1452. }
  1453. //上传新文件
  1454. // const newUploadsChange = ({fileList}, row) => {
  1455. // if (fileList.length > 0) {
  1456. // tableUploadType.value = 'edit'
  1457. // const item = fileList[0]
  1458. // const name = item['originalName'] || ''
  1459. // const fileName = name.substring(0, name.lastIndexOf("."))
  1460. // //更新数据
  1461. // row.fileName = fileName;
  1462. // row.ossFileName = item?.name || ''
  1463. // row.fileUrl = item?.link || ''
  1464. // row.pdfFileUrl = item?.pdfUrl || ''
  1465. // row.filePage = item?.page || ''
  1466. // row.isUpdateUrl=1
  1467. // }
  1468. // }
  1469. // const newUploadsProgress = (val, row) => {
  1470. // row.newBtnLoading = val
  1471. // }
  1472. //批量编辑
  1473. const batchEditClick = () => {
  1474. const rows = deepClone(tableCheckedKeys.value)
  1475. //判断是否满足条件 豆海涛说,先取消限制
  1476. /*const result = rows.every(({ status }) => {
  1477. return status !== 1 && status !== 2
  1478. })
  1479. //判断状态
  1480. if (result) {
  1481. tableUploadType.value = 'edit'
  1482. setTableUploadColumn()
  1483. uploadSaveLoading.value = false
  1484. tableUploadData.value = rows
  1485. showUploadModal.value = true
  1486. } else {
  1487. window.$message?.warning('已上报或已审批的文件不能编辑')
  1488. }*/
  1489. tableUploadType.value = 'edit'
  1490. setTableUploadColumn()
  1491. uploadSaveLoading.value = false
  1492. tableUploadData.value = rows
  1493. showUploadModal.value = true
  1494. }
  1495. //确认编辑上传保存
  1496. const batchEditSaveApi = async (rows) => {
  1497. uploadSaveLoading.value = true
  1498. const { error, code } = await archiveFileApi.batchUpdateSort({
  1499. list: rows,
  1500. }, false)
  1501. //判断状态
  1502. uploadSaveLoading.value = false
  1503. if (!error && code === 200) {
  1504. window.$message?.success('保存成功')
  1505. batchUploadCancel()
  1506. getTableData()
  1507. } else {
  1508. window.$message?.error('保存失败')
  1509. }
  1510. }
  1511. //批量认证
  1512. const CertData = ref([])
  1513. const CertIds = ref([])
  1514. const CertPdf = ref('')
  1515. const CertColumns = [
  1516. { key: 'fileName', name: '文件名称' },
  1517. { key: 'action', name: '操作', width: 100 },
  1518. ]
  1519. //批量认证弹窗
  1520. const showCertificationModal = ref(false)
  1521. const certificationModalClick = () => {
  1522. const rows = tableCheckedKeys.value
  1523. CertData.value = rows
  1524. CertIds.value = rowsToId(rows)
  1525. CertPdf.value = rows[0]?.pdfFileUrl || ''
  1526. const result = rows.every(({ isCertification }) => {
  1527. return isCertification === 0
  1528. })
  1529. const result1 = rows.every(({ status }) => {
  1530. return status === 0 || status === 3
  1531. })//已上报不能认证
  1532. if (!result1) {
  1533. window.$message.warning('已上报的文件不能进行认证')
  1534. } else {
  1535. if (result) {
  1536. CertData.value = rows
  1537. CertIds.value = rowsToId(rows)
  1538. CertPdf.value = rows[0]?.pdfFileUrl || ''
  1539. showCertificationModal.value = true
  1540. } else {
  1541. window.$message?.warning('已认证的文件不能再认证')
  1542. }
  1543. }
  1544. }
  1545. //认证行被点击
  1546. const CertRowClick = ({ row }) => {
  1547. const pdfFileUrl = row?.pdfFileUrl || ''
  1548. if (CertPdf.value !== pdfFileUrl) {
  1549. CertPdf.value = pdfFileUrl
  1550. }
  1551. }
  1552. //认证预览被点击
  1553. const CertRowClick2 = ({ pdfFileUrl }) => {
  1554. const pdfUrl = pdfFileUrl || ''
  1555. if (CertPdf.value !== pdfUrl) {
  1556. CertPdf.value = pdfUrl
  1557. }
  1558. }
  1559. //确认认证
  1560. const CertLoading = ref(false)
  1561. const CertClick = async () => {
  1562. CertLoading.value = true
  1563. const { error, code, msg } = await tasksFlowApi.batchCertification({
  1564. ids: CertIds.value,
  1565. }, false)
  1566. //判断状态
  1567. CertLoading.value = false
  1568. if (!error && code === 200) {
  1569. window.$message?.success('认证成功')
  1570. showCertificationModal.value = false
  1571. searchClick()
  1572. } else {
  1573. window.$message?.error(msg)
  1574. }
  1575. }
  1576. //名称被点击
  1577. const tableRowName = (row) => {
  1578. if (row?.isCertificationValue === '已认证' || row?.isApprovalValue === '已审批') {
  1579. if (row['eVisaFile']) {
  1580. toPdfPage(row['eVisaFile'])
  1581. } else if (row['pdfFileUrl']) {
  1582. toPdfPage(row['pdfFileUrl'])
  1583. } else {
  1584. window.$message?.warning('文件不存在')
  1585. }
  1586. } else {
  1587. if (row['pdfFileUrl']) {
  1588. toPdfPage(row['pdfFileUrl'])
  1589. } else {
  1590. window.$message?.warning('文件不存在')
  1591. }
  1592. }
  1593. }
  1594. //上报
  1595. const isReport = ref(false)
  1596. const reportData = ref([])
  1597. const reportModalClick = () => {
  1598. reportData.value = []
  1599. const rows = tableCheckedKeys.value
  1600. //判断是否满足条件
  1601. const result = rows.every(({ status }) => {
  1602. return status === 0 || status === 3
  1603. })
  1604. const result1 = rows.every(({ isCertification }) => {
  1605. return isCertification === 1
  1606. })
  1607. if (result1) {
  1608. window.$message?.warning('已认证的文件不能进行上报')
  1609. return false
  1610. } else {
  1611. if (!result) {
  1612. window.$message?.warning('已上报的文件不能进行再次上报')
  1613. return false
  1614. }
  1615. }
  1616. rows.sort((a, b) => a.sort - b.sort)
  1617. //展示上报弹窗
  1618. reportData.value = rows
  1619. console.log(reportData.value, ' reportData.valu')
  1620. isReport.value = true
  1621. }
  1622. //上报完成
  1623. const reportFinish = () => {
  1624. searchClick()
  1625. }
  1626. //在线验签
  1627. const onlineLoading = ref(false)
  1628. const onlineVerifyData = ref({})
  1629. const isOnlineVerifyDrawer = ref(false)
  1630. const onlineVerifyOptions = {
  1631. sizes: [50, 50],
  1632. snapOffset: 0,
  1633. minSize: ['10%', '80%'],
  1634. }
  1635. const batchOnline = async () => {
  1636. const rows = tableCheckedKeys.value
  1637. if (rows.length > 1) {
  1638. window.$message?.warning('在线验签只能勾选一条数据进行验签')
  1639. return
  1640. }
  1641. //判断是否满足条件
  1642. const result = rows.every(({ status }) => {
  1643. return status === 2
  1644. })
  1645. //判断状态
  1646. if (!result) {
  1647. window.$message?.warning('存在未审批或未上报数据')
  1648. return
  1649. }
  1650. //发起请求
  1651. //const ids = arrToId(rows)
  1652. onlineLoading.value = true
  1653. /*const { error, code, msg, data } = await queryApi.onlineVerify({
  1654. ids: ids,
  1655. })
  1656. //处理数据
  1657. onlineLoading.value = false
  1658. if (!error && code === 200) {
  1659. onlineVerifyData.value = getObjValue(data)
  1660. //cscTableData.value = getArrValue(data['certBeanVOList'])
  1661. isOnlineVerifyDrawer.value = true
  1662. } else {
  1663. onlineVerifyData.value = {}
  1664. window.$message?.error(msg ?? '操作失败')
  1665. }*/
  1666. onlineVerifyData.value = {}
  1667. isOnlineVerifyDrawer.value = true
  1668. }
  1669. //签名信息
  1670. const cscTableColumn = [
  1671. { key: 'user', name: '签名者', width: 300 },
  1672. { key: 'time', name: '签名时间', width: 200 },
  1673. { key: 'val', name: '摘要' },
  1674. ]
  1675. const cscTableData = ref([])
  1676. //在线验签抽屉被关闭
  1677. const onlineVerifyDrawerClose = () => {
  1678. isOnlineVerifyDrawer.value = false
  1679. onlineLoading.value = false
  1680. }
  1681. //处理时间
  1682. const getTableFileTime = (time) => {
  1683. if (isNullES(time)) return ''
  1684. return time.replace(/-/g, '')
  1685. }
  1686. </script>
  1687. <style lang="scss">
  1688. @import '~style/file/collection.scss';
  1689. //在线验签
  1690. .hc-online-verify-drawer .el-card.hc-new-card-box {
  1691. .hc-card-header-box {
  1692. .online-verify-title {
  1693. font-size: 20px;
  1694. }
  1695. .online-verify-icon {
  1696. display: flex;
  1697. align-items: center;
  1698. cursor: pointer;
  1699. color: #5a5959;
  1700. i {
  1701. font-size: 18px;
  1702. }
  1703. &:hover {
  1704. color: var(--el-color-primary);
  1705. }
  1706. }
  1707. }
  1708. }
  1709. html.dark .hc-online-verify-drawer .el-card.hc-new-card-box {
  1710. background-color: var(--hc-bg-color);
  1711. .hc-card-header-box {
  1712. .online-verify-icon {
  1713. color: var(--el-color-primary);
  1714. }
  1715. }
  1716. }
  1717. </style>