index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. <template>
  2. <ContentWrap>
  3. <!-- 搜索工作栏 -->
  4. <el-form
  5. class="-mb-15px"
  6. :model="queryParams"
  7. ref="queryFormRef"
  8. :inline="true"
  9. label-width="68px"
  10. >
  11. <el-form-item label="模板名字" prop="tbName">
  12. <el-input
  13. v-model="queryParams.tbName"
  14. placeholder="请输入模板名字"
  15. clearable
  16. @keyup.enter="handleQuery"
  17. class="!w-240px"
  18. />
  19. </el-form-item>
  20. <el-form-item label="模板编号" prop="tbCode">
  21. <el-input
  22. v-model="queryParams.tbCode"
  23. placeholder="请输入模板编号"
  24. clearable
  25. @keyup.enter="handleQuery"
  26. class="!w-240px"
  27. />
  28. </el-form-item>
  29. <el-form-item label="模板分类" prop="tbType">
  30. <el-select
  31. v-model="queryParams.tbType"
  32. placeholder="请选择模板分类"
  33. clearable
  34. class="!w-240px"
  35. >
  36. <el-option
  37. v-for="dict in getIntDictOptions(DICT_TYPE.PRESSURE2_TB_TYPE)"
  38. :key="dict.value"
  39. :label="dict.label"
  40. :value="dict.value"
  41. />
  42. </el-select>
  43. </el-form-item>
  44. <el-form-item label="模板类型" prop="reportType">
  45. <el-select
  46. v-model="queryParams.reportType"
  47. placeholder="请选择模板类型"
  48. clearable
  49. class="!w-240px"
  50. >
  51. <el-option
  52. v-for="dict in getIntDictOptions(DICT_TYPE.PRESSURE2_DYNAMIC_REPORT_TYPE)"
  53. :key="dict.value"
  54. :label="dict.label"
  55. :value="dict.value"
  56. />
  57. </el-select>
  58. </el-form-item>
  59. <el-form-item label="项目分类" prop="pjType">
  60. <el-select
  61. v-model="queryParams.pjType"
  62. placeholder="请选择项目分类"
  63. clearable
  64. class="!w-240px"
  65. >
  66. <el-option
  67. v-for="dict in getIntDictOptions(DICT_TYPE.PRESSURE2_DYNAMIC_PROJECT_TYPE)"
  68. :key="dict.value"
  69. :label="dict.label"
  70. :value="dict.value"
  71. />
  72. </el-select>
  73. </el-form-item>
  74. <el-form-item label="版本号" prop="versionNo">
  75. <el-input
  76. v-model="queryParams.versionNo"
  77. placeholder="请输入版本号"
  78. clearable
  79. @keyup.enter="handleQuery"
  80. class="!w-240px"
  81. />
  82. </el-form-item>
  83. <el-form-item label="创建人名" prop="creatorName">
  84. <el-input
  85. v-model="queryParams.creatorName"
  86. placeholder="请输入创建人名"
  87. clearable
  88. @keyup.enter="handleQuery"
  89. class="!w-240px"
  90. />
  91. </el-form-item>
  92. <el-form-item label="创建时间" prop="createTime">
  93. <el-date-picker
  94. v-model="queryParams.createTime"
  95. value-format="YYYY-MM-DD HH:mm:ss"
  96. type="daterange"
  97. start-placeholder="开始日期"
  98. end-placeholder="结束日期"
  99. :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
  100. class="!w-220px"
  101. />
  102. </el-form-item>
  103. <el-form-item>
  104. <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
  105. <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
  106. <el-button
  107. type="primary"
  108. plain
  109. @click="openForm('create')"
  110. v-hasPermi="['pressure2:dynamic-tb:create']"
  111. >
  112. <Icon icon="ep:plus" class="mr-5px" /> 新增
  113. </el-button>
  114. <el-button
  115. type="success"
  116. plain
  117. @click="handleExport"
  118. :loading="exportLoading"
  119. v-hasPermi="['pressure2:dynamic-tb:export']"
  120. >
  121. <Icon icon="ep:download" class="mr-5px" /> 导出
  122. </el-button>
  123. <el-button
  124. type="warning"
  125. plain
  126. @click="handleExportZip"
  127. :disabled="selectedIds.length === 0"
  128. :loading="exportZipLoading"
  129. v-hasPermi="['pressure2:dynamic-tb:batchExport']"
  130. >
  131. <Icon icon="ep:folder" class="mr-5px" /> 批量导出
  132. </el-button>
  133. <el-button
  134. type="primary"
  135. plain
  136. @click="handleImportDialog"
  137. v-hasPermi="['pressure2:dynamic-tb:import']"
  138. >
  139. <Icon icon="ep:upload" class="mr-5px" /> 导入
  140. </el-button>
  141. </el-form-item>
  142. </el-form>
  143. </ContentWrap>
  144. <!-- 列表 -->
  145. <ContentWrap>
  146. <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" :border="true" @selection-change="handleSelectionChange">
  147. <el-table-column type="selection" width="55" />
  148. <el-table-column label="主键" align="center" prop="id" />
  149. <el-table-column label="模板名字" align="center" prop="tbName" width="250"/>
  150. <el-table-column label="模板编号" align="center" prop="tbCode" width="150"/>
  151. <el-table-column label="模板分类" align="center" prop="tbType">
  152. <template #default="scope">
  153. <dict-tag :type="DICT_TYPE.PRESSURE2_TB_TYPE" :value="scope.row.tbType" />
  154. </template>
  155. </el-table-column>
  156. <el-table-column label="模板类型" align="center" prop="reportType">
  157. <template #default="scope">
  158. <dict-tag :type="DICT_TYPE.PRESSURE2_DYNAMIC_REPORT_TYPE" :value="scope.row.reportType" />
  159. </template>
  160. </el-table-column>
  161. <el-table-column label="项目分类" align="center" prop="pjType">
  162. <template #default="scope">
  163. <dict-tag :type="DICT_TYPE.PRESSURE2_DYNAMIC_PROJECT_TYPE" :value="scope.row.pjType" />
  164. </template>
  165. </el-table-column>
  166. <el-table-column label="版本号" align="center" prop="versionNo" />
  167. <el-table-column label="创建人名" align="center" prop="creatorName" />
  168. <el-table-column
  169. label="创建时间"
  170. align="center"
  171. prop="createTime"
  172. :formatter="dateFormatter"
  173. width="180px"
  174. />
  175. <el-table-column label="状态" align="center" prop="status">
  176. <template #default="scope">
  177. <el-tag :type="getStatusType(scope.row.status || 400)">{{getIntDictOptions(DICT_TYPE.COMPRESSION_PROJECT_TEMPLATEMANAGEMENT).find(x => x.value == (scope.row.status || 400))?.label}}</el-tag>
  178. </template>
  179. </el-table-column>
  180. <el-table-column label="操作" align="center" min-width="160px">
  181. <template #default="scope">
  182. <el-button
  183. link
  184. type="primary"
  185. @click="openForm(scope.row.status == 200 ? 'view' : 'update', scope.row.id)"
  186. >
  187. {{ scope.row.status == 200 ? '查看' : '编辑' }}
  188. </el-button>
  189. <router-link :to="'/cybggl/dynamic-tb-col/'+scope.row.id">
  190. <el-button link type="primary" >数据</el-button>
  191. <!-- <el-button link type="primary" :disabled="scope.row.status == 200">数据</el-button> -->
  192. </router-link>
  193. <el-button
  194. link
  195. type="primary"
  196. @click="handleUndercarriage(scope.row)"
  197. v-if="scope.row.status == 200"
  198. >
  199. 下架
  200. </el-button>
  201. <el-button
  202. link
  203. type="primary"
  204. @click="handleShelves(scope.row)"
  205. v-if="(scope.row.status || 400) == 400"
  206. >
  207. 上架
  208. </el-button>
  209. <el-button
  210. link
  211. type="primary"
  212. @click="handleShelves(scope.row)"
  213. v-if="scope.row.status == 300"
  214. >
  215. 重新上架
  216. </el-button>
  217. <!-- <el-button
  218. link
  219. type="danger"
  220. @click="handleDelete(scope.row.id)"
  221. >
  222. 删除
  223. </el-button> -->
  224. </template>
  225. </el-table-column>
  226. </el-table>
  227. <!-- 分页 -->
  228. <Pagination
  229. :total="total"
  230. v-model:page="queryParams.pageNo"
  231. v-model:limit="queryParams.pageSize"
  232. @pagination="getList"
  233. />
  234. </ContentWrap>
  235. <CustomDialog
  236. v-model="shelvesDialogVisible"
  237. title='上架说明'
  238. width="400px"
  239. :showFooter="false"
  240. >
  241. <el-form ref="shelvesFormRef" :model="shelvesForm">
  242. <el-form-item label="原因" prop="cancellationCause">
  243. <el-input
  244. v-model.trim="shelvesForm.shelvesCause"
  245. type="textarea"
  246. resize="vertical"
  247. :autosize="{ minRows: 2, maxRows: 4 }"
  248. placeholder="请输入原因"/>
  249. </el-form-item>
  250. <div style="display: flex; justify-content: center; padding-top: 24px;">
  251. <el-button type="default" @click="()=>{
  252. shelvesDialogVisible = false
  253. shelvesForm.shelvesCause = ''
  254. }">取消</el-button>
  255. <el-button type="primary" @click="handleShelvesSave">确定</el-button>
  256. </div>
  257. </el-form>
  258. </CustomDialog>
  259. <!-- 导入弹窗 -->
  260. <CustomDialog
  261. v-model="importDialogVisible"
  262. title="导入模板数据"
  263. width="500px"
  264. :showFooter="false"
  265. >
  266. <el-form ref="importFormRef" :model="importForm">
  267. <el-form-item label="选择文件" prop="file">
  268. <el-upload
  269. ref="uploadRef"
  270. :auto-upload="false"
  271. :limit="1"
  272. accept=".zip"
  273. v-if="importDialogVisible"
  274. :on-change="handleFileChange"
  275. :on-remove="handleFileRemove"
  276. drag
  277. >
  278. <Icon icon="ep:upload" class="mr-5px" />
  279. <div class="el-upload__text">
  280. 将文件拖到此处,或<em>点击上传</em>
  281. </div>
  282. <template #tip>
  283. <div class="el-upload__tip">仅支持 .zip 格式文件</div>
  284. </template>
  285. </el-upload>
  286. </el-form-item>
  287. <div style="display: flex; justify-content: center; padding-top: 24px;">
  288. <el-button type="default" @click="importDialogVisible = false">取消</el-button>
  289. <el-button type="primary" @click="handleImportSubmit" :loading="importLoading">确定导入</el-button>
  290. </div>
  291. </el-form>
  292. </CustomDialog>
  293. <!-- 表单弹窗:添加/修改 -->
  294. <DynamicTbForm v-if="templateDetailVisible" :id="formProps.id" :type="formProps.type" ref="formRef" v-model:visible="templateDetailVisible" @success="getList" />
  295. </template>
  296. <script setup lang="ts">
  297. import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
  298. import { dateFormatter } from '@/utils/formatTime'
  299. import download from '@/utils/download'
  300. import { DynamicTbApi, DynamicTbVO } from '@/api/pressure2/dynamictb'
  301. import DynamicTbForm from './DynamicTbForm.vue'
  302. import { BoilerConnectRecordReportApi } from '@/api/pressure2/boilerconnectrecordreport'
  303. /** 承压动态报表表单 列表 */
  304. defineOptions({ name: 'DynamicTb' })
  305. const message = useMessage() // 消息弹窗
  306. const { t } = useI18n() // 国际化
  307. const loading = ref(true) // 列表的加载中
  308. const list = ref<DynamicTbVO[]>([]) // 列表的数据
  309. const total = ref(0) // 列表的总页数
  310. const queryParams = reactive({
  311. pageNo: 1,
  312. pageSize: 10,
  313. tbName: undefined,
  314. tbCode: undefined,
  315. tbType: undefined,
  316. reportType: undefined,
  317. pjType: undefined,
  318. versionNo: undefined,
  319. creatorName: undefined,
  320. createTime: [],
  321. })
  322. const queryFormRef = ref() // 搜索的表单
  323. const exportLoading = ref(false) // 导出的加载中
  324. const templateDetailVisible=ref(false) //明细页面显示
  325. // 批量导出
  326. const selectedIds = ref<string[]>([]) // 多选选中的ID列表
  327. const exportZipLoading = ref(false) // 批量导出的加载中
  328. // 导入
  329. const importDialogVisible = ref(false) // 导入弹窗
  330. const importLoading = ref(false) // 导入的加载中
  331. const uploadRef = ref() // 上传组件引用
  332. const importFile = ref<File | null>(null) // 待导入的文件
  333. const importForm = reactive({}) // 导入表单
  334. // 上架
  335. const shelvesDialogVisible=ref(false);
  336. const shelvesForm=ref({shelvesCause:''});
  337. /** 查询列表 */
  338. const getList = async () => {
  339. loading.value = true
  340. try {
  341. const data = await DynamicTbApi.getDynamicTbPage(queryParams)
  342. list.value = data.list
  343. total.value = data.total
  344. } finally {
  345. loading.value = false
  346. }
  347. }
  348. /** 搜索按钮操作 */
  349. const handleQuery = () => {
  350. queryParams.pageNo = 1
  351. getList()
  352. }
  353. /** 重置按钮操作 */
  354. const resetQuery = () => {
  355. queryFormRef.value.resetFields()
  356. handleQuery()
  357. }
  358. /** 添加/修改操作 */
  359. const formRef = ref()
  360. const formProps=ref({type:'',id:0});
  361. const openForm = (type: string, id?: number) => {
  362. //formRef.value.open(type, id)
  363. formProps.value={type:type,id:id};
  364. templateDetailVisible.value=true;
  365. }
  366. /** 删除按钮操作 */
  367. const handleDelete = async (id: number) => {
  368. try {
  369. // 删除的二次确认
  370. await message.delConfirm()
  371. // 发起删除
  372. await DynamicTbApi.deleteDynamicTb(id)
  373. message.success(t('common.delSuccess'))
  374. // 刷新列表
  375. await getList()
  376. } catch {}
  377. }
  378. /** 导出按钮操作 */
  379. const handleExport = async () => {
  380. try {
  381. // 导出的二次确认
  382. await message.exportConfirm()
  383. // 发起导出
  384. exportLoading.value = true
  385. const data = await DynamicTbApi.exportDynamicTb(queryParams)
  386. download.excel(data, '承压动态报表表单.xls')
  387. } catch {
  388. } finally {
  389. exportLoading.value = false
  390. }
  391. }
  392. const getStatusType = (status) => {
  393. switch (status) {
  394. case 100:
  395. return 'primary'
  396. case 200:
  397. return 'success'
  398. case 300:
  399. return 'danger'
  400. case 400:
  401. return 'warning'
  402. case 500:
  403. return 'info'
  404. }
  405. }
  406. const rowData = ref()
  407. // 上架
  408. const handleShelves = async (row) => {
  409. shelvesDialogVisible.value = true
  410. rowData.value = row
  411. }
  412. // 提交上架
  413. const handleShelvesSave = async () => {
  414. ElMessageBox.confirm(`确定上架${rowData.value.tbName}吗?`, '上架提示', {
  415. confirmButtonText: '确 认',
  416. cancelButtonText: '取 消'
  417. }).then(async () => {
  418. const res = await DynamicTbApi.initiateApproval({id: rowData.value.id, reason: shelvesForm.value.shelvesCause})
  419. if(res) {
  420. ElMessage.success('上架成功')
  421. shelvesDialogVisible.value = false
  422. getList()
  423. }
  424. })
  425. }
  426. // 下架
  427. const handleUndercarriage = async (row) => {
  428. try {
  429. const connectInfos = await BoilerConnectRecordReportApi.getByTemplateId({
  430. templateId: row.id,
  431. type: row.reportType === 100 ? 'record' : 'report'
  432. })
  433. if (connectInfos && connectInfos.length > 0) {
  434. ElMessage.warning('该模板存在关联的检验项目,请先删除关联项目后再进行下架操作')
  435. return
  436. }
  437. ElMessageBox.confirm('确定下架该报告模板吗?', '下架提示', {
  438. confirmButtonText: '确 认',
  439. cancelButtonText: '取 消'
  440. }).then(async () => {
  441. try {
  442. const res = await DynamicTbApi.updateStatus({id: row.id, status: 400})
  443. if(res) {
  444. ElMessage.success('下架成功')
  445. getList()
  446. }
  447. } catch (error) {
  448. ElMessage.error('下架失败:' + (error.message || '未知错误'))
  449. }
  450. })
  451. } catch (error) {
  452. ElMessage.error('查询关联项目失败:' + (error.message || '未知错误'))
  453. }
  454. }
  455. /** 初始化 **/
  456. onMounted(() => {
  457. getList()
  458. })
  459. // ==================== 批量导出/导入 ====================
  460. /** 表格多选变化 */
  461. const handleSelectionChange = (selection: DynamicTbVO[]) => {
  462. selectedIds.value = selection.map(item => item.id)
  463. }
  464. /** 批量导出 ZIP */
  465. const handleExportZip = async () => {
  466. if (selectedIds.value.length === 0) {
  467. ElMessage.warning('请先选择要导出的模板')
  468. return
  469. }
  470. try {
  471. await message.exportConfirm()
  472. exportZipLoading.value = true
  473. const data = await DynamicTbApi.exportZip(selectedIds.value)
  474. download.zip(data, '模板数据导出.zip')
  475. ElMessage.success('导出成功')
  476. } catch {
  477. } finally {
  478. exportZipLoading.value = false
  479. }
  480. }
  481. /** 打开导入弹窗 */
  482. const handleImportDialog = () => {
  483. importFile.value = null
  484. importDialogVisible.value = true
  485. }
  486. /** 导入文件选择变化 */
  487. const handleFileChange = (file: any) => {
  488. importFile.value = file.raw
  489. }
  490. /** 导入文件移除 */
  491. const handleFileRemove = () => {
  492. importFile.value = null
  493. }
  494. /** 提交导入 */
  495. const handleImportSubmit = async () => {
  496. if (!importFile.value) {
  497. ElMessage.warning('请先选择要导入的文件')
  498. return
  499. }
  500. try {
  501. importLoading.value = true
  502. await DynamicTbApi.importZip(importFile.value)
  503. ElMessage.success('导入成功')
  504. importFile.value = null
  505. importDialogVisible.value = false
  506. getList()
  507. } catch (e) {
  508. ElMessage.error('导入失败:' + (e?.message || '未知错误'))
  509. } finally {
  510. importLoading.value = false
  511. }
  512. }
  513. </script>