1
0

46 Ревизии b6847bb29d ... 631b76c696

Автор SHA1 Съобщение Дата
  28968 631b76c696 fix: bug fix преди 4 месеца
  WANGKANG 3487b63472 Merge branch 'dev_wk2' into develop преди 5 месеца
  WANGKANG a0dcc1bc51 feat: 1.修改数据加载逻辑 2. 添加自动刷新 преди 5 месеца
  WANGKANG a727c75e9a feat: 总任务测试 преди 5 месеца
  WANGKANG 35856c591a feat: cat测试 преди 5 месеца
  WANGKANG c07210e7a0 feat: masc测试 преди 5 месеца
  WANGKANG 2659eeb6ca feat: 修改模型必要性 преди 5 месеца
  WANGKANG a69bce53e2 feat: 目标检测模型名称可以修改 преди 5 месеца
  WANGKANG fa4e655807 feat: 评估结果展示 преди 5 месеца
  WANGKANG 6a272dc0c9 fix: 修改ShowStatisticResult的封装,添加title преди 5 месеца
  WANGKANG dd86175169 feat: 预测任务结果预览 преди 5 месеца
  WANGKANG 10df04f5c3 feat: 修改ShowStatisticResult组件的封装 преди 5 месеца
  WANGKANG da9d5019d6 fix: 发现一个命名错误 преди 5 месеца
  WANGKANG f0939d04d5 feat: 预览功能 преди 5 месеца
  WANGKANG be7ae9809e feat: 查看日志功能 преди 5 месеца
  WANGKANG de1b8ca6a6 feat: 修改的ViewLog组件 преди 5 месеца
  WANGKANG 3e4dc257a0 feat: 停止功能 преди 5 месеца
  WANGKANG bbd9b2df98 feat: 开始功能 преди 5 месеца
  WANGKANG da43da10d2 feat: 删除功能 преди 5 месеца
  WANGKANG 0051787d8f fix: 修正 弹窗关不掉的问题 преди 5 месеца
  WANGKANG e5ca552392 feat: 总任务-注释轨迹序列-查看-编辑 初步完成 目标检测模型目前还获取不到 преди 5 месеца
  WANGKANG 5b5b03d9af feat: 总任务-可见光-查看-编辑 完成 преди 5 месеца
  WANGKANG 273f4c601b feat: 查看功能-列表展示完善 преди 5 месеца
  Eagle e84e772cff feat: 多源信息融合、异源图像匹配、电子稳相的暂停、继续、停止功能 преди 5 месеца
  WANGKANG 30de862353 feat: 初步实现子任务查看功能 преди 5 месеца
  WANGKANG a610081dc8 feat: 添加一个子任务查看接口 преди 5 месеца
  WANGKANG c506380af1 feat: 添加一个enum преди 5 месеца
  WANGKANG eb7ead22ca fix: 修正表单关闭后再打开内容未重置 преди 5 месеца
  WANGKANG 1dbf83a9eb feat: 总任务新增初步完成 преди 5 месеца
  WANGKANG 40bd03cdfd fix: 算法参数设置 преди 5 месеца
  WANGKANG 9f14d2b0e6 feat: 总任务新增窗口初步完成 преди 5 месеца
  WANGKANG 31fd6e5c13 feat: 总任务添加功能编写(未完成) преди 5 месеца
  WANGKANG dd5f6af347 feat: 可辨识性分析总任务前端任务初步添加 преди 5 месеца
  WANGKANG a72d64a4d8 feat: 可辨识性分析优化 преди 5 месеца
  Eagle 5bf88e391c feat: revert 4nodes labeled file to xywh format преди 5 месеца
  WANGKANG 9829203a45 feat: 目标检测优化 преди 5 месеца
  WANGKANG fdb92e4d25 feat: 优化可见光转红外两个细节 преди 5 месеца
  WANGKANG cf96a0a712 fix: 1. 可见光转红外新增、更新完成 2. 修正若干逻辑 3. 删掉无用方法 преди 5 месеца
  WANGKANG 4646566348 fix: 1. 移除多余的console 2. 可见光转红外新增界面修正 преди 5 месеца
  WANGKANG 96217b761a fix: 1. FromDialog组件添加updateItemOptions方法,用于动态更新表单 2. File组件修正一个警告 преди 5 месеца
  WANGKANG 7e13fc2a75 fix: protable添加一个change方法,可以用于在值发生变化时的回调 преди 5 месеца
  WANGKANG 3e93f505ba fix: 算法名称 преди 5 месеца
  WANGKANG 3540c449ea feat: 模型配置添加新的参数algorithmParameters преди 6 месеца
  WANGKANG 9d4cd04b08 feat: 可辨识性分析添加新的参数,前端适配 преди 6 месеца
  allen f65c4dfe61 Merge branch 'dev_lsk_b12' into develop преди 6 месеца
  Eagle 3fcbd18f3a feat: 数据扩增任务、电子稳相标准化 преди 6 месеца
променени са 33 файла, в които са добавени 2382 реда и са изтрити 327 реда
  1. 146 0
      src/api/interface/demo/algorithmTaskTrack.ts
  2. 75 0
      src/api/modules/demo/algorithmTaskTrack.ts
  3. 8 0
      src/api/modules/demo/match.ts
  4. 8 0
      src/api/modules/demo/traceMerge.ts
  5. 1 1
      src/api/modules/demo/trackSequence.ts
  6. 4 0
      src/api/modules/demo/videoStable.ts
  7. 14 6
      src/components/FormDialog/index.vue
  8. 10 0
      src/components/ProForm/components/Item.vue
  9. 5 5
      src/components/ProForm/index.vue
  10. 2 2
      src/components/Upload/File.vue
  11. 1 0
      src/typings/ProForm.d.ts
  12. 72 10
      src/views/demo/AlgorithmConfigTrack/index.vue
  13. 59 35
      src/views/demo/AlgorithmModelTrack/index.vue
  14. 123 27
      src/views/demo/TargetDetection/index.vue
  15. 1198 0
      src/views/demo/algorithmTaskTrack/index.vue
  16. 16 4
      src/views/demo/components/ShowStatisticResult.vue
  17. 10 5
      src/views/demo/components/ViewLog.vue
  18. 19 6
      src/views/demo/components/img-maker.vue
  19. 15 12
      src/views/demo/data/AmplifyForm.vue
  20. 11 3
      src/views/demo/data/index.vue
  21. 41 0
      src/views/demo/data/reformat.js
  22. 16 0
      src/views/demo/dataAugmentation/index.vue
  23. 14 0
      src/views/demo/imageMosaic/index.vue
  24. 19 3
      src/views/demo/match/index.vue
  25. 13 1
      src/views/demo/targetDamageAcess/index.vue
  26. 15 0
      src/views/demo/targetTrack/index.vue
  27. 123 99
      src/views/demo/toInfrared/index.vue
  28. 29 4
      src/views/demo/traceMerge/index.vue
  29. 188 27
      src/views/demo/trackSequence/index.vue
  30. 8 0
      src/views/demo/utils.ts
  31. 109 74
      src/views/demo/videoStable/index.vue
  32. 8 3
      src/views/taais/homePage/task/index.vue
  33. 2 0
      src/views/task/bizProcess/index.vue

+ 146 - 0
src/api/interface/demo/algorithmTaskTrack.ts

@@ -0,0 +1,146 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface AlgorithmTaskTrackVO extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id: string | number
+
+  /**
+   * 任务名称
+   */
+  name: string
+
+  /**
+   * 任务状态
+   */
+  status: string
+
+  /**
+   * 开始时间
+   */
+  startTime: string
+
+  /**
+   * 结束时间
+   */
+  endTime: string
+
+  /**
+   * 耗时
+   */
+  costSecond: number
+
+  /**
+   * 日志
+   */
+  log: string
+
+  /**
+   * 备注
+   */
+  remarks: string
+
+  /**
+   * 系统
+   */
+  system: string
+}
+
+export interface AlgorithmTaskTrackForm {
+  /**
+   * 主键ID
+   */
+  id?: string | number
+
+  /**
+   * 任务名称
+   */
+  name?: string
+
+  /**
+   * 任务状态
+   */
+  status?: string
+
+  /**
+   * 开始时间
+   */
+  startTime?: string
+
+  /**
+   * 结束时间
+   */
+  endTime?: string
+
+  /**
+   * 耗时
+   */
+  costSecond?: number
+
+  /**
+   * 日志
+   */
+  log?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * 乐观锁
+   */
+  version?: number
+
+  /**
+   * 系统
+   */
+  system?: string
+}
+
+export interface AlgorithmTaskTrackQuery extends PageQuery {
+  /**
+   * 任务名称
+   */
+  name?: string
+
+  /**
+   * 任务状态
+   */
+  status?: string
+
+  /**
+   * 开始时间
+   */
+  startTime?: string
+
+  /**
+   * 结束时间
+   */
+  endTime?: string
+
+  /**
+   * 耗时
+   */
+  costSecond?: number
+
+  /**
+   * 日志
+   */
+  log?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * 系统
+   */
+  system?: string
+
+  /**
+   * 日期范围参数
+   */
+  params?: any
+}

+ 75 - 0
src/api/modules/demo/algorithmTaskTrack.ts

