tuning.vue 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817
  1. <template>
  2. <hc-body id="carry-spot-checks-layout-target-tuning" :loading="treeLoading" :project-nmae="projectInfo?.name" split>
  3. <template #tree>
  4. <HcTree
  5. :auto-expand-keys="treeAutoExpandKeys" :contract-id="contractId" :project-id="projectId"
  6. @node-tap="nodeElTreeClick" @menu-tap="ElTreeMenuClick"
  7. @node-loading="treeNodeLoading"
  8. />
  9. </template>
  10. <hc-new-card>
  11. <template #header>
  12. <div class="hc-card-header-table-title">已形成的案卷</div>
  13. </template>
  14. <template #search>
  15. <div class="w-40">
  16. <el-select v-model="searchForm.queryValueSize" clearable placeholder="限制检索">
  17. <el-option v-for="item in queryValueSizeOption" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
  18. </el-select>
  19. </div>
  20. <div class="ml-2 w-64">
  21. <el-input v-model="searchForm.queryValue" clearable placeholder="请输入案卷名称关键词检索" @keyup="keyUpEvent" />
  22. </div>
  23. <div class="ml-2">
  24. <el-button type="primary" @click="searchClick">搜索</el-button>
  25. </div>
  26. </template>
  27. <template #extra>
  28. <HcTooltip keys="archives_tuning_btn_sort">
  29. <el-button hc-btn :disabled="!searchForm.nodeIds" @click="tableSortClick">
  30. 排序
  31. </el-button>
  32. </HcTooltip>
  33. <el-tooltip
  34. v-if="taskInfoList.length > 0"
  35. class="box-item"
  36. effect="light"
  37. placement="bottom"
  38. >
  39. <template #content>
  40. <div class="task-info">
  41. <div
  42. v-for="item in taskInfoList"
  43. :key="item.taskId"
  44. v-loading="taskListLoad"
  45. class="task-info-item"
  46. >
  47. <div class="task-info-item-left" :class="{ 'text-disable': item.status === 1 }" @click.stop="getInfoDetailClick(item)">
  48. <span>{{ item.taskTime }}</span>
  49. <span v-if="item.status === 1" class="ml-2">待生成</span>
  50. <span v-else class="ml-2">生成</span>
  51. <span class="text-red">{{ item.num }}</span>
  52. <span>条AI数据</span>
  53. </div>
  54. <div v-if="item.state" class="task-info-item-right ml-2" style=" color:#FF7D43;">
  55. <HcIcon class="text-hover" name="loader-2" style=" color:#FF7D43;" />
  56. <span>生成中</span>
  57. </div>
  58. <div v-else v-loading="item?.delLoad" class="task-info-item-right ml-4" @click.stop="delClick(item)">
  59. <HcIcon class="text-hover" name="close-circle" style=" color:#FF7D43;" />
  60. </div>
  61. </div>
  62. </div>
  63. </template>
  64. <el-button
  65. hc-btn
  66. :disabled="tableCheckedKeys.length <= 0"
  67. keys="archives_tuning_btn_ai"
  68. :loading="aiLoading"
  69. @click="AiClick"
  70. @mouseenter="getTaskInfoList"
  71. >
  72. AI题名
  73. </el-button>
  74. </el-tooltip>
  75. <el-button
  76. v-else
  77. hc-btn
  78. :disabled="tableCheckedKeys.length <= 0"
  79. keys="archives_tuning_btn_ai"
  80. :loading="aiLoading"
  81. @click="AiClick"
  82. @mouseenter="getTaskInfoList"
  83. >
  84. AI题名
  85. </el-button>
  86. <HcTooltip keys="archives_tuning_btn_combine">
  87. <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" @click="mergeClick">
  88. 重组
  89. </el-button>
  90. </HcTooltip>
  91. <HcTooltip keys="archives_tuning_btn_num">
  92. <el-button :loading="refreshFileNumberLoading" hc-btn @click="fileNumberClick">
  93. 档号整理
  94. </el-button>
  95. </HcTooltip>
  96. <HcTooltip keys="archives_tuning_update_four">
  97. <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" @click="replaceClick">
  98. 查找替换
  99. </el-button>
  100. </HcTooltip>
  101. <HcTooltip keys="archives_tuning_update_four">
  102. <el-button :loading="refreshFileFourLoading" hc-btn :disabled="tableCheckedKeys.length <= 0" @click="refreshFileFourClick">
  103. 更新案卷四要素
  104. </el-button>
  105. </HcTooltip>
  106. <HcTooltip keys="archives_tuning_btn_lock">
  107. <el-button :disabled="tableCheckedKeys.length <= 0" :loading="lockLoad" hc-btn @click="lockarchives">档案锁定</el-button>
  108. </HcTooltip>
  109. <HcTooltip keys="archives_tuning_btn_unlock">
  110. <el-button :disabled="tableCheckedKeys.length <= 0" :loading="unlockLoad" hc-btn @click="unlockarchives">档案解锁</el-button>
  111. </HcTooltip>
  112. <HcTooltip keys="archives_tuning_btn_remove">
  113. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn @click="movesClick">跨目录移动</el-button>
  114. </HcTooltip>
  115. <HcTooltip keys="archives_tuning_btn_edit">
  116. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn @click="batchEditClick(1)">编辑</el-button>
  117. </HcTooltip>
  118. <HcTooltip keys="archives_tuning_btn_disassemble">
  119. <el-button :disabled="tableCheckedKeys.length <= 0" hc-btn @click="tunModalClick">拆卷</el-button>
  120. </HcTooltip>
  121. <!-- <HcTooltip keys="archives_tuning_btn_del">
  122. <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" @click="delModalClick">
  123. <HcIcon name="delete-bin"/>
  124. <span>删除</span>
  125. </el-button>
  126. </HcTooltip> -->
  127. </template>
  128. <div class="flex-container body">
  129. <div class="hc-c-table-box" :style="{ flex: tableFileShow ? '1' : 'auto' }">
  130. <HcTable
  131. ref="tableRef" :check-style="{ width: 29 }" :column="tableColumn" :datas="tableData"
  132. :index-style="{ width: 70 }" :is-arr-index="false" :loading="tableLoading" :ui="hoverHand ? 'hover-hand' : ''"
  133. is-check is-new is-current-row
  134. :row-style="tableRowStyle" @selection-change="tableSelection"
  135. @row-click="tableRowClick"
  136. >
  137. <template #name="{ row }">
  138. <span class="text-link" :class="row.colourStatus === 2 || row?.actionType === 1 || row?.actionType === 2 ? 'text-orange' : ''">
  139. <HcIcon v-if="row.isLock === 1" name="lock" style=" color:red;font-weight: bold;" />
  140. <HcIcon v-else name="lock-unlock" style=" color:green;font-weight: bold;" />
  141. {{ row?.name }}
  142. </span>
  143. </template>
  144. <template #action="{ row }">
  145. <el-link
  146. v-loading="row.consultLoading"
  147. class="view-file-link"
  148. type="primary"
  149. @click.stop="consultFileClick(row, 1)"
  150. >
  151. 查阅案卷
  152. </el-link>
  153. </template>
  154. </HcTable>
  155. </div>
  156. <div v-if="tableFileShow" class="hc-f-table-box" :style="{ flex: tableFileShow ? 'auto' : '0' }">
  157. <div class="header-box">
  158. <div class="header">卷内文件</div>
  159. <el-tooltip
  160. effect="light"
  161. content="按住鼠标拖动可改变表格高度"
  162. placement="top"
  163. >
  164. <HcIcon class="hc-icon-close text-hover" name="arrow-up-double" style="color:rgb(64, 149, 229);" @mousedown="startDrag($event)" />
  165. </el-tooltip>
  166. <div>
  167. <HcTooltip keys="archives_tuning_btn_insert">
  168. <el-button hc-btn type="success" size="small" :disabled="intableCheckedKeys.length <= 0" @click="insertClick">
  169. 插卷
  170. </el-button>
  171. </HcTooltip>
  172. <el-button hc-btn type="primary" size="small" @click="batchEditClick(2)">
  173. 编辑
  174. </el-button>
  175. <el-button hc-btn type="warning" size="small" @click="closetableFile(2)">
  176. 删除
  177. </el-button>
  178. </div>
  179. </div>
  180. <div v-loading="intableLoading" class="hc-file-table-box">
  181. <HcTable
  182. ref="tableFileRef" :check-style="{ width: 29 }" :column="innertableColumn" :datas="intableData"
  183. :index-style="{ width: 60 }" :loading="intableLoading" is-check is-new
  184. @selection-change="intableSelection"
  185. >
  186. <template #table-column-header-num>
  187. <HcTooltip keys="archives_tuning_btn_sort">
  188. <span class="text-link text-lg" @click="intableSortClick">
  189. <HcIcon class="text-hover" name="arrow-up-down" />
  190. </span>
  191. </HcTooltip>
  192. </template>
  193. <template #fileName="{ row }">
  194. <span class="text-link text-hover" @click="viewfilePdf(row)">{{ row?.fileName }}</span>
  195. </template>
  196. <template #action="{ row }">
  197. <el-link
  198. class="view-file-link"
  199. type="primary"
  200. @click.stop="viewfilePdf(row)"
  201. >
  202. 查阅文件
  203. </el-link>
  204. </template>
  205. </HcTable>
  206. <!-- <HcPages :pages="insearchForm" @change="inpageChange"/> -->
  207. </div>
  208. </div>
  209. </div>
  210. <template #action>
  211. <HcPages :pages="searchForm" :sizes="[20, 50, 100, 200, 300, 500]" @change="pageChange" />
  212. </template>
  213. </hc-new-card>
  214. <!-- 跨目录移动 -->
  215. <hc-new-dialog v-model="movesModal" :loading="movesModalLoading" is-table title="跨目录移动" widths="80vw" @close="movesModalClose" @save="movesModalSave">
  216. <div class="hc-moves-transfer-box">
  217. <div class="hc-moves-transfer-panel">
  218. <div class="panel-header">
  219. <div class="panel-header-label">
  220. <el-checkbox v-model="movesCheckAll" :indeterminate="isIndeterminate" class="space size-xl" @change="handleCheckAllChange">
  221. 选择需要迁移的文件
  222. </el-checkbox>
  223. </div>
  224. <div class="panel-header-extra">{{ checkedMoves.length }}/{{ tableCheckedKeys.length }}</div>
  225. </div>
  226. <div class="panel-body">
  227. <el-scrollbar>
  228. <el-checkbox-group v-model="checkedMoves" @change="handleCheckedMovesChange">
  229. <div v-for="item in tableCheckedKeys" :key="item.id" class="hc-file-checkbox">
  230. <el-checkbox :value="item.id" class="space size-xl">{{ item.name }}</el-checkbox>
  231. </div>
  232. </el-checkbox-group>
  233. </el-scrollbar>
  234. </div>
  235. </div>
  236. <div class="hc-moves-transfer-buttons">
  237. <!-- <el-button hc-btn _icon size="small"
  238. :type="tableCheckedKeys.length <= 0 || checkedMoves.length <= 0 ? '' : 'primary'"
  239. :disabled="tableCheckedKeys.length <= 0 || checkedMoves.length <= 0">
  240. <HcIcon name="arrow-right"/>
  241. </el-button> -->
  242. <HcIcon name="arrow-right-double" style="font-size: 22px;" type="primary" />
  243. </div>
  244. <div class="hc-moves-transfer-panel">
  245. <div class="panel-header">选择移动目录</div>
  246. <div class="panel-body">
  247. <el-scrollbar>
  248. <HcTree :contract-id="contractId" :is-show-menu="false" :project-id="projectId" id-prefix="hc-tree-moves-" is-radio @noderadio="nodeRadio" />
  249. </el-scrollbar>
  250. </div>
  251. </div>
  252. </div>
  253. </hc-new-dialog>
  254. <!-- 调整排序 -->
  255. <hc-new-dialog v-model="sortModal" is-table title="调整排序" widths="980px" :loading="sortModalLoading" @close="sortModalClose" @save="sortModalSave">
  256. <el-alert :closable="false" title="可拖动排序,也可在后面点击图标,切换排序" type="error" />
  257. <div class="hc-table-h">
  258. <HcTable
  259. :column="sortTableColumn" :datas="sortTableData" :index-style="{ width: 60 }"
  260. :loading="sortTableLoading" is-new
  261. is-row-drop ui="hc-table-row-drop" @row-drop="sortTableRowDrop"
  262. >
  263. <template #action="{ index }">
  264. <span class="text-link text-xl" @click="upSortClick(index)">
  265. <HcIcon fill name="arrow-up" />
  266. </span>
  267. <span class="text-link ml-2 text-xl" @click="downSortClick(index)">
  268. <HcIcon fill name="arrow-down" />
  269. </span>
  270. </template>
  271. </HcTable>
  272. </div>
  273. </hc-new-dialog>
  274. <!-- 编辑案卷信息 -->
  275. <hc-new-dialog v-model="showUploadModal" :title="editTitle" widths="80vw">
  276. <template #search>
  277. <el-button hc-btn type="primary" :disabled="tableCheckedKeysUpload.length === 0" @click="replaceClickCollect">
  278. 查找替换
  279. </el-button>
  280. </template>
  281. <HcTable
  282. ref="tableUploadRef"
  283. :column="tableUploadColumn" :datas="tableUploadData" :index-style="{ width: 60 }"
  284. :loading="uploadSaveLoading" is-new ui="hc-form-table" is-check @selection-change="uploadTableSelection"
  285. >
  286. <template #name="{ row }">
  287. <el-input v-model="row.name" :class="row.isFileNumber ? 'is-error' : ''" type="textarea" :autosize="{ minRows: 2, maxRows: 5 }" @input="tableIsInput($event, row, 'name')" />
  288. </template>
  289. <template #fileNumber="{ row }">
  290. <el-input v-model="row.fileNumber" :class="row.isFileNumber ? 'is-error' : ''" @input="tableIsInput($event, row, 'isFileNumber')" />
  291. </template>
  292. <template #fileName="{ row }">
  293. <el-input v-model="row.fileName" :class="row.isFileName ? 'is-error' : ''" type="textarea" @input="tableIsInput($event, row, 'isFileName')" />
  294. </template>
  295. <template v-if="editType === 2" #fileTime="{ row }">
  296. <el-date-picker v-model="row.fileTime" :clearable="false" format="YYYYMMDD" type="date" value-format="YYYYMMDD" />
  297. </template>
  298. <template #unit="{ row }">
  299. <el-input v-model="row.unit" />
  300. </template>
  301. <template #remark="{ row }">
  302. <el-input v-model="row.remark" type="textarea" />
  303. </template>
  304. <template #storageTime="{ row }">
  305. <el-select v-model="row.storageTime" placeholder="请选择" clearable>
  306. <el-option v-for="item in retentionPeriod" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
  307. </el-select>
  308. </template>
  309. </HcTable>
  310. <template #footer>
  311. <div class="lr-dialog-footer">
  312. <div class="left flex items-center" />
  313. <div class="right">
  314. <el-button size="large" @click="batchUploadCancel">
  315. <HcIcon name="close" />
  316. <span>取消</span>
  317. </el-button>
  318. <el-button :disabled="uploadSaveLoading" :loading="uploadSaveLoading" hc-btn type="primary" @click="batchUploadSave">
  319. <HcIcon name="save" />
  320. <span>保存</span>
  321. </el-button>
  322. </div>
  323. </div>
  324. </template>
  325. </hc-new-dialog>
  326. <!-- 查找替换弹窗 -->
  327. <hc-new-dialog v-model="showReplaceModal" widths="50vw" :loading="saveReplaceLoad" @save="saveReplace">
  328. <template #header>
  329. <div class="text-1xl mt-2 text-center font-bold">
  330. {{ replaceTitle }}
  331. </div>
  332. </template>
  333. <div class="replace-dialog-content">
  334. <div class="text-center">
  335. <el-radio-group v-model="tabPosition" style="margin-bottom: 30px" @change="changeTab">
  336. <el-radio-button value="1">新增</el-radio-button>
  337. <el-radio-button value="2">替换</el-radio-button>
  338. <el-radio-button value="3">删除</el-radio-button>
  339. </el-radio-group>
  340. </div>
  341. <el-form
  342. ref="ruleFormRef"
  343. :model="ruleForm"
  344. label-width="auto"
  345. size="large"
  346. >
  347. <el-form-item v-if="tabPosition !== '3'" label="查找内容" prop="query">
  348. <el-input v-model="ruleForm.query" placeholder="请输入原内容" />
  349. </el-form-item>
  350. <el-form-item v-if="tabPosition === '1'" label="新增内容" prop="replace">
  351. <el-input
  352. v-model="ruleForm.replace"
  353. placeholder="请输入新增内容"
  354. />
  355. </el-form-item>
  356. <el-form-item v-if="tabPosition === '2'" label="替换内容" prop="replace">
  357. <el-input
  358. v-model="ruleForm.replace"
  359. placeholder="请输入替换后内容"
  360. />
  361. </el-form-item>
  362. <el-form-item v-if="tabPosition === '3'" label="删除内容" prop="query">
  363. <el-input
  364. v-model="ruleForm.query"
  365. placeholder="请输入原内容"
  366. />
  367. </el-form-item>
  368. <el-form-item v-if="tabPosition === '1'" label="定位条件" prop="position">
  369. <el-select
  370. v-model="ruleForm.position"
  371. placeholder="请选择"
  372. >
  373. <el-option
  374. label="前"
  375. :value="1"
  376. />
  377. <el-option
  378. label="后"
  379. :value="2"
  380. />
  381. </el-select>
  382. </el-form-item>
  383. <el-form-item label="作用范围">
  384. <span>{{ checkInfo }}</span>
  385. </el-form-item>
  386. </el-form>
  387. </div>
  388. </hc-new-dialog>
  389. <!-- 新增重组弹窗 -->
  390. <hc-new-dialog v-model="mergeModalBefore" :loading="mergeModalBeforeLoading" widths="15vw" @close="mergeModalBeforeClose" @save="mergeModalBeforeClick">
  391. <template #header>
  392. <div class="text-1xl mt-2 text-center font-bold">
  393. 并卷或重组
  394. </div>
  395. </template>
  396. <el-radio-group v-model="mergeModalBeforeType">
  397. <el-radio value="1" size="large">并卷</el-radio>
  398. <el-radio value="2" size="large">重组</el-radio>
  399. </el-radio-group>
  400. </hc-new-dialog>
  401. <hc-new-dialog v-model="mergeModal" :loading="combinationClickLoading" widths="50vw" @close="mergeModalClose" @save="combinationClick">
  402. <template #header>
  403. <div class="text-1xl mt-2 text-center font-bold">
  404. 案卷题名修改(并卷后)
  405. </div>
  406. </template>
  407. <hc-table :column="mergeDataColumn" :datas="mergeData" heights="300" :is-index="false" />
  408. <div class="mb-4 mt-4 text-orange font-800">
  409. 并卷后题名
  410. </div>
  411. <el-input v-model="mergeInput" placeholder="请输入并卷后题名" type="textarea" class="blue-text" :autosize="{ minRows: 4, maxRows: 8 }" />
  412. </hc-new-dialog>
  413. <!-- 档案整理弹窗 -->
  414. <hc-new-dialog v-model="fileNumberModal" :loading="refreshFileNumberLoading" widths="30vw" @close="fileModalClose" @save="refreshFileNumberClick">
  415. <template #header>
  416. <div class="text-1xl mt-2 text-center font-bold">
  417. 起始流水号
  418. </div>
  419. </template>
  420. <el-input v-model="startNumber" placeholder="请输入数值1、2、3" class="blue-text" @input="handleNumberInput" />
  421. </hc-new-dialog>
  422. <!-- 排序弹窗 -->
  423. <hc-new-dialog v-model="sortModalDialog" :loading="sortModalDialogLoading" widths="20vw" @close="sortModalDialogClose" @save="sortModalDialogClick">
  424. <template #header>
  425. <div class="text-1xl mt-2 text-center font-bold">
  426. 选择排序规则
  427. </div>
  428. </template>
  429. <el-radio-group v-model="sortTypeVal">
  430. <el-radio value="1" size="large">按节点排序</el-radio>
  431. <el-radio value="2" size="large">按流水号排序</el-radio>
  432. </el-radio-group>
  433. </hc-new-dialog>
  434. <!-- 展开案卷 -->
  435. <CarrySpotChecksDrawer :show="spotChecksDrawer" :file-id="fileId" :checkmeta-file-id="checkmetaFileId" @close="onCarrySpotChecksClose" />
  436. <!-- 卷内编辑查找替换弹窗 -->
  437. <hc-new-dialog v-model="showReplaceModalCollect" widths="50vw" :loading="saveReplaceLoadCollect" @save="saveReplaceCollect">
  438. <template #header>
  439. <div class="text-1xl mt-2 text-center font-bold">
  440. {{ replaceTitleCollect }}
  441. </div>
  442. </template>
  443. <div class="replace-dialog-content">
  444. <div class="text-center">
  445. <el-radio-group v-model="tabPositionCollect" style="margin-bottom: 30px" @change="changeTab">
  446. <el-radio-button value="1">新增</el-radio-button>
  447. <el-radio-button value="2">替换</el-radio-button>
  448. <el-radio-button value="3">删除</el-radio-button>
  449. </el-radio-group>
  450. </div>
  451. <el-form
  452. ref="ruleFormRef"
  453. :model="ruleFormCollect"
  454. label-width="auto"
  455. size="large"
  456. >
  457. <el-form-item v-if="tabPositionCollect !== '3'" label="查找内容" prop="query">
  458. <el-input v-model="ruleFormCollect.query" placeholder="请输入原内容" />
  459. </el-form-item>
  460. <el-form-item v-if="tabPositionCollect === '1'" label="新增内容" prop="replace">
  461. <el-input
  462. v-model="ruleFormCollect.replace"
  463. placeholder="请输入新增内容"
  464. />
  465. </el-form-item>
  466. <el-form-item v-if="tabPositionCollect === '2'" label="替换内容" prop="replace">
  467. <el-input
  468. v-model="ruleFormCollect.replace"
  469. placeholder="请输入替换后内容"
  470. />
  471. </el-form-item>
  472. <el-form-item v-if="tabPositionCollect === '3'" label="删除内容" prop="query">
  473. <el-input
  474. v-model="ruleFormCollect.query"
  475. placeholder="请输入原内容"
  476. />
  477. </el-form-item>
  478. <el-form-item v-if="tabPositionCollect === '1'" label="定位条件" prop="position">
  479. <el-select
  480. v-model="ruleFormCollect.position"
  481. placeholder="请选择"
  482. >
  483. <el-option
  484. label="前"
  485. :value="1"
  486. />
  487. <el-option
  488. label="后"
  489. :value="2"
  490. />
  491. </el-select>
  492. </el-form-item>
  493. </el-form>
  494. </div>
  495. </hc-new-dialog>
  496. <!-- 插卷弹窗 -->
  497. <FileInsertModal ref="fileInsertModalRef" @close="closeFileModal" />
  498. </hc-body>
  499. </template>
  500. <script setup>
  501. import { nextTick, onActivated, onMounted, ref, watch } from 'vue'
  502. import { useAppStore } from '~src/store'
  503. import HcTree from '~src/components/tree/hc-tree.vue'
  504. import { arrToId, deepClone, getArrValue } from 'js-fast-way'
  505. import { rowsToId, rowsToIdNumArr } from '~uti/tools'
  506. import tuningApi from '~api/archiveConfig/tuning.js'
  507. import archiveFileApi from '~api/archiveFile/archiveFileAuto.js'
  508. import archiveFileApiCollect from '~api/archiveFile/archiveFile'
  509. import aiApi from '~api/ai/ai.js'
  510. import { HcDelMsg } from 'hc-vue3-ui'
  511. import { getStoreValue, setStoreValue } from '~src/utils/storage'
  512. import { toPdfPage } from '~uti/btn-auth'
  513. import { getDictionaryBiz } from '~api/other'
  514. import CarrySpotChecksDrawer from './carryDrawer/carrySpotChecksDrawer.vue'
  515. import tasksApi from '~api/tasks/data'
  516. import { useRouter } from 'vue-router'
  517. import FileInsertModal from './FileInsertModal.vue'
  518. //变量
  519. const router = useRouter()
  520. const useAppState = useAppStore()
  521. const projectId = ref(useAppState.getProjectId)
  522. const contractId = ref(useAppState.getContractId)
  523. const projectInfo = ref(useAppState.getProjectInfo)
  524. const isCollapse = ref(useAppState.getCollapse)
  525. const hoverHand = ref(true)
  526. const AppTheme = ref(useAppState.getTheme)
  527. //监听
  528. watch(() => [
  529. useAppState.getCollapse,
  530. useAppState.getTheme,
  531. ], ([Collapse, theme]) => {
  532. isCollapse.value = Collapse
  533. AppTheme.value = theme
  534. })
  535. //渲染完成
  536. onMounted(() => {
  537. // getClassIfyList()
  538. getOptions()
  539. setTableColumns()
  540. getStoragePeriod()
  541. })
  542. onActivated(() => {
  543. // getClassIfyList()
  544. getTableData()
  545. })
  546. const tableFileRef = ref(null)
  547. //树加载
  548. const treeLoading = ref(true)
  549. const treeNodeLoading = () => {
  550. treeLoading.value = false
  551. }
  552. //项目树被点击
  553. //自动展开缓存
  554. const treeAutoExpandKeys = ref(getStoreValue('turningExpandKeys') || [])
  555. const nodeElTreeClick = ({ node, data, keys, key }) => {
  556. //缓存展开的节点
  557. setStoreValue('turningExpandKeys', keys)
  558. treeAutoExpandKeys.value = keys || []
  559. searchForm.value.total = 0
  560. searchForm.value.current = 1
  561. // searchForm.value.size = 20
  562. searchForm.value.nodeIds = data.id || ''
  563. getTableData()
  564. }
  565. //树菜单被点击
  566. const ElTreeMenuClick = async ({ key, node, data, keys }) => {
  567. setStoreValue('turningExpandKeys', keys)
  568. treeAutoExpandKeys.value = keys || []
  569. }
  570. const nodeRadio = ({ node, data, keys, key }) => {
  571. console.log(data, 'data33333')
  572. chnodeId.value = data.id || ''
  573. console.log(chnodeId.value, ' chnodeId.value')
  574. }
  575. //搜索表单
  576. const searchForm = ref({
  577. contractId: null, type: null, approval: null,
  578. current: 1, size: 20, total: 0,
  579. })
  580. const insearchForm = ref({
  581. contractId: null, type: null, approval: null,
  582. current: 1, size: 1000, total: 0,
  583. })
  584. //分页被点击
  585. const pageChange = ({ current, size }) => {
  586. searchForm.value.current = current
  587. searchForm.value.size = size
  588. getTableData()
  589. }
  590. //表格数据
  591. const tableRef = ref(null)
  592. const tableColumn = ref([])
  593. //设置表头
  594. const setTableColumns = () => {
  595. tableColumn.value = [
  596. { key: 'fileNumber', name: '档号' },
  597. { key: 'name', name: '案卷题名', width: 500 },
  598. { key: 'storageTimeValue', name: '保管期限' },
  599. { key: 'pageN', name: '总页数' },
  600. { key: 'action', name: '操作', width:100 },
  601. ]
  602. }
  603. //回车搜索
  604. const keyUpEvent = (e) => {
  605. if (e.key === 'Enter') {
  606. searchForm.value.current = 1
  607. getTableData()
  608. }
  609. }
  610. //搜索
  611. const searchClick = () => {
  612. searchForm.value.current = 1
  613. getTableData()
  614. }
  615. const tableData = ref([])
  616. //获取数据
  617. const tableLoading = ref(false)
  618. const getTableData = async () => {
  619. tableFileShow.value = false
  620. tableLoading.value = true
  621. const { error, code, data } = await tuningApi.pageByArchive({
  622. ...searchForm.value,
  623. projectId: projectId.value,
  624. contractId: contractId.value,
  625. isArchive: 1,
  626. })
  627. tableLoading.value = false
  628. if (!error && code === 200) {
  629. tableData.value = getArrValue(data?.records)
  630. searchForm.value.total = data?.total || 0
  631. } else {
  632. tableData.value = []
  633. searchForm.value.total = 0
  634. }
  635. }
  636. const queryValueSizeOption = ref([])
  637. const getOptions = async () => {//内业资料类型
  638. const { data, code } = await getDictionaryBiz({ code: 'queryValueSize' })
  639. if (code === 200) {
  640. queryValueSizeOption.value = data
  641. }
  642. }
  643. const innertableColumn = ref([])
  644. const intableData = ref([])
  645. //设置表头
  646. const setInnertableColumn = () => {
  647. innertableColumn.value = [
  648. { key: 'fileNumber', name: '文件编号' },
  649. { key: 'fileName', name: '文件题名', width: 500 },
  650. { key: 'fileTime', name: '文件日期' },
  651. { key: 'dutyUser', name: '责任者' },
  652. { key: 'filePage', name: '页数' },
  653. { key: 'action', width:100, name:'操作' },
  654. ]
  655. }
  656. const intableLoading = ref(false)
  657. //获取卷内文件
  658. const getintableData = async () => {
  659. intableLoading.value = true
  660. const { error, code, data } = await tuningApi.getarchiveFilePage({
  661. ...insearchForm.value,
  662. // nodeIds: searchForm.value.nodeIds,
  663. archiveId: checkInid.value,
  664. })
  665. intableLoading.value = false
  666. if (!error && code === 200) {
  667. intableData.value = getArrValue(data['records'])
  668. insearchForm.value.total = data['total'] || 0
  669. } else {
  670. intableData.value = []
  671. insearchForm.value.total = data['total'] || 0
  672. }
  673. }
  674. //多选
  675. const tableCheckedKeys = ref([])
  676. const intableCheckedKeys = ref([])
  677. const tableSelection = (rows) => {
  678. tableCheckedKeys.value = rows
  679. }
  680. const tableRowStyle = ({ row }) => {
  681. // 只根据inType属性判断样式,确保排序后依然有效
  682. if (row?.actionType === 1 || row?.actionType === 2) {
  683. return 'color: orange;'
  684. }
  685. }
  686. const inTableRowStyle = ({ row }) => {
  687. // 只根据inType属性判断样式,确保排序后依然有效
  688. if (row?.pageNum === '') {
  689. return 'color: orange;'
  690. }
  691. }
  692. const intableSelection = (rows) => {
  693. intableCheckedKeys.value = rows
  694. }
  695. const isDragging = ref(false) // 添加一个标志来跟踪鼠标是否按下
  696. const startDrag = (event) => {
  697. isDragging.value = true // 鼠标按下时设置标志为true
  698. const startY = event.clientY
  699. const initialHeight = document.querySelector('.hc-f-table-box').offsetHeight
  700. document.onmousemove = (moveEvent) => {
  701. console.log(isDragging.value, 'isDragging.value')
  702. if (isDragging.value) { // 确保只有在鼠标按下时才会改变高度
  703. const moveY = moveEvent.clientY
  704. const deltaY = startY - moveY // 修改这里,使用 startY 减去 moveY
  705. const newHeight = Math.max(50, initialHeight + deltaY) // 最小高度设为50
  706. document.querySelector('.hc-f-table-box').style.height = `${newHeight}px`
  707. }
  708. }
  709. document.onmouseup = () => {
  710. document.onmousemove = null
  711. document.onmouseup = null
  712. isDragging.value = false // 鼠标释放时设置标志为false
  713. }
  714. }
  715. //删除
  716. const delModalClick = () => {
  717. let ids = ''
  718. const rows = intableCheckedKeys.value
  719. ids = rowsToId(rows)
  720. if (rows.length > 0) {
  721. window?.$messageBox?.alert('请谨慎考虑是否要批量删除卷内文件?', '删除文件', {
  722. showCancelButton: true,
  723. confirmButtonText: '确认删除',
  724. cancelButtonText: '取消',
  725. type: 'warning',
  726. callback: async (action, ctx, close) => {
  727. ctx.confirmButtonLoading = true
  728. if (action === 'confirm') {
  729. const { error, code, data, msg } = await tuningApi.removeFiles({
  730. ids: ids,
  731. archiveId: checkInid.value,
  732. })
  733. ctx.confirmButtonLoading = false
  734. if (!error && code === 200) {
  735. window.$message?.success(msg)
  736. getintableData()
  737. } else {
  738. window.$message?.warning(msg)
  739. }
  740. }
  741. },
  742. })
  743. } else {
  744. window.$message.warning('请先选择文件')
  745. }
  746. }
  747. const splitLoad = ref(false)
  748. const tunModalClick = () => {
  749. const rows = tableCheckedKeys.value
  750. let iscansplit = rows.filter((item) => {
  751. if (item?.isLock === 1) {
  752. return item
  753. }
  754. })
  755. if (iscansplit.length > 0) {
  756. window.$message.warning('选择的案卷已被锁定,不允许拆卷')
  757. } else {
  758. splitLoad.value = true
  759. window?.$messageBox?.alert('请谨慎考虑是否要批量拆除已经案卷及卷内文件?', '拆除案卷', {
  760. showCancelButton: true,
  761. confirmButtonText: '确认拆卷',
  762. cancelButtonText: '取消',
  763. type: 'warning',
  764. callback: async (action, ctx, close) => {
  765. if (action === 'confirm') {
  766. console.log(1111)
  767. ctx.confirmButtonLoading = true
  768. let ids = ''
  769. ids = rowsToId(rows)
  770. const { error, code, data, msg } = await tuningApi.splitArchive({
  771. ids: ids,
  772. })
  773. ctx.confirmButtonLoading = true
  774. if (!error && code === 200) {
  775. window.$message?.success(msg)
  776. getTableData()
  777. } else {
  778. window.$message?.error(msg)
  779. }
  780. }
  781. },
  782. })
  783. }
  784. }
  785. //左右拖动,改变树形结构宽度
  786. const leftWidth = ref(382)
  787. const onmousedown = () => {
  788. const leftNum = isCollapse.value ? 142 : 272
  789. document.onmousemove = (ve) => {
  790. let diffVal = ve.clientX - leftNum
  791. if (diffVal >= 310 && diffVal <= 900) {
  792. leftWidth.value = diffVal
  793. }
  794. }
  795. document.onmouseup = () => {
  796. document.onmousemove = null
  797. document.onmouseup = null
  798. }
  799. }
  800. //跨目录移动
  801. const movesModal = ref(false)
  802. const movesClick = () => {
  803. movesModal.value = true
  804. }
  805. //选择需要迁移的文件
  806. const movesCheckAll = ref(false)
  807. const isIndeterminate = ref(true)
  808. const checkedMoves = ref([])
  809. //全选
  810. const handleCheckAllChange = (val) => {
  811. const checked = tableCheckedKeys.value
  812. const keys = rowsToIdNumArr(checked)
  813. checkedMoves.value = val ? keys : []
  814. isIndeterminate.value = false
  815. }
  816. //勾选
  817. const handleCheckedMovesChange = (value) => {
  818. const keys = tableCheckedKeys.value
  819. const checkedCount = value.length
  820. movesCheckAll.value = checkedCount === keys.length
  821. isIndeterminate.value = checkedCount > 0 && checkedCount < keys.length
  822. }
  823. //保存
  824. const movesModalLoading = ref(false)
  825. const chnodeId = ref('')
  826. const movesModalSave = async () => {
  827. movesModalLoading.value = true
  828. console.log(checkedMoves.value, 'checkedMoves.value')
  829. let ids = checkedMoves.value.join(',')
  830. const { error, code, data, msg } = await tuningApi.moveArchive({
  831. ids: ids,
  832. nodeId: chnodeId.value,
  833. })
  834. movesModalLoading.value = false
  835. if (!error && code === 200) {
  836. console.log(msg, 'msg')
  837. window.$message?.success(msg)
  838. getTableData()
  839. } else {
  840. window.$message?.warning(msg)
  841. }
  842. movesModal.value = false
  843. }
  844. //关闭
  845. const movesModalClose = () => {
  846. movesModal.value = false
  847. }
  848. //表格排序
  849. const sortModal = ref(false)
  850. //显示
  851. const intableSortClick = () => {
  852. sortModal.value = true
  853. sortType.value = 2
  854. setsortTableColumn()
  855. getSortTableData()
  856. }
  857. //表格行被点击
  858. const tableFileShow = ref(false)
  859. const checkInid = ref('')
  860. const checkRow = ref({})
  861. const tableRowClick = ({ row }) => {
  862. tableFileShow.value = true
  863. intableLoading.value = true
  864. checkRow.value = row
  865. checkInid.value = row.id
  866. fileId.value = row.id
  867. setInnertableColumn()
  868. getintableData()
  869. // 限制 hc-f-table-box 的初始高度不超过容器的一半
  870. nextTick(()=>{
  871. const containerHeight = document.querySelector('.flex-container').clientHeight
  872. const maxHeight = containerHeight / 6
  873. const initialHeight = Math.min(document.querySelector('.hc-f-table-box').offsetHeight, maxHeight)
  874. document.querySelector('.hc-f-table-box').style.height = `${initialHeight}px`
  875. })
  876. }
  877. //收起卷内文件
  878. const closetableFile = () => {
  879. tableFileShow.value = false
  880. }
  881. //卷内文件点击
  882. //搜索表单
  883. const sortSearchForm = ref({
  884. current: 1, size: 20, total: 0,
  885. })
  886. //分页被点击
  887. const sortPageChange = ({ current, size }) => {
  888. searchForm.value.current = current
  889. searchForm.value.size = size
  890. getSortTableData()
  891. }
  892. const setsortTableColumn = () => {
  893. if (sortType.value === 1) {
  894. sortTableColumn.value = [
  895. { key: 'fileNumber', name: '档号', width: 160 },
  896. { key: 'name', name: '案卷名称' },
  897. { key: 'action', name: '排序', width: 90 },
  898. ]
  899. } else if (sortType.value === 2) {
  900. sortTableColumn.value = [
  901. { key: 'fileNumber', name: '文件编号', width: 160 },
  902. { key: 'fileName', name: '文件名称' },
  903. { key: 'action', name: '排序', width: 90 },
  904. ]
  905. }
  906. }
  907. //表格数据
  908. const sortTableColumn = ref([
  909. { key: 'fileNumber', name: '档号', width: 160 },
  910. { key: 'name', name: '案卷名称' },
  911. { key: 'action', name: '排序', width: 90 },
  912. ])
  913. const sortTableData = ref([])
  914. const sortTableLoading = ref(false)
  915. const sortType = ref(null)
  916. const getSortTableData = async () => {
  917. if (sortType.value === 1) {
  918. sortTableLoading.value = true
  919. const { error, code, data } = await tuningApi.pageByArchive({
  920. ...searchForm.value,
  921. projectId: projectId.value,
  922. contractId: contractId.value,
  923. isArchive: 0,
  924. })
  925. sortTableLoading.value = false
  926. if (!error && code === 200) {
  927. sortTableData.value = getArrValue(data['records'])
  928. sortSearchForm.value.total = data['total'] || 0
  929. } else {
  930. sortTableData.value = []
  931. sortSearchForm.value.total = 0
  932. }
  933. } else if (sortType.value === 2) {
  934. sortTableLoading.value = true
  935. const { error, code, data } = await tuningApi.getarchiveFilePage({
  936. ...insearchForm.value,
  937. nodeIds: searchForm.value.nodeIds,
  938. archiveId: checkInid.value,
  939. })
  940. sortTableLoading.value = false
  941. if (!error && code === 200) {
  942. sortTableData.value = getArrValue(data['records'])
  943. sortSearchForm.value.total = data['total'] || 0
  944. } else {
  945. sortTableData.value = []
  946. sortSearchForm.value.total = 0
  947. }
  948. }
  949. sortSearchForm.value.current = 1
  950. }
  951. //拖动完成
  952. const sortTableRowDrop = (rows) => {
  953. sortTableData.value = rows
  954. }
  955. //向下
  956. const downSortClick = (index) => {
  957. const indexs = index + 1
  958. const data = sortTableData.value
  959. if (indexs !== data.length) {
  960. const tmp = data.splice(indexs, 1)
  961. sortTableData.value.splice(index, 0, tmp[0])
  962. } else {
  963. window?.$message?.warning('已经处于置底,无法下移')
  964. }
  965. }
  966. //向上
  967. const upSortClick = (index) => {
  968. const data = sortTableData.value || []
  969. if (index !== 0) {
  970. const tmp = data.splice(index - 1, 1)
  971. sortTableData.value.splice(index, 0, tmp[0])
  972. } else {
  973. window?.$message?.warning('已经处于置顶,无法上移')
  974. }
  975. }
  976. //保存
  977. const sortModalLoading = ref(false)
  978. const sortModalSave = async () => {
  979. sortModalLoading.value = true
  980. const { error, code } = await tuningApi.archiveFileBatchUpdate({
  981. list: sortTableData.value,
  982. }, false)
  983. //判断状态
  984. sortModalLoading.value = false
  985. if (!error && code === 200) {
  986. sortModal.value = false
  987. getintableData()
  988. } else {
  989. window.$message?.error('保存失败')
  990. }
  991. }
  992. //关闭
  993. const sortModalClose = () => {
  994. sortModal.value = false
  995. }
  996. //编辑
  997. const showUploadModal = ref(false)
  998. const isBuiltDrawing = ref(0)
  999. const editTitle = ref('')
  1000. const editType = ref()
  1001. //批量上传保存
  1002. const uploadSaveLoading = ref(false)
  1003. //批量编辑
  1004. //批量编辑
  1005. const batchEditClick = (type) => {
  1006. let rows = []
  1007. if (type === 1) {
  1008. editTitle.value = '编辑案卷信息'
  1009. editType.value = 1
  1010. rows = deepClone(tableCheckedKeys.value)
  1011. // 检查是否有被锁定的案卷
  1012. const lockedArchives = tableCheckedKeys.value.filter(item => item.isLock === 1)
  1013. if (lockedArchives.length > 0) {
  1014. window.$message.warning('选择的案卷中包含被锁定的项,无法更新')
  1015. return
  1016. }
  1017. } else {
  1018. editTitle.value = '编辑文件信息'
  1019. editType.value = 2
  1020. rows = deepClone(intableCheckedKeys.value)
  1021. }
  1022. //判断状态
  1023. setTableUploadColumn(type)
  1024. uploadSaveLoading.value = false
  1025. tableUploadData.value = rows
  1026. console.log(checkRow.value, 'checkRow.value')
  1027. if (checkRow.value?.isLock !== 1) {
  1028. if (rows.length > 0) {
  1029. showUploadModal.value = true
  1030. } else {
  1031. window.$message.warning('请先选择文件')
  1032. }
  1033. } else {
  1034. window.$message.warning('该案卷已被锁定,不允许编辑卷内文件')
  1035. }
  1036. }
  1037. //设置文件表头
  1038. //保管期限
  1039. const retentionPeriod = ref([
  1040. ])
  1041. const getStoragePeriod = async () => {
  1042. const { error, code, data } = await tasksApi.queryTaskTypeStatus({
  1043. typeOrStatus: 'storage_period',
  1044. })
  1045. //处理数据
  1046. if (!error && code === 200) {
  1047. retentionPeriod.value = getArrValue(data)
  1048. retentionPeriod.value = retentionPeriod.value.filter(item=>item.dictKey !== '0')
  1049. } else {
  1050. retentionPeriod.value = []
  1051. }
  1052. }
  1053. const tableUploadRef = ref(null)
  1054. const tableUploadColumn = ref([])
  1055. const setTableUploadColumn = (type) => {
  1056. if (type === 1) {
  1057. tableUploadColumn.value = [
  1058. { key: 'fileNumber', name: '档号', width:160 },
  1059. { key: 'name', name: '案卷题名' },
  1060. { key: 'storageTime', name: '保管期限', width:100 },
  1061. { key: 'unit', name: '立卷单位', width:200 },
  1062. { key: 'remark', name: '备注', width:180 },
  1063. ]
  1064. } else {
  1065. tableUploadColumn.value = [
  1066. { key: 'fileNumber', name: '文件编号' },
  1067. { key: 'fileName', name: '文件题名', width:500 },
  1068. { key: 'fileTime', name: '文件日期' },
  1069. { key: 'dutyUser', name: '责任者' },
  1070. ]
  1071. }
  1072. }
  1073. const tableUploadData = ref([])
  1074. const batchUploadCancel = () => {
  1075. showUploadModal.value = false
  1076. tableUploadData.value = []
  1077. }
  1078. //多选
  1079. const tableCheckedKeysUpload = ref([])
  1080. const uploadTableSelection = (rows) => {
  1081. tableCheckedKeysUpload.value = rows
  1082. }
  1083. //确认上传保存
  1084. const batchUploadSaveApi = async (rows) => {
  1085. uploadSaveLoading.value = true
  1086. const { error, code } = await archiveFileApi.batchUploadSave({
  1087. list: rows,
  1088. }, false)
  1089. //判断状态
  1090. uploadSaveLoading.value = false
  1091. if (!error && code === 200) {
  1092. window.$message?.success('保存成功')
  1093. batchUploadCancel()
  1094. getTableData()
  1095. } else {
  1096. window.$message?.error('保存失败')
  1097. }
  1098. }
  1099. //确认上传保存
  1100. const archiveFileBatchUpdate = async (rows) => {
  1101. uploadSaveLoading.value = true
  1102. const { error, code } = await tuningApi.archiveFileBatchUpdate({
  1103. list: rows,
  1104. }, false)
  1105. //判断状态
  1106. uploadSaveLoading.value = false
  1107. if (!error && code === 200) {
  1108. window.$message?.success('保存成功')
  1109. batchUploadCancel()
  1110. getTableData()
  1111. } else {
  1112. window.$message?.error('保存失败')
  1113. }
  1114. }
  1115. //批量新增编辑保存
  1116. const batchUploadSave = async () => {
  1117. const rows = tableUploadData.value
  1118. if (rows.length > 0) {
  1119. //验证表单数据
  1120. uploadSaveLoading.value = true
  1121. let isTableRows = false
  1122. //判断数据
  1123. if (isTableRows) {
  1124. uploadSaveLoading.value = false
  1125. window.$message?.warning('请先完善表单信息')
  1126. } else {
  1127. console.log(rows, 'rows')
  1128. if (editType.value === 2) {
  1129. //数据处理
  1130. rows.forEach((element, index) => {
  1131. const { dates } = element
  1132. element.startDate = dates ? dates[0] : null
  1133. element.endDate = dates ? dates[1] : null
  1134. element.autoFileSort = index + 1
  1135. })
  1136. await archiveFileBatchUpdate(rows)
  1137. } else {
  1138. await batchUploadSaveApi(rows)
  1139. }
  1140. // if (tableUploadType.value === 'add') {
  1141. // await batchUploadSaveApi(rows)
  1142. // } else {
  1143. // await batchEditSaveApi(rows)
  1144. // }
  1145. }
  1146. } else {
  1147. window.$message?.warning('请先上传文件')
  1148. }
  1149. }
  1150. const lockLoad = ref(false)
  1151. const unlockLoad = ref(false)
  1152. //档案锁定
  1153. const lockarchives = async () => {
  1154. lockLoad.value = true
  1155. let ids = ''
  1156. const rows = tableCheckedKeys.value
  1157. ids = rowsToId(rows)
  1158. const { error, code, data, msg } = await tuningApi.archivesautoLock({
  1159. ids: ids,
  1160. })
  1161. lockLoad.value = false
  1162. if (!error && code === 200) {
  1163. console.log(msg, 'msg')
  1164. window.$message?.success(msg)
  1165. getTableData()
  1166. } else {
  1167. window.$message?.warning(msg)
  1168. }
  1169. }
  1170. const unlockarchives = async () => {
  1171. unlockLoad.value = true
  1172. let ids = ''
  1173. const rows = tableCheckedKeys.value
  1174. ids = rowsToId(rows)
  1175. const { error, code, data, msg } = await tuningApi.archivesautoUnLock({
  1176. ids: ids,
  1177. })
  1178. unlockLoad.value = false
  1179. if (!error && code === 200) {
  1180. window.$message?.success(msg)
  1181. getTableData()
  1182. } else {
  1183. window.$message?.warning(msg)
  1184. }
  1185. }
  1186. //查看卷内文件pdf
  1187. const viewfilePdf = (row) => {
  1188. fileId.value = row.archiveId
  1189. // 先重置值,确保每次点击都能触发变化
  1190. checkmetaFileId.value = ''
  1191. spotChecksDrawer.value = false
  1192. // 使用nextTick确保DOM更新后再设置新值
  1193. nextTick(() => {
  1194. checkmetaFileId.value = row.id
  1195. spotChecksDrawer.value = true
  1196. })
  1197. }
  1198. //档号整理
  1199. const startNumber = ref('')
  1200. const fileNumberClick = ()=>{
  1201. fileNumberModal.value = true
  1202. }
  1203. const handleNumberInput = (value) => {
  1204. // 只保留数字
  1205. startNumber.value = value.replace(/[^\d]/g, '')
  1206. }
  1207. const fileModalClose = ()=>{
  1208. fileNumberModal.value = false
  1209. startNumber.value = ''
  1210. }
  1211. //档号整理弹窗
  1212. const fileNumberModal = ref(false)
  1213. const refreshFileNumberLoading = ref(false)
  1214. const refreshFileNumberClick = async () => {
  1215. if (!startNumber.value) {
  1216. window.$message?.warning('请输入起始流水号')
  1217. return
  1218. }
  1219. const { error, code, msg } = await tuningApi.refreshFileNumber({
  1220. projectId: projectId.value,
  1221. contractId: contractId.value,
  1222. nodeId: searchForm.value.nodeIds || '',
  1223. isArchive: 1,
  1224. startNumber:startNumber.value,
  1225. })
  1226. if (!error && code === 200) {
  1227. window.$message?.success(msg)
  1228. fileModalClose()
  1229. getTableData()
  1230. } else {
  1231. window.$message?.warning(msg)
  1232. }
  1233. }
  1234. //更新案卷四要素
  1235. const refreshFileFourLoading = ref(false)
  1236. const refreshFileFourClick = async ()=>{
  1237. if (tableCheckedKeys.value.length === 0) {
  1238. window.$message?.warning('请选择需要更新的案卷')
  1239. return
  1240. }
  1241. // 检查是否有被锁定的案卷
  1242. const lockedArchives = tableCheckedKeys.value.filter(item => item.isLock === 1)
  1243. if (lockedArchives.length > 0) {
  1244. window.$message.warning('选择的案卷中包含被锁定的项,无法更新')
  1245. return
  1246. }
  1247. refreshFileFourLoading.value = true
  1248. const rows = tableCheckedKeys.value
  1249. let ids = ''
  1250. ids = arrToId(rows)
  1251. const { error, code, data, msg } = await tuningApi.updateArchiveFour({
  1252. projectId: projectId.value,
  1253. archiveIds:ids,
  1254. })
  1255. refreshFileFourLoading.value = false
  1256. if (!error && code === 200) {
  1257. window.$message?.success(msg)
  1258. getTableData()
  1259. } else {
  1260. window.$message?.warning(msg)
  1261. }
  1262. }
  1263. // 查找替换弹窗相关变量
  1264. const showReplaceModal = ref(false)
  1265. // 查找替换弹窗相关变量
  1266. const replaceTitle = ref('查找替换')
  1267. const checkInfo = ref('')
  1268. // 触发查找替换弹窗显示
  1269. const replaceClick = () => {
  1270. checkInfo.value = ''
  1271. if (tableCheckedKeys.value.length === 0) {
  1272. window.$message?.warning('请选择需要更新的案卷')
  1273. return
  1274. }
  1275. // 检查是否有被锁定的案卷
  1276. const lockedArchives = tableCheckedKeys.value.filter(item => item.isLock === 1)
  1277. if (lockedArchives.length > 0) {
  1278. window.$message.warning('选择的案卷中包含被锁定的项,无法操作')
  1279. return
  1280. }
  1281. // 更新checkInfo的值
  1282. checkInfo.value = `共计${tableCheckedKeys.value.length}项,档号为${tableCheckedKeys.value.map(item => item.fileNumber).join(',')}`
  1283. ruleForm.value = {}
  1284. showReplaceModal.value = true
  1285. }
  1286. const changeTab = ()=>{
  1287. ruleForm.value = {}
  1288. }
  1289. const tabPosition = ref('1')
  1290. const ruleFormRef = ref(null)
  1291. const ruleForm = ref({})
  1292. const saveReplaceLoad = ref(false)
  1293. const saveReplace = async ()=>{
  1294. const rows = tableCheckedKeys.value
  1295. let ids = ''
  1296. ids = arrToId(rows)
  1297. // 保存前去除空格
  1298. if (ruleForm.value.query) {
  1299. ruleForm.value.query = ruleForm.value.query.trim()
  1300. }
  1301. if (ruleForm.value.replace) {
  1302. ruleForm.value.replace = ruleForm.value.replace.trim()
  1303. }
  1304. saveReplaceLoad.value = true
  1305. const { error, code, data, msg } = await tuningApi.findAndReplace({
  1306. ...ruleForm.value,
  1307. ids,
  1308. type:tabPosition.value,
  1309. })
  1310. saveReplaceLoad.value = false
  1311. if (!error && code === 200) {
  1312. window.$message?.success(msg)
  1313. showReplaceModal.value = false
  1314. getTableData()
  1315. } else {
  1316. window.$message?.warning(msg)
  1317. }
  1318. }
  1319. //并卷
  1320. const combinationClickLoading = ref(false)
  1321. const combinationClick = async ()=>{
  1322. if (!mergeInput.value) return window.$message?.warning('请输入并卷后案卷题名')
  1323. combinationClickLoading.value = true
  1324. let ids = ''
  1325. const rows = tableCheckedKeys.value
  1326. ids = rowsToId(rows)
  1327. const { error, code, data, msg } = await tuningApi.reCreateArchiveAuto({
  1328. ids: ids,
  1329. name:mergeInput.value,
  1330. type:1,
  1331. })
  1332. combinationClickLoading.value = false
  1333. if (!error && code === 200) {
  1334. window.$message?.success(msg)
  1335. getTableData()
  1336. mergeModal.value = false
  1337. mergeModalBeforeClose()
  1338. } else {
  1339. window.$message?.error(msg)
  1340. }
  1341. }
  1342. const mergeModalBefore = ref(false)
  1343. const mergeModalBeforeLoading = ref(false)
  1344. const mergeModalBeforeClose = ()=>{
  1345. mergeModalBefore.value = false
  1346. mergeModalBeforeType.value = ''
  1347. }
  1348. const mergeModalBeforeClick = async ()=>{
  1349. if (!mergeModalBeforeType.value) return window.$message?.warning('请选择并卷方式')
  1350. if (mergeModalBeforeType.value === '1') {
  1351. mergeModal.value = true
  1352. mergeInput.value = ''
  1353. } else {
  1354. mergeModalBeforeLoading.value = true
  1355. let ids = ''
  1356. const rows = tableCheckedKeys.value
  1357. ids = rowsToId(rows)
  1358. const { error, code, data, msg } = await tuningApi.reCreateArchiveAuto({
  1359. ids: ids,
  1360. type:2,
  1361. })
  1362. mergeModalBeforeLoading.value = false
  1363. if (!error && code === 200) {
  1364. window.$message?.success(msg)
  1365. getTableData()
  1366. mergeModalBeforeClose()
  1367. } else {
  1368. window.$message?.error(msg)
  1369. }
  1370. }
  1371. }
  1372. const mergeModalBeforeType = ref('')
  1373. const mergeModal = ref(false)
  1374. const mergeInput = ref('')
  1375. const mergeModalClose = ()=>{
  1376. mergeModal.value = false
  1377. }
  1378. const mergeData = ref([])
  1379. const mergeClick = ()=>{
  1380. if (tableCheckedKeys.value.length === 0) {
  1381. window.$message?.warning('请选择需要更新的案卷')
  1382. return
  1383. }
  1384. // 检查是否有被锁定的案卷
  1385. const lockedArchives = tableCheckedKeys.value.filter(item => item.isLock === 1)
  1386. if (lockedArchives.length > 0) {
  1387. window.$message.warning('选择的案卷中包含被锁定的项,无法并卷')
  1388. return
  1389. }
  1390. mergeData.value = deepClone(tableCheckedKeys.value)
  1391. mergeModalBefore.value = true
  1392. // mergeModal.value = true
  1393. // mergeInput.value = ''
  1394. }
  1395. const mergeDataColumn = [
  1396. { key: 'fileNumber', name: '档号', width: 160, align: 'center' },
  1397. { key: 'name', name: '案卷题名', align: 'center' },
  1398. ]
  1399. const aiLoading = ref(false)
  1400. const AiClick = async ()=>{
  1401. // 检查是否有被锁定的案卷
  1402. const lockedArchives = tableCheckedKeys.value.filter(item => item.isLock === 1)
  1403. if (lockedArchives.length > 0) {
  1404. window.$message.warning('选择的案卷中包含被锁定的项,无法进行AI题名')
  1405. return
  1406. }
  1407. let ids = ''
  1408. const rows = tableCheckedKeys.value
  1409. ids = rowsToId(rows)
  1410. aiLoading.value = true
  1411. const { error, code, data, msg } = await aiApi.creatFileNameFormAI({
  1412. ids: ids,
  1413. projectId:projectId.value,
  1414. contractId:contractId.value,
  1415. })
  1416. aiLoading.value = false
  1417. if (!error && code === 200) {
  1418. window.$message?.success(msg)
  1419. getTableData()
  1420. } else {
  1421. window.$message?.error(msg)
  1422. }
  1423. }
  1424. const taskInfoList = ref([])
  1425. const getInfoDetailClick = (item)=>{
  1426. console.log('详情')
  1427. const { status } = item
  1428. if (status === 1) return
  1429. router.push({ path: '/archives/manage/ai', query:{ taskId:item.taskId } })//ai
  1430. }
  1431. const taskListLoad = ref(false)
  1432. const getTaskInfoList = async ()=>{
  1433. taskListLoad.value = true
  1434. const { error, code, data } = await aiApi.getArchiveAiTask({
  1435. projectId: projectId.value,
  1436. contractId: contractId.value,
  1437. })
  1438. taskListLoad.value = false
  1439. if (!error && code === 200) {
  1440. taskInfoList.value = getArrValue(data)
  1441. } else {
  1442. taskInfoList.value = []
  1443. }
  1444. }
  1445. const delClick = (item)=>{
  1446. HcDelMsg(async (resolve) => {
  1447. const { error, code, msg } = await aiApi.deletedArchiveAiTask({
  1448. taskId: item.taskId,
  1449. })
  1450. if (!error && code === 200) {
  1451. window.$message?.success(msg)
  1452. getTaskInfoList()
  1453. }
  1454. resolve() //关闭弹窗的回调
  1455. })
  1456. }
  1457. //排序
  1458. const sortModalDialog = ref(false)
  1459. const sortModalDialogLoading = ref(false)
  1460. const sortModalDialogClick = async () => {
  1461. const { error, code, msg } = await tuningApi.sortRule({
  1462. type: sortTypeVal.value,
  1463. projectId: projectId.value,
  1464. })
  1465. if (!error && code === 200) {
  1466. window.$message?.success(msg)
  1467. sortModalDialogClose()
  1468. getTableData()
  1469. }
  1470. }
  1471. const sortModalDialogClose = ()=>{
  1472. sortModalDialog.value = false
  1473. sortTypeVal.value = '1' // 重置排序类型
  1474. }
  1475. const tableSortClick = () => {
  1476. console.log('排序')
  1477. sortModalDialog.value = true
  1478. }
  1479. const sortTypeVal = ref('1')
  1480. //查阅案卷// 2. 添加组件引用
  1481. const spotChecksDrawer = ref(false)
  1482. const fileId = ref('')//案卷id
  1483. const checkmetaFileId = ref('')//卷内文件id
  1484. const consultFileClick = (row) => {
  1485. spotChecksDrawer.value = true
  1486. fileId.value = row.id || ''
  1487. checkmetaFileId.value = ''
  1488. }
  1489. //关闭抽查
  1490. const onCarrySpotChecksClose = () => {
  1491. spotChecksDrawer.value = false
  1492. fileId.value = ''
  1493. checkmetaFileId.value = ''
  1494. }
  1495. //编辑卷内文件的查找替换
  1496. const saveReplaceLoadCollect = ref(false)
  1497. const showReplaceModalCollect = ref(false)
  1498. const ruleFormCollect = ref({})
  1499. const replaceClickCollect = ()=>{
  1500. if (tableCheckedKeysUpload.value.length === 0) {
  1501. window.$message?.warning('请选择需要更新的案卷')
  1502. return
  1503. }
  1504. // 检查是否有被锁定的案卷
  1505. const lockedArchives = tableUploadData.value.filter(item => item.isLock === 1)
  1506. if (lockedArchives.length > 0) {
  1507. window.$message.warning('选择的案卷中包含被锁定的项,无法操作')
  1508. return
  1509. }
  1510. showReplaceModalCollect.value = true
  1511. ruleFormCollect.value = {}
  1512. }
  1513. const saveReplaceCollect = async ()=>{
  1514. const rows = tableCheckedKeysUpload.value
  1515. let ids = ''
  1516. ids = arrToId(rows)
  1517. // 保存前去除空格
  1518. if (ruleFormCollect.value.query) {
  1519. ruleFormCollect.value.query = ruleFormCollect.value.query.trim()
  1520. }
  1521. if (ruleFormCollect.value.replace) {
  1522. ruleFormCollect.value.replace = ruleFormCollect.value.replace.trim()
  1523. }
  1524. saveReplaceLoadCollect.value = true
  1525. const { error, code, data, msg } = await archiveFileApiCollect.findAndReplace({
  1526. ...ruleFormCollect.value,
  1527. ids,
  1528. type:tabPositionCollect.value,
  1529. })
  1530. saveReplaceLoadCollect.value = false
  1531. if (!error && code === 200) {
  1532. window.$message?.success(msg)
  1533. showReplaceModalCollect.value = false
  1534. await getintableData()
  1535. intableData.value.forEach(item=>{
  1536. tableUploadData.value.forEach(ele=>{
  1537. if (item.id === ele.id) {
  1538. ele.fileName = item.fileName
  1539. }
  1540. })
  1541. })
  1542. tableUploadRef.value.clearSelection()
  1543. } else {
  1544. window.$message?.warning(msg)
  1545. }
  1546. }
  1547. const replaceTitleCollect = ref('查找替换')
  1548. const tabPositionCollect = ref('1')
  1549. const insertClick = ()=>{
  1550. fileInsertModalRef.value?.openInsertDialog(intableCheckedKeys.value, searchForm.value.nodeIds, checkInid.value)
  1551. }
  1552. const fileInsertModalRef = ref(null)
  1553. const closeFileModal = ()=>{
  1554. tableFileRef.value?.clearSelection()
  1555. }
  1556. </script>
  1557. <style lang="scss" scoped>
  1558. @import '~style/archives/tuning.scss';
  1559. // @import '~style/file/scoped/collection.scss';
  1560. </style>
  1561. <style lang="scss">
  1562. // @import '~style/file/collection.scss';
  1563. @import '~src/styles/theme/archives/tuning.scss';
  1564. .hover-hand {
  1565. cursor: pointer;
  1566. }
  1567. .panel-body .el-checkbox {
  1568. white-space: normal;
  1569. height: auto;
  1570. }
  1571. .text-disable {
  1572. cursor: not-allowed;
  1573. opacity: 0.6; /* 可选,添加透明度以视觉区分 */
  1574. pointer-events: none; /* 阻止所有指针事件 */
  1575. }
  1576. </style>
  1577. <style lang="scss" scoped>
  1578. @import '~style/archives/tuning.scss';
  1579. .flex-container {
  1580. display: flex;
  1581. flex-direction: column;
  1582. height: 100%;
  1583. }
  1584. .hc-c-table-box {
  1585. flex: 1; /* 默认占据所有空间 */
  1586. overflow-y: auto; /* 允许垂直滚动 */
  1587. }
  1588. .hc-f-table-box {
  1589. flex: 0; /* 初始时不占据空间 */
  1590. overflow-y: auto; /* 允许垂直滚动 */
  1591. transition: flex 0.3s ease; /* 添加过渡效果 */
  1592. }
  1593. .drag-icon {
  1594. cursor: ns-resize;
  1595. user-select: none;
  1596. position: absolute;
  1597. right: 20px;
  1598. top: 10px;
  1599. }
  1600. .replace-dialog-content{
  1601. background-color:#E9E9E9;
  1602. padding: 15px;
  1603. }
  1604. </style>
  1605. <style>
  1606. .blue-text .el-textarea__inner {
  1607. color: #409eff;
  1608. }
  1609. </style>
  1610. <style lang="scss">
  1611. html.dark{
  1612. .replace-dialog-content{
  1613. background-color:transparent;
  1614. padding: 15px;
  1615. }
  1616. }
  1617. </style>
  1618. <style lang="scss" scoped>
  1619. .task-info{
  1620. display: flex;
  1621. flex-direction: column;
  1622. justify-content:center;
  1623. align-items: center;
  1624. padding: 15px;
  1625. border-radius: 4px;
  1626. max-height: 300px;
  1627. overflow-y:auto ;
  1628. .task-info-item{
  1629. font-weight: bolder;
  1630. display: flex;
  1631. align-items: center;
  1632. justify-content: space-evenly;
  1633. width: 100%;
  1634. color: rgba(63, 158, 255, 1);
  1635. cursor: pointer;
  1636. margin-top: 10px;
  1637. }
  1638. }
  1639. </style>
  1640. <style lang="scss" scoped>
  1641. .view-file-link {
  1642. color: var(--el-color-primary);
  1643. &:hover {
  1644. color: var(--el-color-primary-light-3);
  1645. }
  1646. }
  1647. </style>