41 Commits e84e772cff ... 3487b63472

Auteur SHA1 Message Date
  WANGKANG 3487b63472 Merge branch 'dev_wk2' into develop il y a 5 mois
  WANGKANG a0dcc1bc51 feat: 1.修改数据加载逻辑 2. 添加自动刷新 il y a 5 mois
  WANGKANG a727c75e9a feat: 总任务测试 il y a 5 mois
  WANGKANG 35856c591a feat: cat测试 il y a 5 mois
  WANGKANG c07210e7a0 feat: masc测试 il y a 5 mois
  WANGKANG 2659eeb6ca feat: 修改模型必要性 il y a 5 mois
  WANGKANG a69bce53e2 feat: 目标检测模型名称可以修改 il y a 5 mois
  WANGKANG fa4e655807 feat: 评估结果展示 il y a 5 mois
  WANGKANG 6a272dc0c9 fix: 修改ShowStatisticResult的封装,添加title il y a 5 mois
  WANGKANG dd86175169 feat: 预测任务结果预览 il y a 5 mois
  WANGKANG 10df04f5c3 feat: 修改ShowStatisticResult组件的封装 il y a 5 mois
  WANGKANG da9d5019d6 fix: 发现一个命名错误 il y a 5 mois
  WANGKANG f0939d04d5 feat: 预览功能 il y a 5 mois
  WANGKANG be7ae9809e feat: 查看日志功能 il y a 5 mois
  WANGKANG de1b8ca6a6 feat: 修改的ViewLog组件 il y a 5 mois
  WANGKANG 3e4dc257a0 feat: 停止功能 il y a 5 mois
  WANGKANG bbd9b2df98 feat: 开始功能 il y a 5 mois
  WANGKANG da43da10d2 feat: 删除功能 il y a 5 mois
  WANGKANG 0051787d8f fix: 修正 弹窗关不掉的问题 il y a 5 mois
  WANGKANG e5ca552392 feat: 总任务-注释轨迹序列-查看-编辑 初步完成 目标检测模型目前还获取不到 il y a 5 mois
  WANGKANG 5b5b03d9af feat: 总任务-可见光-查看-编辑 完成 il y a 5 mois
  WANGKANG 273f4c601b feat: 查看功能-列表展示完善 il y a 5 mois
  WANGKANG 30de862353 feat: 初步实现子任务查看功能 il y a 5 mois
  WANGKANG a610081dc8 feat: 添加一个子任务查看接口 il y a 5 mois
  WANGKANG c506380af1 feat: 添加一个enum il y a 5 mois
  WANGKANG eb7ead22ca fix: 修正表单关闭后再打开内容未重置 il y a 5 mois
  WANGKANG 1dbf83a9eb feat: 总任务新增初步完成 il y a 5 mois
  WANGKANG 40bd03cdfd fix: 算法参数设置 il y a 5 mois
  WANGKANG 9f14d2b0e6 feat: 总任务新增窗口初步完成 il y a 5 mois
  WANGKANG 31fd6e5c13 feat: 总任务添加功能编写(未完成) il y a 5 mois
  WANGKANG dd5f6af347 feat: 可辨识性分析总任务前端任务初步添加 il y a 5 mois
  WANGKANG a72d64a4d8 feat: 可辨识性分析优化 il y a 5 mois
  WANGKANG 9829203a45 feat: 目标检测优化 il y a 5 mois
  WANGKANG fdb92e4d25 feat: 优化可见光转红外两个细节 il y a 5 mois
  WANGKANG cf96a0a712 fix: 1. 可见光转红外新增、更新完成 2. 修正若干逻辑 3. 删掉无用方法 il y a 5 mois
  WANGKANG 4646566348 fix: 1. 移除多余的console 2. 可见光转红外新增界面修正 il y a 5 mois
  WANGKANG 96217b761a fix: 1. FromDialog组件添加updateItemOptions方法,用于动态更新表单 2. File组件修正一个警告 il y a 5 mois
  WANGKANG 7e13fc2a75 fix: protable添加一个change方法,可以用于在值发生变化时的回调 il y a 5 mois
  WANGKANG 3e93f505ba fix: 算法名称 il y a 5 mois
  WANGKANG 3540c449ea feat: 模型配置添加新的参数algorithmParameters il y a 6 mois
  WANGKANG 9d4cd04b08 feat: 可辨识性分析添加新的参数,前端适配 il y a 6 mois

+ 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}`)
+}

+ 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 })
 }

+ 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 () {

+ 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: '请输入备注'
       }
     }

+ 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': '测试',