@@ -0,0 +1,75 @@
+import http from '@/api'
+import { AlgorithmTaskTrackVO, AlgorithmTaskTrackForm, AlgorithmTaskTrackQuery } from '@/api/interface/demo/algorithmTaskTrack'
+
+/**
+ * @name 查询可辨识性分析总任务列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listAlgorithmTaskTrackApi = (query: AlgorithmTaskTrackQuery) => {
+  return http.get<AlgorithmTaskTrackVO[]>('/demo/algorithmTaskTrack/list', query, { loading: true })
+}
+
+/**
+ * @name 查询可辨识性分析总任务详细
+ * @param id id
+ * @returns returns
+ */
+export const getAlgorithmTaskTrackApi = (id: string | number) => {
+  return http.get<AlgorithmTaskTrackVO>(`/demo/algorithmTaskTrack/${id}`)
+}
+
+/**
+ * @name 新增可辨识性分析总任务
+ * @param data data
+ * @returns returns
+ */
+export const addAlgorithmTaskTrackApi = (data: AlgorithmTaskTrackForm) => {
+  return http.post<any>('/demo/algorithmTaskTrack', data, { loading: false })
+}
+
+/**
+ * @name 修改可辨识性分析总任务
+ * @param data data
+ * @returns returns
+ */
+export const updateAlgorithmTaskTrackApi = (data: AlgorithmTaskTrackForm) => {
+  return http.put<any>('/demo/algorithmTaskTrack', data, { loading: false })
+}
+
+/**
+ * @name 删除可辨识性分析总任务
+ * @param id id
+ * @returns returns
+ */
+export const delAlgorithmTaskTrackApi = (id: string | number | Array<string | number>) => {
+  return http.delete<any>(`/demo/algorithmTaskTrack/${id}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/demo/algorithmTaskTrack/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importAlgorithmTaskTrackDataApi = (data: any) => {
+  return http.post('/demo/algorithmTaskTrack/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportAlgorithmTaskTrackApi = (data: any) => {
+  return http.downloadPost('/demo/algorithmTaskTrack/export', data)
+}
+
+export const listSubTaskAlgorithmTaskTrackApi = (id: string | number) => {
+  return http.get(`/demo/algorithmTaskTrack/listSubTask/${id}`)
+}

+ 8 - 0
src/api/modules/demo/match.ts

@@ -35,6 +35,14 @@ export const execute = data => {
   return http.get<any>('/demo/match/execute', data, { loading: false })
 }
 
+export const stopApi = data => {
+  return http.get<any>('/demo/match/stop', data, { loading: false })
+}
+
+export const hangupApi = data => {
+  return http.get<any>('/demo/match/hangup', data, { loading: false })
+}
+
 export const getResult = data => {
   return http.get<any>('/demo/match/result', data, { loading: false })
 }

+ 8 - 0
src/api/modules/demo/traceMerge.ts

@@ -31,6 +31,14 @@ export const executeApi = data => {
   return http.post<any>('/demo/traceMerge/execute', data, { loading: false })
 }
 
+export const stopApi = data => {
+  return http.post<any>('/demo/traceMerge/stop', data, { loading: false })
+}
+
+export const hangupApi = data => {
+  return http.post<any>('/demo/traceMerge/hangup', data, { loading: false })
+}
+
 export const getResApi = data => {
   return http.get<any>('/demo/traceMerge/result', data, { loading: false })
 }

+ 1 - 1
src/api/modules/demo/trackSequence.ts

@@ -115,6 +115,6 @@ export const previewEvaluateTrackSequenceApi = (id: string | number) => {
   return http.get('/demo/trackSequence/previewEvaluateResult/' + id, {}, { loading: false })
 }
 
-export const getStatisticsResultToInfraredApi = (id: string | number) => {
+export const getStatisticsResultTrackSequenceApi = (id: string | number) => {
   return http.get('/demo/trackSequence/statistics_result/' + id, {}, { loading: false })
 }

+ 4 - 0
src/api/modules/demo/videoStable.ts

@@ -83,6 +83,10 @@ export const stopVideoStableApi = (id: String | Number) => {
   return http.get('/demo/videoStable/stop/' + id)
 }
 
+export const hangupVideoStableApi = (id: String | Number) => {
+  return http.get('/demo/videoStable/hangup/' + id)
+}
+
 export const getCompareImageApi = (taskId: String, idx: String | Number) => {
   return http.get('/demo/videoStable/compare/' + taskId + '/' + idx)
 }

+ 14 - 6
src/components/FormDialog/index.vue

@@ -25,7 +25,7 @@
 </template>
 
 <script setup lang="ts" name="FormDialog">
-import { ref, ComputedRef, computed, reactive } from 'vue'
+import { ref, ComputedRef, computed, reactive, nextTick } from 'vue'
 import ProFrom from '@/components/ProForm/index.vue'
 import { ElMessage } from 'element-plus'
 import FileUpload from '@/components/Upload/File.vue'
@@ -130,10 +130,10 @@ const handleCancel = () => {
   //console.log(parameter.value.model)
   const formEl = proFormRef.value?.proFormRef
   if (!formEl) return
-  if (parameter.value.model?.url) {
-    ElMessage.info('请先删除已经上传的图片')
-    return
-  }
+  // if (parameter.value.model?.url) {
+  //   ElMessage.info('请先删除已经上传的图片')
+  //   return
+  // }
   proFormRef.value?.resetForm(formEl)
   butLoading.value = false
   dialogVisible.value = false
@@ -150,8 +150,16 @@ const openDialog = (params: FormParameterProps, algoModelId = null) => {
   dialogVisible.value = true
 }
 
+const updateItemOptions = (itemsOptions: ProForm.ItemsOptions[]) => {
+  // console.log('updateItemOptions', itemsOptions)
+  nextTick(() => {
+    parameter.value.itemsOptions = Object.assign([], itemsOptions)
+  })
+}
+
 defineExpose({
-  openDialog
+  openDialog,
+  updateItemOptions
 })
 </script>
 

+ 10 - 0
src/components/ProForm/components/Item.vue

@@ -5,6 +5,7 @@
     v-model.trim="_formModel[handleProp(item.prop)]"
     :data="['tree-select'].includes(item.compOptions.elTagName!) ? itemEnum : []"
     :options="['cascader', 'select-v2'].includes(item.compOptions.elTagName!) ? itemEnum : []"
+    @change="handleInputChange(item, formModel)"
   >
     <template v-if="item.compOptions.elTagName === 'cascader'" #default="{ data }">
       <span>{{ data[item.compOptions.labelKey || 'label'] }}</span>
@@ -44,10 +45,13 @@
 <script setup lang="ts" name="Item">
 import { computed, inject, ref } from 'vue'
 import { handleProp } from '@/utils'
+
 interface FormItem {
   item: ProForm.ItemsOptions
   formModel: Record<string, any>
+  change?: (val: any) => void
 }
+
 const props = defineProps<FormItem>()
 const _formModel = computed(() => props.formModel)
 const elTagNameValue = computed(() => {
@@ -73,4 +77,10 @@ const itemEnum = computed(() => {
   }
   return enumData
 })
+
+const handleInputChange = (item: ProForm.ItemsOptions, formModel: Record<string, any>) => {
+  if (item.change) {
+    props.change(item, formModel)
+  }
+}
 </script>

+ 5 - 5
src/components/ProForm/index.vue

@@ -2,7 +2,7 @@
   <component :is="'el-form'" v-bind="_formOptions" ref="proFormRef" :model="formModel">
     <el-row :gutter="5">
       <template v-for="item in itemsOptions" :key="item.prop">
-        <el-col :span="item.span || 24" g v-if="show(item.show)">
+        <el-col :span="item.span || 24" v-if="show(item.show)">
           <component :is="'el-form-item'" v-bind="item">
             <template #label>
               <el-space :size="4">
@@ -46,7 +46,7 @@
             <template v-else-if="item.compOptions.elTagName === 'imgs-upload-s3'">
               <ImgsS3 v-model="formModel[item.prop]" v-bind="$attrs" />
             </template>
-            <Item v-else :item="item" :form-model="formModel" />
+            <Item v-else :item="item" :form-model="formModel" :change="item.change" />
           </component>
         </el-col>
       </template>
@@ -96,8 +96,8 @@ const props = withDefaults(defineProps<ProFormProps>(), {
 const show = (showFunction: any) => {
   if (!showFunction) return true
   if (typeof showFunction == 'function') {
-    // 直接调用 showFunction 函数,并传入 formModel.value
-    return showFunction(formModel.value)
+    // 直接调用 showFunction 函数,并传入 formModel,方便修改参数
+    return showFunction(formModel)
   }
   // 如果 showFunction 不是函数,直接返回 true 显示该表单项
   return true
@@ -213,5 +213,5 @@ defineExpose({
 })
 </script>
 <style scoped lang="scss">
-@import './index.scss';
+@import './index';
 </style>

+ 2 - 2
src/components/Upload/File.vue

@@ -66,7 +66,7 @@ interface UploadFileProps {
   icon?: string
   fileType?: Array<string>
   uploadApiPath?: string // 上传文件服务器地址
-  canRemove: boolean // 是否显示删除按钮
+  canRemove?: boolean // 是否显示删除按钮
 }
 
 // 默认值
@@ -81,7 +81,7 @@ const props = withDefaults(defineProps<UploadFileProps>(), {
   isShowTip: true,
   uploadApiPath: '/common/upload',
   icon: 'upload-filled',
-  canRemove: false
+  canRemove: true
 })
 
 const baseUrl = import.meta.env.VITE_API_URL

+ 1 - 0
src/typings/ProForm.d.ts

@@ -66,6 +66,7 @@ declare namespace ProForm {
     rules?: FormItemRule[]
     span?: number // 表单col宽度
     show?: (params?: any) => Promise<any> | boolean | string // 是否显示 默认显示
+    change?: (item: any, params?: any) => void // 值改变时触发
     /** 表单组件配置项 */
     compOptions: CompAttributes // 表单组件配置项
   }

+ 72 - 10
src/views/demo/AlgorithmConfigTrack/index.vue

@@ -166,19 +166,47 @@ const columns = reactive<ColumnProps<any>[]>([
     }
   },
   {
-    prop: 'algorithmAddress',
-    label: '算法地址',
+    prop: 'startApi',
+    label: '开始api',
     search: {
       el: 'input'
     }
   },
   {
-    prop: 'parameterConfig',
+    prop: 'pauseApi',
+    label: '暂停api',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'terminateApi',
+    label: '终止api',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'parameters',
     label: '参数配置',
     search: {
       el: 'input'
     }
   },
+  // {
+  //   prop: 'algorithmAddress',
+  //   label: '算法地址',
+  //   search: {
+  //     el: 'input'
+  //   }
+  // },
+  // {
+  //   prop: 'parameterConfig',
+  //   label: '参数配置',
+  //   search: {
+  //     el: 'input'
+  //   }
+  // },
   {
     prop: 'remarks',
     label: '备注',
@@ -237,23 +265,57 @@ const setItemsOptions = () => {
       }
     },
     {
-      label: '算法地址',
-      prop: 'algorithmAddress',
-      rules: [{ required: true, message: '算法地址不能为空', trigger: 'blur' }],
+      label: '开始api',
+      prop: 'startApi',
+      rules: [{ required: true, message: '开始api不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入开始api'
+      }
+    },
+    {
+      label: '暂停api',
+      prop: 'pauseApi',
+      rules: [{ required: false, message: '暂停api不能为空', trigger: 'blur' }],
       compOptions: {
-        placeholder: '请输入算法地址'
+        placeholder: '请输入暂停api'
+      }
+    },
+    {
+      label: '终止api',
+      prop: 'terminateApi',
+      rules: [{ required: true, message: '终止api不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入终止api'
       }
     },
     {
       label: '参数配置',
-      prop: 'parameterConfig',
-      rules: [{ required: true, message: '参数配置不能为空', trigger: 'blur' }],
+      prop: 'parameters',
+      rules: [{ required: false, message: '参数配置不能为空', trigger: 'blur' }],
       compOptions: {
         type: 'textarea',
         clearable: true,
-        placeholder: '请输入内容'
+        placeholder: '请输入参数配置'
       }
     },
+    // {
+    //   label: '算法地址',
+    //   prop: 'algorithmAddress',
+    //   rules: [{ required: true, message: '算法地址不能为空', trigger: 'blur' }],
+    //   compOptions: {
+    //     placeholder: '请输入算法地址'
+    //   }
+    // },
+    // {
+    //   label: '参数配置',
+    //   prop: 'parameterConfig',
+    //   rules: [{ required: true, message: '参数配置不能为空', trigger: 'blur' }],
+    //   compOptions: {
+    //     type: 'textarea',
+    //     clearable: true,
+    //     placeholder: '请输入内容'
+    //   }
+    // },
     {
       label: '备注',
       prop: 'remarks',

+ 59 - 35
src/views/demo/AlgorithmModelTrack/index.vue

@@ -70,7 +70,7 @@ import {
 } from '@/api/modules/demo/AlgorithmModelTrack'
 
 import { enumAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
-import { AlgorithmType, SubSystem, enumsModelStatus, enumsAlgorithmType, enumsSubSystem } from '@/views/demo/utils'
+import { AlgorithmType, SubSystem, enumsModelStatus, enumsAlgorithmType, enumsSubSystem, AlgorithmType2 } from '@/views/demo/utils'
 
 // ProTable 实例
 const proTable = ref<ProTableInstance>()
@@ -148,16 +148,16 @@ const columns = reactive<ColumnProps<any>[]>([
     },
     minWidth: 200
   },
-  {
-    prop: 'type',
-    label: '类型',
-    tag: true,
-    enum: enumsAlgorithmType,
-    search: {
-      el: 'select'
-    },
-    width: 120
-  },
+  // {
+  //   prop: 'type',
+  //   label: '类型',
+  //   tag: true,
+  //   enum: enumsAlgorithmType,
+  //   search: {
+  //     el: 'select'
+  //   },
+  //   width: 120
+  // },
   //   {
   //     prop: 'parentId',
   //     label: '父id',
@@ -176,16 +176,16 @@ const columns = reactive<ColumnProps<any>[]>([
     },
     width: 120
   },
-  {
-    prop: 'modelStatus',
-    label: '模型状态',
-    tag: true,
-    enum: enumsModelStatus,
-    search: {
-      el: 'select'
-    },
-    width: 120
-  },
+  // {
+  //   prop: 'modelStatus',
+  //   label: '模型状态',
+  //   tag: true,
+  //   enum: enumsModelStatus,
+  //   search: {
+  //     el: 'select'
+  //   },
+  //   width: 120
+  // },
   //   {
   //     prop: 'sampleNumber',
   //     label: '训练样本数',
@@ -204,11 +204,19 @@ const columns = reactive<ColumnProps<any>[]>([
   //   },
   {
     prop: 'modelAddress',
-    label: '模型',
+    label: '模型地址',
     search: {
       el: 'input'
     },
-    width: 120
+    width: 240
+  },
+  {
+    prop: 'algorithmParameters',
+    label: '算法参数',
+    search: {
+      el: 'input'
+    },
+    width: 200
   },
   {
     prop: 'remarks',
@@ -228,6 +236,7 @@ const columns = reactive<ColumnProps<any>[]>([
   //   },
   { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
 ])
+
 // 表单配置项
 let itemsOptions: ProForm.ItemsOptions[] = []
 
@@ -235,21 +244,16 @@ const enumsAlgorithmConfigTrack = ref<any>([])
 
 onMounted(async () => {
   const result: any = await enumAlgorithmConfigTrackApi()
-  // console.log(result)
-  // console.log(result['data'])
+  const tmp = []
   for (let item of result['data']) {
-    // console.log(item)
-    // console.log(item['type'])
-    // console.log(item['subsystem'])
-    // console.log(AlgorithmType[item['type']])
-    // console.log(SubSystem[item['subsystem']])
-    // console.log(AlgorithmType)
-    // console.log(SubSystem)
-    // console.log('-------------------')
-    item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']]
+    if (item['type'] == AlgorithmType2['预测/推理']) {
+      const tmpItem = { ...item }
+      tmpItem['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']]
+      tmp.push(tmpItem)
+    }
   }
 
-  enumsAlgorithmConfigTrack.value = result['data']
+  enumsAlgorithmConfigTrack.value = tmp
   return result['data']
 })
 
@@ -273,6 +277,16 @@ const setItemsOptions = () => {
         placeholder: '请输入模型名称'
       }
     },
+    // {
+    //   label: '分系统',
+    //   prop: 'subSystem',
+    //   rules: [{required: true, message: '分系统不能为空', trigger: 'blur'}],
+    //   compOptions: {
+    //     elTagName: 'select',
+    //     placeholder: '请选择分系统',
+    //     enum: enumsSubSystem,
+    //   }
+    // },
     {
       label: '模型',
       prop: 'modelInputOssId',
@@ -300,6 +314,16 @@ const setItemsOptions = () => {
     //     placeholder: '请输入训练循环次数'
     //   }
     // },
+    {
+      label: '算法参数',
+      prop: 'algorithmParameters',
+      rules: [{ required: false, message: '算法参数不能为空', trigger: 'blur' }],
+      compOptions: {
+        type: 'textarea',
+        clearable: true,
+        placeholder: '请输入算法参数'
+      }
+    },
     {
       label: '备注',
       prop: 'remarks',

+ 123 - 27
src/views/demo/TargetDetection/index.vue

@@ -28,10 +28,16 @@
       </template>
       <!-- 表格操作 -->
       <template #operation="scope">
-        <el-button type="primary" link icon="View" v-if="scope.row.algorithmModelId != null" @click="openModelDialog(scope.row)">
-          <!--@click="openStartDialog(scope.row)"  -->
+        <!--        <el-button type="primary" link icon="View" @click="openModelDialog(scope.row)">-->
+        <!--          &lt;!&ndash;@click="openStartDialog(scope.row)"  &ndash;&gt;-->
+        <!--          详情-->
+        <!--        </el-button>-->
+        <el-button type="primary" link icon="View" v-auth="['demo:TargetDetection:query']" @click="openDialog(3, '详情', scope.row)">
           详情
         </el-button>
+        <el-button type="primary" link icon="EditPen" v-auth="['demo:TargetDetection:edit']" @click="openDialog(2, '编辑', scope.row)">
+          编辑
+        </el-button>
         <el-button
           type="primary"
           link
@@ -77,24 +83,6 @@
         >
           模型
         </el-button>
-        <!--        <el-button-->
-        <!--          type="primary"-->
-        <!--          link-->
-        <!--          icon="View"-->
-        <!--          v-auth="['demo:TargetDetection:query']"-->
-        <!--          @click="openDialog(3, '目标检测查看', scope.row)"-->
-        <!--        >-->
-        <!--          查看-->
-        <!--        </el-button>-->
-        <!--        <el-button-->
-        <!--          type="primary"-->
-        <!--          link-->
-        <!--          icon="EditPen"-->
-        <!--          v-auth="['demo:TargetDetection:edit']"-->
-        <!--          @click="openDialog(2, '目标检测编辑', scope.row)"-->
-        <!--        >-->
-        <!--          编辑-->
-        <!--        </el-button>-->
         <el-button type="primary" link icon="Delete" v-auth="['demo:TargetDetection:remove']" @click="deleteTargetDetection(scope.row)">
           删除
         </el-button>
@@ -162,14 +150,12 @@ import {
 } from '@/api/modules/demo/TargetDetection'
 
 import { listDataSeqApi } from '@/api/modules/demo/DataSeq'
-
 import { enumAlgorithmModelTrackApi, getAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
-import { enumAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
+import { enumAlgorithmConfigTrackApi, getAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
 import { updateTrackSequenceApi } from '@/api/modules/demo/trackSequence'
 import ViewLog from '@/views/demo/components/ViewLog.vue'
 import { AlgorithmType2 } from '@/views/demo/utils'
 import { addAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
-
 import useWebSocketStore from '@/stores/modules/websocket'
 import { resetHeart } from '@/utils/websocket'
 
@@ -192,7 +178,7 @@ onMounted(async () => {
   enumsAlgorithmConfigTrack.value = []
   const tmp_data: any = result['data']
   for (const item of tmp_data) {
-    if (item.subsystem === SubSystem__['目标检测'] && item.type === AlgorithmType2['预测/推理']) {
+    if (item.subsystem === SubSystem__['目标检测']) {
       item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']]
       enumsAlgorithmConfigTrack.value.push(item)
     }
@@ -227,7 +213,7 @@ const setItemsOptions222 = () => {
       prop: 'modelName',
       rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
       compOptions: {
-        disabled: true,
+        disabled: false,
         placeholder: '请输入模型名称'
       }
     },
@@ -368,10 +354,17 @@ const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
 const openDialog = async (type: number, title: string, row?: any) => {
   let res = { data: {} }
   if (row?.id) {
-    res = await getTargetDetectionApi(row?.id || null)
+    res = await getTargetDetectionApi(row.id || null)
+    const params = JSON.parse(res.data['algorithmParameters'])
+    if (params.otherParams) {
+      res.data = { ...res.data, ...params.otherParams }
+    }
   }
   // 重置表单
   setItemsOptions()
+  if (row?.id) {
+    itemsOptions = await updateItemsOptions(row.algorithmId)
+  }
   const params = {
     title,
     width: 580,
@@ -430,6 +423,14 @@ const columns = reactive<ColumnProps<any>[]>([
     label: '模型名称',
     width: 200
   },
+  {
+    prop: 'algorithmParameters',
+    label: '算法参数',
+    search: {
+      el: 'input'
+    },
+    width: 150
+  },
   // {
   //   prop: 'algorithmModelId',
   //   label: '模型',
@@ -516,6 +517,52 @@ onMounted(async () => {
   updateWnumsAlgorithmModelTrack()
 })
 
+const remove_unnecessary_parameters = (itemsOptions: ProForm.ItemsOptions[]): ProForm.ItemsOptions[] => {
+  try {
+    const endIndex = itemsOptions.findIndex(option => option['label'] === '备注')
+    if (endIndex !== -1) {
+      itemsOptions = itemsOptions.slice(0, endIndex + 1)
+    }
+    return itemsOptions
+  } catch (error) {
+    console.error('移除不必要的参数时出错:', error)
+    // ElMessage.error('移除不必要的参数时出错,请检查!');
+    return itemsOptions // 返回原始选项,避免进一步的问题
+  }
+}
+
+const updateItemsOptions = async (algorithmId: any) => {
+  try {
+    const result = await getAlgorithmConfigTrackApi(algorithmId)
+    if (result.code === 200) {
+      // 处理结果
+      const parameters = JSON.parse(result.data['parameters'])
+      // console.log('parameters: ', parameters)
+
+      const itemsOptions_new = remove_unnecessary_parameters(itemsOptions)
+      for (const item of parameters) {
+        // 添加新的表单项选项
+        itemsOptions_new.push({
+          label: item['name'],
+          prop: item['agName'],
+          rules: [{ required: item['required'], message: item['agName'] + '不能为空', trigger: 'blur' }],
+          tooltip: item['prompt'],
+          compOptions: {
+            elTagName: 'input',
+            placeholder: item['defaultValue']
+            // value: item['defaultValue']
+          }
+        })
+      }
+      formDialogRef.value?.updateItemOptions(itemsOptions_new)
+      return itemsOptions_new
+    }
+  } catch (err) {
+    console.log(err)
+    ElMessage.error('获取算法配置失败,请检查!')
+  }
+}
+
 // 表单配置项
 let itemsOptions: ProForm.ItemsOptions[] = []
 const setItemsOptions = () => {
@@ -550,14 +597,62 @@ const setItemsOptions = () => {
         placeholder: '请上传数据集'
       }
     },
+    {
+      label: '选择算法',
+      prop: 'algorithmId',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择算法',
+        enum: enumsAlgorithmConfigTrack,
+        clearable: true,
+        onChange: async (value: any) => {
+          if (value != undefined && value != null && value != '') {
+            await updateItemsOptions(value)
+          }
+        }
+      }
+    },
+    {
+      label: '任务类型',
+      prop: 'type',
+      rules: [{ required: true, message: '任务类型不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        elTagName: 'select',
+        placeholder: '请选择模任务类型',
+        enum: enumsAlgorithmType,
+        clearable: true,
+        value: ''
+      },
+      show: params => {
+        if (params.value.algorithmId != undefined) {
+          for (let i = 0; i < enumsAlgorithmConfigTrack.value.length; i++) {
+            if (enumsAlgorithmConfigTrack.value[i]['value'] === params.value.algorithmId) {
+              params.value.type = enumsAlgorithmConfigTrack.value[i]['type']
+              return true
+            }
+          }
+        }
+        return false
+      }
+    },
     {
       label: '选择模型',
       prop: 'algorithmModelId',
       rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
+      show: params => {
+        if (params.value.type == AlgorithmType2['预测/推理']) {
+          return true
+        }
+        params.value.algorithmModelId = ''
+        return false
+      },
       compOptions: {
         elTagName: 'select',
         placeholder: '请选择模型',
-        enum: enumsAlgorithmModelTrack
+        enum: enumsAlgorithmModelTrack,
+        clearable: true
       }
     },
     {
@@ -565,6 +660,7 @@ const setItemsOptions = () => {
       prop: 'remarks',
       rules: [],
       compOptions: {
+        elTagName: 'input',
         placeholder: '请输入备注'
       }
     }

+ 1198 - 0
src/views/demo/algorithmTaskTrack/index.vue

@@ -0,0 +1,1198 @@
+<template>
+  <div class="table-box">
+    <ProTable ref="proTable" :columns="columns" row-key="id" :request-api="listAlgorithmTaskTrackApi">
+      <!-- 表格 header 按钮 -->
+      <template #tableHeader="scope">
+        <el-button type="primary" v-auth="['demo:algorithmTaskTrack:add']" icon="CirclePlus" @click="dialogVisibleAddTask = true"> 新增 </el-button>
+        <!--        <el-button type="primary" v-auth="['demo:algorithmTaskTrack:import']" icon="Upload" plain @click="batchAdd"> 导入-->
+        <!--        </el-button>-->
+        <!--        <el-button type="primary" v-auth="['demo:algorithmTaskTrack:export']" icon="Download" plain @click="downloadFile"> 导出-->
+        <!--        </el-button>-->
+        <el-button
+          type="danger"
+          v-auth="['demo:algorithmTaskTrack:remove']"
+          icon="Delete"
+          plain
+          :disabled="!scope.isSelected"
+          @click="batchDelete(scope.selectedListIds)"
+        >
+          批量删除
+        </el-button>
+      </template>
+      <!-- 表格操作 -->
+      <template #operation="scope">
+        <el-button type="primary" link icon="View" v-auth="['demo:algorithmTaskTrack:query']" @click="openViewDialog(scope.row)"> 查看 </el-button>
+        <!--        <el-button-->
+        <!--          type="primary"-->
+        <!--          link-->
+        <!--          icon="EditPen"-->
+        <!--          v-auth="['demo:algorithmTaskTrack:edit']"-->
+        <!--          @click="openDialog(2, '可辨识性分析总任务编辑', scope.row)"-->
+        <!--        >-->
+        <!--          编辑-->
+        <!--        </el-button>-->
+        <el-button type="primary" link icon="Delete" v-auth="['demo:algorithmTaskTrack:remove']" @click="deleteAlgorithmTaskTrack(scope.row)">
+          删除
+        </el-button>
+      </template>
+    </ProTable>
+    <FormDialog ref="formDialogRef" />
+    <ImportExcel ref="dialogRef" />
+    <el-dialog v-model="dialogVisibleAddTask" title="可辨识性分析总任务新增" width="700" @open="handleOpenAddTask()" :before-close="handleClose">
+      <el-form ref="formAddTaskRef" :model="formAddTask" :rules="rulesAddTask" label-width="auto" style="max-width: 600px">
+        <el-form-item label="任务名称" prop="name">
+          <el-input v-model="formAddTask.name" placeholder="请输入任务名称" />
+        </el-form-item>
+        <el-form-item label="是否转红外" prop="ifToInfrared">
+          <el-checkbox v-model="formAddTask.ifToInfrared" @click="setIfToInfrared()" />
+        </el-form-item>
+        <el-form-item label="选择转红外算法" v-show="formAddTask.ifToInfrared" prop="toInfraredAlgorithmId">
+          <div class="form-item1">
+            <el-select v-model="formAddTask.toInfraredAlgorithmId" placeholder="请选择转红外算法" clearable>
+              <el-option v-for="item in enumsAlgorithmConfigTrack_toInfrared" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+            <el-button
+              @click="setAlgorithmParams(formAddTask.toInfraredAlgorithmId, 'toInfraredAlgorithmParams')"
+              style="margin-left: 10px"
+              :disabled="formAddTask.toInfraredAlgorithmId == undefined || formAddTask.toInfraredAlgorithmId == ''"
+            >
+              <SvgIcon :name="'Setting'" style="margin-right: 5px" />
+              设置算法参数
+            </el-button>
+          </div>
+        </el-form-item>
+        <el-form-item label="选择可见光转红外模型" v-show="formAddTask.ifToInfrared" prop="toInfraredModelId">
+          <el-select v-model="formAddTask.toInfraredModelId" placeholder="请选择可见光转红外模型" clearable>
+            <el-option v-for="item in toInfraredModelList" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="选择数据集" prop="inputDatasetOssId">
+          <el-select v-model="formAddTask.inputDatasetOssId" placeholder="请选择数据集" clearable>
+            <el-option v-for="item in datasetList" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="上传数据集" prop="inputDatasetOssId">
+          <File ref="fileUploadRef" :file-type="['zip']" :file-size="4096" @update:model-value="fileUploadDatasetChange" />
+        </el-form-item>
+        <el-form-item label="选择视觉算法" prop="trackSequenceAlgorithmId">
+          <div class="form-item1">
+            <el-select v-model="formAddTask.trackSequenceAlgorithmId" placeholder="请选择视觉算法" clearable>
+              <el-option v-for="item in visionAlgorithmList" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+            <el-button
+              @click="setAlgorithmParams(formAddTask.trackSequenceAlgorithmId, 'trackSequenceAlgorithmParams')"
+              style="margin-left: 10px"
+              :disabled="formAddTask.trackSequenceAlgorithmId == undefined || formAddTask.trackSequenceAlgorithmId == ''"
+            >
+              <SvgIcon :name="'Setting'" style="margin-right: 5px" />
+              设置算法参数
+            </el-button>
+          </div>
+        </el-form-item>
+        <el-form-item label="选择目标检测模型" prop="TD_modelId">
+          <el-select v-model="formAddTask.TD_modelId" placeholder="请选择目标检测模型" clearable>
+            <el-option v-for="item in targetDetectionModelList" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="选择视觉算法模型" prop="trackSequenceModelId">
+          <el-select v-model="formAddTask.trackSequenceModelId" placeholder="请选择视觉算法模型" clearable>
+            <el-option v-for="item in visionAlgorithmModelList" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="是否评估" prop="ifEvaluate">
+          <el-checkbox v-model="formAddTask.ifEvaluate" />
+        </el-form-item>
+        <el-form-item label="上传真实标签" prop="inputEvaluateLabelOssId" v-show="formAddTask.ifEvaluate">
+          <File ref="fileUploadEvaluateLabelRef" :model-value="formAddTask.inputEvaluateLabelOssId" :file-type="['txt']" :file-size="4096" @update:model-value="fileUploadChangeEvaluateLabel" />
+        </el-form-item>
+        <el-form-item label="选择视觉评估算法" prop="trackSequenceEvaluateAlgorithmId" v-show="formAddTask.ifEvaluate">
+          <div class="form-item1">
+            <el-select v-model="formAddTask.trackSequenceEvaluateAlgorithmId" placeholder="请选择视觉评估算法" clearable>
+              <el-option v-for="item in visionEvaluateAlgorithmList" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+            <el-button
+              @click="setAlgorithmParams(formAddTask.trackSequenceEvaluateAlgorithmId, 'trackSequenceEvaluateAlgorithmParams')"
+              style="margin-left: 10px"
+              :disabled="formAddTask.trackSequenceEvaluateAlgorithmId == undefined || formAddTask.trackSequenceEvaluateAlgorithmId == ''"
+            >
+              <SvgIcon :name="'Setting'" style="margin-right: 5px" />
+              设置算法参数
+            </el-button>
+          </div>
+        </el-form-item>
+        <el-form-item label="备注" prop="remarks">
+          <el-input v-model="formAddTask.remarks" placeholder="请输入备注" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="dialogVisibleAddTask = false">取消</el-button>
+        <el-button type="primary" @click="addAlgorithmTaskTrack"> 确定</el-button>
+      </template>
+    </el-dialog>
+    <el-dialog v-model="dialogVisibleView" @open="handleOpenView()" title="可辨识性分析总任务查看" width="90%">
+      <div style="width: 100%; height: auto; overflow: auto">
+        <el-table :data="viewData" border height="500px">
+          <el-table-column prop="id" label="主键ID" width="180" />
+          <el-table-column prop="name" label="任务名称" width="150">
+            <template #default="scope">
+              <el-tooltip :content="scope.row.name" raw-content placement="top-start" v-if="scope.row.name">
+                <span>{{ scope.row.name && scope.row.name.length > 15 ? scope.row.name.substring(0, 15) + '...' : scope.row.name }} </span>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column prop="status" label="任务状态" width="150">
+            <template #default="scope">
+              <el-tag type="success">
+                {{ Status__[scope.row.status] }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="type" label="类型" width="120">
+            <template #default="scope">
+              <el-tag type="success">
+                {{ AlgorithmType[scope.row.type] }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="subsystem" label="分系统" width="200">
+            <template #default="scope">
+              <el-tag type="success">
+                {{ SubSystem[scope.row.subsystem] }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="algorithmName" label="算法名称" width="200" />
+          <el-table-column prop="modelName" label="模型名称" width="200" />
+          <el-table-column prop="algorithmParameters" label="算法参数" width="150">
+            <template #default="scope">
+              <el-tooltip :content="scope.row.algorithmParameters" raw-content placement="top-start" v-if="scope.row.algorithmParameters">
+                <span
+                  >{{
+                    scope.row.outputPath && scope.row.algorithmParameters.length > 15
+                      ? scope.row.algorithmParameters.substring(0, 15) + '...'
+                      : scope.row.algorithmParameters
+                  }}
+                </span>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column prop="startTime" label="开始时间" width="180" />
+          <el-table-column prop="endTime" label="结束时间" width="180" />
+          <el-table-column prop="costSecond" label="耗时" width="120" />
+          <el-table-column prop="log" label="日志" width="120">
+            <template #default="scope">
+              <el-tooltip :content="scope.row.log" raw-content placement="top-start" v-if="scope.row.log">
+                <span>{{ scope.row.outputPath && scope.row.log.length > 15 ? scope.row.log.substring(0, 15) + '...' : scope.row.log }} </span>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column prop="outputPath" label="输出路径" width="120">
+            <template #default="scope">
+              <el-tooltip :content="scope.row.outputPath" raw-content placement="top-start" v-if="scope.row.outputPath">
+                <span
+                  >{{
+                    scope.row.outputPath && scope.row.outputPath.length > 15 ? scope.row.outputPath.substring(0, 15) + '...' : scope.row.outputPath
+                  }}
+                </span>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+          <el-table-column prop="remarks" label="备注" width="120" />
+          <el-table-column prop="operation" label="操作" width="300" fixed="right">
+            <template #default="scope">
+              <el-button
+                type="primary"
+                link
+                icon="View"
+                v-if="scope.row.status == '0' || scope.row.status == '3' || scope.row.status == '4'"
+                @click="startSubTask(scope.row)"
+              >
+                开始
+              </el-button>
+              <el-popconfirm title="确定终止此任务吗?" @confirm="stopSubTask(scope.row)" v-if="scope.row.status == '1'">
+                <template #reference>
+                  <el-button type="primary" link icon="Delete"> 终止</el-button>
+                </template>
+              </el-popconfirm>
+              <el-button type="primary" link icon="View" @click="openLogSubTask(scope.row)" v-if="scope.row.status != '0'"> 日志 </el-button>
+              <el-button
+                type="primary"
+                link
+                icon="View"
+                v-if="scope.row.status == '2' && scope.row.type == AlgorithmType2['预测/推理']"
+                @click="previewSubTask(scope.row)"
+              >
+                预览
+              </el-button>
+              <el-button
+                type="primary"
+                link
+                icon="View"
+                v-if="scope.row.status == '2' && scope.row.type == AlgorithmType2['预测/推理']"
+                @click="showStatisticResultSubTask(scope.row)"
+              >
+                结果
+              </el-button>
+              <el-button
+                type="primary"
+                link
+                icon="View"
+                v-if="scope.row.status == '2' && scope.row.type == AlgorithmType2['测试']"
+                @click="showEvaluateResultSubTask(scope.row)"
+              >
+                结果
+              </el-button>
+              <!-- <el-button
+                type="primary"
+                link
+                icon="View"
+                v-if="scope.row.subsystem === SubSystem__['注释轨迹序列'] &&  scope.row.status == '2' && scope.row.type === AlgorithmType2['预测/推理']"
+                @click="showEvaluateSubTask(scope.row)"
+              >
+                评估
+              </el-button> -->
+              <el-button type="primary" link icon="View" @click="openSubTaskViewDialog(3, '子任务查看', scope.row)"> 查看 </el-button>
+              <el-button type="primary" link icon="EditPen" @click="openSubTaskViewDialog(2, '子任务编辑', scope.row)"> 编辑 </el-button>
+              <el-button type="danger" link icon="Delete" @click="deletSubTask(scope.row)"> 删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </el-dialog>
+    <ViewLog ref="viewLogRef" />
+    <PreviewCompareImages ref="previewImagesRef" />
+    <ShowStatisticResult ref="showStatisticResultRef" />
+  </div>
+</template>
+
+<script setup lang="tsx" name="AlgorithmTaskTrack">
+import { ref, reactive, onMounted } from 'vue'
+import { useHandleData } from '@/hooks/useHandleData'
+import { useDownload } from '@/hooks/useDownload'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import ProTable from '@/components/ProTable/index.vue'
+import ImportExcel from '@/components/ImportExcel/index.vue'
+import FormDialog from '@/components/FormDialog/index.vue'
+import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
+import {
+  listAlgorithmTaskTrackApi,
+  delAlgorithmTaskTrackApi,
+  addAlgorithmTaskTrackApi,
+  updateAlgorithmTaskTrackApi,
+  importTemplateApi,
+  importAlgorithmTaskTrackDataApi,
+  exportAlgorithmTaskTrackApi,
+  getAlgorithmTaskTrackApi,
+  listSubTaskAlgorithmTaskTrackApi
+} from '@/api/modules/demo/algorithmTaskTrack'
+import { AlgorithmType, AlgorithmType2, enumsAlgorithmType, enumsSubSystem, Status__, SubSystem, SubSystem__ } from '@/views/demo/utils'
+import { enumAlgorithmConfigTrackApi, getAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
+import SvgIcon from '@/components/SvgIcon/index.vue'
+import { listDataSeqApi } from '@/api/modules/demo/DataSeq'
+import File from '@/components/Upload/File.vue'
+import { enumAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
+import statusEnums from '@/utils/status'
+import {
+  addTrackSequenceApi,
+  delTrackSequenceApi,
+  getLogTrackSequenceApi,
+  getStatisticsResultTrackSequenceApi,
+  getTrackSequenceApi,
+  previewEvaluateTrackSequenceApi,
+  previewPredictResultTrackSequenceModelApi,
+  startTrackSequenceApi,
+  stopTrackSequenceApi,
+  updateTrackSequenceApi
+} from '@/api/modules/demo/trackSequence'
+import {
+  delToInfraredApi,
+  getLogToInfraredApi,
+  getStatisticsResultToInfraredApi,
+  getToInfraredApi,
+  previewPredictResultToInfraredModelApi,
+  startToInfraredApi,
+  stopToInfraredApi,
+  updateToInfraredApi
+} from '@/api/modules/demo/toInfrared'
+import {
+  getLogTargetDetectionApi,
+  getTargetDetectionApi,
+  startTargetDetectionApi,
+  stopTargetDetectionApi,
+  updateTargetDetectionApi
+} from '@/api/modules/demo/TargetDetection'
+import { delDataAugmentationApi } from '@/api/modules/demo/dataAugmentation'
+import ViewLog from '@/views/demo/components/ViewLog.vue'
+import PreviewCompareImages from '@/views/demo/components/PreviewCompareImages.vue'
+import ShowStatisticResult from '@/views/demo/components/ShowStatisticResult.vue'
+import useWebSocketStore from '@/stores/modules/websocket'
+import { resetHeart } from '@/utils/websocket'
+
+onMounted(() => {
+  const websocketStore = useWebSocketStore()
+  websocketStore.websocket.onmessage = (e: any) => {
+    if (e.data.indexOf('heartbeat') > 0) {
+      resetHeart()
+    }
+    if (e.data.indexOf('ping') > 0) {
+      return
+    }
+    console.log(e)
+    handleOpenView()
+  }
+})
+
+const startSubTask = async (row: any) => {
+  let res: any = null
+  if (row.subsystem === SubSystem__['可见光转红外']) {
+    res = await startToInfraredApi(row.id)
+  } else if (row.subsystem === SubSystem__['目标检测']) {
+    res = await startTargetDetectionApi(row.id)
+  } else if (row.subsystem === SubSystem__['注释轨迹序列']) {
+    res = await startTrackSequenceApi(row.id)
+  } else {
+    ElMessage.error('暂不支持该子任务类型')
+    return
+  }
+  if (res.code === 200) {
+    ElMessage.success('任务已开始,请等待完成!')
+  } else {
+    ElMessage.error('任务开始失败,请检查!')
+  }
+  handleOpenView()
+}
+const stopSubTask = async (row: any) => {
+  let res: any = null
+  if (row.subsystem === SubSystem__['可见光转红外']) {
+    res = await stopToInfraredApi(row.id)
+  } else if (row.subsystem === SubSystem__['目标检测']) {
+    res = await stopTargetDetectionApi(row.id)
+  } else if (row.subsystem === SubSystem__['注释轨迹序列']) {
+    res = await stopTrackSequenceApi(row.id)
+  } else {
+    ElMessage.error('暂不支持该子任务类型')
+    return
+  }
+  if (res.code === 200) {
+    ElMessage.success('终止任务成功!')
+  } else {
+    ElMessage.error('终止任务失败,请检查!')
+  }
+  handleOpenView()
+}
+
+const viewLogRef = ref()
+const openLogSubTask = async (row: any) => {
+  if (row.subsystem === SubSystem__['可见光转红外']) {
+    viewLogRef.value.handleOpen(row.id, getLogToInfraredApi)
+  } else if (row.subsystem === SubSystem__['目标检测']) {
+    viewLogRef.value.handleOpen(row.id, getLogTargetDetectionApi)
+  } else if (row.subsystem === SubSystem__['注释轨迹序列']) {
+    viewLogRef.value.handleOpen(row.id, getLogTrackSequenceApi)
+  } else {
+    ElMessage.error('暂不支持该子任务类型')
+    return
+  }
+}
+const previewImagesRef = ref()
+const previewSubTask = async (row: any) => {
+  if (row.subsystem === SubSystem__['可见光转红外']) {
+    previewImagesRef.value?.handleOpen(previewPredictResultToInfraredModelApi, row.id)
+  } else if (row.subsystem === SubSystem__['目标检测']) {
+    ElMessage.error('暂不支持该子任务类型')
+    return
+  } else if (row.subsystem === SubSystem__['注释轨迹序列']) {
+    previewImagesRef.value?.handleOpen(previewPredictResultTrackSequenceModelApi, row.id)
+  } else {
+    ElMessage.error('暂不支持该子任务类型')
+    return
+  }
+}
+const showStatisticResultRef = ref()
+const showStatisticResultSubTask = async (row: any) => {
+  if (row.subsystem === SubSystem__['可见光转红外']) {
+    showStatisticResultRef.value.get_statistics_result(row.id, getStatisticsResultToInfraredApi)
+  } else if (row.subsystem === SubSystem__['目标检测']) {
+    ElMessage.error('暂不支持该子任务类型')
+    return
+  } else if (row.subsystem === SubSystem__['注释轨迹序列']) {
+    showStatisticResultRef.value.get_statistics_result(row.id, getStatisticsResultTrackSequenceApi)
+  } else {
+    ElMessage.error('暂不支持该子任务类型')
+    return
+  }
+}
+const showEvaluateResultSubTask = async (row: any) => {
+  console.log('=============')
+  console.log(row.subsystem)
+  if (row.subsystem === SubSystem__['可见光转红外']) {
+    ElMessage.error('暂不支持该子任务类型')
+    return
+  } else if (row.subsystem === SubSystem__['目标检测']) {
+    ElMessage.error('暂不支持该子任务类型')
+    return
+  } else if (row.subsystem === SubSystem__['注释轨迹序列']) {
+    showStatisticResultRef.value.get_statistics_result(row.id, previewEvaluateTrackSequenceApi, '评估结果')
+  } else {
+    ElMessage.error('暂不支持该子任务类型')
+    return
+  }
+}
+const showEvaluateSubTask = async (row: any) => {}
+
+const deletSubTask = async (row: any) => {
+  if (row.subsystem === SubSystem__['可见光转红外']) {
+    await useHandleData(delToInfraredApi, row.id, '删除【' + row.name + '】可见光转红外')
+  } else if (row.subsystem === SubSystem__['目标检测']) {
+    await useHandleData(delDataAugmentationApi, row.id, '删除任务【' + row.name + '】目标检测')
+  } else if (row.subsystem === SubSystem__['注释轨迹序列']) {
+    await useHandleData(delTrackSequenceApi, row.id, '删除【' + row.name + '】注视轨迹序列')
+  } else {
+    ElMessage.error('暂不支持该子任务类型')
+  }
+  handleOpenView()
+}
+
+const loadSomeData = async (row?: any) => {
+  datasetList.value = await getDatasetList()
+  if (row.subsystem === SubSystem__['可见光转红外']) {
+    enumsAlgorithmConfigTrack_toInfrared.value = await getEnumsAlgorithmConfigTrack('可见光转红外', ['预测/推理'])
+    await getToInfraredModelList()
+  } else if (row.subsystem === SubSystem__['目标检测']) {
+  } else if (row.subsystem === SubSystem__['注释轨迹序列']) {
+    enumsAlgorithmConfigTrack_trackSequence.value = await getEnumsAlgorithmConfigTrack('注释轨迹序列', [AlgorithmType[row.type]])
+    enumsAlgorithmModelTrack.value = await getEnumsAlgorithmModelTrack('注释轨迹序列')
+    enumsAlgorithmModelTrack_TD.value = await getEnumsAlgorithmModelTrack('目标检测')
+  }
+}
+
+const openSubTaskViewDialog = async (type: number, title: string, row?: any) => {
+  let res = { data: {} }
+  let api: any = null
+  if (row?.id) {
+    console.log(row)
+    if (row.subsystem === SubSystem__['可见光转红外']) {
+      console.log('可见光转红外')
+      res = await getToInfraredApi(row.id || null)
+      api = updateToInfraredApi
+
+      // 重置表单
+      setItemsOptions_ToInfrared()
+    } else if (row.subsystem === SubSystem__['目标检测']) {
+      console.log('目标检测')
+      res = await getTargetDetectionApi(row.id || null)
+      api = updateTargetDetectionApi
+    } else if (row.subsystem === SubSystem__['注释轨迹序列']) {
+      console.log('注释轨迹序列')
+      res = await getTrackSequenceApi(row.id || null)
+      api = updateTrackSequenceApi
+
+      // 重置表单
+      setItemsOptions_TrackSequence()
+    } else {
+      console.log('其他')
+      ElMessage.error('暂不支持该子任务类型')
+      return
+    }
+    const params = JSON.parse(res.data['algorithmParameters'])
+    if (params.otherParams) {
+      res.data = { ...res.data, ...params.otherParams }
+    }
+  }
+
+  if (row?.id) {
+    itemsOptions = await updateItemsOptions(row.algorithmId)
+  }
+  await loadSomeData(row)
+  const params = {
+    title: title,
+    width: 600,
+    isEdit: type !== 3,
+    itemsOptions: itemsOptions,
+    model: res.data,
+    api: api,
+    getTableList: handleOpenView
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+const remove_unnecessary_parameters = (itemsOptions: ProForm.ItemsOptions[]): ProForm.ItemsOptions[] => {
+  try {
+    const endIndex = itemsOptions.findIndex(option => option['label'] === '备注')
+    if (endIndex !== -1) {
+      itemsOptions = itemsOptions.slice(0, endIndex + 1)
+    }
+    return itemsOptions
+  } catch (error) {
+    console.error('移除不必要的参数时出错:', error)
+    // ElMessage.error('移除不必要的参数时出错,请检查!');
+    return itemsOptions // 返回原始选项,避免进一步的问题
+  }
+}
+
+const updateItemsOptions = async (algorithmId: any) => {
+  try {
+    const result = await getAlgorithmConfigTrackApi(algorithmId)
+    if (result.code === 200) {
+      // 处理结果
+      const parameters = JSON.parse(result.data['parameters'])
+      // console.log('parameters: ', parameters)
+
+      const itemsOptions_new = remove_unnecessary_parameters(itemsOptions)
+      for (const item of parameters) {
+        // 添加新的表单项选项
+        itemsOptions_new.push({
+          label: item['name'],
+          prop: item['agName'],
+          rules: [{ required: item['required'], message: item['agName'] + '不能为空', trigger: 'blur' }],
+          tooltip: item['prompt'],
+          compOptions: {
+            elTagName: 'input',
+            placeholder: item['defaultValue']
+            // value: item['defaultValue']
+          }
+        })
+      }
+      formDialogRef.value?.updateItemOptions(itemsOptions_new)
+      return itemsOptions_new
+    } else {
+      return itemsOptions // 返回原始选项,避免进一步的问题
+    }
+  } catch (err) {
+    console.log(err)
+    ElMessage.error('获取算法配置失败,请检查!')
+    return itemsOptions // 返回原始选项,避免进一步的问题
+  }
+}
+
+const setItemsOptions_ToInfrared = () => {
+  itemsOptions = [
+    {
+      label: '任务名称',
+      prop: 'name',
+      rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'input',
+        placeholder: '请输入任务名称'
+      }
+    },
+    {
+      label: '选择数据集',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择或者上传数据集',
+        enum: datasetList,
+        clearable: true
+      }
+    },
+    {
+      label: '上传数据集',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['zip'],
+        placeholder: '请上传数据集'
+      }
+    },
+    {
+      label: '选择算法',
+      prop: 'algorithmId',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择算法',
+        enum: enumsAlgorithmConfigTrack_toInfrared,
+        clearable: true,
+        onChange: async (value: any) => {
+          if (value != undefined && value != null && value != '') {
+            await updateItemsOptions(value)
+          }
+        }
+      }
+    },
+    {
+      label: '任务类型',
+      prop: 'type',
+      rules: [{ required: true, message: '任务类型不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        elTagName: 'select',
+        placeholder: '请选择任务类型',
+        enum: enumsAlgorithmType,
+        clearable: true,
+        value: ''
+      },
+      show: params => {
+        if (params.value.algorithmId != undefined) {
+          for (let i = 0; i < enumsAlgorithmConfigTrack_toInfrared.value.length; i++) {
+            if (enumsAlgorithmConfigTrack_toInfrared.value[i]['value'] === params.value.algorithmId) {
+              params.value.type = enumsAlgorithmConfigTrack_toInfrared.value[i]['type']
+              return true
+            }
+          }
+        }
+        return false
+      }
+    },
+    {
+      label: '选择模型',
+      prop: 'algorithmModelId',
+      rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
+      show: params => {
+        if (params.value.type == AlgorithmType2['预测/推理']) {
+          return true
+        }
+        return false
+      },
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择模型',
+        enum: toInfraredModelList,
+        clearable: true
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [],
+      compOptions: {
+        elTagName: 'input',
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+const enumsAlgorithmConfigTrack_trackSequence = ref<any[]>([])
+const enumsAlgorithmModelTrack = ref<any[]>([])
+const enumsAlgorithmModelTrack_TD = ref<any[]>([])
+const setItemsOptions_TrackSequence = () => {
+  itemsOptions = [
+    {
+      label: '任务名称',
+      prop: 'name',
+      rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入任务名称'
+      }
+    },
+    {
+      label: '选择数据集',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择或者上传数据集',
+        enum: datasetList,
+        clearable: true
+      }
+    },
+    {
+      label: '上传数据集',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['zip'],
+        placeholder: '请上传数据集'
+      }
+    },
+    {
+      label: '选择算法',
+      prop: 'algorithmId',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择算法',
+        enum: enumsAlgorithmConfigTrack_trackSequence,
+        clearable: true,
+        onChange: async (value: any) => {
+          if (value != undefined && value != null && value != '') {
+            await updateItemsOptions(value)
+          }
+        }
+      }
+    },
+    {
+      label: '任务类型',
+      prop: 'type',
+      rules: [{ required: true, message: '任务类型不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        elTagName: 'select',
+        placeholder: '请选择任务类型',
+        enum: enumsAlgorithmType,
+        clearable: true,
+        value: ''
+      },
+      show: params => {
+        if (params.value.algorithmId != undefined) {
+          for (let i = 0; i < enumsAlgorithmConfigTrack_trackSequence.value.length; i++) {
+            if (enumsAlgorithmConfigTrack_trackSequence.value[i]['value'] === params.value.algorithmId) {
+              params.value.type = enumsAlgorithmConfigTrack_trackSequence.value[i]['type']
+              return true
+            }
+          }
+        }
+        return false
+      }
+    },
+    {
+      label: '选择模型',
+      prop: 'algorithmModelId',
+      rules: [{ required: false, message: '模型不能为空', trigger: 'blur' }],
+      show: params => {
+        if (params.value.type == AlgorithmType2['预测/推理']) {
+          return true
+        }
+        params.value.algorithmModelId = ''
+        return false
+      },
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择模型',
+        enum: enumsAlgorithmModelTrack,
+        clearable: true
+      }
+    },
+    {
+      label: '选择目标检测模型',
+      prop: 'algorithmModelTargetDetectionId',
+      rules: [{ required: true, message: '目标检测模型不能为空', trigger: 'blur' }],
+      show: params => {
+        if (params.value.type == AlgorithmType2['预测/推理']) {
+          return true
+        }
+        params.value.algorithmModelTargetDetectionId = ''
+        return false
+      },
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择目标检测模型',
+        enum: enumsAlgorithmModelTrack_TD,
+        clearable: true
+      }
+    },
+    {
+      label: '上传标签',
+      prop: 'inputLabelOssId',
+      rules: [{ required: true, message: '标签不能为空', trigger: 'blur' }],
+      show: params => {
+        if (params.value.type == AlgorithmType2['测试']) {
+          return true
+        }
+        return false
+      },
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['txt'],
+        placeholder: '请上传标签'
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+
+const dialogVisibleView = ref(false)
+const viewData = ref<any[]>([])
+const subTaskAlgorithmTaskTrack_id = ref<any>(null)
+const openViewDialog = async (row: any) => {
+  dialogVisibleView.value = true
+  subTaskAlgorithmTaskTrack_id.value = row.id
+}
+const handleOpenView = async () => {
+  const res = await listSubTaskAlgorithmTaskTrackApi(subTaskAlgorithmTaskTrack_id.value)
+  if (res.code === 200) {
+    viewData.value = res.data
+  } else {
+    ElMessage.error('获取子任务失败')
+  }
+}
+
+const fileUploadRef = ref()
+const fileUploadDatasetChange = (value: any) => {
+  console.log('fileUploadChange: ', value)
+  formAddTask.value['inputDatasetOssId'] = value
+}
+const fileUploadEvaluateLabelRef = ref()
+const fileUploadChangeEvaluateLabel = (value: any) => {
+  console.log('fileUploadChangeEvaluateLabel: ', value)
+  formAddTask.value['inputEvaluateLabelOssId'] = value
+}
+
+const getEnumsAlgorithmModelTrack = async (subSystem: string) => {
+  const result: any = await enumAlgorithmModelTrackApi()
+  const res_list: any[] = []
+  const tmp_data: any = result['data']
+  for (const item of tmp_data) {
+    if (SubSystem[item['subsystem']] === subSystem) {
+      const tmp_item = { ...item }
+      tmp_item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']] + '-' + item['algorithmName']
+      res_list.push(tmp_item)
+    }
+  }
+  return res_list
+}
+
+const getEnumsAlgorithmConfigTrack = async (subSystem: string, type_list_: string[]) => {
+  const result = await enumAlgorithmConfigTrackApi()
+  const res_list: any[] = []
+  const tmp_data: any = result['data']
+
+  const type_list: any[] = type_list_.map(item => parseInt(AlgorithmType2[item]))
+
+  for (const item of tmp_data) {
+    if (parseInt(item.subsystem) === parseInt(SubSystem__[subSystem])) {
+      if (type_list !== undefined && type_list.length > 0) {
+        if (type_list.includes(parseInt(item.type))) {
+          const tmp_item = { ...item }
+          tmp_item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']]
+          res_list.push(tmp_item)
+        }
+      } else {
+        const tmp_item = { ...item }
+        tmp_item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']]
+        res_list.push(tmp_item)
+      }
+    }
+  }
+  return res_list
+}
+
+const dialogVisibleAddTask = ref(false)
+const handleClose = (done: () => void) => {
+  ElMessageBox.confirm('确定关闭吗?')
+    .then(() => {
+      done()
+    })
+    .catch(() => {
+      // catch error
+    })
+}
+const formAddTask = ref({ ifEvaluate: false, ifToInfrared: false })
+const formAddTaskRef = ref()
+const addAlgorithmTaskTrack = async () => {
+  formAddTaskRef.value
+    .validate()
+    .then(async () => {
+      console.log('formAddTask: ', formAddTask.value)
+      console.log(fileUploadRef.value.uploadFileListExport)
+      const res = await addAlgorithmTaskTrackApi(formAddTask.value)
+      if (res.code === 200) {
+        ElMessage.success('新增可辨识性分析总任务成功')
+        dialogVisibleAddTask.value = false
+        proTable.value?.getTableList()
+      } else {
+        ElMessage.error('新增可辨识性分析总任务失败')
+      }
+    })
+    .catch(() => {
+      console.log('error')
+      ElMessage.error('请检查表单')
+    })
+}
+
+const rulesAddTask = {
+  // todo: 校验规则
+  name: [{ required: true, message: '可见光转红外算法不能为空', trigger: 'blur' }],
+  ifToInfrared: [{ required: false, message: '是否转红外不能为空', trigger: 'blur' }],
+  toInfraredAlgorithmId: [{ required: false, message: '可见光转红外算法不能为空', trigger: 'blur' }],
+  inputDatasetOssId: [{ required: true, message: '数据集不能为空', trigger: 'blur' }],
+  targetDetectionModelList: [{ required: true, message: '目标模型不能为空', trigger: 'blur' }],
+  inputEvaluateLabelOssId: [{ required: false, message: '评估标签不能为空', trigger: 'blur' }],
+  remarks: [{ required: false, message: '备注不能为空', trigger: 'blur' }]
+}
+
+const enumsAlgorithmConfigTrack_toInfrared = ref<any[]>([])
+const setIfToInfrared = async () => {
+  formAddTask.value.toInfraredAlgorithmId = ''
+  if (formAddTask.value?.ifToInfrared === true) {
+    enumsAlgorithmConfigTrack_toInfrared.value = await getEnumsAlgorithmConfigTrack('可见光转红外', ['预测/推理'])
+  }
+}
+
+const getItemsOptions = async (algorithmId: any) => {
+  try {
+    const result = await getAlgorithmConfigTrackApi(algorithmId)
+    if (result.code === 200) {
+      // 处理结果
+      const parameters = JSON.parse(result.data['parameters'])
+      // console.log('parameters: ', parameters)
+
+      let itemsOptions_new: any[] = []
+      for (const item of parameters) {
+        // 添加新的表单项选项
+        itemsOptions_new.push({
+          label: item['name'],
+          labelWidth: "200px",
+          prop: item['agName'],
+          rules: [{ required: item['required'], message: item['agName'] + '不能为空', trigger: 'blur' }],
+          tooltip: item['prompt'],
+          compOptions: {
+            elTagName: 'input',
+            placeholder: item['defaultValue']
+            // value: item['defaultValue']
+          }
+        })
+      }
+      return itemsOptions_new
+    }
+  } catch (err) {
+    console.log(err)
+    ElMessage.error('获取算法配置失败,请检查!')
+    return []
+  }
+}
+
+const setAlgorithmParams = async (id: string | number, paramsName: string) => {
+  const itemsOptions__ = await getItemsOptions(id)
+  const params = {
+    title: '设置算法参数',
+    width: 650,
+    isEdit: true,
+    itemsOptions: itemsOptions__,
+    model: formAddTask,
+    api: async params => {
+      console.log('itemsOptions__: ', itemsOptions__)
+      let params_new = {}
+      if (itemsOptions__ && itemsOptions__.length > 0) {
+        for (const item of itemsOptions__) {
+          params_new[item['prop']] = params[item['prop']]
+        }
+        formAddTask.value[paramsName] = params_new
+        console.log('params: ', params)
+        console.log('params_new: ', params_new)
+        console.log('formAddTask: ', formAddTask.value)
+      }
+      return { code: 200, message: 'success' }
+    },
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+const datasetList = ref<any[]>([])
+
+const getDatasetList = async (subSystem: string) => {
+  const qyery = {
+    subsystem: subSystem ? SubSystem__[subSystem] : undefined,
+    pageNum: 1,
+    pageSize: 1000
+  }
+  const result: any = await listDataSeqApi(qyery)
+  const data = result['data']['list']
+  let res_list: any[] = []
+  for (const item of data) {
+    res_list.push({
+      value: item['inputOssId'],
+      label: item['name'] + '-' + SubSystem[item['subsystem']]
+    })
+  }
+  return res_list
+}
+
+const getDatasetList__ = async () => {
+  datasetList.value = await getDatasetList('')
+}
+
+const toInfraredModelList = ref<any[]>([])
+const getToInfraredModelList = async () => {
+  toInfraredModelList.value = await getEnumsAlgorithmModelTrack('可见光转红外')
+}
+
+const visionAlgorithmList = ref<any[]>([])
+const getVisionAlgorithmList = async () => {
+  visionAlgorithmList.value = await getEnumsAlgorithmConfigTrack('注释轨迹序列', ['预测/推理'])
+}
+
+const targetDetectionModelList = ref<any[]>([])
+const getTargetDetectionModelList = async () => {
+  targetDetectionModelList.value = await getEnumsAlgorithmModelTrack('目标检测')
+}
+
+const visionAlgorithmModelList = ref<any[]>([])
+const getVisionAlgorithmModelList = async () => {
+  visionAlgorithmModelList.value = await getEnumsAlgorithmModelTrack('注释轨迹序列')
+}
+
+const visionEvaluateAlgorithmList = ref<any[]>([])
+const getVisionEvaluateAlgorithmList = async () => {
+  visionEvaluateAlgorithmList.value = await getEnumsAlgorithmConfigTrack('注释轨迹序列', ['测试'])
+}
+
+const handleOpenAddTask = async () => {
+  formAddTask.value = { ifEvaluate: false, ifToInfrared: false }
+}
+
+onMounted(async () => {
+  await getDatasetList__()
+  await getToInfraredModelList()
+  await getVisionAlgorithmList()
+  await getTargetDetectionModelList()
+  await getVisionAlgorithmModelList()
+  await getVisionEvaluateAlgorithmList()
+})
+
+// ProTable 实例
+const proTable = ref<ProTableInstance>()
+
+// 删除可辨识性分析总任务信息
+const deleteAlgorithmTaskTrack = async (params: any) => {
+  await useHandleData(delAlgorithmTaskTrackApi, params.id, '删除【' + params.id + '】可辨识性分析总任务')
+  proTable.value?.getTableList()
+}
+
+// 批量删除可辨识性分析总任务信息
+const batchDelete = async (ids: string[]) => {
+  await useHandleData(delAlgorithmTaskTrackApi, ids, '删除所选可辨识性分析总任务信息')
+  proTable.value?.clearSelection()
+  proTable.value?.getTableList()
+}
+
+// 导出可辨识性分析总任务列表
+const downloadFile = async () => {
+  ElMessageBox.confirm('确认导出可辨识性分析总任务数据?', '温馨提示', { type: 'warning' }).then(() =>
+    useDownload(exportAlgorithmTaskTrackApi, '可辨识性分析总任务列表', proTable.value?.searchParam)
+  )
+}
+
+// 批量添加可辨识性分析总任务
+const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
+const batchAdd = () => {
+  const params = {
+    title: '可辨识性分析总任务',
+    tempApi: importTemplateApi,
+    importApi: importAlgorithmTaskTrackDataApi,
+    getTableList: proTable.value?.getTableList
+  }
+  dialogRef.value?.acceptParams(params)
+}
+
+const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
+// 打开弹框的功能
+const openDialog = async (type: number, title: string, row?: any) => {
+  let res = { data: {} }
+  if (row?.id) {
+    res = await getAlgorithmTaskTrackApi(row?.id || null)
+  }
+  // 重置表单
+  setItemsOptions()
+  const params = {
+    title,
+    width: 580,
+    isEdit: type !== 3,
+    itemsOptions: itemsOptions,
+    model: type == 1 ? {} : res.data,
+    api: type == 1 ? addAlgorithmTaskTrackApi : updateAlgorithmTaskTrackApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+// 表格配置项
+const columns = reactive<ColumnProps<any>[]>([
+  { type: 'selection', fixed: 'left', width: 70 },
+  { prop: 'id', label: '主键ID' },
+  {
+    prop: 'name',
+    label: '任务名称',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'status',
+    label: '任务状态',
+    search: {
+      el: 'select'
+    },
+    tag: true,
+    enum: statusEnums,
+    width: 150
+  },
+  {
+    prop: 'startTime',
+    label: '开始时间',
+    search: {
+      el: 'date-picker',
+      props: { type: 'datetimerange', valueFormat: 'YYYY-MM-DD HH:mm:ss' }
+    },
+    width: 120
+  },
+  {
+    prop: 'endTime',
+    label: '结束时间',
+    search: {
+      el: 'date-picker',
+      props: { type: 'datetimerange', valueFormat: 'YYYY-MM-DD HH:mm:ss' }
+    },
+    width: 120
+  },
+  {
+    prop: 'costSecond',
+    label: '耗时',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  {
+    prop: 'log',
+    label: '日志',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'remarks',
+    label: '备注',
+    search: {
+      el: 'input'
+    }
+  },
+  // {
+  //   prop: 'system',
+  //   label: '系统',
+  //   search: {
+  //     el: 'input'
+  //   },
+  //   width: 120
+  // },
+  { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
+])
+// 表单配置项
+let itemsOptions: ProForm.ItemsOptions[] = []
+const setItemsOptions = () => {
+  itemsOptions = [
+    {
+      label: '任务名称',
+      prop: 'name',
+      rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入任务名称'
+      }
+    }
+  ]
+}
+</script>
+
+<style lang="scss" scoped>
+.form-item1 {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  width: 100%;
+}
+</style>

+ 16 - 4
src/views/demo/components/ShowStatisticResult.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-dialog v-model="showResultDialogVisible" :title="props.title" width="700">
+  <el-dialog v-model="showResultDialogVisible" :title="title" width="700">
     <el-card style="width: 100%; margin-bottom: 10px">
       <div class="evaluate-data">
         <template v-for="(item, index) in ResultData" :key="index">
@@ -13,10 +13,12 @@
 
 <script setup lang="ts">
 import { ref } from 'vue'
+
 const props = defineProps({
   api: {
     type: Function,
-    required: true
+    required: false,
+    default: () => {}
   },
   title: {
     type: String,
@@ -25,10 +27,20 @@ const props = defineProps({
   }
 })
 
+const title = ref(props.title)
+
 const showResultDialogVisible = ref(false)
 const ResultData = ref([])
-const get_statistics_result = async (id: number | string) => {
-  const res: any = await props.api(id)
+const get_statistics_result = async (id: number | string, api: Function = undefined, title__: string = undefined) => {
+  let res: any = {}
+  if (!api) {
+    res = await props.api(id)
+  } else {
+    res = await api(id)
+  }
+  if (title__) {
+    title.value = title__
+  }
   ResultData.value = res.data
   showResultDialogVisible.value = true
 }

+ 10 - 5
src/views/demo/components/ViewLog.vue

@@ -39,9 +39,14 @@ const innerRef = ref()
 const isAutoScroll = ref(true)
 const listenerMouse = ref()
 
-const getLog = async () => {
+const getLog = async (api: Function = undefined) => {
   try {
-    const result: any = await props.getLogApi(logId.value)
+    let result: any = null
+    if (!api) {
+      result = await props.getLogApi(logId.value)
+    } else {
+      result = await api(logId.value)
+    }
     if (result.code == 200) {
       log.value = result.data
       if (isAutoScroll.value) {
@@ -56,15 +61,15 @@ const getLog = async () => {
     clearInterval(intervalLog.value)
   }
 }
-const handleOpen = id => {
+const handleOpen = (id: String | Number, api: Function = undefined) => {
   logId.value = id
   logVisible.value = true
   isAutoScroll.value = true
   log.value = ''
 
-  getLog()
+  getLog(api)
   intervalLog.value = setInterval(() => {
-    getLog()
+    getLog(api)
   }, logRefreshTime.value)
 
   nextTick(function () {

+ 19 - 6
src/views/demo/components/img-maker.vue

@@ -5,10 +5,11 @@
       <el-button plain type="primary" class="shape-border" @click="enableDragMode" :disabled="state.dragMode">移动图片</el-button>
 
       <el-button plain type="primary" style="margin-left: 30px" class="shape-border" @click="selectLastObject" :disabled="!!state.activeTarget"
-        >选择最后一个标注(w)</el-button
+        >选择标注(w)</el-button
       >
       <el-button plain type="primary" class="shape-border" @click="rotate(8)" :disabled="!state.activeTarget"> 顺时针旋转(r) </el-button>
       <el-button plain type="primary" class="shape-border" @click="rotate(-8)" :disabled="!state.activeTarget">逆时针旋转(e)</el-button>
+      <el-button plain type="primary" class="shape-border" @click="deleteOne">删除(Back)</el-button>
       <el-button plain type="primary" style="margin-left: 30px" class="shape-border" @click="changeZoom(1.1)">放大图片</el-button>
       <el-button plain type="primary" class="shape-border" @click="changeZoom(0.9)">缩小图片</el-button>
       <!-- <el-button plain type="primary" class="shape-border" @click="drawPolygon('polygon')">多边形</el-button> -->
@@ -18,7 +19,7 @@
 </template>
 <script lang="ts" setup>
 import { fabric } from 'fabric'
-import { reactive, watch, onMounted } from 'vue'
+import { reactive, watch, onMounted, computed } from 'vue'
 import { ElMessage } from 'element-plus'
 // import { sortPoints } from '@/utils/fabric'
 
@@ -93,6 +94,7 @@ const state = reactive({
   activeLine: '' as any,
   line: {} as canvasPoint
 })
+
 watch(
   () => props.classDef,
   value => {
@@ -133,14 +135,23 @@ const changeZoom = multi => {
   state.canvas.renderAll()
 }
 
+const deleteOne = () => {
+  const obj = state.canvas.getActiveObject()
+  state.canvas.remove(obj)
+}
+
 const loadInit = () => {
   drawTypeChange('rectangle')
   state.color = props.classDef && props.classDef.color ? props.classDef.color : '#E34F51'
   if (!props.isPicOnly) {
     document.addEventListener('keydown', function (e) {
+      console.log(e.key, state.activeTarget, state.canvas.getActiveObject())
       if (e.key === 'w' || e.key === 'W') {
         selectLastObject()
         return
+      } else if (e.key === 'Backspace') {
+        const obj = state.canvas.getActiveObject()
+        state.canvas.remove(obj)
       }
       if (state.activeTarget) {
         if (e.key === 'r' || e.key === 'R') {
@@ -199,8 +210,9 @@ const loadInit = () => {
       for (let i = 0; i < props.jsonData.length; i++) {
         let config = props.jsonData[i]
         let subArr = config.subArr
-        const lW = imgInstance.width * state.radio
-        const lH = imgInstance.height * state.radio
+        console.log('ratio', state.radio)
+        const lW = imgInstance.width //* state.radio
+        const lH = imgInstance.height //* state.radio
         let obj = new fabric.Path(
           'M ' +
             subArr[1] * lW +
@@ -786,6 +798,7 @@ const getData = () => {
           // }
         })
       } else {
+        // console.log('else')
         marks.forEach(mark => {
           let poi = {
             x: getPoint(aCoords[mark].x),
@@ -794,8 +807,8 @@ const getData = () => {
           // console.log(poi)
           poi = getRealPoint(poi)
           // console.log(poi)
-          poi.x = poi.x / state.realRadioX / 1920
-          poi.y = poi.y / state.realRadioY / 1080
+          poi.x = poi.x / 1920
+          poi.y = poi.y / 1080
           // console.log(poi)
           point['nodes'].push(poi)
           // point['nodes'].push(getRealPoint(poi))

+ 15 - 12
src/views/demo/data/AmplifyForm.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="amplify-main">
-    <ProForm :items-options="items" :model="model"></ProForm>
+    <ProForm ref="proFormRef" :items-options="items"></ProForm>
     <el-button type="primary" v-if="showSelectBatchButton" style="margin-left: 50px" @click="showDataSelectionDialog()">选择批次</el-button>
 
     <el-dialog v-model="dataDialogVisible" title="选择数据批次" style="width: 70vw">
@@ -37,14 +37,15 @@ import { reactive, ref, computed, onMounted, defineEmits } from 'vue'
 import ProForm from '@/components/ProForm/index.vue'
 import { batchListDataApi } from '@/api/modules/demo/data'
 import { getDictsApi } from '@/api/modules/system/dictData'
+import ProFrom from '@/components/ProForm/index.vue'
 
 const emit = defineEmits(['updateData', 'updateModel', 'updateParams'])
-
+const proFormRef = ref<InstanceType<typeof ProFrom> | null>(null)
 // 数据
-let model = {
-  taskName: 'sss',
+const model = ref({
+  taskName: '',
   transfer: null
-}
+})
 
 const dataDialogVisible = ref(false)
 let batchDataList = ref(reactive([] as any[]))
@@ -54,12 +55,14 @@ let tempDeselectedBatchDataList = ref(reactive([] as any[]))
 let parameList = ref(reactive([] as any[]))
 let queryBatchData = ref(reactive([] as any[]))
 
-const props = defineProps({ showSelectBatchButton: Boolean })
+const props = defineProps({ showSelectBatchButton: Boolean, dataList: Array, useData: Boolean })
 
 onMounted(() => {
-  batchListDataApi().then(res => {
-    queryBatchData.value = reactive(res.data)
-  })
+  !props.useData &&
+    batchListDataApi().then(res => {
+      queryBatchData.value = reactive(res.data)
+    })
+  props.useData && (queryBatchData.value = props.dataList) // && console.log('load data', props.dataList)
 
   getDictsApi('expand_data_params').then(res => {
     parameList.value = reactive(JSON.parse(res.data[0].remark))
@@ -75,9 +78,9 @@ onMounted(() => {
           placeholder: '请输入' + item.name
         }
       })
-      model[`${item.agName}`] = item.defaultValue
+      // model.value[`${item.agName}`] = item.defaultValue
     })
-    emit('updateModel', model)
+    emit('updateModel', proFormRef.value.formModel)
     // Emit parameList 给父组件
     emit('updateParams', parameList.value)
   })
@@ -149,7 +152,7 @@ let items: ProForm.ItemsOptions[] = reactive([
     compOptions: {
       elTagName: 'input',
       clearable: true,
-      placeholder: '请输入用户名'
+      placeholder: '请输入任务名称'
     }
   },
   {

+ 11 - 3
src/views/demo/data/index.vue

@@ -212,6 +212,7 @@ const deleteData = async (params: any) => {
   await useHandleData(delDataApi, params.id, `删除【${params.name}】数据`)
   proTable.value?.getTableList()
 }
+import { fourNodes2xywh, xywh2fourNodes } from './reformat'
 
 // 标注图片
 const markImg = data => {
@@ -245,9 +246,11 @@ const markImg = data => {
           .get<any>(state.cacheData.labelurl)
           .then(res => {
             state.jsonData = []
-            console.log(res)
+            res = xywh2fourNodes(res)
+            // console.log('check3', res)
+
             let arr = res.replace('\r', '').split('\n')
-            console.log(arr)
+            // console.log(arr)
             for (let i = 0; i < arr.length; i++) {
               let subArr = arr[i].split(' ')
               // console.log(subArr)
@@ -352,7 +355,12 @@ const handleImgSuccess = data => {
     filename = filename.substring(1)
   }
   // console.log(filename)
-
+  let pData = fourNodes2xywh(data['data'])
+  // console.log('check1', data['data'])
+  data['data'] = pData
+  // let a = xywh2fourNodes(pData)
+  // console.log('check2', a)
+  // let rData = xywh2fourNodes(pData)
   labelFile(data['data'], filename).then(res => {
     // console.log(res)
     if (res.code === 200) {

+ 41 - 0
src/views/demo/data/reformat.js

@@ -0,0 +1,41 @@
+export const fourNodes2xywh = function (data) {
+  let lines = data.replace('\r', '').split('\n')
+  let res = []
+  lines.forEach(line => {
+    const arr = line.split(' ')
+    let tmp = []
+    tmp.push(arr[0])
+    tmp.push((parseFloat(arr[3]) + parseFloat(arr[5])) / 2)
+    tmp.push((parseFloat(arr[2]) + parseFloat(arr[4])) / 2)
+    tmp.push(Math.abs(arr[5] - arr[3]))
+    tmp.push(Math.abs(arr[4] - arr[2]))
+    res.push(tmp.join(' '))
+  })
+  // console.log(res)
+  return res.join('\r\n')
+}
+
+export const xywh2fourNodes = function (data) {
+  let lines = data.replace('\r', '').split('\n')
+  let res = []
+  lines.forEach(line => {
+    const arr = line.split(' ')
+    let tmp = []
+    tmp.push(arr[0])
+    tmp.push(parseFloat(arr[1]) + parseFloat(arr[3]) / 2)
+    tmp.push(parseFloat(arr[2]) - parseFloat(arr[4]) / 2)
+
+    tmp.push(parseFloat(arr[1]) + parseFloat(arr[3]) / 2)
+    tmp.push(parseFloat(arr[2]) + parseFloat(arr[4]) / 2)
+
+    tmp.push(parseFloat(arr[1]) - parseFloat(arr[3]) / 2)
+    tmp.push(parseFloat(arr[2]) + parseFloat(arr[4]) / 2)
+
+    tmp.push(parseFloat(arr[1]) - parseFloat(arr[3]) / 2)
+    tmp.push(parseFloat(arr[2]) - parseFloat(arr[4]) / 2)
+
+    res.push(tmp.join(' '))
+  })
+  // console.log(res)
+  return res.join('\r\n')
+}

+ 16 - 0
src/views/demo/dataAugmentation/index.vue

@@ -111,6 +111,7 @@ import DataAugmentationFormDialog from '@/components/DataAugmentationFormDialog/
 import PreviewCompareImages from '@/views/demo/components/PreviewCompareImages.vue'
 import { ProTableInstance, ColumnProps, EnumProps } from '@/components/ProTable/interface'
 import ViewLog from '@/views/demo/components/ViewLog.vue'
+
 import {
   listDataAugmentationApi,
   delDataAugmentationApi,
@@ -130,6 +131,8 @@ import {
   getCompareImageApiNew,
   pauseDataAugmentationApi
 } from '@/api/modules/demo/dataAugmentation'
+import { getDictsApi } from '@/api/modules/system/dictData'
+import { any } from 'vue-types'
 // import {  } from '@/api/modules/system/dictData'
 // import { S } from 'vite/dist/node/types.d-aGj9QkWt'
 // import { servicesVersion } from 'typescript'
@@ -228,8 +231,19 @@ onMounted(() => {
     proTable.value?.getTableList()
   }, 5000)
   getTaskType()
+  getZipFileDes()
 })
+const zipFileDes = ref('')
+const getZipFileDes = async () => {
+  let res = await getDictsApi('zip_file_format_description')
 
+  res.data.forEach(item => {
+    // 检查item对象是否包含dict和des属性
+    if (item.dictLabel === '图像增强') {
+      zipFileDes.value = item.remark
+    }
+  })
+}
 const startDataAugmentation = async (params: any) => {
   const res = await startDataAugmentationApi(params.id)
   if (res.code === 200) {
@@ -529,6 +543,7 @@ let itemsOptions: ProForm.ItemsOptions[] = [
   {
     label: '图片集压缩包',
     prop: 'inputOssId',
+    tooltip: zipFileDes,
     rules: [{ required: true, message: '数据压缩包不能为空', trigger: 'change' }],
     compOptions: {
       elTagName: 'file-upload',
@@ -568,6 +583,7 @@ const addParams = params => {
     const obj = JSON.parse(validJsonString)
     obj.forEach(param => {
       model.value[param.agName] = param.defaultValue
+
       itemsOptions.push({
         // hideLabelSuffix: false,
         label: param.name,

+ 14 - 0
src/views/demo/imageMosaic/index.vue

@@ -119,6 +119,7 @@ import {
   getMetricApi,
   pauseDataAugmentationApi
 } from '@/api/modules/demo/dataAugmentation'
+import { getDictsApi } from '@/api/modules/system/dictData'
 // import {  } from '@/api/modules/system/dictData'
 
 const viewLogRef = ref()
@@ -215,7 +216,19 @@ onMounted(() => {
     proTable.value?.getTableList()
   }, 5000)
   getTaskType()
+  getZipFileDes()
 })
+const zipFileDes = ref('')
+const getZipFileDes = async () => {
+  let res = await getDictsApi('zip_file_format_description')
+
+  res.data.forEach(item => {
+    // 检查item对象是否包含dict和des属性
+    if (item.dictLabel === '图像拼接') {
+      zipFileDes.value = item.remark
+    }
+  })
+}
 
 const startDataAugmentation = async (params: any) => {
   const res = await startDataAugmentationApi(params.id)
@@ -514,6 +527,7 @@ let itemsOptions: ProForm.ItemsOptions[] = [
   {
     label: '图片集压缩包',
     prop: 'inputOssId',
+    tooltip: zipFileDes,
     rules: [{ required: true, message: '数据压缩包不能为空', trigger: 'change' }],
     compOptions: {
       elTagName: 'file-upload',

+ 19 - 3
src/views/demo/match/index.vue

@@ -28,7 +28,9 @@
       <!-- 表格操作 -->
       <template #operation="scope">
         <el-button type="primary" icon="View" link @click="doExecute(scope.row)">开始任务</el-button>
-
+        <el-button type="primary" link icon="View" @click="hangupTask(scope.row)"> 暂停任务 </el-button>
+        <el-button type="primary" link icon="View" @click="doExecute(scope.row)"> 继续任务 </el-button>
+        <el-button type="primary" link icon="View" @click="stopTask(scope.row)"> 停止任务 </el-button>
         <el-button type="primary" icon="View" link @click="showData(scope.row)">执行结果</el-button>
 
         <el-button type="primary" icon="View" link @click="showLog(scope.row)">查看日志</el-button>
@@ -68,7 +70,7 @@
         <file @update:model-value="updateFile" :file-size="2048" :file-type="['zip']"></file>
       </el-container>
 
-      <el-container v-for="(item, index) in jsonParams" :key="index" style=" align-items: center;margin-top: 5px">
+      <el-container v-for="(item, index) in jsonParams" :key="index" style="align-items: center; margin-top: 5px">
         <span style="min-width: 80px; max-width: 150px">{{ item.name }}</span>
         <el-tooltip :content="item.prompt" placement="top">
           <el-icon><InfoFilled /></el-icon>
@@ -155,7 +157,9 @@ import {
   getMatchApi,
   createTask,
   execute,
-  getResult
+  getResult,
+  hangupApi,
+  stopApi
 } from '@/api/modules/demo/match'
 import File from '@/components/Upload/File.vue'
 import { getDictsApi } from '@/api/modules/system/dictData'
@@ -229,6 +233,18 @@ const doExecute = function (row) {
   })
 }
 
+const hangupTask = function (row) {
+  hangupApi({ taskId: row.id }).then(res => {
+    console.log(res)
+  })
+}
+
+const stopTask = function (row) {
+  stopApi({ taskId: row.id }).then(res => {
+    console.log(res)
+  })
+}
+
 const jsonParams = ref([])
 const dialogVisible = ref(false)
 const openCreateDialog = async function () {

+ 13 - 1
src/views/demo/targetDamageAcess/index.vue

@@ -128,7 +128,7 @@ import {
   pauseDataAugmentationApi
 } from '@/api/modules/demo/dataAugmentation'
 // import {  } from '@/api/modules/system/dictData'
-
+import { getDictsApi } from '@/api/modules/system/dictData'
 const viewLogRef = ref()
 //打开指标窗口查看算法指标信息
 const metricDialogVisible = ref(false)
@@ -217,8 +217,19 @@ onMounted(() => {
     proTable.value?.getTableList()
   }, 5000)
   getTaskType()
+  getZipFileDes()
 })
+const zipFileDes = ref('')
+const getZipFileDes = async () => {
+  let res = await getDictsApi('zip_file_format_description')
 
+  res.data.forEach(item => {
+    // 检查item对象是否包含dict和des属性
+    if (item.dictLabel === '目标毁伤评估') {
+      zipFileDes.value = item.remark
+    }
+  })
+}
 const startDataAugmentation = async (params: any) => {
   const res = await startDataAugmentationApi(params.id)
   if (res.code === 200) {
@@ -516,6 +527,7 @@ let itemsOptions: ProForm.ItemsOptions[] = [
   {
     label: '图片集压缩包',
     prop: 'inputOssId',
+    tooltip: zipFileDes,
     rules: [{ required: true, message: '数据压缩包不能为空', trigger: 'change' }],
     compOptions: {
       elTagName: 'file-upload',

+ 15 - 0
src/views/demo/targetTrack/index.vue

@@ -133,6 +133,7 @@ import {
   getCompareImageApiNew,
   pauseDataAugmentationApi
 } from '@/api/modules/demo/dataAugmentation'
+import { getDictsApi } from '@/api/modules/system/dictData'
 // import { VideoPlayer } from 'vue-video-player'
 // import 'vue-video-player/dist/simple.css'
 
@@ -394,8 +395,21 @@ onMounted(() => {
     proTable.value?.getTableList()
   }, 5000)
   getTaskType()
+  getZipFileDes()
 })
 
+const zipFileDes = ref('')
+const getZipFileDes = async () => {
+  let res = await getDictsApi('zip_file_format_description')
+
+  res.data.forEach(item => {
+    // 检查item对象是否包含dict和des属性
+    if (item.dictLabel === '多目标追踪') {
+      zipFileDes.value = item.remark
+    }
+  })
+}
+
 const startDataAugmentation = async (params: any) => {
   const res = await startDataAugmentationApi(params.id)
   if (res.code === 200) {
@@ -622,6 +636,7 @@ let itemsOptions: ProForm.ItemsOptions[] = [
   {
     label: '图片集压缩包',
     prop: 'inputOssId',
+    tooltip: zipFileDes,
     rules: [{ required: true, message: '数据压缩包不能为空', trigger: 'change' }],
     compOptions: {
       elTagName: 'file-upload',

+ 123 - 99
src/views/demo/toInfrared/index.vue

@@ -24,10 +24,8 @@
       </template>
       <!-- 表格操作 -->
       <template #operation="scope">
-        <el-button type="primary" link icon="View" v-if="scope.row.algorithmModelId != null" @click="openModelDialog(scope.row)">
-          <!--@click="openStartDialog(scope.row)"  -->
-          详情
-        </el-button>
+        <el-button type="primary" link icon="View" @click="openDialog(3, '详情', scope.row)"> 详情 </el-button>
+        <el-button type="primary" link icon="EditPen" v-auth="['demo:toInfrared:edit']" @click="openDialog(2, '编辑', scope.row)"> 编辑 </el-button>
         <el-button
           type="primary"
           link
@@ -94,8 +92,6 @@
         >
           日志
         </el-button>
-        <!-- <el-button type="primary" link icon="View" v-auth="['demo:toInfrared:query']" @click="openDialog(3, '查看', scope.row)"> 查看 </el-button> -->
-        <!-- <el-button type="primary" link icon="EditPen"v-auth="['demo:toInfrared:edit']" @click="openDialog(2, '编辑', scope.row)"> 编辑 </el-button> -->
         <el-button
           type="primary"
           link
@@ -175,19 +171,15 @@ import {
 
 import { getImagesApi, listDataSeqApi } from '@/api/modules/demo/DataSeq'
 
-import { enumAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
-import { getAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
-import { enumAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
+import { enumAlgorithmModelTrackApi, addAlgorithmModelTrackApi, getAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
+import { enumAlgorithmConfigTrackApi, getAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
 import statusEnums from '@/utils/status'
 import { AlgorithmType, SubSystem, SubSystem__, enumsAlgorithmType, enumsSubSystem, AlgorithmType2 } from '@/views/demo/utils'
 import PreviewCompareImages from '@/views/demo/components/PreviewCompareImages.vue'
-import { addAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
 import ViewLog from '@/views/demo/components/ViewLog.vue'
 import useWebSocketStore from '@/stores/modules/websocket'
 import { resetHeart } from '@/utils/websocket'
-
 import ShowStatisticResult from '@/views/demo/components/ShowStatisticResult.vue'
-
 const showStatisticResultRef = ref()
 
 onMounted(() => {
@@ -217,7 +209,7 @@ onMounted(async () => {
   enumsAlgorithmConfigTrack.value = []
   const tmp_data: any = result['data']
   for (const item of tmp_data) {
-    if (item.subsystem === SubSystem__['可见光转红外'] && item.type === AlgorithmType2['预测/推理']) {
+    if (item.subsystem === SubSystem__['可见光转红外']) {
       item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']]
       enumsAlgorithmConfigTrack.value.push(item)
     }
@@ -252,6 +244,7 @@ const setItemsOptions222 = () => {
       prop: 'modelName',
       rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
       compOptions: {
+        elTagName: 'input',
         placeholder: '请输入模型名称'
       }
     },
@@ -260,6 +253,7 @@ const setItemsOptions222 = () => {
       prop: 'modelPath',
       rules: [{ required: false, message: '模型文件不能为空', trigger: 'blur' }],
       compOptions: {
+        elTagName: 'input',
         placeholder: '请输入模型名称',
         disabled: true
       }
@@ -269,6 +263,7 @@ const setItemsOptions222 = () => {
       prop: 'remarks',
       rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
       compOptions: {
+        elTagName: 'input',
         placeholder: '请输入备注'
       }
     }
@@ -334,24 +329,6 @@ const showToInfraredModel = async (id: any) => {
 
 const viewLogRef = ref()
 
-const openModelDialog = async row => {
-  const algorithmModelId = row.algorithmModelId
-  const result: any = await getAlgorithmModelTrackApi(algorithmModelId)
-
-  // console.log(result.data)
-  setItemsOptionsModel()
-  const params = {
-    title: '模型',
-    width: 580,
-    isEdit: false,
-    itemsOptions: itemsOptions,
-    model: result.data,
-    api: updateToInfraredApi,
-    getTableList: proTable.value?.getTableList
-  }
-  formDialogRef.value?.openDialog(params)
-}
-
 const startToInfrared = async (params: any) => {
   const res: any = await startToInfraredApi(params.id)
   if (res.code === 200) {
@@ -438,13 +415,20 @@ const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
 const openDialog = async (type: number, title: string, row?: any) => {
   let res = { data: {} }
   if (row?.id) {
-    res = await getToInfraredApi(row?.id || null)
+    res = await getToInfraredApi(row.id || null)
+    const params = JSON.parse(res.data['algorithmParameters'])
+    if (params.otherParams) {
+      res.data = { ...res.data, ...params.otherParams }
+    }
   }
   // 重置表单
   setItemsOptions()
+  if (row?.id) {
+    itemsOptions = await updateItemsOptions(row.algorithmId)
+  }
   const params = {
     title,
-    width: 580,
+    width: 600,
     isEdit: type !== 3,
     itemsOptions: itemsOptions,
     model: type == 1 ? {} : res.data,
@@ -501,6 +485,14 @@ const columns = reactive<ColumnProps<any>[]>([
     label: '模型名称',
     width: 200
   },
+  {
+    prop: 'algorithmParameters',
+    label: '算法参数',
+    search: {
+      el: 'input'
+    },
+    width: 150
+  },
   // {
   //   prop: 'algorithmModelId',
   //   label: '模型',
@@ -544,6 +536,52 @@ const columns = reactive<ColumnProps<any>[]>([
   },
   { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
 ])
+
+const remove_unnecessary_parameters = (itemsOptions: ProForm.ItemsOptions[]): ProForm.ItemsOptions[] => {
+  try {
+    const endIndex = itemsOptions.findIndex(option => option['label'] === '备注')
+    if (endIndex !== -1) {
+      itemsOptions = itemsOptions.slice(0, endIndex + 1)
+    }
+    return itemsOptions
+  } catch (error) {
+    console.error('移除不必要的参数时出错:', error)
+    // ElMessage.error('移除不必要的参数时出错,请检查!');
+    return itemsOptions // 返回原始选项,避免进一步的问题
+  }
+}
+
+const updateItemsOptions = async (algorithmId: any) => {
+  try {
+    const result = await getAlgorithmConfigTrackApi(algorithmId)
+    if (result.code === 200) {
+      // 处理结果
+      const parameters = JSON.parse(result.data['parameters'])
+      // console.log('parameters: ', parameters)
+
+      const itemsOptions_new = remove_unnecessary_parameters(itemsOptions)
+      for (const item of parameters) {
+        // 添加新的表单项选项
+        itemsOptions_new.push({
+          label: item['name'],
+          prop: item['agName'],
+          rules: [{ required: item['required'], message: item['agName'] + '不能为空', trigger: 'blur' }],
+          tooltip: item['prompt'],
+          compOptions: {
+            elTagName: 'input',
+            placeholder: item['defaultValue']
+            // value: item['defaultValue']
+          }
+        })
+      }
+      formDialogRef.value?.updateItemOptions(itemsOptions_new)
+      return itemsOptions_new
+    }
+  } catch (err) {
+    console.log(err)
+    ElMessage.error('获取算法配置失败,请检查!')
+  }
+}
 // 表单配置项
 let itemsOptions: ProForm.ItemsOptions[] = []
 const setItemsOptions = () => {
@@ -553,6 +591,7 @@ const setItemsOptions = () => {
       prop: 'name',
       rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
       compOptions: {
+        elTagName: 'input',
         placeholder: '请输入任务名称'
       }
     },
@@ -578,14 +617,61 @@ const setItemsOptions = () => {
         placeholder: '请上传数据集'
       }
     },
+    {
+      label: '选择算法',
+      prop: 'algorithmId',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择算法',
+        enum: enumsAlgorithmConfigTrack,
+        clearable: true,
+        onChange: async (value: any) => {
+          if (value != undefined && value != null && value != '') {
+            await updateItemsOptions(value)
+          }
+        }
+      }
+    },
+    {
+      label: '任务类型',
+      prop: 'type',
+      rules: [{ required: true, message: '任务类型不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        elTagName: 'select',
+        placeholder: '请选择模任务类型',
+        enum: enumsAlgorithmType,
+        clearable: true,
+        value: ''
+      },
+      show: params => {
+        if (params.value.algorithmId != undefined) {
+          for (let i = 0; i < enumsAlgorithmConfigTrack.value.length; i++) {
+            if (enumsAlgorithmConfigTrack.value[i]['value'] === params.value.algorithmId) {
+              params.value.type = enumsAlgorithmConfigTrack.value[i]['type']
+              return true
+            }
+          }
+        }
+        return false
+      }
+    },
     {
       label: '选择模型',
       prop: 'algorithmModelId',
       rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
+      show: params => {
+        if (params.value.type == AlgorithmType2['预测/推理']) {
+          return true
+        }
+        return false
+      },
       compOptions: {
         elTagName: 'select',
         placeholder: '请选择模型',
-        enum: enumsAlgorithmModelTrack
+        enum: enumsAlgorithmModelTrack,
+        clearable: true
       }
     },
     {
@@ -593,6 +679,7 @@ const setItemsOptions = () => {
       prop: 'remarks',
       rules: [],
       compOptions: {
+        elTagName: 'input',
         placeholder: '请输入备注'
       }
     }
@@ -655,6 +742,7 @@ const setItemsOptions2 = () => {
       prop: 'name',
       rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
       compOptions: {
+        elTagName: 'input',
         disabled: true,
         placeholder: '请输入任务名称'
       }
@@ -674,71 +762,7 @@ const setItemsOptions2 = () => {
       prop: 'remarks',
       rules: [],
       compOptions: {
-        placeholder: '请输入备注'
-      }
-    }
-  ]
-}
-
-const setItemsOptionsModel = () => {
-  itemsOptions = [
-    {
-      label: '算法ID',
-      prop: 'algorithmId',
-      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
-      compOptions: {
-        disabled: true,
-        placeholder: '请输入算法'
-      }
-    },
-    {
-      label: '算法类型',
-      prop: 'algorithmType',
-      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
-      compOptions: {
-        disabled: true,
-        elTagName: 'select',
-        placeholder: '请输入算法',
-        enum: enumsAlgorithmConfigTrack
-      }
-    },
-    {
-      label: '算法参数',
-      prop: 'parameterConfig',
-      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
-      compOptions: {
-        placeholder: '请输入模型名称'
-      }
-    },
-    {
-      label: '模型ID',
-      prop: 'id',
-      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
-      compOptions: {
-        placeholder: '请输入模型名称'
-      }
-    },
-    {
-      label: '模型名称',
-      prop: 'modelName',
-      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
-      compOptions: {
-        placeholder: '请输入模型名称'
-      }
-    },
-    {
-      label: '模型保存路径',
-      prop: 'modelAddress',
-      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
-      compOptions: {
-        placeholder: '请输入模型名称'
-      }
-    },
-    {
-      label: '备注',
-      prop: 'remarks',
-      rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
-      compOptions: {
+        elTagName: 'input',
         placeholder: '请输入备注'
       }
     }

+ 29 - 4
src/views/demo/traceMerge/index.vue

@@ -26,7 +26,10 @@
         <!--          编辑-->
         <!--        </el-button>-->
         <!--        <el-button type="primary" link icon="Delete" v-auth="['demo:traceMerge:remove']" @click="deleteTraceMerge(scope.row)"> 删除 </el-button>-->
-        <el-button type="primary" link icon="View" @click="execute(scope.row)"> 执行任务 </el-button>
+        <el-button type="primary" link icon="View" @click="execute(scope.row)"> 开始任务 </el-button>
+        <el-button type="primary" link icon="View" @click="hangupTask(scope.row)"> 暂停任务 </el-button>
+        <el-button type="primary" link icon="View" @click="execute(scope.row)"> 继续任务 </el-button>
+        <el-button type="primary" link icon="View" @click="stopTask(scope.row)"> 停止任务 </el-button>
         <el-button type="primary" link icon="View" @click="display(scope.row)"> 展示结果 </el-button>
         <el-button type="primary" link icon="View" @click="showLog(scope.row)"> 查看日志 </el-button>
         <el-button type="primary" link icon="View" @click="showResult(scope.row)"> 查看指标 </el-button>
@@ -43,9 +46,9 @@
         </el-container>
         <el-container style="margin-top: 20px">
           <span style="min-width: 80px">任务文件</span>
-          <file @update:model-value="updateFiles" :file-size="20" :file-type="['mat']"></file>
+          <file @update:model-value="updateFiles" :file-size="20" :file-type="['mat', 'json', 'txt']"></file>
         </el-container>
-        <el-container v-for="(item, index) in jsonParams" :key="index" style=" align-items: center;margin-top: 5px">
+        <el-container v-for="(item, index) in jsonParams" :key="index" style="align-items: center; margin-top: 5px">
           <span style="min-width: 80px; max-width: 150px">{{ item.name }}</span>
           <el-tooltip :content="item.prompt" placement="top">
             <el-icon><InfoFilled /></el-icon>
@@ -100,9 +103,11 @@ import {
   exportTraceMergeApi,
   getResApi,
   getTraceMergeApi,
+  hangupApi,
   importTemplateApi,
   importTraceMergeDataApi,
   listTraceMergeApi,
+  stopApi,
   updateTraceMergeApi
 } from '@/api/modules/demo/traceMerge'
 import File from '@/components/Upload/File.vue'
@@ -184,6 +189,26 @@ const execute = function (row) {
   })
 }
 
+const hangupTask = function (row) {
+  hangupApi({ taskId: row.id }).then(res => {
+    if (res.code == 200) {
+      ElMessage.success('暂停成功!')
+    } else {
+      ElMessage.error('暂停失败: ' + res.msg)
+    }
+  })
+}
+
+const stopTask = function (row) {
+  stopApi({ taskId: row.id }).then(res => {
+    if (res.code == 200) {
+      ElMessage.success('停止成功!')
+    } else {
+      ElMessage.error('停止失败: ' + res.msg)
+    }
+  })
+}
+
 const jsonParams = ref([])
 const createTask = async function () {
   const res = await getOneAlgorithmConfigApi({ algorithmName: '多源信息融合' })
@@ -198,7 +223,7 @@ const createTask = async function () {
 
 const submitCreateTask = function () {
   if (params.value.preprocessPath == null || params.value.preprocessPath === '') {
-    ElMessage.error('请上传mat文件!')
+    ElMessage.error('请上传源数据文件!')
     return
   } else if (params.value.name == null || params.value.name === '') {
     ElMessage.error('请输入任务名称!')

+ 188 - 27
src/views/demo/trackSequence/index.vue

@@ -9,10 +9,7 @@
     <ProTable ref="proTable" :columns="columns" row-key="id" :request-api="listTrackSequenceApi">
       <!-- 表格 header 按钮 -->
       <template #tableHeader="scope">
-        <el-button type="primary" v-auth="['demo:trackSequence:add']" icon="CirclePlus" @click="openDialog(1, '注视轨迹序列新增')">
-          新增(MASC)
-        </el-button>
-        <el-button type="primary" v-auth="['demo:trackSequence:add']" icon="CirclePlus" @click="addCATDialog()"> 新增(CAT) </el-button>
+        <el-button type="primary" v-auth="['demo:trackSequence:add']" icon="CirclePlus" @click="openDialog(1, '注视轨迹序列新增')"> 新增 </el-button>
         <!-- <el-button type="primary" v-auth="['demo:trackSequence:import']" icon="Upload" plain @click="batchAdd"> 导入 </el-button>
         <el-button type="primary" v-auth="['demo:trackSequence:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button> -->
         <el-button
@@ -28,10 +25,11 @@
       </template>
       <!-- 表格操作 -->
       <template #operation="scope">
-        <el-button type="primary" link icon="View" v-if="scope.row.algorithmModelId != null" @click="openModelDialog(scope.row.id)">
+        <el-button type="primary" link icon="View" @click="openDialog(3, '详情', scope.row)">
           <!--@click="openStartDialog(scope.row)"  -->
           详情
         </el-button>
+        <el-button type="primary" link icon="EditPen" @click="openDialog(2, '编辑', scope.row)"> 编辑 </el-button>
         <el-button
           type="primary"
           link
@@ -116,8 +114,6 @@
         >
           模型
         </el-button>
-        <!-- <el-button type="primary" link icon="View" v-auth="['demo:toInfrared:query']" @click="openDialog(3, '查看', scope.row)"> 查看 </el-button> -->
-        <!-- <el-button type="primary" link icon="EditPen"v-auth="['demo:toInfrared:edit']" @click="openDialog(2, '编辑', scope.row)"> 编辑 </el-button> -->
         <el-button
           type="primary"
           link
@@ -134,7 +130,7 @@
     <ImportExcel ref="dialogRef" />
     <ViewLog ref="viewLogRef" :get-log-api="getLogTrackSequenceApi" />
     <PreviewCompareImages ref="previewImagesRef" />
-    <ShowStatisticResult ref="showStatisticResultRef" :api="getStatisticsResultToInfraredApi" />
+    <ShowStatisticResult ref="showStatisticResultRef" :api="getStatisticsResultTrackSequenceApi" />
     <ShowStatisticResult ref="showEvaluateResultRef" :api="previewEvaluateTrackSequenceApi" title="评估结果" />
     <el-dialog v-model="showModelDialogVisible" title="模型列表" width="1000">
       <el-scrollbar ref="scrollbarRef" id="scrollbarRef1" height="500px">
@@ -154,9 +150,12 @@
                 <el-link :href="model.url" type="primary" icon="Download" :underline="false" target="_blank" style="margin-right: 20px"
                   >下载
                 </el-link>
-                <el-button type="success" link @click="addModel(model.path, model.name)"
-                  ><el-icon> <Plus /> </el-icon>添加模型</el-button
-                >
+                <el-button type="success" link @click="addModel(model.path, model.name)">
+                  <el-icon>
+                    <Plus />
+                  </el-icon>
+                  添加模型
+                </el-button>
               </el-form-item>
             </el-form>
           </el-card>
@@ -193,11 +192,11 @@ import {
   showCATModelApi,
   previewPredictResultTrackSequenceModelApi,
   previewEvaluateTrackSequenceApi,
-  getStatisticsResultToInfraredApi
+  getStatisticsResultTrackSequenceApi
 } from '@/api/modules/demo/trackSequence'
 import { enumAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
 import { getAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
-import { enumAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
+import { enumAlgorithmConfigTrackApi, getAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
 
 import { listDataSeqApi } from '@/api/modules/demo/DataSeq'
 import statusEnums from '@/utils/status'
@@ -209,6 +208,7 @@ import { resetHeart } from '@/utils/websocket'
 import PreviewCompareImages from '@/views/demo/components/PreviewCompareImages.vue'
 
 import ShowStatisticResult from '@/views/demo/components/ShowStatisticResult.vue'
+import { getTargetDetectionApi } from '@/api/modules/demo/TargetDetection'
 
 const showStatisticResultRef = ref()
 const showEvaluateResultRef = ref()
@@ -274,7 +274,7 @@ const setItemsOptions222 = async () => {
       prop: 'modelName',
       rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
       compOptions: {
-        disabled: true,
+        disabled: false,
         placeholder: '请输入模型名称'
       }
     },
@@ -409,7 +409,7 @@ const addCATDialog = async () => {
 
 const showEvaluate = (row: any) => {
   const newItem = {
-    id: row.id
+    predictTaskId: row.id
   }
 
   const enumsAlgorithmConfigTrack__: Array<any> = []
@@ -439,6 +439,28 @@ const showEvaluate = (row: any) => {
         enum: enumsAlgorithmConfigTrack__
       }
     },
+    {
+      label: '选择Label文件',
+      prop: 'inputLabelOssId',
+      rules: [{ required: false, message: 'Label文件不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择或者上传Label文件',
+        enum: datasetList,
+        clearable: true
+      }
+    },
+    {
+      label: "上传Label文件",
+      prop: 'inputLabelOssId',
+      rules: [{ required: false, message: '请上传Label文件', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['txt'],
+        placeholder: '请上传数据集'
+      }
+    },
     {
       label: '备注',
       prop: 'remarks',
@@ -454,7 +476,7 @@ const showEvaluate = (row: any) => {
     isEdit: true,
     itemsOptions: itemsOptions,
     model: newItem,
-    api: addEvaluateTrackSequenceApi,
+    api: addTrackSequenceApi,
     getTableList: proTable.value?.getTableList
   }
   formDialogRef.value?.openDialog(params)
@@ -557,10 +579,17 @@ const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
 const openDialog = async (type: number, title: string, row?: any) => {
   let res = { data: {} }
   if (row?.id) {
-    res = await getTrackSequenceApi(row?.id || null)
+    res = await getTrackSequenceApi(row.id || null)
+    const params = JSON.parse(res.data['algorithmParameters'])
+    if (params.otherParams) {
+      res.data = { ...res.data, ...params.otherParams }
+    }
   }
   // 重置表单
   setItemsOptions()
+  if (row?.id) {
+    itemsOptions = await updateItemsOptions(row.algorithmId)
+  }
   const params = {
     title,
     width: 580,
@@ -619,6 +648,14 @@ const columns = reactive<ColumnProps<any>[]>([
     label: '模型名称',
     width: 200
   },
+  {
+    prop: 'algorithmParameters',
+    label: '算法参数',
+    search: {
+      el: 'input'
+    },
+    width: 150
+  },
   // {
   //   prop: 'algorithmModelId',
   //   label: '模型',
@@ -663,6 +700,52 @@ const columns = reactive<ColumnProps<any>[]>([
   { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
 ])
 
+const remove_unnecessary_parameters = (itemsOptions: ProForm.ItemsOptions[]): ProForm.ItemsOptions[] => {
+  try {
+    const endIndex = itemsOptions.findIndex(option => option['label'] === '备注')
+    if (endIndex !== -1) {
+      itemsOptions = itemsOptions.slice(0, endIndex + 1)
+    }
+    return itemsOptions
+  } catch (error) {
+    console.error('移除不必要的参数时出错:', error)
+    // ElMessage.error('移除不必要的参数时出错,请检查!');
+    return itemsOptions // 返回原始选项,避免进一步的问题
+  }
+}
+
+const updateItemsOptions = async (algorithmId: any) => {
+  try {
+    const result = await getAlgorithmConfigTrackApi(algorithmId)
+    if (result.code === 200) {
+      // 处理结果
+      const parameters = JSON.parse(result.data['parameters'])
+      // console.log('parameters: ', parameters)
+
+      const itemsOptions_new = remove_unnecessary_parameters(itemsOptions)
+      for (const item of parameters) {
+        // 添加新的表单项选项
+        itemsOptions_new.push({
+          label: item['name'],
+          prop: item['agName'],
+          rules: [{ required: item['required'], message: item['agName'] + '不能为空', trigger: 'blur' }],
+          tooltip: item['prompt'],
+          compOptions: {
+            elTagName: 'input',
+            placeholder: item['defaultValue']
+            // value: item['defaultValue']
+          }
+        })
+      }
+      formDialogRef.value?.updateItemOptions(itemsOptions_new)
+      return itemsOptions_new
+    }
+  } catch (err) {
+    console.log(err)
+    ElMessage.error('获取算法配置失败,请检查!')
+  }
+}
+
 // 表单配置项
 let itemsOptions: ProForm.ItemsOptions[] = []
 const setItemsOptions = () => {
@@ -698,24 +781,96 @@ const setItemsOptions = () => {
       }
     },
     {
-      label: '选择模型',
+      label: '选择算法',
+      prop: 'algorithmId',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择算法',
+        enum: enumsAlgorithmConfigTrack,
+        clearable: true,
+        onChange: async (value: any) => {
+          if (value != undefined && value != null && value != '') {
+            await updateItemsOptions(value)
+          }
+        }
+      }
+    },
+    {
+      label: '任务类型',
+      prop: 'type',
+      rules: [{ required: true, message: '任务类型不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        elTagName: 'select',
+        placeholder: '请选择任务类型',
+        enum: enumsAlgorithmType,
+        clearable: true,
+        value: ''
+      },
+      show: params => {
+        if (params.value.algorithmId != undefined) {
+          for (let i = 0; i < enumsAlgorithmConfigTrack.value.length; i++) {
+            if (enumsAlgorithmConfigTrack.value[i]['value'] === params.value.algorithmId) {
+              params.value.type = enumsAlgorithmConfigTrack.value[i]['type']
+              return true
+            }
+          }
+        }
+        return false
+      }
+    },
+    {
+      label: '视觉模型',
       prop: 'algorithmModelId',
-      rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
+      rules: [{ required: false, message: '模型不能为空', trigger: 'blur' }],
+      show: params => {
+        if (params.value.type == AlgorithmType2['预测/推理']) {
+          return true
+        }
+        params.value.algorithmModelId = ''
+        return false
+      },
       compOptions: {
         elTagName: 'select',
         placeholder: '请选择模型',
-        enum: enumsAlgorithmModelTrack
+        enum: enumsAlgorithmModelTrack,
+        clearable: true
       }
     },
     {
-      label: '选择算法',
-      prop: 'algorithmId',
-      rules: [{ required: true, message: '请选择算法', trigger: 'blur' }],
+      label: '目标检测模型',
+      prop: 'algorithmModelTargetDetectionId',
+      rules: [{ required: true, message: '目标检测模型不能为空', trigger: 'blur' }],
+      show: params => {
+        if (params.value.type == AlgorithmType2['预测/推理']) {
+          return true
+        }
+        params.value.algorithmModelTargetDetectionId = ''
+        return false
+      },
       compOptions: {
-        disabled: false,
         elTagName: 'select',
-        placeholder: '请输入算法',
-        enum: enumsAlgorithmConfigTrack
+        placeholder: '请选择目标检测模型',
+        enum: enumsAlgorithmModelTrack_TD,
+        clearable: true
+      }
+    },
+    {
+      label: '上传标签',
+      prop: 'inputLabelOssId',
+      rules: [{ required: true, message: '标签不能为空', trigger: 'blur' }],
+      show: params => {
+        if (params.value.type == AlgorithmType2['测试']) {
+          return true
+        }
+        return false
+      },
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['txt'],
+        placeholder: '请上传标签'
       }
     },
     {
@@ -819,6 +974,7 @@ onMounted(async () => {
 })
 
 const enumsAlgorithmModelTrack = ref<any>([])
+const enumsAlgorithmModelTrack_TD = ref<any>([])
 
 const updateEnumsAlgorithmModelTrack = async () => {
   const result: any = await enumAlgorithmModelTrackApi()
@@ -829,11 +985,16 @@ const updateEnumsAlgorithmModelTrack = async () => {
     if (item.type !== AlgorithmType2['预测/推理']) {
       continue
     }
-    if (SubSystem[item['subsystem']] === '注释轨迹序列' || SubSystem[item['subsystem']] === '目标检测') {
+    if (SubSystem[item['subsystem']] === '注释轨迹序列') {
       item['label'] =
         item['value'] + '_' + item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']] + '-' + item['algorithmName']
       enumsAlgorithmModelTrack.value.push(item)
     }
+    if (SubSystem[item['subsystem']] === '目标检测') {
+      item['label'] =
+        item['value'] + '_' + item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']] + '-' + item['algorithmName']
+      enumsAlgorithmModelTrack_TD.value.push(item)
+    }
   }
 }
 

+ 8 - 0
src/views/demo/utils.ts

@@ -16,6 +16,14 @@ export const Status = {
   中断: '4'
 }
 
+export const Status__ = {
+  '0': '未开始',
+  '1': '运行中',
+  '2': '完成',
+  '3': '失败',
+  '4': '中断'
+}
+
 export const AlgorithmType = {
   '0': '训练',
   '1': '测试',

+ 109 - 74
src/views/demo/videoStable/index.vue

@@ -30,10 +30,17 @@
           link
           icon="View"
           @click="startVideoStable(scope.row)"
-          v-if="scope.row.status == '0' || scope.row.status == '3' || scope.row.status == '4'"
+          v-if="scope.row.status == '0' || scope.row.status == '3' || scope.row.status == '2'"
         >
           开始
         </el-button>
+
+        <el-button type="primary" link icon="View" @click="startVideoStable(scope.row)" v-if="scope.row.status == '4'"> 继续 </el-button>
+        <el-popconfirm title="确定暂停此任务吗?" @confirm="hangupVideoStable(scope.row)" v-if="scope.row.status == '1'">
+          <template #reference>
+            <el-button type="primary" link icon="View"> 暂停 </el-button>
+          </template>
+        </el-popconfirm>
         <el-popconfirm title="确定终止此任务吗?" @confirm="stopVideoStable(scope.row)" v-if="scope.row.status == '1'">
           <template #reference>
             <el-button type="primary" link icon="View"> 终止 </el-button>
@@ -89,13 +96,15 @@ import {
   // getCompareImageApi,
   // getCompareImageCountApi,
   getImagesApi,
-  getLogVideoStableApi
+  getLogVideoStableApi,
+  hangupVideoStableApi
 } from '@/api/modules/demo/videoStable'
 
 import useWebSocketStore from '@/stores/modules/websocket'
 import { resetHeart } from '@/utils/websocket'
 import ViewLog from '@/views/demo/components/ViewLog.vue'
 import PreviewCompareImages from '@/views/demo/components/PreviewCompareImages.vue'
+import { getOneAlgorithmConfigApi, listAlgorithmConfigApi } from '@/api/modules/demo/algorithmConfig'
 
 const previewCompareImagesRef = ref()
 const previewCompare = async row => {
@@ -138,6 +147,16 @@ const stopVideoStable = async (params: any) => {
   proTable.value?.getTableList()
 }
 
+const hangupVideoStable = async (params: any) => {
+  const res = await hangupVideoStableApi(params.id)
+  if (res.code === 200) {
+    ElMessage.success('任务暂停成功')
+  } else {
+    ElMessage.error('任务暂停失败!')
+  }
+  proTable.value?.getTableList()
+}
+
 // ProTable 实例
 const proTable = ref<ProTableInstance>()
 
@@ -181,7 +200,7 @@ const openDialog = async (type: number, title: string, row?: any) => {
     res = await getVideoStableApi(row?.id || null)
   }
   // 重置表单
-  setItemsOptions()
+  await setItemsOptions()
   const params = {
     title,
     width: 580,
@@ -338,7 +357,7 @@ const columns = reactive<ColumnProps<any>[]>([
 ])
 // 表单配置项
 let itemsOptions: ProForm.ItemsOptions[] = []
-const setItemsOptions = () => {
+const setItemsOptions = async () => {
   itemsOptions = [
     {
       label: '任务名称',
@@ -359,76 +378,76 @@ const setItemsOptions = () => {
         placeholder: '请上传图片集压缩包'
       }
     },
-    {
-      label: '网格大小',
-      prop: 'block_size',
-      rules: [],
-      compOptions: {
-        type: 'input',
-        clearable: true,
-        placeholder: '默认50'
-      }
-    },
-    {
-      label: '扩散半径',
-      prop: 'radius',
-      rules: [],
-      compOptions: {
-        type: 'input',
-        clearable: true,
-        placeholder: '默认500'
-      }
-    },
-    {
-      label: '缓冲区大小',
-      prop: 'buffer_size',
-      rules: [],
-      compOptions: {
-        type: 'input',
-        clearable: true,
-        placeholder: '默认200'
-      }
-    },
-    {
-      label: '角点质量',
-      prop: 'cornerquality',
-      rules: [],
-      compOptions: {
-        type: 'input',
-        clearable: true,
-        placeholder: '默认0.2'
-      }
-    },
-    {
-      label: '角点最小距离',
-      prop: 'cornerminDistance',
-      rules: [],
-      compOptions: {
-        type: 'input',
-        clearable: true,
-        placeholder: '默认5'
-      }
-    },
-    {
-      label: '光流层级',
-      prop: 'lklevel',
-      rules: [],
-      compOptions: {
-        type: 'input',
-        clearable: true,
-        placeholder: '默认3'
-      }
-    },
-    {
-      label: '光流窗口大小',
-      prop: 'lkwinSiz',
-      rules: [],
-      compOptions: {
-        type: 'input',
-        clearable: true,
-        placeholder: '默认15'
-      }
-    },
+    // {
+    //   label: '网格大小',
+    //   prop: 'block_size',
+    //   rules: [],
+    //   compOptions: {
+    //     type: 'input',
+    //     clearable: true,
+    //     placeholder: '默认50'
+    //   }
+    // },
+    // {
+    //   label: '扩散半径',
+    //   prop: 'radius',
+    //   rules: [],
+    //   compOptions: {
+    //     type: 'input',
+    //     clearable: true,
+    //     placeholder: '默认500'
+    //   }
+    // },
+    // {
+    //   label: '缓冲区大小',
+    //   prop: 'buffer_size',
+    //   rules: [],
+    //   compOptions: {
+    //     type: 'input',
+    //     clearable: true,
+    //     placeholder: '默认200'
+    //   }
+    // },
+    // {
+    //   label: '角点质量',
+    //   prop: 'cornerquality',
+    //   rules: [],
+    //   compOptions: {
+    //     type: 'input',
+    //     clearable: true,
+    //     placeholder: '默认0.2'
+    //   }
+    // },
+    // {
+    //   label: '角点最小距离',
+    //   prop: 'cornerminDistance',
+    //   rules: [],
+    //   compOptions: {
+    //     type: 'input',
+    //     clearable: true,
+    //     placeholder: '默认5'
+    //   }
+    // },
+    // {
+    //   label: '光流层级',
+    //   prop: 'lklevel',
+    //   rules: [],
+    //   compOptions: {
+    //     type: 'input',
+    //     clearable: true,
+    //     placeholder: '默认3'
+    //   }
+    // },
+    // {
+    //   label: '光流窗口大小',
+    //   prop: 'lkwinSiz',
+    //   rules: [],
+    //   compOptions: {
+    //     type: 'input',
+    //     clearable: true,
+    //     placeholder: '默认15'
+    //   }
+    // },
     {
       label: '备注',
       prop: 'remarks',
@@ -444,6 +463,22 @@ const setItemsOptions = () => {
       }
     }
   ]
+
+  const res = await getOneAlgorithmConfigApi({ algorithmName: '电子稳相' })
+  const config = JSON.parse(res.data.parameters)
+  config.forEach(item => {
+    itemsOptions.push({
+      label: item.name,
+      prop: item.agName,
+      rules: [],
+      compOptions: {
+        type: 'input',
+        clearable: true,
+        placeholder: item.defaultValue
+      },
+      tooltip: item.prompt
+    })
+  })
 }
 </script>
 

+ 8 - 3
src/views/taais/homePage/task/index.vue

@@ -110,7 +110,9 @@
           @update-data="updateBatchData"
           @update-model="updateModelData"
           @update-params="updateParamsList"
-          :show-select-batch-button="false"
+          :show-select-batch-button="true"
+          :use-data="true"
+          :data-list="selectedBatchDataList"
         />
       </el-container>
       <el-container style="height: 10px"></el-container>
@@ -202,11 +204,13 @@ const updateBatchData = data => {
 
 const updateModelData = data => {
   model.value = data
+  console.log('model', model.value)
 }
 
 // 监听 parameList 更新
 const updateParamsList = data => {
   parameList.value = data
+  console.log('params', parameList.value)
 }
 
 // 提交逻辑
@@ -219,8 +223,9 @@ const getTrainAugmentationParams = () => {
   })
 
   return {
-    batchNum,
+    batchNum: batchNum,
     taskName: model.value.taskName,
+    augmentationType: model.value.augmentationType,
     otherParams: parameList.value
   }
 }
@@ -276,7 +281,6 @@ const valid = data => {
 }
 
 const submit = () => {
-  console.log('submit data, formdata is: ', formData)
   const params = {
     taskName: formData.taskName,
     taskType: formData.taskType,
@@ -287,6 +291,7 @@ const submit = () => {
     hasTrainAugmentation: formData.expandData,
     trainAugmentationParams: getTrainAugmentationParams()
   }
+  console.log('submit data', params)
   let result = valid(params)
   // console.log(result)
   if (result.code !== 200) {

+ 2 - 0
src/views/task/bizProcess/index.vue

@@ -412,10 +412,12 @@ const loadVerifyResult = async (name, filepath) => {
   }
 }
 
+import { xywh2fourNodes } from '../../demo/data/reformat'
 const setDetail = obj => {
   http.get<any>(obj.labelUrl).then(res => {
     obj.jsonData = []
     // console.log('result', res)
+    res = xywh2fourNodes(res)
     let arr = res.replace('\r', '').split('\n')
     // console.log(arr)
     for (let i = 0; i < arr.length; i++) {