浏览代码

feat: change execute task behavour

Suuuuuukang 9 月之前
父节点
当前提交
5f1e1d6ac8

+ 4 - 0
src/api/modules/ag/model.ts

@@ -27,6 +27,10 @@ export const addModelApi = (data: ModelForm) => {
   return http.post<any>('/ag/model', data, { loading: false })
 }
 
+export const queryModelList = (data: ModelForm) => {
+  return http.get<any>('/ag/model/algoList', data, { loading: false })
+}
+
 export const addAlgorithmTaskConfigurationApi = (data: ModelForm) => {
   return http.post<any>('/task/taskConfiguration/importModel', data, { loading: false })
 }

+ 5 - 2
src/components/FormDialog/index.vue

@@ -88,7 +88,7 @@ const handleSubmit = () => {
   if (!formEl) return
   formEl.validate(valid => {
     if (valid) {
-      parameter.value.api!({ ...formModel, ...parameter.value.model }).then(res => {
+      parameter.value.api!({ ...formModel, ...parameter.value.model, algorithmId: algorithmModelId.value }).then(res => {
         if (res.code == 200) {
           proFormRef.value?.resetForm(formEl)
           ElMessage.success('操作成功')
@@ -126,8 +126,11 @@ const handleCancel = () => {
   dialogVisible.value = false
 }
 
+let algorithmModelId = ref(0)
+
 // 接收父组件参数
-const openDialog = (params: FormParameterProps) => {
+const openDialog = (params: FormParameterProps, algoModelId) => {
+  algorithmModelId.value = algoModelId
   parameter.value = { ...parameter.value, ...params }
   _options.value.disabled = !parameter.value.isEdit
   butLoading.value = false

+ 111 - 87
src/views/taais/homePage/task/index.vue

@@ -28,11 +28,15 @@
         <span class="span_class">选择算法</span>
         <el-container style="display: flex; flex-direction: column">
           <el-container v-for="(item, index) in formData.algorithms" :key="index" style="margin-top: 5px">
-            <el-select style="width: 200px" v-model="formData.algoIdx[index]" placeholder="请选择" @change="onModelSelect(index)">
+            <el-select style="width: 200px" v-model="formData.algoIdx[index]" placeholder="请选择" @change="onAlgorithmModelSelect(index)">
               <el-option v-for="(item1, index) in algorithms" :key="item1.id" :label="item1.name" :value="index"> </el-option>
             </el-select>
             <el-button style="margin-left: 20px" @click="showSuperParameterConfig(item, index)"> 超参配置 </el-button>
-            <el-button @click="showAddModelDialog"> 导入模型 </el-button>
+            <span class="span_class1">选择模型</span>
+            <el-select style="width: 200px" v-model="formData.algoModelId[index]" placeholder="未选择将使用默认模型">
+              <el-option v-for="item1 in formData.algoModelList[index]" :key="item1.id" :label="item1.modelName" :value="item1.id"> </el-option>
+            </el-select>
+            <el-button @click="showAddModelDialog(item, index)"> 导入模型 </el-button>
             <el-button v-show="formData.algorithms.length > 1" @click="removeItem(index)"> 删除算法 </el-button>
             <el-button v-show="formData.taskType === '1' && index + 1 === formData.algorithms.length" @click="appendNewItem"> 添加算法 </el-button>
           </el-container>
@@ -169,8 +173,8 @@
 
 <script setup lang="ts">
 import { reactive, ref, onMounted, computed } from 'vue'
-import { addAlgorithmTaskConfigurationApi } from '@/api/modules/ag/model'
-import { createTaskApi, getAlgorithmOptionApi } from '@/api/modules/task/task'
+import { addModelApi, queryModelList } from '@/api/modules/ag/model'
+import { createTaskApi } from '@/api/modules/task/task'
 import FormDialog from '@/components/FormDialog/index.vue'
 import { useRouter } from 'vue-router'
 import { listTaskConfigurationApi } from '@/api/modules/task/taskConfiguration'
@@ -229,6 +233,7 @@ const valid = data => {
 }
 
 const submit = () => {
+  console.log('submit data, formdata is: ', formData)
   const params = {
     taskName: formData.taskName,
     taskType: formData.taskType,
@@ -246,17 +251,33 @@ const submit = () => {
     return
   }
 
+  let __idx = 0
   params.algTaskList.forEach(obj => {
     obj.algorithmId = obj.id
     // if (!obj.trainParams) {
     //   return
     // }
+    let o1 = JSON.parse(obj.trainParams)
+    let o2 = JSON.parse(obj.verifyParams)
+    let o3 = JSON.parse(obj.testParams)
+    if (formData.algoModelId[__idx] && formData.algoModelId[__idx].length > 0) {
+      const __trained = {
+        agName: 'pretrained_model',
+        defaultValue: true,
+        modelId: formData.algoModelId[__idx]
+      }
+      o1.push(__trained)
+      o2.push(__trained)
+      o3.push(__trained)
+    }
+
     obj.params =
-      JSON.stringify(JSON.parse(obj.trainParams)) +
+      JSON.stringify(o1) +
       ';;;' +
-      JSON.stringify(JSON.parse(obj.verifyParams)) +
+      JSON.stringify(o2) +
       ';;;' +
-      JSON.stringify(JSON.parse(obj.testParams))
+      JSON.stringify(o3)
+    __idx++
   })
   // console.log('submit', params)
 
@@ -346,10 +367,7 @@ const canDeselect = computed(() => {
 })
 
 const handleUpdateModelList = () => {
-  listTaskConfigurationApi({ pageNum: 1, pageSize: 10000 }).then(res => {
-    // console.log(res)
-    algorithms = reactive(res.data.list)
-  })
+  updateModelList(UPDATE_INDEX.value.id, UPDATE_INDEX.value.idx)
 }
 
 onMounted(() => {
@@ -414,6 +432,8 @@ const formData = reactive({
   tasks: [],
   algorithms: [{}],
   algoIdx: [null],
+  algoModelId: [null],
+  algoModelList: [[]],
   // 训练数据
   data: [null],
   // 测试数据
@@ -473,95 +493,90 @@ const showSuperParameterConfig = (item, index) => {
 
 let algorithms = reactive([])
 
-const onModelSelect = index => {
+const onAlgorithmModelSelect = index => {
   formData.algorithms[index] = algorithms[formData.algoIdx[index]]
+  updateModelList(formData.algorithms[index].id, index)
 }
 
 const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
 
-const showAddModelDialog = () => {
-  getAlgorithmOptionApi().then(res => {
-    let allAgloData = {
-      value: res.data
-    }
-    const params = {
-      title: '算法模型配置',
-      width: 580,
-      isEdit: true,
-      itemsOptions: [
-        {
-          label: '模型名称',
-          prop: 'modelName',
-          rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
-          compOptions: {
-            placeholder: '请输入模型名称'
-          }
-        },
-        {
-          label: '模型',
-          prop: 'modelAddress',
-          rules: [], //{ required: true, message: '模型不能为空', trigger: 'blur' }
-          compOptions: {
-            elTagName: 'slot'
-          }
-        },
-        {
-          label: '训练算法地址',
-          prop: 'trainUrl',
-          rules: [{ required: true, message: '训练算法地址不能为空', trigger: 'blur' }],
-          compOptions: {
-            placeholder: '请输入训练算法地址'
-          }
-        },
-        {
-          label: '训练超参配置',
-          prop: 'trainParams',
-          compOptions: {
-            placeholder: '请输入训练超参'
-          }
-        },
-        {
-          label: '验证算法地址',
-          prop: 'valUrl',
-          rules: [{ required: true, message: '验证算法地址不能为空', trigger: 'blur' }],
-          compOptions: {
-            placeholder: '请输入验证算法地址'
-          }
-        },
-        {
-          label: '验证超参配置',
-          prop: 'valParams',
-          compOptions: {
-            placeholder: '请输入验证超参'
-          }
-        },
-        {
-          label: '测试算法地址',
-          prop: 'testUrl',
-          rules: [{ required: true, message: '测试算法地址不能为空', trigger: 'blur' }],
-          compOptions: {
-            placeholder: '请输入测试算法地址'
-          }
-        },
-        {
-          label: '测试超参配置',
-          prop: 'testParams',
-          compOptions: {
-            placeholder: '请输入测试超参'
-          }
+
+let UPDATE_INDEX = ref({ id: null, idx: null })
+const showAddModelDialog = (item, index) => {
+  let _id = null
+  try {
+    _id = item.id
+  } catch (e) {
+    ElMessage.error("请先选择算法模型")
+    return
+  }
+  if (!_id || _id.length === 0) {
+    ElMessage.error("请先选择算法模型")
+    return
+  }
+  UPDATE_INDEX.value = {
+    id: _id,
+    idx: index
+  }
+  const params = {
+    title: '算法模型配置',
+    width: 580,
+    isEdit: true,
+    itemsOptions: [
+      {
+        label: '模型名称',
+        prop: 'modelName',
+        rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+        compOptions: {
+          placeholder: '请输入模型名称'
         }
-      ],
-      model: {},
-      api: addAlgorithmTaskConfigurationApi
-    }
+      },
+      {
+        label: '模型',
+        prop: 'modelAddress',
+        rules: [], //{ required: true, message: '模型不能为空', trigger: 'blur' }
+        compOptions: {
+          elTagName: 'slot'
+        }
+      },
+      {
+        label: '训练样本数',
+        prop: 'sampleNumber',
+        compOptions: {
+          placeholder: '请输入训练样本数'
+        }
+      },
+      {
+        label: '训练循环次数',
+        prop: 'cycleEpoch',
+        compOptions: {
+          placeholder: '请输入训练循环次数'
+        }
+      }
+    ],
+    model: {},
+    api: addModelApi
+  }
+  console.log('check item:', item)
+  formDialogRef.value?.openDialog(params, item.id)
+}
 
-    formDialogRef.value?.openDialog(params)
+// 获取算法模型绑定列表
+const updateModelList = (id, index) => {
+  // 获取算法列表?
+  queryModelList({id: id}).then(res => {
+    console.log('algorithm task model get: ', res)
+    if (res.code === 200) {
+      formData.algoModelList[index] = [ {id: null, modelName: '未选择'} , ...res.data]
+    }
   })
 }
 
 const appendNewItem = () => {
   formData.algorithms.push({})
   formData.algoIdx.push(null)
+  formData.algoModelId.push(null)
+  formData.algoModelList.push([])
 }
 const appendNewDataItem = isTrainData => {
   if (isTrainData) {
@@ -573,6 +588,8 @@ const appendNewDataItem = isTrainData => {
 const removeItem = idx => {
   formData.algorithms.splice(idx, 1)
   formData.algoIdx.splice(idx, 1)
+  formData.algoModelId.splice(idx, 1)
+  formData.algoModelList.splice(idx, 1)
 }
 const removeDataItem = (idx, isTrainData) => {
   if (isTrainData) {
@@ -603,4 +620,11 @@ const cancel = () => {
   width: 120px;
   font-size: 13px;
 }
+.span_class1 {
+  display: flex;
+  align-self: center;
+  justify-content: center;
+  width: 65px;
+  font-size: 13px;
+}
 </style>

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

@@ -36,7 +36,10 @@
 
         <el-button type="primary" link icon="finished" @click="showResult(scope.row)"> 执行结果 </el-button>
 
-        <el-button type="primary" link icon="Refresh" @click="reRunTask(scope.row)"> 重新执行 </el-button>
+        <el-button v-show="scope.row.name.indexOf('训练') === -1" type="primary" link icon="search" @click="showExecutedTime(scope.row)"> 执行时间 </el-button>
+
+        <el-button v-if="scope.row.name.indexOf('训练') === -1" type="primary" link icon="Refresh" @click="reRunTask(scope.row)"> 执行训练 </el-button>
+        <el-button v-else type="primary" link icon="Refresh" @click="startTask(scope.row)"> 开始训练 </el-button>
 
         <el-button type="primary" link icon="Refresh" @click="exportData(scope.row)"> 导出结果 </el-button>
 
@@ -51,6 +54,22 @@
     </ProTable>
     <FormDialog ref="formDialogRef" />
     <ImportExcel ref="dialogRef" />
+
+    <el-dialog v-model="executedTimeVisible" title="执行时间统计" width="70%">
+      <el-container v-for="(item, index) in executedTimeData" :key="index">
+        <el-container style="display: flex;flex-direction: column">
+          <h4 v-if="index === 0"> 单幅图像最短运行时间 </h4>
+          <h4 v-else-if="index === 1"> 单幅图像最短运行时间 </h4>
+          <h4 v-else-if="index === 2"> 单幅图像最短运行时间 </h4>
+          <div style="display: flex; flex-direction: row">
+            <h5> 前处理用时: {{ item['preprocess'] }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </h5>
+            <h5> 推理用时: {{ item['inference'] }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </h5>
+            <h5> 后处理用时: {{ item['postprocess'] }} </h5>
+          </div>
+        </el-container>
+      </el-container>
+    </el-dialog>
+
     <el-dialog v-model="dialogVisible" title="日志" width="70%">
       <div class="log" ref="logRef">
         <div class="p" v-for="(item, index) in logInfo" :key="index">{{ item }}</div>
@@ -252,6 +271,23 @@ let resultDialogVisible = ref(false)
 let refSelectData = ref(reactive({}))
 const reRunTask = row => {
   http.post<any>('/identification/identificationSubtaskDetails/execute', { taskId: row.id }, { loading: false })
+    .then(res => {
+      if (res.code !== 200) {
+        ElMessage.error(res.msg)
+      } else {
+        ElMessage.success('启动成功')
+      }
+    })
+}
+const startTask = row => {
+  http.post<any>('/identification/identificationSubtaskDetails/startTask', { taskId: row.id }, { loading: false })
+    .then(res => {
+      if (res.code !== 200) {
+        ElMessage.error(res.msg)
+      } else {
+        ElMessage.success('启动成功')
+      }
+    })
 }
 const typeDefs = ref(reactive([]))
 
@@ -264,6 +300,35 @@ const exportData = row => {
   })
 }
 
+let executedTimeVisible = ref(false)
+let executedTimeData = ref([])
+const showExecutedTime = row => {
+  // row.remarks = '[\n' +
+  //   '{\n' +
+  //   '"preprocess": 1,\n' +
+  //   '"inference": 2,\n' +
+  //   '"postprocess": 3\n' +
+  //   '},\n' +
+  //   '{\n' +
+  //   '"preprocess": 11,\n' +
+  //   '"inference": 22,\n' +
+  //   '"postprocess": 33\n' +
+  //   '},\n' +
+  //   '{\n' +
+  //   '"preprocess": 111,\n' +
+  //   '"inference": 233,\n' +
+  //   '"postprocess": 333\n' +
+  //   '}\n' +
+  //   ']'
+  try {
+    executedTimeData.value = JSON.parse(row.remarks)
+  } catch (e) {
+    ElMessage.error("解析JSON错误,请检查任务是否已完成")
+    return
+  }
+  executedTimeVisible.value = true
+}
+
 let imgDataList = ref(reactive([]))
 let titleMsg = ref('')
 let valDialogVisible = ref(false)
@@ -675,7 +740,7 @@ const columns = reactive<ColumnProps<any>[]>([
   },
   {
     prop: 'costSecond',
-    label: '耗时'
+    label: '耗时(ms)'
   },
   {
     prop: 'log',