index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. <template>
  2. <div class="table-box">
  3. <ProTable ref="proTable" :columns="columns" row-key="id" :request-api="listToInfraredApi">
  4. <!-- 表格 header 按钮 -->
  5. <template #tableHeader="scope">
  6. <el-button type="primary" v-auth="['demo:toInfrared:add']" icon="CirclePlus" @click="openDialog(1, '可见光转红外新增')"> 新增 </el-button>
  7. <!-- <el-button type="primary" v-auth="['demo:toInfrared:import']" icon="Upload" plain @click="batchAdd"> 导入 </el-button>
  8. <el-button type="primary" v-auth="['demo:toInfrared:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button> -->
  9. <el-button
  10. type="danger"
  11. v-auth="['demo:toInfrared:remove']"
  12. icon="Delete"
  13. plain
  14. :disabled="!scope.isSelected"
  15. @click="batchDelete(scope.selectedListIds)"
  16. >
  17. 批量删除
  18. </el-button>
  19. </template>
  20. <!-- 表格操作 -->
  21. <template #operation="scope">
  22. <el-button type="primary" link icon="View" v-if="scope.row.algorithmModelId != null" @click="openModelDialog(scope.row)">
  23. <!--@click="openStartDialog(scope.row)" -->
  24. 详情
  25. </el-button>
  26. <el-button
  27. type="primary"
  28. link
  29. icon="View"
  30. v-auth="['demo:ToInfrared:start']"
  31. v-if="scope.row.status == '0' || scope.row.status == '3' || scope.row.status == '4'"
  32. @click="startToInfrared(scope.row)"
  33. >
  34. <!--@click="openStartDialog(scope.row)" -->
  35. 开始
  36. </el-button>
  37. <el-popconfirm title="确定终止此任务吗?" @confirm="stopToInfrared(scope.row)" v-if="scope.row.status == '1'">
  38. <template #reference>
  39. <el-button type="primary" link icon="Delete"> 终止</el-button>
  40. </template>
  41. </el-popconfirm>
  42. <el-button
  43. type="primary"
  44. link
  45. icon="View"
  46. v-auth="['demo:DataSeq:query']"
  47. v-if="scope.row.status == '2' && scope.row.type == AlgorithmType2['预测/推理']"
  48. @click="preview(scope.row)"
  49. >
  50. 预览
  51. </el-button>
  52. <el-button
  53. type="primary"
  54. link
  55. icon="View"
  56. v-auth="['demo:ToInfrared:download']"
  57. v-if="scope.row.status == '2'"
  58. @click="dowloadToInfrared(scope.row)"
  59. >
  60. 下载
  61. </el-button>
  62. <!-- <el-button type="primary" link icon="View" v-auth="['demo:toInfrared:query']" @click="openDialog(3, '查看', scope.row)"> 查看 </el-button> -->
  63. <!-- <el-button type="primary" link icon="EditPen"v-auth="['demo:toInfrared:edit']" @click="openDialog(2, '编辑', scope.row)"> 编辑 </el-button> -->
  64. <el-button
  65. type="primary"
  66. link
  67. icon="Delete"
  68. v-auth="['demo:toInfrared:remove']"
  69. @click="deleteToInfrared(scope.row)"
  70. :disabled="scope.row.status == '1'"
  71. >
  72. 删除
  73. </el-button>
  74. </template>
  75. </ProTable>
  76. <FormDialog ref="formDialogRef" />
  77. <ImportExcel ref="dialogRef" />
  78. <PreviewImages :visible="dialogVisible" :urls="imageUrls" @close="dialogVisible = false" />
  79. </div>
  80. </template>
  81. <script setup lang="tsx" name="ToInfrared">
  82. import { ref, reactive, onMounted } from 'vue'
  83. import { useHandleData } from '@/hooks/useHandleData'
  84. import { useDownload } from '@/hooks/useDownload'
  85. import { ElMessage, ElMessageBox } from 'element-plus'
  86. import ProTable from '@/components/ProTable/index.vue'
  87. import ImportExcel from '@/components/ImportExcel/index.vue'
  88. import FormDialog from '@/components/FormDialog/index.vue'
  89. import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
  90. import {
  91. listToInfraredApi,
  92. delToInfraredApi,
  93. addToInfraredApi,
  94. updateToInfraredApi,
  95. importTemplateApi,
  96. importToInfraredDataApi,
  97. exportToInfraredApi,
  98. startToInfraredApi,
  99. stopToInfraredApi,
  100. dowloadToInfraredApi,
  101. getToInfraredApi
  102. } from '@/api/modules/demo/toInfrared'
  103. import { getImagesApi, listDataSeqApi } from '@/api/modules/demo/DataSeq'
  104. import { enumAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
  105. import { getAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
  106. import { enumAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
  107. import statusEnums from '@/utils/status'
  108. import { AlgorithmType, SubSystem, SubSystem__, enumsAlgorithmType, enumsSubSystem, AlgorithmType2 } from '@/views/demo/utils'
  109. import PreviewImages from '@/views/demo/components/PreviewImages.vue'
  110. import { Row } from 'element-plus/es/components/table-v2/src/components'
  111. const dialogVisible = ref(false)
  112. const imageUrls = ref([])
  113. const preview = async row => {
  114. console.log('showImages:', row.inputOssId)
  115. const data: any = await getImagesApi(row.inputOssId, '_to_infrared', false, 'predict')
  116. imageUrls.value = data.data
  117. dialogVisible.value = true
  118. }
  119. const openModelDialog = async row => {
  120. const algorithmModelId = row.algorithmModelId
  121. const result: any = await getAlgorithmModelTrackApi(algorithmModelId)
  122. // console.log(result.data)
  123. setItemsOptionsModel()
  124. const params = {
  125. title: '模型',
  126. width: 580,
  127. isEdit: false,
  128. itemsOptions: itemsOptions,
  129. model: result.data,
  130. api: updateToInfraredApi,
  131. getTableList: proTable.value?.getTableList
  132. }
  133. formDialogRef.value?.openDialog(params)
  134. }
  135. const startToInfrared = async (params: any) => {
  136. const res: any = await startToInfraredApi(params.id)
  137. if (res.code === 200) {
  138. ElMessage.success('任务已开始,请等待完成!')
  139. } else {
  140. ElMessage.error('任务开始失败,请检查!')
  141. }
  142. proTable.value?.getTableList()
  143. }
  144. const stopToInfrared = async (params: any) => {
  145. const res: any = await stopToInfraredApi(params.id)
  146. if (res.code === 200) {
  147. ElMessage.success('终止任务成功!')
  148. } else {
  149. ElMessage.error('终止任务失败,请检查!')
  150. }
  151. proTable.value?.getTableList()
  152. }
  153. const dowloadToInfrared = async (params: any) => {
  154. if (params.type == AlgorithmType2['训练']) {
  155. await useDownload(dowloadToInfraredApi, params.name, params.id, true, '.pt')
  156. } else if (params.type == AlgorithmType2['预测/推理']) {
  157. await useDownload(dowloadToInfraredApi, params.name, params.id, true, '.zip')
  158. }
  159. }
  160. const openStartDialog = async (row: any) => {
  161. let res = { data: {} }
  162. if (row?.id) {
  163. res = await getToInfraredApi(row?.id || null)
  164. }
  165. // 重置表单
  166. setItemsOptions2()
  167. const params = {
  168. title: '开始任务',
  169. width: 580,
  170. isEdit: true,
  171. itemsOptions: itemsOptions,
  172. model: res.data,
  173. api: startToInfraredApi,
  174. getTableList: proTable.value?.getTableList
  175. }
  176. formDialogRef.value?.openDialog(params)
  177. }
  178. // ProTable 实例
  179. const proTable = ref<ProTableInstance>()
  180. // 删除可见光转红外信息
  181. const deleteToInfrared = async (params: any) => {
  182. await useHandleData(delToInfraredApi, params.id, '删除【' + params.id + '】可见光转红外')
  183. proTable.value?.getTableList()
  184. }
  185. // 批量删除可见光转红外信息
  186. const batchDelete = async (ids: string[]) => {
  187. await useHandleData(delToInfraredApi, ids, '删除所选可见光转红外信息')
  188. proTable.value?.clearSelection()
  189. proTable.value?.getTableList()
  190. }
  191. // 导出可见光转红外列表
  192. const downloadFile = async () => {
  193. ElMessageBox.confirm('确认导出可见光转红外数据?', '温馨提示', { type: 'warning' }).then(() =>
  194. useDownload(exportToInfraredApi, '可见光转红外列表', proTable.value?.searchParam)
  195. )
  196. }
  197. // 批量添加可见光转红外
  198. const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
  199. const batchAdd = () => {
  200. const params = {
  201. title: '可见光转红外',
  202. tempApi: importTemplateApi,
  203. importApi: importToInfraredDataApi,
  204. getTableList: proTable.value?.getTableList
  205. }
  206. dialogRef.value?.acceptParams(params)
  207. }
  208. const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
  209. // 打开弹框的功能
  210. const openDialog = async (type: number, title: string, row?: any) => {
  211. let res = { data: {} }
  212. if (row?.id) {
  213. res = await getToInfraredApi(row?.id || null)
  214. }
  215. // 重置表单
  216. setItemsOptions()
  217. const params = {
  218. title,
  219. width: 580,
  220. isEdit: type !== 3,
  221. itemsOptions: itemsOptions,
  222. model: type == 1 ? {} : res.data,
  223. api: type == 1 ? addToInfraredApi : updateToInfraredApi,
  224. getTableList: proTable.value?.getTableList
  225. }
  226. formDialogRef.value?.openDialog(params)
  227. }
  228. // 表格配置项
  229. const columns = reactive<ColumnProps<any>[]>([
  230. { type: 'selection', fixed: 'left', width: 70 },
  231. { prop: 'id', label: '主键ID', width: 180 },
  232. {
  233. prop: 'name',
  234. label: '任务名称',
  235. search: {
  236. el: 'input'
  237. },
  238. width: 150
  239. },
  240. {
  241. prop: 'status',
  242. label: '任务状态',
  243. search: {
  244. el: 'select'
  245. },
  246. tag: true,
  247. enum: statusEnums,
  248. width: 150
  249. },
  250. {
  251. prop: 'type',
  252. label: '类型',
  253. tag: true,
  254. enum: enumsAlgorithmType,
  255. width: 120
  256. },
  257. {
  258. prop: 'subsystem',
  259. label: '分系统',
  260. tag: true,
  261. enum: enumsSubSystem,
  262. width: 200
  263. },
  264. {
  265. prop: 'algorithmName',
  266. label: '算法名称',
  267. width: 200
  268. },
  269. {
  270. prop: 'modelName',
  271. label: '模型名称',
  272. width: 200
  273. },
  274. // {
  275. // prop: 'algorithmModelId',
  276. // label: '模型',
  277. // search: {
  278. // el: 'input'
  279. // },
  280. // width: 150
  281. // },
  282. {
  283. prop: 'startTime',
  284. label: '开始时间',
  285. width: 180
  286. },
  287. {
  288. prop: 'endTime',
  289. label: '结束时间',
  290. width: 180
  291. },
  292. {
  293. prop: 'costSecond',
  294. label: '耗时',
  295. width: 120
  296. },
  297. {
  298. prop: 'log',
  299. label: '日志',
  300. width: 120
  301. },
  302. {
  303. prop: 'outputPath',
  304. label: '输出路径',
  305. width: 120
  306. },
  307. {
  308. prop: 'remarks',
  309. label: '备注',
  310. search: {
  311. el: 'input'
  312. },
  313. width: 120
  314. },
  315. { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
  316. ])
  317. // 表单配置项
  318. let itemsOptions: ProForm.ItemsOptions[] = []
  319. const setItemsOptions = () => {
  320. itemsOptions = [
  321. {
  322. label: '任务名称',
  323. prop: 'name',
  324. rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
  325. compOptions: {
  326. placeholder: '请输入任务名称'
  327. }
  328. },
  329. {
  330. label: '选择数据集',
  331. prop: 'inputOssId',
  332. rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
  333. compOptions: {
  334. elTagName: 'select',
  335. placeholder: '请选择或者上传数据集',
  336. enum: getImageDataList,
  337. clearable: true
  338. }
  339. },
  340. {
  341. label: '上传数据集',
  342. prop: 'inputOssId',
  343. rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
  344. compOptions: {
  345. elTagName: 'file-upload',
  346. fileSize: 4096,
  347. fileType: ['zip'],
  348. placeholder: '请上传数据集'
  349. }
  350. },
  351. {
  352. label: '选择模型',
  353. prop: 'algorithmModelId',
  354. rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
  355. compOptions: {
  356. elTagName: 'select',
  357. placeholder: '请选择模型',
  358. enum: enumsAlgorithmModelTrack
  359. }
  360. },
  361. {
  362. label: '备注',
  363. prop: 'remarks',
  364. rules: [],
  365. compOptions: {
  366. placeholder: '请输入备注'
  367. }
  368. }
  369. ]
  370. }
  371. const getImageDataList = ref<any>([])
  372. onMounted(async () => {
  373. const qyery = {
  374. subsystem: SubSystem__['可见光转红外'],
  375. pageNum: 1,
  376. pageSize: 25
  377. }
  378. const result: any = await listDataSeqApi(qyery)
  379. const data = result['data']['list']
  380. for (const item of data) {
  381. getImageDataList.value.push({
  382. value: item['inputOssId'],
  383. label: item['name']
  384. })
  385. }
  386. })
  387. const enumsAlgorithmModelTrack = ref<any>([])
  388. onMounted(async () => {
  389. const result: any = await enumAlgorithmModelTrackApi()
  390. // console.log(result.data);
  391. enumsAlgorithmModelTrack.value = []
  392. for (const item of result.data) {
  393. if (SubSystem[item['subsystem']] === '可见光转红外') {
  394. item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']] + '-' + item['algorithmName']
  395. enumsAlgorithmModelTrack.value.push(item)
  396. }
  397. }
  398. })
  399. const setItemsOptions2 = () => {
  400. itemsOptions = [
  401. {
  402. label: '任务名称',
  403. prop: 'name',
  404. rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
  405. compOptions: {
  406. disabled: true,
  407. placeholder: '请输入任务名称'
  408. }
  409. },
  410. {
  411. label: '选择模型',
  412. prop: 'algorithmModel',
  413. rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
  414. compOptions: {
  415. elTagName: 'select',
  416. placeholder: '请选择模型',
  417. enum: enumsAlgorithmModelTrack
  418. }
  419. },
  420. {
  421. label: '备注',
  422. prop: 'remarks',
  423. rules: [],
  424. compOptions: {
  425. placeholder: '请输入备注'
  426. }
  427. }
  428. ]
  429. }
  430. const enumsAlgorithmConfigTrack = ref<any>([])
  431. onMounted(async () => {
  432. const result = await enumAlgorithmConfigTrackApi()
  433. enumsAlgorithmConfigTrack.value = result['data']
  434. for (const item of enumsAlgorithmConfigTrack.value) {
  435. item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']]
  436. }
  437. return result['data']
  438. })
  439. const setItemsOptionsModel = () => {
  440. itemsOptions = [
  441. {
  442. label: '算法ID',
  443. prop: 'algorithmId',
  444. rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
  445. compOptions: {
  446. disabled: true,
  447. placeholder: '请输入算法'
  448. }
  449. },
  450. {
  451. label: '算法类型',
  452. prop: 'algorithmType',
  453. rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
  454. compOptions: {
  455. disabled: true,
  456. elTagName: 'select',
  457. placeholder: '请输入算法',
  458. enum: enumsAlgorithmConfigTrack
  459. }
  460. },
  461. {
  462. label: '算法参数',
  463. prop: 'parameterConfig',
  464. rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
  465. compOptions: {
  466. placeholder: '请输入模型名称'
  467. }
  468. },
  469. {
  470. label: '模型ID',
  471. prop: 'id',
  472. rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
  473. compOptions: {
  474. placeholder: '请输入模型名称'
  475. }
  476. },
  477. {
  478. label: '模型名称',
  479. prop: 'modelName',
  480. rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
  481. compOptions: {
  482. placeholder: '请输入模型名称'
  483. }
  484. },
  485. {
  486. label: '模型保存路径',
  487. prop: 'modelAddress',
  488. rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
  489. compOptions: {
  490. placeholder: '请输入模型名称'
  491. }
  492. },
  493. {
  494. label: '备注',
  495. prop: 'remarks',
  496. rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
  497. compOptions: {
  498. placeholder: '请输入备注'
  499. }
  500. }
  501. ]
  502. }
  503. </script>