allen 1 mēnesi atpakaļ
vecāks
revīzija
ac22ba0d8a
38 mainītis faili ar 2050 papildinājumiem un 917 dzēšanām
  1. 2 0
      ips-admin/src/main/java/com/ips/RuoYiApplication.java
  2. 26 0
      ips-admin/src/main/java/com/ips/system/controller/BizTrainingController.java
  3. 26 0
      ips-admin/src/main/java/com/ips/system/controller/ClassifyTestController.java
  4. 26 0
      ips-admin/src/main/java/com/ips/system/controller/DistillationController.java
  5. 26 0
      ips-admin/src/main/java/com/ips/system/controller/ExtractedFeaturesController.java
  6. 7 104
      ips-admin/src/main/java/com/ips/system/domain/BizTraining.java
  7. 7 105
      ips-admin/src/main/java/com/ips/system/domain/ClassifyTest.java
  8. 7 105
      ips-admin/src/main/java/com/ips/system/domain/Distillation.java
  9. 11 103
      ips-admin/src/main/java/com/ips/system/domain/ExtractedFeatures.java
  10. 6 4
      ips-admin/src/main/java/com/ips/system/domain/Preprocessed.java
  11. 6 0
      ips-admin/src/main/java/com/ips/system/service/IBizTrainingService.java
  12. 6 0
      ips-admin/src/main/java/com/ips/system/service/IClassifyTestService.java
  13. 6 0
      ips-admin/src/main/java/com/ips/system/service/IDistillationService.java
  14. 6 0
      ips-admin/src/main/java/com/ips/system/service/IExtractedFeaturesService.java
  15. 106 21
      ips-admin/src/main/java/com/ips/system/service/impl/BizTrainingServiceImpl.java
  16. 92 0
      ips-admin/src/main/java/com/ips/system/service/impl/ClassifyTestServiceImpl.java
  17. 95 4
      ips-admin/src/main/java/com/ips/system/service/impl/DistillationServiceImpl.java
  18. 91 1
      ips-admin/src/main/java/com/ips/system/service/impl/ExtractedFeaturesServiceImpl.java
  19. 32 17
      ips-admin/src/main/java/com/ips/system/service/impl/PreprocessedServiceImpl.java
  20. 13 11
      ips-admin/src/main/java/com/ips/system/utils/AlgorithmCaller.java
  21. 132 34
      ips-admin/src/main/java/com/ips/system/utils/CommonUtils.java
  22. 28 8
      ips-admin/src/main/resources/mapper/biz/BizTrainingMapper.xml
  23. 28 8
      ips-admin/src/main/resources/mapper/biz/ClassifyTestMapper.xml
  24. 28 8
      ips-admin/src/main/resources/mapper/biz/DistillationMapper.xml
  25. 28 8
      ips-admin/src/main/resources/mapper/biz/ExtractedFeaturesMapper.xml
  26. 28 8
      ips-admin/src/main/resources/mapper/biz/PreprocessedMapper.xml
  27. 35 19
      ips-ui/src/api/biz/distillation.js
  28. 35 19
      ips-ui/src/api/biz/features.js
  29. 35 19
      ips-ui/src/api/biz/test.js
  30. 35 19
      ips-ui/src/api/biz/training.js
  31. 1 0
      ips-ui/src/background.js
  32. 109 43
      ips-ui/src/views/biz/config/index.vue
  33. 215 59
      ips-ui/src/views/biz/distillation/index.vue
  34. 210 58
      ips-ui/src/views/biz/features/index.vue
  35. 52 11
      ips-ui/src/views/biz/preprocessed/index.vue
  36. 215 60
      ips-ui/src/views/biz/test/index.vue
  37. 215 60
      ips-ui/src/views/biz/training/index.vue
  38. 24 1
      sql/biz.sql

+ 2 - 0
ips-admin/src/main/java/com/ips/RuoYiApplication.java

@@ -5,6 +5,7 @@ import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 import org.springframework.context.ApplicationContext;
+import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -16,6 +17,7 @@ import org.springframework.web.bind.annotation.RestController;
 @RestController
 @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
 @MapperScan(basePackages = "com.ips.system.mapper")
+@EnableAsync
 public class RuoYiApplication
 {
     private static ApplicationContext applicationContext;

+ 26 - 0
ips-admin/src/main/java/com/ips/system/controller/BizTrainingController.java

@@ -2,6 +2,10 @@ package com.ips.system.controller;
 
 import java.util.List;
 import javax.servlet.http.HttpServletResponse;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.ips.common.utils.StringUtils;
+import com.ips.system.domain.Distillation;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -101,4 +105,26 @@ public class BizTrainingController extends BaseController
     {
         return toAjax(bizTrainingService.deleteBizTrainingByIds(ids));
     }
+
+    @PreAuthorize("@ss.hasPermi('biz:training:add')")
+    @GetMapping(value = "/run/{id}")
+    public AjaxResult run(@PathVariable("id") Long id) throws JsonProcessingException {
+        String errorMsg = bizTrainingService.run(id);
+        if(StringUtils.isEmpty(errorMsg)){
+            return success(errorMsg);
+        } else {
+            return error(errorMsg);
+        }
+    }
+
+    @PreAuthorize("@ss.hasPermi('biz:training:add')")
+    @GetMapping(value = "/getResultDetails/{id}")
+    public AjaxResult getResultDetails(@PathVariable("id") Long id) throws JsonProcessingException {
+        BizTraining obj = bizTrainingService.getResultDetails(id);
+        if(obj != null){
+            return success(obj);
+        } else {
+            return error("获取详情失败");
+        }
+    }
 }

+ 26 - 0
ips-admin/src/main/java/com/ips/system/controller/ClassifyTestController.java

@@ -2,6 +2,10 @@ package com.ips.system.controller;
 
 import java.util.List;
 import javax.servlet.http.HttpServletResponse;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.ips.common.utils.StringUtils;
+import com.ips.system.domain.Distillation;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -101,4 +105,26 @@ public class ClassifyTestController extends BaseController
     {
         return toAjax(classifyTestService.deleteClassifyTestByIds(ids));
     }
+
+    @PreAuthorize("@ss.hasPermi('biz:test:add')")
+    @GetMapping(value = "/run/{id}")
+    public AjaxResult run(@PathVariable("id") Long id) throws JsonProcessingException {
+        String errorMsg = classifyTestService.run(id);
+        if(StringUtils.isEmpty(errorMsg)){
+            return success(errorMsg);
+        } else {
+            return error(errorMsg);
+        }
+    }
+
+    @PreAuthorize("@ss.hasPermi('biz:test:add')")
+    @GetMapping(value = "/getResultDetails/{id}")
+    public AjaxResult getResultDetails(@PathVariable("id") Long id) throws JsonProcessingException {
+        ClassifyTest obj = classifyTestService.getResultDetails(id);
+        if(obj != null){
+            return success(obj);
+        } else {
+            return error("获取详情失败");
+        }
+    }
 }

+ 26 - 0
ips-admin/src/main/java/com/ips/system/controller/DistillationController.java

@@ -2,6 +2,10 @@ package com.ips.system.controller;
 
 import java.util.List;
 import javax.servlet.http.HttpServletResponse;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.ips.common.utils.StringUtils;
+import com.ips.system.domain.ExtractedFeatures;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -101,4 +105,26 @@ public class DistillationController extends BaseController
     {
         return toAjax(distillationService.deleteDistillationByIds(ids));
     }
+
+    @PreAuthorize("@ss.hasPermi('biz:distillation:add')")
+    @GetMapping(value = "/run/{id}")
+    public AjaxResult run(@PathVariable("id") Long id) throws JsonProcessingException {
+        String errorMsg = distillationService.run(id);
+        if(StringUtils.isEmpty(errorMsg)){
+            return success(errorMsg);
+        } else {
+            return error(errorMsg);
+        }
+    }
+
+    @PreAuthorize("@ss.hasPermi('biz:distillation:add')")
+    @GetMapping(value = "/getResultDetails/{id}")
+    public AjaxResult getResultDetails(@PathVariable("id") Long id) throws JsonProcessingException {
+        Distillation obj = distillationService.getResultDetails(id);
+        if(obj != null){
+            return success(obj);
+        } else {
+            return error("获取详情失败");
+        }
+    }
 }

+ 26 - 0
ips-admin/src/main/java/com/ips/system/controller/ExtractedFeaturesController.java

@@ -2,6 +2,10 @@ package com.ips.system.controller;
 
 import java.util.List;
 import javax.servlet.http.HttpServletResponse;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.ips.common.utils.StringUtils;
+import com.ips.system.domain.Preprocessed;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -101,4 +105,26 @@ public class ExtractedFeaturesController extends BaseController
     {
         return toAjax(extractedFeaturesService.deleteExtractedFeaturesByIds(ids));
     }
+
+    @PreAuthorize("@ss.hasPermi('biz:features:add')")
+    @GetMapping(value = "/run/{id}")
+    public AjaxResult run(@PathVariable("id") Long id) throws JsonProcessingException {
+        String errorMsg = extractedFeaturesService.run(id);
+        if(StringUtils.isEmpty(errorMsg)){
+            return success(errorMsg);
+        } else {
+            return error(errorMsg);
+        }
+    }
+
+    @PreAuthorize("@ss.hasPermi('biz:features:add')")
+    @GetMapping(value = "/getResultDetails/{id}")
+    public AjaxResult getResultDetails(@PathVariable("id") Long id) throws JsonProcessingException {
+        ExtractedFeatures obj = extractedFeaturesService.getResultDetails(id);
+        if(obj != null){
+            return success(obj);
+        } else {
+            return error("获取详情失败");
+        }
+    }
 }

+ 7 - 104
ips-admin/src/main/java/com/ips/system/domain/BizTraining.java

@@ -4,6 +4,7 @@ import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ips.common.annotation.Excel;
 import com.ips.common.core.domain.BaseEntity;
+import lombok.Data;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 
@@ -13,6 +14,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
  * @author Allen
  * @date 2025-05-21
  */
+@Data
 public class BizTraining extends BaseEntity
 {
     private static final long serialVersionUID = 1L;
@@ -42,114 +44,15 @@ public class BizTraining extends BaseEntity
     private String status;
 
     /** 开始时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date startTime;
 
     /** 结束时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date endTime;
 
-    public void setId(Long id) 
-    {
-        this.id = id;
-    }
+    private String algorithmName;
 
-    public Long getId() 
-    {
-        return id;
-    }
-    public void setTaskName(String taskName) 
-    {
-        this.taskName = taskName;
-    }
-
-    public String getTaskName() 
-    {
-        return taskName;
-    }
-    public void setAlgorithmId(Long algorithmId) 
-    {
-        this.algorithmId = algorithmId;
-    }
-
-    public Long getAlgorithmId() 
-    {
-        return algorithmId;
-    }
-    public void setInputPath(String inputPath) 
-    {
-        this.inputPath = inputPath;
-    }
-
-    public String getInputPath() 
-    {
-        return inputPath;
-    }
-    public void setOutputPath(String outputPath) 
-    {
-        this.outputPath = outputPath;
-    }
-
-    public String getOutputPath() 
-    {
-        return outputPath;
-    }
-    public void setAlgorithmParams(String algorithmParams) 
-    {
-        this.algorithmParams = algorithmParams;
-    }
-
-    public String getAlgorithmParams() 
-    {
-        return algorithmParams;
-    }
-    public void setStatus(String status) 
-    {
-        this.status = status;
-    }
-
-    public String getStatus() 
-    {
-        return status;
-    }
-    public void setStartTime(Date startTime) 
-    {
-        this.startTime = startTime;
-    }
-
-    public Date getStartTime() 
-    {
-        return startTime;
-    }
-    public void setEndTime(Date endTime) 
-    {
-        this.endTime = endTime;
-    }
-
-    public Date getEndTime() 
-    {
-        return endTime;
-    }
-
-    @Override
-    public String toString() {
-        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
-            .append("id", getId())
-            .append("taskName", getTaskName())
-            .append("algorithmId", getAlgorithmId())
-            .append("inputPath", getInputPath())
-            .append("outputPath", getOutputPath())
-            .append("algorithmParams", getAlgorithmParams())
-            .append("status", getStatus())
-            .append("startTime", getStartTime())
-            .append("endTime", getEndTime())
-            .append("remark", getRemark())
-            .append("createBy", getCreateBy())
-            .append("createTime", getCreateTime())
-            .append("updateBy", getUpdateBy())
-            .append("updateTime", getUpdateTime())
-            .toString();
-    }
 }

+ 7 - 105
ips-admin/src/main/java/com/ips/system/domain/ClassifyTest.java

@@ -4,6 +4,7 @@ import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ips.common.annotation.Excel;
 import com.ips.common.core.domain.BaseEntity;
+import lombok.Data;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 
@@ -13,6 +14,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
  * @author Allen
  * @date 2025-05-21
  */
+@Data
 public class ClassifyTest extends BaseEntity
 {
     private static final long serialVersionUID = 1L;
@@ -42,114 +44,14 @@ public class ClassifyTest extends BaseEntity
     private String status;
 
     /** 开始时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date startTime;
 
     /** 结束时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date endTime;
 
-    public void setId(Long id) 
-    {
-        this.id = id;
-    }
-
-    public Long getId() 
-    {
-        return id;
-    }
-    public void setTaskName(String taskName) 
-    {
-        this.taskName = taskName;
-    }
-
-    public String getTaskName() 
-    {
-        return taskName;
-    }
-    public void setAlgorithmId(Long algorithmId) 
-    {
-        this.algorithmId = algorithmId;
-    }
-
-    public Long getAlgorithmId() 
-    {
-        return algorithmId;
-    }
-    public void setInputPath(String inputPath) 
-    {
-        this.inputPath = inputPath;
-    }
-
-    public String getInputPath() 
-    {
-        return inputPath;
-    }
-    public void setOutputPath(String outputPath) 
-    {
-        this.outputPath = outputPath;
-    }
-
-    public String getOutputPath() 
-    {
-        return outputPath;
-    }
-    public void setAlgorithmParams(String algorithmParams) 
-    {
-        this.algorithmParams = algorithmParams;
-    }
-
-    public String getAlgorithmParams() 
-    {
-        return algorithmParams;
-    }
-    public void setStatus(String status) 
-    {
-        this.status = status;
-    }
-
-    public String getStatus() 
-    {
-        return status;
-    }
-    public void setStartTime(Date startTime) 
-    {
-        this.startTime = startTime;
-    }
-
-    public Date getStartTime() 
-    {
-        return startTime;
-    }
-    public void setEndTime(Date endTime) 
-    {
-        this.endTime = endTime;
-    }
-
-    public Date getEndTime() 
-    {
-        return endTime;
-    }
-
-    @Override
-    public String toString() {
-        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
-            .append("id", getId())
-            .append("taskName", getTaskName())
-            .append("algorithmId", getAlgorithmId())
-            .append("inputPath", getInputPath())
-            .append("outputPath", getOutputPath())
-            .append("algorithmParams", getAlgorithmParams())
-            .append("status", getStatus())
-            .append("startTime", getStartTime())
-            .append("endTime", getEndTime())
-            .append("remark", getRemark())
-            .append("createBy", getCreateBy())
-            .append("createTime", getCreateTime())
-            .append("updateBy", getUpdateBy())
-            .append("updateTime", getUpdateTime())
-            .toString();
-    }
+    private String algorithmName;
 }

+ 7 - 105
ips-admin/src/main/java/com/ips/system/domain/Distillation.java

@@ -4,6 +4,7 @@ import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ips.common.annotation.Excel;
 import com.ips.common.core.domain.BaseEntity;
+import lombok.Data;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 
@@ -13,6 +14,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
  * @author Allen
  * @date 2025-05-21
  */
+@Data
 public class Distillation extends BaseEntity
 {
     private static final long serialVersionUID = 1L;
@@ -42,114 +44,14 @@ public class Distillation extends BaseEntity
     private String status;
 
     /** 开始时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date startTime;
 
     /** 结束时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date endTime;
 
-    public void setId(Long id) 
-    {
-        this.id = id;
-    }
-
-    public Long getId() 
-    {
-        return id;
-    }
-    public void setTaskName(String taskName) 
-    {
-        this.taskName = taskName;
-    }
-
-    public String getTaskName() 
-    {
-        return taskName;
-    }
-    public void setAlgorithmId(Long algorithmId) 
-    {
-        this.algorithmId = algorithmId;
-    }
-
-    public Long getAlgorithmId() 
-    {
-        return algorithmId;
-    }
-    public void setInputPath(String inputPath) 
-    {
-        this.inputPath = inputPath;
-    }
-
-    public String getInputPath() 
-    {
-        return inputPath;
-    }
-    public void setOutputPath(String outputPath) 
-    {
-        this.outputPath = outputPath;
-    }
-
-    public String getOutputPath() 
-    {
-        return outputPath;
-    }
-    public void setAlgorithmParams(String algorithmParams) 
-    {
-        this.algorithmParams = algorithmParams;
-    }
-
-    public String getAlgorithmParams() 
-    {
-        return algorithmParams;
-    }
-    public void setStatus(String status) 
-    {
-        this.status = status;
-    }
-
-    public String getStatus() 
-    {
-        return status;
-    }
-    public void setStartTime(Date startTime) 
-    {
-        this.startTime = startTime;
-    }
-
-    public Date getStartTime() 
-    {
-        return startTime;
-    }
-    public void setEndTime(Date endTime) 
-    {
-        this.endTime = endTime;
-    }
-
-    public Date getEndTime() 
-    {
-        return endTime;
-    }
-
-    @Override
-    public String toString() {
-        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
-            .append("id", getId())
-            .append("taskName", getTaskName())
-            .append("algorithmId", getAlgorithmId())
-            .append("inputPath", getInputPath())
-            .append("outputPath", getOutputPath())
-            .append("algorithmParams", getAlgorithmParams())
-            .append("status", getStatus())
-            .append("startTime", getStartTime())
-            .append("endTime", getEndTime())
-            .append("remark", getRemark())
-            .append("createBy", getCreateBy())
-            .append("createTime", getCreateTime())
-            .append("updateBy", getUpdateBy())
-            .append("updateTime", getUpdateTime())
-            .toString();
-    }
+    private String algorithmName;
 }

+ 11 - 103
ips-admin/src/main/java/com/ips/system/domain/ExtractedFeatures.java

@@ -1,9 +1,13 @@
 package com.ips.system.domain;
 
 import java.util.Date;
+import java.util.List;
+
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ips.common.annotation.Excel;
 import com.ips.common.core.domain.BaseEntity;
+import com.ips.system.dto.ParentFolderInfoDTO;
+import lombok.Data;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 
@@ -13,6 +17,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
  * @author Allen
  * @date 2025-05-21
  */
+@Data
 public class ExtractedFeatures extends BaseEntity
 {
     private static final long serialVersionUID = 1L;
@@ -42,114 +47,17 @@ public class ExtractedFeatures extends BaseEntity
     private String status;
 
     /** 开始时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date startTime;
 
     /** 结束时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date endTime;
 
-    public void setId(Long id) 
-    {
-        this.id = id;
-    }
-
-    public Long getId() 
-    {
-        return id;
-    }
-    public void setTaskName(String taskName) 
-    {
-        this.taskName = taskName;
-    }
-
-    public String getTaskName() 
-    {
-        return taskName;
-    }
-    public void setAlgorithmId(Long algorithmId) 
-    {
-        this.algorithmId = algorithmId;
-    }
-
-    public Long getAlgorithmId() 
-    {
-        return algorithmId;
-    }
-    public void setInputPath(String inputPath) 
-    {
-        this.inputPath = inputPath;
-    }
-
-    public String getInputPath() 
-    {
-        return inputPath;
-    }
-    public void setOutputPath(String outputPath) 
-    {
-        this.outputPath = outputPath;
-    }
-
-    public String getOutputPath() 
-    {
-        return outputPath;
-    }
-    public void setAlgorithmParams(String algorithmParams) 
-    {
-        this.algorithmParams = algorithmParams;
-    }
-
-    public String getAlgorithmParams() 
-    {
-        return algorithmParams;
-    }
-    public void setStatus(String status) 
-    {
-        this.status = status;
-    }
-
-    public String getStatus() 
-    {
-        return status;
-    }
-    public void setStartTime(Date startTime) 
-    {
-        this.startTime = startTime;
-    }
-
-    public Date getStartTime() 
-    {
-        return startTime;
-    }
-    public void setEndTime(Date endTime) 
-    {
-        this.endTime = endTime;
-    }
+    private String algorithmName;
 
-    public Date getEndTime() 
-    {
-        return endTime;
-    }
+    private List<ParentFolderInfoDTO> parentFolderInfoDTOList;
 
-    @Override
-    public String toString() {
-        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
-            .append("id", getId())
-            .append("taskName", getTaskName())
-            .append("algorithmId", getAlgorithmId())
-            .append("inputPath", getInputPath())
-            .append("outputPath", getOutputPath())
-            .append("algorithmParams", getAlgorithmParams())
-            .append("status", getStatus())
-            .append("startTime", getStartTime())
-            .append("endTime", getEndTime())
-            .append("remark", getRemark())
-            .append("createBy", getCreateBy())
-            .append("createTime", getCreateTime())
-            .append("updateBy", getUpdateBy())
-            .append("updateTime", getUpdateTime())
-            .toString();
-    }
 }

+ 6 - 4
ips-admin/src/main/java/com/ips/system/domain/Preprocessed.java

@@ -45,15 +45,17 @@ public class Preprocessed extends BaseEntity
     private String status;
 
     /** 开始时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date startTime;
 
     /** 结束时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date endTime;
 
     private List<FileInfoDTO> folderInfoDTO;
 
+    private String algorithmName;
+
 }

+ 6 - 0
ips-admin/src/main/java/com/ips/system/service/IBizTrainingService.java

@@ -1,6 +1,8 @@
 package com.ips.system.service;
 
 import java.util.List;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.ips.system.domain.BizTraining;
 
 /**
@@ -58,4 +60,8 @@ public interface IBizTrainingService
      * @return 结果
      */
     public int deleteBizTrainingById(Long id);
+
+    String run(Long id) throws JsonProcessingException;
+
+    BizTraining getResultDetails(Long id);
 }

+ 6 - 0
ips-admin/src/main/java/com/ips/system/service/IClassifyTestService.java

@@ -1,6 +1,8 @@
 package com.ips.system.service;
 
 import java.util.List;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.ips.system.domain.ClassifyTest;
 
 /**
@@ -58,4 +60,8 @@ public interface IClassifyTestService
      * @return 结果
      */
     public int deleteClassifyTestById(Long id);
+
+    ClassifyTest getResultDetails(Long id);
+
+    String run(Long id) throws JsonProcessingException;
 }

+ 6 - 0
ips-admin/src/main/java/com/ips/system/service/IDistillationService.java

@@ -1,6 +1,8 @@
 package com.ips.system.service;
 
 import java.util.List;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.ips.system.domain.Distillation;
 
 /**
@@ -58,4 +60,8 @@ public interface IDistillationService
      * @return 结果
      */
     public int deleteDistillationById(Long id);
+
+    String run(Long id) throws JsonProcessingException;
+
+    Distillation getResultDetails(Long id);
 }

+ 6 - 0
ips-admin/src/main/java/com/ips/system/service/IExtractedFeaturesService.java

@@ -1,6 +1,8 @@
 package com.ips.system.service;
 
 import java.util.List;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.ips.system.domain.ExtractedFeatures;
 
 /**
@@ -58,4 +60,8 @@ public interface IExtractedFeaturesService
      * @return 结果
      */
     public int deleteExtractedFeaturesById(Long id);
+
+    String run(Long id) throws JsonProcessingException;
+
+    ExtractedFeatures getResultDetails(Long id);
 }

+ 106 - 21
ips-admin/src/main/java/com/ips/system/service/impl/BizTrainingServiceImpl.java

@@ -1,7 +1,23 @@
 package com.ips.system.service.impl;
 
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ips.common.utils.DateUtils;
+import com.ips.common.utils.StringUtils;
+import com.ips.system.domain.AlgorithmConfig;
+import com.ips.system.domain.Distillation;
+import com.ips.system.dto.AlgorithmParamsDto;
+import com.ips.system.service.IAlgorithmConfigService;
+import com.ips.system.utils.AlgorithmCaller;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ips.system.mapper.BizTrainingMapper;
@@ -10,87 +26,156 @@ import com.ips.system.service.IBizTrainingService;
 
 /**
  * 模型训练Service业务层处理
- * 
+ *
  * @author Allen
  * @date 2025-05-21
  */
 @Service
-public class BizTrainingServiceImpl implements IBizTrainingService 
-{
+public class BizTrainingServiceImpl implements IBizTrainingService {
+
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
     @Autowired
     private BizTrainingMapper bizTrainingMapper;
 
+    @Autowired
+    private IAlgorithmConfigService algorithmConfigService;
+
     /**
      * 查询模型训练
-     * 
+     *
      * @param id 模型训练主键
      * @return 模型训练
      */
     @Override
-    public BizTraining selectBizTrainingById(Long id)
-    {
+    public BizTraining selectBizTrainingById(Long id) {
         return bizTrainingMapper.selectBizTrainingById(id);
     }
 
     /**
      * 查询模型训练列表
-     * 
+     *
      * @param bizTraining 模型训练
      * @return 模型训练
      */
     @Override
-    public List<BizTraining> selectBizTrainingList(BizTraining bizTraining)
-    {
+    public List<BizTraining> selectBizTrainingList(BizTraining bizTraining) {
         return bizTrainingMapper.selectBizTrainingList(bizTraining);
     }
 
     /**
      * 新增模型训练
-     * 
+     *
      * @param bizTraining 模型训练
      * @return 结果
      */
     @Override
-    public int insertBizTraining(BizTraining bizTraining)
-    {
+    public int insertBizTraining(BizTraining bizTraining) {
         bizTraining.setCreateTime(DateUtils.getNowDate());
         return bizTrainingMapper.insertBizTraining(bizTraining);
     }
 
     /**
      * 修改模型训练
-     * 
+     *
      * @param bizTraining 模型训练
      * @return 结果
      */
     @Override
-    public int updateBizTraining(BizTraining bizTraining)
-    {
+    public int updateBizTraining(BizTraining bizTraining) {
         bizTraining.setUpdateTime(DateUtils.getNowDate());
         return bizTrainingMapper.updateBizTraining(bizTraining);
     }
 
     /**
      * 批量删除模型训练
-     * 
+     *
      * @param ids 需要删除的模型训练主键
      * @return 结果
      */
     @Override
-    public int deleteBizTrainingByIds(Long[] ids)
-    {
+    public int deleteBizTrainingByIds(Long[] ids) {
         return bizTrainingMapper.deleteBizTrainingByIds(ids);
     }
 
     /**
      * 删除模型训练信息
-     * 
+     *
      * @param id 模型训练主键
      * @return 结果
      */
     @Override
-    public int deleteBizTrainingById(Long id)
-    {
+    public int deleteBizTrainingById(Long id) {
         return bizTrainingMapper.deleteBizTrainingById(id);
     }
+
+    @Override
+    public String run(Long id) throws JsonProcessingException {
+        BizTraining training = bizTrainingMapper.selectBizTrainingById(id);
+        if (training == null || training.getAlgorithmId() == null) {
+            return "无法找到该任务,id:" + id;
+        }
+        Long algorithmId = training.getAlgorithmId();
+        AlgorithmConfig algorithmConfig = algorithmConfigService.selectAlgorithmConfigById(algorithmId);
+        training.setStartTime(new Date());
+        training.setStatus("1");
+        this.updateBizTraining(training);
+        CompletableFuture.runAsync(() -> {
+            // 异步逻辑
+            doRun(algorithmConfig, training);
+        });
+        return null;
+    }
+
+    private void doRun(AlgorithmConfig algorithmConfig, BizTraining training) {
+        String algorithmPath = algorithmConfig.getAlgorithmPath();
+
+        // 组装json
+        String inputPath = training.getInputPath();
+        String outputPath = training.getOutputPath();
+        ObjectMapper objectMapper = new ObjectMapper();
+        Map<String, Object> params = new HashMap<>(0);
+
+        String errorMsg = "";
+        try {
+            if (StringUtils.isNotEmpty(training.getAlgorithmParams())) {
+
+                objectMapper.readValue(
+                        training.getAlgorithmParams(),
+                        new TypeReference<Map<String, Object>>() {
+                        }
+                );
+            }
+            AlgorithmParamsDto algorithmParamsDto = new AlgorithmParamsDto(inputPath, outputPath, params);
+            // 对象 → JSON 字符串
+            String json = objectMapper.writeValueAsString(algorithmParamsDto);
+            // 处理算法
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
+        } catch (JsonProcessingException e) {
+            logger.error("格式化失败", e);
+            errorMsg = "格式化失败";
+        }
+        //处理结果
+        if (StringUtils.isEmpty(errorMsg)) {
+            training.setStatus("2");
+        } else {
+            training.setStatus("3");
+        }
+        training.setEndTime(new Date());
+        this.updateBizTraining(training);
+    }
+
+    @Override
+    public BizTraining getResultDetails(Long id) {
+        BizTraining bizTraining = this.selectBizTrainingById(id);
+        String inputPath = bizTraining.getInputPath();
+//        try {
+//            List<FileInfoDTO> fileInfoDTOList = CommonUtils.getSortedFiles(inputPath, "dat");
+//            extractedFeatures.setFolderInfoDTO(fileInfoDTOList);
+//        } catch (IOException e) {
+//            logger.error("读取文件夹错误", e);
+//            return null;
+//        }
+        return bizTraining;
+    }
 }

+ 92 - 0
ips-admin/src/main/java/com/ips/system/service/impl/ClassifyTestServiceImpl.java

@@ -1,7 +1,24 @@
 package com.ips.system.service.impl;
 
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ips.common.utils.DateUtils;
+import com.ips.common.utils.StringUtils;
+import com.ips.system.domain.AlgorithmConfig;
+import com.ips.system.domain.BizTraining;
+import com.ips.system.domain.Distillation;
+import com.ips.system.dto.AlgorithmParamsDto;
+import com.ips.system.service.IAlgorithmConfigService;
+import com.ips.system.utils.AlgorithmCaller;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ips.system.mapper.ClassifyTestMapper;
@@ -17,9 +34,14 @@ import com.ips.system.service.IClassifyTestService;
 @Service
 public class ClassifyTestServiceImpl implements IClassifyTestService 
 {
+
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
     @Autowired
     private ClassifyTestMapper classifyTestMapper;
 
+    @Autowired
+    private IAlgorithmConfigService algorithmConfigService;
+
     /**
      * 查询分类测试
      * 
@@ -93,4 +115,74 @@ public class ClassifyTestServiceImpl implements IClassifyTestService
     {
         return classifyTestMapper.deleteClassifyTestById(id);
     }
+
+    @Override
+    public String run(Long id) throws JsonProcessingException {
+        ClassifyTest classifyTest = classifyTestMapper.selectClassifyTestById(id);
+        if(classifyTest == null || classifyTest.getAlgorithmId() == null){
+            return "无法找到该任务,id:"+id;
+        }
+        Long algorithmId = classifyTest.getAlgorithmId();
+        AlgorithmConfig algorithmConfig = algorithmConfigService.selectAlgorithmConfigById(algorithmId);
+        classifyTest.setStartTime(new Date());
+        classifyTest.setStatus("1");
+        this.updateClassifyTest(classifyTest);
+        CompletableFuture.runAsync(() -> {
+            // 异步逻辑
+            doRun(algorithmConfig, classifyTest);
+        });
+        return null;
+    }
+
+    private void doRun(AlgorithmConfig algorithmConfig, ClassifyTest classifyTest) {
+        String algorithmPath = algorithmConfig.getAlgorithmPath();
+
+        // 组装json
+        String inputPath = classifyTest.getInputPath();
+        String outputPath = classifyTest.getOutputPath();
+        ObjectMapper objectMapper = new ObjectMapper();
+        Map<String, Object> params = new HashMap<>(0);
+
+        String errorMsg = "";
+        try {
+            if (StringUtils.isNotEmpty(classifyTest.getAlgorithmParams())) {
+
+                objectMapper.readValue(
+                        classifyTest.getAlgorithmParams(),
+                        new TypeReference<Map<String, Object>>() {
+                        }
+                );
+            }
+            AlgorithmParamsDto algorithmParamsDto = new AlgorithmParamsDto(inputPath, outputPath, params);
+            // 对象 → JSON 字符串
+            String json = objectMapper.writeValueAsString(algorithmParamsDto);
+            // 处理算法
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
+        } catch (JsonProcessingException e) {
+            logger.error("格式化失败", e);
+            errorMsg = "格式化失败";
+        }
+        //处理结果
+        if (StringUtils.isEmpty(errorMsg)) {
+            classifyTest.setStatus("2");
+        } else {
+            classifyTest.setStatus("3");
+        }
+        classifyTest.setEndTime(new Date());
+        this.updateClassifyTest(classifyTest);
+    }
+
+    @Override
+    public ClassifyTest getResultDetails(Long id) {
+        ClassifyTest classifyTest = this.selectClassifyTestById(id);
+        String inputPath = classifyTest.getInputPath();
+//        try {
+//            List<FileInfoDTO> fileInfoDTOList = CommonUtils.getSortedFiles(inputPath, "dat");
+//            extractedFeatures.setFolderInfoDTO(fileInfoDTOList);
+//        } catch (IOException e) {
+//            logger.error("读取文件夹错误", e);
+//            return null;
+//        }
+        return classifyTest;
+    }
 }

+ 95 - 4
ips-admin/src/main/java/com/ips/system/service/impl/DistillationServiceImpl.java

@@ -1,12 +1,28 @@
 package com.ips.system.service.impl;
 
-import java.util.List;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ips.common.utils.DateUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import com.ips.system.mapper.DistillationMapper;
+import com.ips.common.utils.StringUtils;
+import com.ips.system.domain.AlgorithmConfig;
+import com.ips.system.domain.ClassifyTest;
 import com.ips.system.domain.Distillation;
+import com.ips.system.dto.AlgorithmParamsDto;
+import com.ips.system.mapper.DistillationMapper;
+import com.ips.system.service.IAlgorithmConfigService;
 import com.ips.system.service.IDistillationService;
+import com.ips.system.utils.AlgorithmCaller;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
 
 /**
  * 知识蒸馏Service业务层处理
@@ -17,9 +33,13 @@ import com.ips.system.service.IDistillationService;
 @Service
 public class DistillationServiceImpl implements IDistillationService 
 {
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
     @Autowired
     private DistillationMapper distillationMapper;
 
+    @Autowired
+    private IAlgorithmConfigService algorithmConfigService;
     /**
      * 查询知识蒸馏
      * 
@@ -93,4 +113,75 @@ public class DistillationServiceImpl implements IDistillationService
     {
         return distillationMapper.deleteDistillationById(id);
     }
+
+    @Override
+    public String run(Long id) throws JsonProcessingException {
+        Distillation distillation = distillationMapper.selectDistillationById(id);
+        if(distillation == null || distillation.getAlgorithmId() == null){
+            return "无法找到该任务,id:"+id;
+        }
+        Long algorithmId = distillation.getAlgorithmId();
+        AlgorithmConfig algorithmConfig = algorithmConfigService.selectAlgorithmConfigById(algorithmId);
+        distillation.setStartTime(new Date());
+        distillation.setStatus("1");
+        this.updateDistillation(distillation);
+
+        CompletableFuture.runAsync(() -> {
+            // 异步逻辑
+            doRun(algorithmConfig, distillation);
+        });
+        return null;
+    }
+
+    private void doRun(AlgorithmConfig algorithmConfig, Distillation distillation) {
+        String algorithmPath = algorithmConfig.getAlgorithmPath();
+
+        // 组装json
+        String inputPath = distillation.getInputPath();
+        String outputPath = distillation.getOutputPath();
+        ObjectMapper objectMapper = new ObjectMapper();
+        Map<String, Object> params = new HashMap<>(0);
+
+        String errorMsg = "";
+        try {
+            if (StringUtils.isNotEmpty(distillation.getAlgorithmParams())) {
+
+                objectMapper.readValue(
+                        distillation.getAlgorithmParams(),
+                        new TypeReference<Map<String, Object>>() {
+                        }
+                );
+            }
+            AlgorithmParamsDto algorithmParamsDto = new AlgorithmParamsDto(inputPath, outputPath, params);
+            // 对象 → JSON 字符串
+            String json = objectMapper.writeValueAsString(algorithmParamsDto);
+            // 处理算法
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
+        } catch (JsonProcessingException e) {
+            logger.error("格式化失败", e);
+            errorMsg = "格式化失败";
+        }
+        //处理结果
+        if (StringUtils.isEmpty(errorMsg)) {
+            distillation.setStatus("2");
+        } else {
+            distillation.setStatus("3");
+        }
+        distillation.setEndTime(new Date());
+        this.updateDistillation(distillation);
+    }
+
+    @Override
+    public Distillation getResultDetails(Long id) {
+        Distillation distillation = this.selectDistillationById(id);
+        String inputPath = distillation.getInputPath();
+//        try {
+//            List<FileInfoDTO> fileInfoDTOList = CommonUtils.getSortedFiles(inputPath, "dat");
+//            extractedFeatures.setFolderInfoDTO(fileInfoDTOList);
+//        } catch (IOException e) {
+//            logger.error("读取文件夹错误", e);
+//            return null;
+//        }
+        return distillation;
+    }
 }

+ 91 - 1
ips-admin/src/main/java/com/ips/system/service/impl/ExtractedFeaturesServiceImpl.java

@@ -1,7 +1,25 @@
 package com.ips.system.service.impl;
 
-import java.util.List;
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ips.common.utils.DateUtils;
+import com.ips.common.utils.StringUtils;
+import com.ips.system.domain.AlgorithmConfig;
+import com.ips.system.domain.Distillation;
+import com.ips.system.domain.Preprocessed;
+import com.ips.system.dto.AlgorithmParamsDto;
+import com.ips.system.dto.FileInfoDTO;
+import com.ips.system.dto.ParentFolderInfoDTO;
+import com.ips.system.service.IAlgorithmConfigService;
+import com.ips.system.utils.AlgorithmCaller;
+import com.ips.system.utils.CommonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ips.system.mapper.ExtractedFeaturesMapper;
@@ -17,9 +35,14 @@ import com.ips.system.service.IExtractedFeaturesService;
 @Service
 public class ExtractedFeaturesServiceImpl implements IExtractedFeaturesService 
 {
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
     @Autowired
     private ExtractedFeaturesMapper extractedFeaturesMapper;
 
+    @Autowired
+    private IAlgorithmConfigService algorithmConfigService;
+
     /**
      * 查询特征提取
      * 
@@ -93,4 +116,71 @@ public class ExtractedFeaturesServiceImpl implements IExtractedFeaturesService
     {
         return extractedFeaturesMapper.deleteExtractedFeaturesById(id);
     }
+
+    @Override
+    public String run(Long id) throws JsonProcessingException {
+        ExtractedFeatures extractedFeatures = extractedFeaturesMapper.selectExtractedFeaturesById(id);
+        if(extractedFeatures == null || extractedFeatures.getAlgorithmId() == null){
+            return "无法找到该任务,id:"+id;
+        }
+        Long algorithmId = extractedFeatures.getAlgorithmId();
+        AlgorithmConfig algorithmConfig = algorithmConfigService.selectAlgorithmConfigById(algorithmId);
+        extractedFeatures.setStartTime(new Date());
+        extractedFeatures.setStatus("1");
+        this.updateExtractedFeatures(extractedFeatures);
+
+        CompletableFuture.runAsync(() -> {
+            // 异步逻辑
+            doRun(algorithmConfig, extractedFeatures);
+        });
+        return null;
+    }
+
+    private void doRun(AlgorithmConfig algorithmConfig, ExtractedFeatures extractedFeatures) {
+        String algorithmPath = algorithmConfig.getAlgorithmPath();
+
+        // 组装json
+        String inputPath = extractedFeatures.getInputPath();
+        String outputPath = extractedFeatures.getOutputPath();
+        ObjectMapper objectMapper = new ObjectMapper();
+        Map<String, Object> params = new HashMap<>(0);
+
+        String errorMsg = "";
+        try {
+            if (StringUtils.isNotEmpty(extractedFeatures.getAlgorithmParams())) {
+
+                objectMapper.readValue(
+                        extractedFeatures.getAlgorithmParams(),
+                        new TypeReference<Map<String, Object>>() {
+                        }
+                );
+            }
+            AlgorithmParamsDto algorithmParamsDto = new AlgorithmParamsDto(inputPath, outputPath, params);
+            // 对象 → JSON 字符串
+            String json = objectMapper.writeValueAsString(algorithmParamsDto);
+            // 处理算法
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
+        } catch (JsonProcessingException e) {
+            logger.error("格式化失败", e);
+            errorMsg = "格式化失败";
+        }
+        //处理结果
+        if (StringUtils.isEmpty(errorMsg)) {
+            extractedFeatures.setStatus("2");
+        } else {
+            extractedFeatures.setStatus("3");
+        }
+        extractedFeatures.setEndTime(new Date());
+        this.updateExtractedFeatures(extractedFeatures);
+    }
+
+
+    @Override
+    public ExtractedFeatures getResultDetails(Long id) {
+        ExtractedFeatures extractedFeatures = this.selectExtractedFeaturesById(id);
+        String inputPath = extractedFeatures.getInputPath();
+        List<ParentFolderInfoDTO> parentFolderInfoDTOList = CommonUtils.getFolderStructureWithFilter(inputPath, Arrays.asList("dat"));
+        extractedFeatures.setParentFolderInfoDTOList(parentFolderInfoDTOList);
+        return extractedFeatures;
+    }
 }

+ 32 - 17
ips-admin/src/main/java/com/ips/system/service/impl/PreprocessedServiceImpl.java

@@ -2,6 +2,7 @@ package com.ips.system.service.impl;
 
 import java.io.IOException;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
@@ -9,6 +10,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ips.common.utils.DateUtils;
 import com.ips.common.utils.StringUtils;
 import com.ips.system.domain.AlgorithmConfig;
+import com.ips.system.domain.ExtractedFeatures;
 import com.ips.system.dto.AlgorithmParamsDto;
 import com.ips.system.dto.FileInfoDTO;
 import com.ips.system.dto.FolderInfoDTO;
@@ -119,8 +121,6 @@ public class PreprocessedServiceImpl implements IPreprocessedService
     }
 
     @Override
-    @Async
-    @Transactional
     public String run(Long id) throws JsonProcessingException {
         Preprocessed preprocessed = preprocessedMapper.selectPreprocessedById(id);
         if(preprocessed == null || preprocessed.getAlgorithmId() == null){
@@ -132,34 +132,49 @@ public class PreprocessedServiceImpl implements IPreprocessedService
         preprocessed.setStatus("1");
         this.updatePreprocessed(preprocessed);
 
+        CompletableFuture.runAsync(() -> {
+            // 异步逻辑
+            doRun(algorithmConfig, preprocessed);
+        });
+        return null;
+    }
+
+    private void doRun(AlgorithmConfig algorithmConfig, Preprocessed preprocessed) {
         String algorithmPath = algorithmConfig.getAlgorithmPath();
 
         // 组装json
         String inputPath = preprocessed.getInputPath();
         String outputPath = preprocessed.getOutputPath();
         ObjectMapper objectMapper = new ObjectMapper();
-        Map<String, Object> params = objectMapper.readValue(
-                preprocessed.getAlgorithmParams(),
-                new TypeReference<Map<String, Object>>() {}
-        );
-        AlgorithmParamsDto algorithmParamsDto = new AlgorithmParamsDto(inputPath,outputPath,params);
-
-        // 创建 ObjectMapper(Jackson 核心类)
-
-        // 对象 → JSON 字符串
-        String json = objectMapper.writeValueAsString(algorithmParamsDto);
-        // 处理算法
-        String errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
-        //处理结果
+        Map<String, Object> params = new HashMap<>(0);
 
-        if(StringUtils.isEmpty(errorMsg)){
+        String errorMsg = "";
+        try {
+            if (StringUtils.isNotEmpty(preprocessed.getAlgorithmParams())) {
+
+                objectMapper.readValue(
+                        preprocessed.getAlgorithmParams(),
+                        new TypeReference<Map<String, Object>>() {
+                        }
+                );
+            }
+            AlgorithmParamsDto algorithmParamsDto = new AlgorithmParamsDto(inputPath, outputPath, params);
+            // 对象 → JSON 字符串
+            String json = objectMapper.writeValueAsString(algorithmParamsDto);
+            // 处理算法
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
+        } catch (JsonProcessingException e) {
+            logger.error("格式化失败", e);
+            errorMsg = "格式化失败";
+        }
+        //处理结果
+        if (StringUtils.isEmpty(errorMsg)) {
             preprocessed.setStatus("2");
         } else {
             preprocessed.setStatus("3");
         }
         preprocessed.setEndTime(new Date());
         this.updatePreprocessed(preprocessed);
-        return errorMsg;
     }
 
     @Override

+ 13 - 11
ips-admin/src/main/java/com/ips/system/utils/AlgorithmCaller.java

@@ -4,11 +4,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
@@ -37,8 +35,9 @@ public class AlgorithmCaller {
         }
     }
 
+
     /**
-     * 根据json字符串生成input.json文件到指定目录
+     * 根据json字符串生成input.json文件到指定目录(解决中文乱码问题)
      * @param directory 目标目录
      * @param jsonContent JSON内容字符串
      * @return 生成的JSON文件路径
@@ -61,15 +60,15 @@ public class AlgorithmCaller {
             }
         }
 
-        // 创建input.json文件
+        // 创建input.json文件(使用UTF-8编码写入)
         File jsonFile = new File(directory, "input.json");
-        try (FileWriter writer = new FileWriter(jsonFile)) {
+        try (OutputStreamWriter writer = new OutputStreamWriter(
+                Files.newOutputStream(jsonFile.toPath()), StandardCharsets.UTF_8)) {
             writer.write(jsonContent);
         }
 
         return jsonFile.getAbsolutePath();
     }
-
     /**
      * 调用Python代码
      * @param pythonScriptPath Python脚本路径
@@ -153,6 +152,8 @@ public class AlgorithmCaller {
      * @return 执行结果
      */
     public static String executeAlgorithm(String programPath, String jsonContent) {
+        logger.info("调用算法开始,programPath:{},jsonContent:{}", programPath, jsonContent);
+        String errorMsg = "";
         try {
             // 1. 获取工作目录
             String workingDirectory = getAlgorithmRootPath(programPath);
@@ -169,9 +170,10 @@ public class AlgorithmCaller {
                 throw new IllegalArgumentException("Unsupported program type: " + programPath);
             }
         } catch (Exception e) {
-            String errorMsg = String.format("Algorithm execution failed: %s", e.getMessage());
+            errorMsg = String.format("Algorithm execution failed: %s", e.getMessage());
             logger.error(errorMsg, e);
-            return errorMsg;
         }
+        logger.info("调用算法结束");
+        return errorMsg;
     }
 }

+ 132 - 34
ips-admin/src/main/java/com/ips/system/utils/CommonUtils.java

@@ -2,13 +2,14 @@ package com.ips.system.utils;
 
 import com.ips.system.dto.FileInfoDTO;
 import com.ips.system.dto.FolderInfoDTO;
+import com.ips.system.dto.ParentFolderInfoDTO;
 
+import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.Comparator;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -61,6 +62,7 @@ public class CommonUtils {
 
     /**
      * 获取文件夹下所有文件(fileName不含后缀),并按文件名(不含后缀)排序
+     *
      * @param folderPath 文件夹路径
      * @return 排序后的文件列表
      * @throws IOException 如果读取文件出错
@@ -96,8 +98,9 @@ public class CommonUtils {
 
     /**
      * 获取文件夹下指定扩展名的文件(fileName不含后缀),并按文件名(不含后缀)排序
+     *
      * @param folderPath 文件夹路径
-     * @param extension 文件扩展名(可带点或不带点),null表示获取所有文件,""表示无后缀文件
+     * @param extension  文件扩展名(可带点或不带点),null表示获取所有文件,""表示无后缀文件
      * @return 排序后的文件列表
      * @throws IOException 如果读取文件出错
      */
@@ -160,36 +163,131 @@ public class CommonUtils {
         return (dotIndex == -1) ? "" : filename.substring(dotIndex + 1);
     }
 
-    // 测试方法
-    public static void main(String[] args) {
-        try {
-            String folderPath = "D:\\ips\\algrothm\\preprocess\\test\\test1";
-
-            // 1. 获取所有文件(fileName不含后缀)
-            System.out.println("所有文件(fileName不含后缀):");
-            List<FileInfoDTO> allFiles = getAllSortedFiles(folderPath);
-            allFiles.forEach(file -> System.out.printf("%-30s %-15s %10d bytes %s%n",
-                    file.getFileName(),
-                    "(" + file.getFullName() + ")",
-                    file.getFileSize(),
-                    file.getExtension().isEmpty() ? "[无后缀]" : "扩展名: " + file.getExtension()));
-
-            // 2. 获取PDF文件(fileName不含后缀)
-            System.out.println("\nPDF文件(fileName不含后缀):");
-            List<FileInfoDTO> pdfFiles = getSortedFiles(folderPath, "dat");
-            pdfFiles.forEach(file -> System.out.printf("%-30s %-15s %10d bytes %s%n",
-                    file.getFileName(),
-                    "(" + file.getFullName() + ")",
-                    file.getFileSize(),
-                    file.getExtension().isEmpty() ? "[无后缀]" : "扩展名: " + file.getExtension()));
-            // 3. 获取无后缀文件
-            System.out.println("\n无后缀文件:");
-            List<FileInfoDTO> noExtensionFiles = getSortedFiles(folderPath, "");
-            noExtensionFiles.forEach(file -> System.out.printf("%-30s %10d bytes%n",
-                    file.getFileName(), file.getFileSize()));
-
-        } catch (IOException e) {
-            System.err.println("处理文件时出错: " + e.getMessage());
+//    // 测试方法
+//    public static void main(String[] args) {
+//        try {
+//            String folderPath = "D:\\ips\\algrothm\\preprocess\\test\\test1";
+//
+//            // 1. 获取所有文件(fileName不含后缀)
+//            System.out.println("所有文件(fileName不含后缀):");
+//            List<FileInfoDTO> allFiles = getAllSortedFiles(folderPath);
+//            allFiles.forEach(file -> System.out.printf("%-30s %-15s %10d bytes %s%n",
+//                    file.getFileName(),
+//                    "(" + file.getFullName() + ")",
+//                    file.getFileSize(),
+//                    file.getExtension().isEmpty() ? "[无后缀]" : "扩展名: " + file.getExtension()));
+//
+//            // 2. 获取PDF文件(fileName不含后缀)
+//            System.out.println("\nPDF文件(fileName不含后缀):");
+//            List<FileInfoDTO> pdfFiles = getSortedFiles(folderPath, "dat");
+//            pdfFiles.forEach(file -> System.out.printf("%-30s %-15s %10d bytes %s%n",
+//                    file.getFileName(),
+//                    "(" + file.getFullName() + ")",
+//                    file.getFileSize(),
+//                    file.getExtension().isEmpty() ? "[无后缀]" : "扩展名: " + file.getExtension()));
+//            // 3. 获取无后缀文件
+//            System.out.println("\n无后缀文件:");
+//            List<FileInfoDTO> noExtensionFiles = getSortedFiles(folderPath, "");
+//            noExtensionFiles.forEach(file -> System.out.printf("%-30s %10d bytes%n",
+//                    file.getFileName(), file.getFileSize()));
+//
+//        } catch (IOException e) {
+//            System.err.println("处理文件时出错: " + e.getMessage());
+//        }
+//    }
+
+    /**
+     * 获取指定路径下所有子文件夹的结构信息
+     * @param rootPath 根目录路径
+     * @param targetExtensions 目标文件后缀列表(不带点)
+     * @return 子文件夹的ParentFolderInfoDTO列表
+     */
+    public static List<ParentFolderInfoDTO> getFolderStructureWithFilter(String rootPath, List<String> targetExtensions) {
+        File rootDir = new File(rootPath);
+        if (!rootDir.exists() || !rootDir.isDirectory()) {
+            throw new IllegalArgumentException("Invalid root directory path: " + rootPath);
         }
+
+        List<ParentFolderInfoDTO> result = new ArrayList<>();
+
+        // 获取所有子文件夹(第一级)
+        File[] subFolders = rootDir.listFiles(File::isDirectory);
+        if (subFolders != null) {
+            Arrays.stream(subFolders).forEach(subFolder -> {
+                // 每个子文件夹作为一个ParentFolderInfoDTO
+                ParentFolderInfoDTO parentFolder = new ParentFolderInfoDTO(subFolder.getName());
+
+                // 获取子文件夹下的孙子文件夹(第二级)
+                File[] grandchildFolders = subFolder.listFiles(File::isDirectory);
+                if (grandchildFolders != null) {
+                    Arrays.stream(grandchildFolders).forEach(grandchildFolder -> {
+                        // 每个孙子文件夹作为一个FolderInfoDTO
+                        FolderInfoDTO grandchildFolderInfo = new FolderInfoDTO(grandchildFolder.getName());
+
+                        // 获取孙子文件夹中符合后缀条件的文件
+                        List<FileInfoDTO> filteredFiles = getFilesWithExtensions(grandchildFolder, targetExtensions);
+                        grandchildFolderInfo.getFiles().addAll(filteredFiles);
+
+                        // 将孙子文件夹添加到子文件夹的files列表中
+                        parentFolder.getFiles().add(grandchildFolderInfo);
+                    });
+                }
+
+                result.add(parentFolder);
+            });
+        }
+
+        return result;
     }
-}
+
+    /**
+     * 获取指定文件夹中符合后缀条件的文件
+     * @param folder 文件夹
+     * @param extensions 目标文件后缀列表(不带点)
+     * @return 符合条件的文件列表
+     */
+    private static List<FileInfoDTO> getFilesWithExtensions(File folder, List<String> extensions) {
+        File[] files = folder.listFiles(file -> {
+            if (file.isFile()) {
+                String fileName = file.getName();
+                int dotIndex = fileName.lastIndexOf('.');
+                if (dotIndex > 0) {
+                    String extension = fileName.substring(dotIndex + 1).toLowerCase();
+                    return extensions.isEmpty() || extensions.contains(extension);
+                }
+            }
+            return false;
+        });
+
+        if (files == null) {
+            return Collections.emptyList();
+        }
+
+        return Arrays.stream(files)
+                .map(file -> {
+                    String fileName = file.getName();
+                    int dotIndex = fileName.lastIndexOf('.');
+                    String nameWithoutExtension = dotIndex > 0 ? fileName.substring(0, dotIndex) : fileName;
+                    String extension = dotIndex > 0 ? fileName.substring(dotIndex + 1) : "";
+
+                    try {
+                        long fileSize = Files.size(file.toPath());
+                        return new FileInfoDTO(
+                                nameWithoutExtension,
+                                fileName,
+                                file.getAbsolutePath(),
+                                fileSize,
+                                extension
+                        );
+                    } catch (IOException e) {
+                        throw new RuntimeException("Failed to get file size for: " + file.getAbsolutePath(), e);
+                    }
+                })
+                .collect(Collectors.toList());
+    }
+
+//    public static void main(String[] args) {
+//        List<ParentFolderInfoDTO> jpg = getFolderStructureWithFilter("D:\\验收材料\\西工大\\输入输出样例0524\\3特征提取\\频域特征\\输入\\数据集", Arrays.asList("jpg"));
+//        System.out.println(jpg);
+//    }
+}

+ 28 - 8
ips-admin/src/main/resources/mapper/biz/BizTrainingMapper.xml

@@ -19,27 +19,47 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="createTime"    column="create_time"    />
         <result property="updateBy"    column="update_by"    />
         <result property="updateTime"    column="update_time"    />
+        <result property="algorithmName"    column="algorithm_name"    />
     </resultMap>
 
     <sql id="selectBizTrainingVo">
-        select id, task_name, algorithm_id, input_path, output_path, algorithm_params, status, start_time, end_time, remark, create_by, create_time, update_by, update_time from biz_training
+        SELECT
+            bt.id,
+            bt.task_name,
+            bt.algorithm_id,
+            bt.input_path,
+            bt.output_path,
+            bt.algorithm_params,
+            bt.`status`,
+            bt.start_time,
+            bt.end_time,
+            bt.remark,
+            bt.create_by,
+            bt.create_time,
+            bt.update_by,
+            bt.update_time,
+            bac.algorithm_name
+        FROM
+            biz_training bt
+        LEFT JOIN biz_algorithm_config bac ON bac.id = bt.algorithm_id
     </sql>
 
     <select id="selectBizTrainingList" parameterType="BizTraining" resultMap="BizTrainingResult">
         <include refid="selectBizTrainingVo"/>
         <where>  
-            <if test="taskName != null  and taskName != ''"> and task_name like concat('%', #{taskName}, '%')</if>
-            <if test="algorithmId != null "> and algorithm_id = #{algorithmId}</if>
-            <if test="status != null  and status != ''"> and status = #{status}</if>
-            <if test="startTime != null "> and start_time = #{startTime}</if>
-            <if test="endTime != null "> and end_time = #{endTime}</if>
-            <if test="remark != null  and remark != ''"> and remark = #{remark}</if>
+            <if test="taskName != null  and taskName != ''"> and bt.task_name like concat('%', #{taskName}, '%')</if>
+            <if test="algorithmId != null "> and bt.algorithm_id = #{algorithmId}</if>
+            <if test="status != null  and status != ''"> and bt.status = #{status}</if>
+            <if test="startTime != null "> and bt.start_time = #{startTime}</if>
+            <if test="endTime != null "> and bt.end_time = #{endTime}</if>
+            <if test="remark != null  and remark != ''"> and bt.remark = #{remark}</if>
         </where>
+        order by bt.id desc
     </select>
     
     <select id="selectBizTrainingById" parameterType="Long" resultMap="BizTrainingResult">
         <include refid="selectBizTrainingVo"/>
-        where id = #{id}
+        where bt.id = #{id}
     </select>
 
     <insert id="insertBizTraining" parameterType="BizTraining" useGeneratedKeys="true" keyProperty="id">

+ 28 - 8
ips-admin/src/main/resources/mapper/biz/ClassifyTestMapper.xml

@@ -19,27 +19,47 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="createTime"    column="create_time"    />
         <result property="updateBy"    column="update_by"    />
         <result property="updateTime"    column="update_time"    />
+        <result property="algorithmName"    column="algorithm_name"    />
     </resultMap>
 
     <sql id="selectClassifyTestVo">
-        select id, task_name, algorithm_id, input_path, output_path, algorithm_params, status, start_time, end_time, remark, create_by, create_time, update_by, update_time from biz_classify_test
+        SELECT
+            bct.id,
+            bct.task_name,
+            bct.algorithm_id,
+            bct.input_path,
+            bct.output_path,
+            bct.algorithm_params,
+            bct.STATUS,
+            bct.start_time,
+            bct.end_time,
+            bct.remark,
+            bct.create_by,
+            bct.create_time,
+            bct.update_by,
+            bct.update_time,
+            bac.algorithm_name
+        FROM
+            biz_classify_test bct
+        LEFT JOIN biz_algorithm_config bac ON bac.id = bct.algorithm_id
     </sql>
 
     <select id="selectClassifyTestList" parameterType="ClassifyTest" resultMap="ClassifyTestResult">
         <include refid="selectClassifyTestVo"/>
         <where>  
-            <if test="taskName != null  and taskName != ''"> and task_name like concat('%', #{taskName}, '%')</if>
-            <if test="algorithmId != null "> and algorithm_id = #{algorithmId}</if>
-            <if test="status != null  and status != ''"> and status = #{status}</if>
-            <if test="startTime != null "> and start_time = #{startTime}</if>
-            <if test="endTime != null "> and end_time = #{endTime}</if>
-            <if test="remark != null  and remark != ''"> and remark = #{remark}</if>
+            <if test="taskName != null  and taskName != ''"> and bct.task_name like concat('%', #{taskName}, '%')</if>
+            <if test="algorithmId != null "> and bct.algorithm_id = #{algorithmId}</if>
+            <if test="status != null  and status != ''"> and bct.status = #{status}</if>
+            <if test="startTime != null "> and bct.start_time = #{startTime}</if>
+            <if test="endTime != null "> and bct.end_time = #{endTime}</if>
+            <if test="remark != null  and remark != ''"> and bct.remark = #{remark}</if>
         </where>
+        order by bct.id desc
     </select>
     
     <select id="selectClassifyTestById" parameterType="Long" resultMap="ClassifyTestResult">
         <include refid="selectClassifyTestVo"/>
-        where id = #{id}
+        where bct.id = #{id}
     </select>
 
     <insert id="insertClassifyTest" parameterType="ClassifyTest" useGeneratedKeys="true" keyProperty="id">

+ 28 - 8
ips-admin/src/main/resources/mapper/biz/DistillationMapper.xml

@@ -19,27 +19,47 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="createTime"    column="create_time"    />
         <result property="updateBy"    column="update_by"    />
         <result property="updateTime"    column="update_time"    />
+        <result property="algorithmName"    column="algorithm_name"    />
     </resultMap>
 
     <sql id="selectDistillationVo">
-        select id, task_name, algorithm_id, input_path, output_path, algorithm_params, status, start_time, end_time, remark, create_by, create_time, update_by, update_time from biz_distillation
+        SELECT
+            bd.id,
+            bd.task_name,
+            bd.algorithm_id,
+            bd.input_path,
+            bd.output_path,
+            bd.algorithm_params,
+            bd.STATUS,
+            bd.start_time,
+            bd.end_time,
+            bd.remark,
+            bd.create_by,
+            bd.create_time,
+            bd.update_by,
+            bd.update_time,
+            bac.algorithm_name
+        FROM
+            biz_distillation bd
+        LEFT JOIN biz_algorithm_config bac ON bac.id = bd.algorithm_id
     </sql>
 
     <select id="selectDistillationList" parameterType="Distillation" resultMap="DistillationResult">
         <include refid="selectDistillationVo"/>
         <where>  
-            <if test="taskName != null  and taskName != ''"> and task_name like concat('%', #{taskName}, '%')</if>
-            <if test="algorithmId != null "> and algorithm_id = #{algorithmId}</if>
-            <if test="status != null  and status != ''"> and status = #{status}</if>
-            <if test="startTime != null "> and start_time = #{startTime}</if>
-            <if test="endTime != null "> and end_time = #{endTime}</if>
-            <if test="remark != null  and remark != ''"> and remark like concat('%', #{remark}, '%')</if>
+            <if test="taskName != null  and taskName != ''"> and bd.task_name like concat('%', #{taskName}, '%')</if>
+            <if test="algorithmId != null "> and bd.algorithm_id = #{algorithmId}</if>
+            <if test="status != null  and status != ''"> and bd.status = #{status}</if>
+            <if test="startTime != null "> and bd.start_time = #{startTime}</if>
+            <if test="endTime != null "> and bd.end_time = #{endTime}</if>
+            <if test="remark != null  and remark != ''"> and bd.remark like concat('%', #{remark}, '%')</if>
         </where>
+        order by bd.id desc
     </select>
     
     <select id="selectDistillationById" parameterType="Long" resultMap="DistillationResult">
         <include refid="selectDistillationVo"/>
-        where id = #{id}
+        where bd.id = #{id}
     </select>
 
     <insert id="insertDistillation" parameterType="Distillation" useGeneratedKeys="true" keyProperty="id">

+ 28 - 8
ips-admin/src/main/resources/mapper/biz/ExtractedFeaturesMapper.xml

@@ -19,27 +19,47 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="createTime"    column="create_time"    />
         <result property="updateBy"    column="update_by"    />
         <result property="updateTime"    column="update_time"    />
+        <result property="algorithmName"    column="algorithm_name"    />
     </resultMap>
 
     <sql id="selectExtractedFeaturesVo">
-        select id, task_name, algorithm_id, input_path, output_path, algorithm_params, status, start_time, end_time, remark, create_by, create_time, update_by, update_time from biz_extracted_features
+        SELECT
+            bef.id,
+            bef.task_name,
+            bef.algorithm_id,
+            bef.input_path,
+            bef.output_path,
+            bef.algorithm_params,
+            bef.STATUS,
+            bef.start_time,
+            bef.end_time,
+            bef.remark,
+            bef.create_by,
+            bef.create_time,
+            bef.update_by,
+            bef.update_time,
+            bac.algorithm_name
+        FROM
+            biz_extracted_features bef
+            LEFT JOIN biz_algorithm_config bac ON bac.id = bef.algorithm_id
     </sql>
 
     <select id="selectExtractedFeaturesList" parameterType="ExtractedFeatures" resultMap="ExtractedFeaturesResult">
         <include refid="selectExtractedFeaturesVo"/>
         <where>  
-            <if test="taskName != null  and taskName != ''"> and task_name like concat('%', #{taskName}, '%')</if>
-            <if test="algorithmId != null "> and algorithm_id = #{algorithmId}</if>
-            <if test="status != null  and status != ''"> and status = #{status}</if>
-            <if test="startTime != null "> and start_time = #{startTime}</if>
-            <if test="endTime != null "> and end_time = #{endTime}</if>
-            <if test="remark != null  and remark != ''"> and remark = #{remark}</if>
+            <if test="taskName != null  and taskName != ''"> and bef.task_name like concat('%', #{taskName}, '%')</if>
+            <if test="algorithmId != null "> and bef.algorithm_id = #{algorithmId}</if>
+            <if test="status != null  and status != ''"> and bef.status = #{status}</if>
+            <if test="startTime != null "> and bef.start_time = #{startTime}</if>
+            <if test="endTime != null "> and bef.end_time = #{endTime}</if>
+            <if test="remark != null  and remark != ''"> and bef.remark = #{remark}</if>
         </where>
+        order by bef.id desc
     </select>
     
     <select id="selectExtractedFeaturesById" parameterType="Long" resultMap="ExtractedFeaturesResult">
         <include refid="selectExtractedFeaturesVo"/>
-        where id = #{id}
+        where bef.id = #{id}
     </select>
 
     <insert id="insertExtractedFeatures" parameterType="ExtractedFeatures" useGeneratedKeys="true" keyProperty="id">

+ 28 - 8
ips-admin/src/main/resources/mapper/biz/PreprocessedMapper.xml

@@ -19,27 +19,47 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="createTime"    column="create_time"    />
         <result property="updateBy"    column="update_by"    />
         <result property="updateTime"    column="update_time"    />
+        <result property="algorithmName"    column="algorithm_name"    />
     </resultMap>
 
     <sql id="selectPreprocessedVo">
-        select id, task_name, algorithm_id, input_path, output_path, algorithm_params, status, start_time, end_time, remark, create_by, create_time, update_by, update_time from biz_preprocessed
+        SELECT
+            bp.id,
+            bp.task_name,
+            bp.algorithm_id,
+            bp.input_path,
+            bp.output_path,
+            bp.algorithm_params,
+            bp.STATUS,
+            bp.start_time,
+            bp.end_time,
+            bp.remark,
+            bp.create_by,
+            bp.create_time,
+            bp.update_by,
+            bp.update_time,
+            bac.algorithm_name
+        FROM
+            biz_preprocessed bp
+        LEFT JOIN biz_algorithm_config bac ON bac.id = bp.algorithm_id
     </sql>
 
     <select id="selectPreprocessedList" parameterType="Preprocessed" resultMap="PreprocessedResult">
         <include refid="selectPreprocessedVo"/>
         <where>  
-            <if test="taskName != null  and taskName != ''"> and task_name like concat('%', #{taskName}, '%')</if>
-            <if test="algorithmId != null "> and algorithm_id = #{algorithmId}</if>
-            <if test="status != null  and status != ''"> and status = #{status}</if>
-            <if test="startTime != null "> and start_time = #{startTime}</if>
-            <if test="endTime != null "> and end_time = #{endTime}</if>
-            <if test="remark != null  and remark != ''"> and remark = #{remark}</if>
+            <if test="taskName != null  and taskName != ''"> and bp.task_name like concat('%', #{taskName}, '%')</if>
+            <if test="algorithmId != null "> and bp.algorithm_id = #{algorithmId}</if>
+            <if test="status != null  and status != ''"> and bp.status = #{status}</if>
+            <if test="startTime != null "> and bp.start_time = #{startTime}</if>
+            <if test="endTime != null "> and bp.end_time = #{endTime}</if>
+            <if test="remark != null  and remark != ''"> and bp.remark = #{remark}</if>
         </where>
+        order by bp.id desc
     </select>
     
     <select id="selectPreprocessedById" parameterType="Long" resultMap="PreprocessedResult">
         <include refid="selectPreprocessedVo"/>
-        where id = #{id}
+        where bp.id = #{id}
     </select>
 
     <insert id="insertPreprocessed" parameterType="Preprocessed" useGeneratedKeys="true" keyProperty="id">

+ 35 - 19
ips-ui/src/api/biz/distillation.js

@@ -1,44 +1,60 @@
-import request from '@/utils/request'
+import request from "@/utils/request";
 
 // 查询知识蒸馏列表
 export function listDistillation(query) {
   return request({
-    url: '/biz/distillation/list',
-    method: 'get',
-    params: query
-  })
+    url: "/biz/distillation/list",
+    method: "get",
+    params: query,
+  });
 }
 
 // 查询知识蒸馏详细
 export function getDistillation(id) {
   return request({
-    url: '/biz/distillation/' + id,
-    method: 'get'
-  })
+    url: "/biz/distillation/" + id,
+    method: "get",
+  });
 }
 
 // 新增知识蒸馏
 export function addDistillation(data) {
   return request({
-    url: '/biz/distillation',
-    method: 'post',
-    data: data
-  })
+    url: "/biz/distillation",
+    method: "post",
+    data: data,
+  });
 }
 
 // 修改知识蒸馏
 export function updateDistillation(data) {
   return request({
-    url: '/biz/distillation',
-    method: 'put',
-    data: data
-  })
+    url: "/biz/distillation",
+    method: "put",
+    data: data,
+  });
 }
 
 // 删除知识蒸馏
 export function delDistillation(id) {
   return request({
-    url: '/biz/distillation/' + id,
-    method: 'delete'
-  })
+    url: "/biz/distillation/" + id,
+    method: "delete",
+  });
+}
+
+// 运行知识蒸馏
+export function run(id) {
+  return request({
+    url: "/biz/distillation/run/" + id,
+    method: "get",
+  });
+}
+
+// 获取运行结果详情
+export function getResultDetails(id) {
+  return request({
+    url: "/biz/distillation/getResultDetails/" + id,
+    method: "get",
+  });
 }

+ 35 - 19
ips-ui/src/api/biz/features.js

@@ -1,44 +1,60 @@
-import request from '@/utils/request'
+import request from "@/utils/request";
 
 // 查询特征提取列表
 export function listFeatures(query) {
   return request({
-    url: '/biz/features/list',
-    method: 'get',
-    params: query
-  })
+    url: "/biz/features/list",
+    method: "get",
+    params: query,
+  });
 }
 
 // 查询特征提取详细
 export function getFeatures(id) {
   return request({
-    url: '/biz/features/' + id,
-    method: 'get'
-  })
+    url: "/biz/features/" + id,
+    method: "get",
+  });
 }
 
 // 新增特征提取
 export function addFeatures(data) {
   return request({
-    url: '/biz/features',
-    method: 'post',
-    data: data
-  })
+    url: "/biz/features",
+    method: "post",
+    data: data,
+  });
 }
 
 // 修改特征提取
 export function updateFeatures(data) {
   return request({
-    url: '/biz/features',
-    method: 'put',
-    data: data
-  })
+    url: "/biz/features",
+    method: "put",
+    data: data,
+  });
 }
 
 // 删除特征提取
 export function delFeatures(id) {
   return request({
-    url: '/biz/features/' + id,
-    method: 'delete'
-  })
+    url: "/biz/features/" + id,
+    method: "delete",
+  });
+}
+
+// 运行特征提取
+export function run(id) {
+  return request({
+    url: "/biz/features/run/" + id,
+    method: "get",
+  });
+}
+
+// 获取运行结果详情
+export function getResultDetails(id) {
+  return request({
+    url: "/biz/features/getResultDetails/" + id,
+    method: "get",
+  });
 }

+ 35 - 19
ips-ui/src/api/biz/test.js

@@ -1,44 +1,60 @@
-import request from '@/utils/request'
+import request from "@/utils/request";
 
 // 查询分类测试列表
 export function listTest(query) {
   return request({
-    url: '/biz/test/list',
-    method: 'get',
-    params: query
-  })
+    url: "/biz/test/list",
+    method: "get",
+    params: query,
+  });
 }
 
 // 查询分类测试详细
 export function getTest(id) {
   return request({
-    url: '/biz/test/' + id,
-    method: 'get'
-  })
+    url: "/biz/test/" + id,
+    method: "get",
+  });
 }
 
 // 新增分类测试
 export function addTest(data) {
   return request({
-    url: '/biz/test',
-    method: 'post',
-    data: data
-  })
+    url: "/biz/test",
+    method: "post",
+    data: data,
+  });
 }
 
 // 修改分类测试
 export function updateTest(data) {
   return request({
-    url: '/biz/test',
-    method: 'put',
-    data: data
-  })
+    url: "/biz/test",
+    method: "put",
+    data: data,
+  });
 }
 
 // 删除分类测试
 export function delTest(id) {
   return request({
-    url: '/biz/test/' + id,
-    method: 'delete'
-  })
+    url: "/biz/test/" + id,
+    method: "delete",
+  });
+}
+
+// 运行分类测试
+export function run(id) {
+  return request({
+    url: "/biz/test/run/" + id,
+    method: "get",
+  });
+}
+
+// 获取运行结果详情
+export function getResultDetails(id) {
+  return request({
+    url: "/biz/test/getResultDetails/" + id,
+    method: "get",
+  });
 }

+ 35 - 19
ips-ui/src/api/biz/training.js

@@ -1,44 +1,60 @@
-import request from '@/utils/request'
+import request from "@/utils/request";
 
 // 查询模型训练列表
 export function listTraining(query) {
   return request({
-    url: '/biz/training/list',
-    method: 'get',
-    params: query
-  })
+    url: "/biz/training/list",
+    method: "get",
+    params: query,
+  });
 }
 
 // 查询模型训练详细
 export function getTraining(id) {
   return request({
-    url: '/biz/training/' + id,
-    method: 'get'
-  })
+    url: "/biz/training/" + id,
+    method: "get",
+  });
 }
 
 // 新增模型训练
 export function addTraining(data) {
   return request({
-    url: '/biz/training',
-    method: 'post',
-    data: data
-  })
+    url: "/biz/training",
+    method: "post",
+    data: data,
+  });
 }
 
 // 修改模型训练
 export function updateTraining(data) {
   return request({
-    url: '/biz/training',
-    method: 'put',
-    data: data
-  })
+    url: "/biz/training",
+    method: "put",
+    data: data,
+  });
 }
 
 // 删除模型训练
 export function delTraining(id) {
   return request({
-    url: '/biz/training/' + id,
-    method: 'delete'
-  })
+    url: "/biz/training/" + id,
+    method: "delete",
+  });
+}
+
+// 运行模型训练
+export function run(id) {
+  return request({
+    url: "/biz/training/run/" + id,
+    method: "get",
+  });
+}
+
+// 获取运行结果详情
+export function getResultDetails(id) {
+  return request({
+    url: "/biz/training/getResultDetails/" + id,
+    method: "get",
+  });
 }

+ 1 - 0
ips-ui/src/background.js

@@ -31,6 +31,7 @@ async function createWindow() {
   });
   win.maximize();
 //  win.show();
+// 打开控制台
 //  win.webContents.openDevTools();
   ipcMain.on("getPrinterList", (event) => {
     //主线程获取打印机列表

+ 109 - 43
ips-ui/src/views/biz/config/index.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      size="small"
+      :inline="true"
+      v-show="showSearch"
+      label-width="68px"
+    >
       <el-form-item label="算法名称" prop="algorithmName">
         <el-input
           v-model="queryParams.algorithmName"
@@ -10,7 +17,11 @@
         />
       </el-form-item>
       <el-form-item label="算法类型" prop="algorithmType">
-        <el-select v-model="queryParams.algorithmType" placeholder="请选择算法类型" clearable>
+        <el-select
+          v-model="queryParams.algorithmType"
+          placeholder="请选择算法类型"
+          clearable
+        >
           <el-option
             v-for="dict in dict.type.biz_algorithm_type"
             :key="dict.value"
@@ -20,8 +31,16 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="handleQuery"
+          >搜索</el-button
+        >
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置</el-button
+        >
       </el-form-item>
     </el-form>
 
@@ -34,7 +53,8 @@
           size="mini"
           @click="handleAdd"
           v-hasPermi="['biz:config:add']"
-        >新增</el-button>
+          >新增</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -45,7 +65,8 @@
           :disabled="single"
           @click="handleUpdate"
           v-hasPermi="['biz:config:edit']"
-        >修改</el-button>
+          >修改</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -56,7 +77,8 @@
           :disabled="multiple"
           @click="handleDelete"
           v-hasPermi="['biz:config:remove']"
-        >删除</el-button>
+          >删除</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -66,22 +88,37 @@
           size="mini"
           @click="handleExport"
           v-hasPermi="['biz:config:export']"
-        >导出</el-button>
+          >导出</el-button
+        >
       </el-col>
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
     </el-row>
 
-    <el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange">
+    <el-table
+      v-loading="loading"
+      :data="configList"
+      @selection-change="handleSelectionChange"
+    >
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="编号" align="center" prop="id" />
       <el-table-column label="算法名称" align="center" prop="algorithmName" />
       <el-table-column label="算法类型" align="center" prop="algorithmType">
         <template slot-scope="scope">
-          <dict-tag :options="dict.type.biz_algorithm_type" :value="scope.row.algorithmType"/>
+          <dict-tag
+            :options="dict.type.biz_algorithm_type"
+            :value="scope.row.algorithmType"
+          />
         </template>
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remark" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column
+        label="操作"
+        align="center"
+        class-name="small-padding fixed-width"
+      >
         <template slot-scope="scope">
           <el-button
             size="mini"
@@ -89,20 +126,22 @@
             icon="el-icon-edit"
             @click="handleUpdate(scope.row)"
             v-hasPermi="['biz:config:edit']"
-          >修改</el-button>
+            >修改</el-button
+          >
           <el-button
             size="mini"
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
             v-hasPermi="['biz:config:remove']"
-          >删除</el-button>
+            >删除</el-button
+          >
         </template>
       </el-table-column>
     </el-table>
 
     <pagination
-      v-show="total>0"
+      v-show="total > 0"
       :total="total"
       :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize"
@@ -110,7 +149,13 @@
     />
 
     <!-- 添加或修改算法配置对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+    <el-dialog
+      :title="title"
+      :visible.sync="open"
+      width="500px"
+      append-to-body
+      :close-on-click-modal="false"
+    >
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="算法名称" prop="algorithmName">
           <el-input v-model="form.algorithmName" placeholder="请输入算法名称" />
@@ -129,10 +174,18 @@
           <el-input v-model="form.algorithmPath" placeholder="请输入内容" />
         </el-form-item>
         <el-form-item label="算法参数" prop="algorithmParams">
-          <el-input v-model="form.algorithmParams" type="textarea" placeholder="请输入内容" />
+          <el-input
+            v-model="form.algorithmParams"
+            type="textarea"
+            placeholder="请输入内容"
+          />
         </el-form-item>
         <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
+          <el-input
+            v-model="form.remark"
+            type="textarea"
+            placeholder="请输入内容"
+          />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -144,11 +197,17 @@
 </template>
 
 <script>
-import { listConfig, getConfig, delConfig, addConfig, updateConfig } from "@/api/biz/config";
+import {
+  listConfig,
+  getConfig,
+  delConfig,
+  addConfig,
+  updateConfig,
+} from "@/api/biz/config";
 
 export default {
   name: "Config",
-  dicts: ['biz_algorithm_type'],
+  dicts: ["biz_algorithm_type"],
   data() {
     return {
       // 遮罩层
@@ -179,8 +238,7 @@ export default {
       // 表单参数
       form: {},
       // 表单校验
-      rules: {
-      }
+      rules: {},
     };
   },
   created() {
@@ -190,7 +248,7 @@ export default {
     /** 查询算法配置列表 */
     getList() {
       this.loading = true;
-      listConfig(this.queryParams).then(response => {
+      listConfig(this.queryParams).then((response) => {
         this.configList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -212,7 +270,7 @@ export default {
         createBy: null,
         createTime: null,
         updateBy: null,
-        updateTime: null
+        updateTime: null,
       };
       this.resetForm("form");
     },
@@ -228,9 +286,9 @@ export default {
     },
     // 多选框选中数据
     handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
-      this.multiple = !selection.length
+      this.ids = selection.map((item) => item.id);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
     },
     /** 新增按钮操作 */
     handleAdd() {
@@ -241,8 +299,8 @@ export default {
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
-      const id = row.id || this.ids
-      getConfig(id).then(response => {
+      const id = row.id || this.ids;
+      getConfig(id).then((response) => {
         this.form = response.data;
         this.open = true;
         this.title = "修改算法配置";
@@ -250,16 +308,16 @@ export default {
     },
     /** 提交按钮 */
     submitForm() {
-      this.$refs["form"].validate(valid => {
+      this.$refs["form"].validate((valid) => {
         if (valid) {
           if (this.form.id != null) {
-            updateConfig(this.form).then(response => {
+            updateConfig(this.form).then((response) => {
               this.$modal.msgSuccess("修改成功");
               this.open = false;
               this.getList();
             });
           } else {
-            addConfig(this.form).then(response => {
+            addConfig(this.form).then((response) => {
               this.$modal.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -271,19 +329,27 @@ export default {
     /** 删除按钮操作 */
     handleDelete(row) {
       const ids = row.id || this.ids;
-      this.$modal.confirm('是否确认删除算法配置编号为"' + ids + '"的数据项?').then(function() {
-        return delConfig(ids);
-      }).then(() => {
-        this.getList();
-        this.$modal.msgSuccess("删除成功");
-      }).catch(() => {});
+      this.$modal
+        .confirm('是否确认删除算法配置编号为"' + ids + '"的数据项?')
+        .then(function () {
+          return delConfig(ids);
+        })
+        .then(() => {
+          this.getList();
+          this.$modal.msgSuccess("删除成功");
+        })
+        .catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
-      this.download('biz/config/export', {
-        ...this.queryParams
-      }, `config_${new Date().getTime()}.xlsx`)
-    }
-  }
+      this.download(
+        "biz/config/export",
+        {
+          ...this.queryParams,
+        },
+        `config_${new Date().getTime()}.xlsx`
+      );
+    },
+  },
 };
 </script>

+ 215 - 59
ips-ui/src/views/biz/distillation/index.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      size="small"
+      :inline="true"
+      v-show="showSearch"
+      label-width="68px"
+    >
       <el-form-item label="任务名称" prop="taskName">
         <el-input
           v-model="queryParams.taskName"
@@ -10,15 +17,26 @@
         />
       </el-form-item>
       <el-form-item label="算法" prop="algorithmId">
-        <el-input
+        <el-select
           v-model="queryParams.algorithmId"
-          placeholder="请输入算法"
-          clearable
+          placeholder="请选择算法"
           @keyup.enter.native="handleQuery"
-        />
+          clearable
+        >
+          <el-option
+            v-for="option in configOptions"
+            :key="option.id"
+            :label="option.name"
+            :value="option.id"
+          />
+        </el-select>
       </el-form-item>
       <el-form-item label="状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择状态"
+          clearable
+        >
           <el-option
             v-for="dict in dict.type.biz_status"
             :key="dict.value"
@@ -27,25 +45,37 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="开始时间" prop="startTime">
-        <el-date-picker clearable
+      <!-- <el-form-item label="开始时间" prop="startTime">
+        <el-date-picker
+          clearable
           v-model="queryParams.startTime"
           type="date"
           value-format="yyyy-MM-dd"
-          placeholder="请选择开始时间">
+          placeholder="请选择开始时间"
+        >
         </el-date-picker>
       </el-form-item>
       <el-form-item label="结束时间" prop="endTime">
-        <el-date-picker clearable
+        <el-date-picker
+          clearable
           v-model="queryParams.endTime"
           type="date"
           value-format="yyyy-MM-dd"
-          placeholder="请选择结束时间">
+          placeholder="请选择结束时间"
+        >
         </el-date-picker>
-      </el-form-item>
+      </el-form-item> -->
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="handleQuery"
+          >搜索</el-button
+        >
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置</el-button
+        >
       </el-form-item>
     </el-form>
 
@@ -58,7 +88,8 @@
           size="mini"
           @click="handleAdd"
           v-hasPermi="['biz:distillation:add']"
-        >新增</el-button>
+          >新增</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -69,7 +100,8 @@
           :disabled="single"
           @click="handleUpdate"
           v-hasPermi="['biz:distillation:edit']"
-        >修改</el-button>
+          >修改</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -80,7 +112,8 @@
           :disabled="multiple"
           @click="handleDelete"
           v-hasPermi="['biz:distillation:remove']"
-        >删除</el-button>
+          >删除</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -90,54 +123,94 @@
           size="mini"
           @click="handleExport"
           v-hasPermi="['biz:distillation:export']"
-        >导出</el-button>
+          >导出</el-button
+        >
       </el-col>
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
     </el-row>
 
-    <el-table v-loading="loading" :data="distillationList" @selection-change="handleSelectionChange">
+    <el-table
+      v-loading="loading"
+      :data="distillationList"
+      @selection-change="handleSelectionChange"
+    >
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="编号" align="center" prop="id" />
       <el-table-column label="任务名称" align="center" prop="taskName" />
-      <el-table-column label="算法" align="center" prop="algorithmId" />
+      <el-table-column label="算法" align="center" prop="algorithmName" />
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="dict.type.biz_status" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.biz_status" :value="scope.row.status" />
         </template>
       </el-table-column>
-      <el-table-column label="开始时间" align="center" prop="startTime" width="180">
+      <el-table-column
+        label="开始时间"
+        align="center"
+        prop="startTime"
+        width="180"
+      >
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ parseTime(scope.row.startTime) }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="结束时间" align="center" prop="endTime" width="180">
+      <el-table-column
+        label="结束时间"
+        align="center"
+        prop="endTime"
+        width="180"
+      >
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ parseTime(scope.row.endTime) }}</span>
         </template>
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remark" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column
+        label="操作"
+        align="center"
+        class-name="small-padding fixed-width"
+      >
         <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleRun(scope.row)"
+            v-hasPermi="['biz:preprocessed:add']"
+            >运行</el-button
+          >
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleGetResult(scope.row)"
+            v-hasPermi="['biz:preprocessed:add']"
+            >查看结果</el-button
+          >
           <el-button
             size="mini"
             type="text"
             icon="el-icon-edit"
             @click="handleUpdate(scope.row)"
             v-hasPermi="['biz:distillation:edit']"
-          >修改</el-button>
+            >修改</el-button
+          >
           <el-button
             size="mini"
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
             v-hasPermi="['biz:distillation:remove']"
-          >删除</el-button>
+            >删除</el-button
+          >
         </template>
       </el-table-column>
     </el-table>
 
     <pagination
-      v-show="total>0"
+      v-show="total > 0"
       :total="total"
       :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize"
@@ -145,13 +218,31 @@
     />
 
     <!-- 添加或修改知识蒸馏对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+    <el-dialog
+      :title="title"
+      :visible.sync="open"
+      width="500px"
+      append-to-body
+      :close-on-click-modal="false"
+    >
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="任务名称" prop="taskName">
           <el-input v-model="form.taskName" placeholder="请输入任务名称" />
         </el-form-item>
         <el-form-item label="算法" prop="algorithmId">
-          <el-input v-model="form.algorithmId" placeholder="请输入算法" />
+          <el-select
+            v-model="form.algorithmId"
+            placeholder="请选择算法"
+            @change="changeAlgorithmId"
+            clearable
+          >
+            <el-option
+              v-for="option in configOptions"
+              :key="option.id"
+              :label="option.name"
+              :value="option.id"
+            />
+          </el-select>
         </el-form-item>
         <el-form-item label="输入路径" prop="inputPath">
           <el-input v-model="form.inputPath" placeholder="请输入输入路径" />
@@ -160,10 +251,18 @@
           <el-input v-model="form.outputPath" placeholder="请输入输出路径" />
         </el-form-item>
         <el-form-item label="算法参数" prop="algorithmParams">
-          <el-input v-model="form.algorithmParams" type="textarea" placeholder="请输入内容" />
+          <el-input
+            v-model="form.algorithmParams"
+            type="textarea"
+            placeholder="请输入内容"
+          />
         </el-form-item>
         <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
+          <el-input
+            v-model="form.remark"
+            type="textarea"
+            placeholder="请输入内容"
+          />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -175,13 +274,24 @@
 </template>
 
 <script>
-import { listDistillation, getDistillation, delDistillation, addDistillation, updateDistillation } from "@/api/biz/distillation";
+import {
+  listDistillation,
+  getDistillation,
+  delDistillation,
+  addDistillation,
+  updateDistillation,
+  run,
+  getResultDetails,
+} from "@/api/biz/distillation";
 
+import { getStatic } from "@/api/biz/common";
+import { getOptionsByType } from "@/api/biz/config";
 export default {
   name: "Distillation",
-  dicts: ['biz_status'],
+  dicts: ["biz_status"],
   data() {
     return {
+      staticsUrl: process.env.VUE_APP_BASE_API + "/biz/common/getStatic",
       // 遮罩层
       loading: true,
       // 选中数组
@@ -214,18 +324,27 @@ export default {
       // 表单参数
       form: {},
       // 表单校验
-      rules: {
-      }
+      rules: {},
+      configOptions: [],
+      resultDetails: {},
+      detailsOpen: false,
+      jsonResult: {},
+      selectFileName: "",
     };
   },
   created() {
     this.getList();
+    this.getOptions();
+  },
+  activated() {
+    this.getList();
+    this.getOptions();
   },
   methods: {
     /** 查询知识蒸馏列表 */
     getList() {
       this.loading = true;
-      listDistillation(this.queryParams).then(response => {
+      listDistillation(this.queryParams).then((response) => {
         this.distillationList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -252,7 +371,7 @@ export default {
         createBy: null,
         createTime: null,
         updateBy: null,
-        updateTime: null
+        updateTime: null,
       };
       this.resetForm("form");
     },
@@ -268,9 +387,9 @@ export default {
     },
     // 多选框选中数据
     handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
-      this.multiple = !selection.length
+      this.ids = selection.map((item) => item.id);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
     },
     /** 新增按钮操作 */
     handleAdd() {
@@ -281,25 +400,31 @@ export default {
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
-      const id = row.id || this.ids
-      getDistillation(id).then(response => {
+      const id = row.id || this.ids;
+      getDistillation(id).then((response) => {
         this.form = response.data;
         this.open = true;
         this.title = "修改知识蒸馏";
       });
     },
+    handleRun(row) {
+      const id = row.id;
+      run(id).then((response) => {
+        alert("任务开始运行!");
+      });
+    },
     /** 提交按钮 */
     submitForm() {
-      this.$refs["form"].validate(valid => {
+      this.$refs["form"].validate((valid) => {
         if (valid) {
           if (this.form.id != null) {
-            updateDistillation(this.form).then(response => {
+            updateDistillation(this.form).then((response) => {
               this.$modal.msgSuccess("修改成功");
               this.open = false;
               this.getList();
             });
           } else {
-            addDistillation(this.form).then(response => {
+            addDistillation(this.form).then((response) => {
               this.$modal.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -311,19 +436,50 @@ export default {
     /** 删除按钮操作 */
     handleDelete(row) {
       const ids = row.id || this.ids;
-      this.$modal.confirm('是否确认删除知识蒸馏编号为"' + ids + '"的数据项?').then(function() {
-        return delDistillation(ids);
-      }).then(() => {
-        this.getList();
-        this.$modal.msgSuccess("删除成功");
-      }).catch(() => {});
+      this.$modal
+        .confirm('是否确认删除知识蒸馏编号为"' + ids + '"的数据项?')
+        .then(function () {
+          return delDistillation(ids);
+        })
+        .then(() => {
+          this.getList();
+          this.$modal.msgSuccess("删除成功");
+        })
+        .catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
-      this.download('biz/distillation/export', {
-        ...this.queryParams
-      }, `distillation_${new Date().getTime()}.xlsx`)
-    }
-  }
+      this.download(
+        "biz/distillation/export",
+        {
+          ...this.queryParams,
+        },
+        `distillation_${new Date().getTime()}.xlsx`
+      );
+    },
+    getOptions() {
+      getOptionsByType("4").then((response) => {
+        this.configOptions = response.data;
+      });
+    },
+    changeAlgorithmId() {
+      const algorithmId = this.form.algorithmId;
+      const config = this.configOptions.find((item) => item.id === algorithmId);
+      if (config && config.params) {
+        this.form.algorithmParams = config.params;
+      } else {
+        this.form.algorithmParams = "";
+      }
+    },
+    handleGetResult(row) {
+      this.resultDetails = {};
+      this.selectFileName = "";
+      const id = row.id;
+      getResultDetails(id).then((response) => {
+        this.resultDetails = response.data;
+        this.detailsOpen = true;
+      });
+    },
+  },
 };
 </script>

+ 210 - 58
ips-ui/src/views/biz/features/index.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      size="small"
+      :inline="true"
+      v-show="showSearch"
+      label-width="68px"
+    >
       <el-form-item label="任务名称" prop="taskName">
         <el-input
           v-model="queryParams.taskName"
@@ -10,15 +17,26 @@
         />
       </el-form-item>
       <el-form-item label="算法" prop="algorithmId">
-        <el-input
+        <el-select
           v-model="queryParams.algorithmId"
-          placeholder="请输入算法"
-          clearable
+          placeholder="请选择算法"
           @keyup.enter.native="handleQuery"
-        />
+          clearable
+        >
+          <el-option
+            v-for="option in configOptions"
+            :key="option.id"
+            :label="option.name"
+            :value="option.id"
+          />
+        </el-select>
       </el-form-item>
       <el-form-item label="状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择状态"
+          clearable
+        >
           <el-option
             v-for="dict in dict.type.biz_status"
             :key="dict.value"
@@ -27,22 +45,26 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="开始时间" prop="startTime">
-        <el-date-picker clearable
+      <!-- <el-form-item label="开始时间" prop="startTime">
+        <el-date-picker
+          clearable
           v-model="queryParams.startTime"
           type="date"
           value-format="yyyy-MM-dd"
-          placeholder="请选择开始时间">
+          placeholder="请选择开始时间"
+        >
         </el-date-picker>
       </el-form-item>
       <el-form-item label="结束时间" prop="endTime">
-        <el-date-picker clearable
+        <el-date-picker
+          clearable
           v-model="queryParams.endTime"
           type="date"
           value-format="yyyy-MM-dd"
-          placeholder="请选择结束时间">
+          placeholder="请选择结束时间"
+        >
         </el-date-picker>
-      </el-form-item>
+      </el-form-item> -->
       <el-form-item label="备注" prop="remark">
         <el-input
           v-model="queryParams.remark"
@@ -52,8 +74,16 @@
         />
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="handleQuery"
+          >搜索</el-button
+        >
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置</el-button
+        >
       </el-form-item>
     </el-form>
 
@@ -66,7 +96,8 @@
           size="mini"
           @click="handleAdd"
           v-hasPermi="['biz:features:add']"
-        >新增</el-button>
+          >新增</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -77,7 +108,8 @@
           :disabled="single"
           @click="handleUpdate"
           v-hasPermi="['biz:features:edit']"
-        >修改</el-button>
+          >修改</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -88,7 +120,8 @@
           :disabled="multiple"
           @click="handleDelete"
           v-hasPermi="['biz:features:remove']"
-        >删除</el-button>
+          >删除</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -98,54 +131,94 @@
           size="mini"
           @click="handleExport"
           v-hasPermi="['biz:features:export']"
-        >导出</el-button>
+          >导出</el-button
+        >
       </el-col>
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
     </el-row>
 
-    <el-table v-loading="loading" :data="featuresList" @selection-change="handleSelectionChange">
+    <el-table
+      v-loading="loading"
+      :data="featuresList"
+      @selection-change="handleSelectionChange"
+    >
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="编号" align="center" prop="id" />
       <el-table-column label="任务名称" align="center" prop="taskName" />
-      <el-table-column label="算法" align="center" prop="algorithmId" />
+      <el-table-column label="算法" align="center" prop="algorithmName" />
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="dict.type.biz_status" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.biz_status" :value="scope.row.status" />
         </template>
       </el-table-column>
-      <el-table-column label="开始时间" align="center" prop="startTime" width="180">
+      <el-table-column
+        label="开始时间"
+        align="center"
+        prop="startTime"
+        width="180"
+      >
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ parseTime(scope.row.startTime) }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="结束时间" align="center" prop="endTime" width="180">
+      <el-table-column
+        label="结束时间"
+        align="center"
+        prop="endTime"
+        width="180"
+      >
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ parseTime(scope.row.endTime) }}</span>
         </template>
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remark" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column
+        label="操作"
+        align="center"
+        class-name="small-padding fixed-width"
+      >
         <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleRun(scope.row)"
+            v-hasPermi="['biz:preprocessed:add']"
+            >运行</el-button
+          >
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleGetResult(scope.row)"
+            v-hasPermi="['biz:preprocessed:add']"
+            >查看结果</el-button
+          >
           <el-button
             size="mini"
             type="text"
             icon="el-icon-edit"
             @click="handleUpdate(scope.row)"
             v-hasPermi="['biz:features:edit']"
-          >修改</el-button>
+            >修改</el-button
+          >
           <el-button
             size="mini"
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
             v-hasPermi="['biz:features:remove']"
-          >删除</el-button>
+            >删除</el-button
+          >
         </template>
       </el-table-column>
     </el-table>
 
     <pagination
-      v-show="total>0"
+      v-show="total > 0"
       :total="total"
       :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize"
@@ -153,13 +226,31 @@
     />
 
     <!-- 添加或修改特征提取对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+    <el-dialog
+      :title="title"
+      :visible.sync="open"
+      width="500px"
+      append-to-body
+      :close-on-click-modal="false"
+    >
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="任务名称" prop="taskName">
           <el-input v-model="form.taskName" placeholder="请输入任务名称" />
         </el-form-item>
         <el-form-item label="算法" prop="algorithmId">
-          <el-input v-model="form.algorithmId" placeholder="请输入算法" />
+          <el-select
+            v-model="form.algorithmId"
+            placeholder="请选择算法"
+            @change="changeAlgorithmId"
+            clearable
+          >
+            <el-option
+              v-for="option in configOptions"
+              :key="option.id"
+              :label="option.name"
+              :value="option.id"
+            />
+          </el-select>
         </el-form-item>
         <el-form-item label="输入路径" prop="inputPath">
           <el-input v-model="form.inputPath" placeholder="请输入输入路径" />
@@ -168,7 +259,11 @@
           <el-input v-model="form.outputPath" placeholder="请输入输出路径" />
         </el-form-item>
         <el-form-item label="算法参数" prop="algorithmParams">
-          <el-input v-model="form.algorithmParams" type="textarea" placeholder="请输入内容" />
+          <el-input
+            v-model="form.algorithmParams"
+            type="textarea"
+            placeholder="请输入内容"
+          />
         </el-form-item>
         <el-form-item label="备注" prop="remark">
           <el-input v-model="form.remark" placeholder="请输入备注" />
@@ -183,13 +278,24 @@
 </template>
 
 <script>
-import { listFeatures, getFeatures, delFeatures, addFeatures, updateFeatures } from "@/api/biz/features";
+import {
+  listFeatures,
+  getFeatures,
+  delFeatures,
+  addFeatures,
+  updateFeatures,
+  run,
+  getResultDetails,
+} from "@/api/biz/features";
 
+import { getStatic } from "@/api/biz/common";
+import { getOptionsByType } from "@/api/biz/config";
 export default {
   name: "Features",
-  dicts: ['biz_status'],
+  dicts: ["biz_status"],
   data() {
     return {
+      staticsUrl: process.env.VUE_APP_BASE_API + "/biz/common/getStatic",
       // 遮罩层
       loading: true,
       // 选中数组
@@ -222,18 +328,27 @@ export default {
       // 表单参数
       form: {},
       // 表单校验
-      rules: {
-      }
+      rules: {},
+      configOptions: [],
+      resultDetails: {},
+      detailsOpen: false,
+      jsonResult: {},
+      selectFileName: "",
     };
   },
   created() {
     this.getList();
+    this.getOptions();
+  },
+  activated() {
+    this.getList();
+    this.getOptions();
   },
   methods: {
     /** 查询特征提取列表 */
     getList() {
       this.loading = true;
-      listFeatures(this.queryParams).then(response => {
+      listFeatures(this.queryParams).then((response) => {
         this.featuresList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -260,7 +375,7 @@ export default {
         createBy: null,
         createTime: null,
         updateBy: null,
-        updateTime: null
+        updateTime: null,
       };
       this.resetForm("form");
     },
@@ -276,9 +391,9 @@ export default {
     },
     // 多选框选中数据
     handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
-      this.multiple = !selection.length
+      this.ids = selection.map((item) => item.id);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
     },
     /** 新增按钮操作 */
     handleAdd() {
@@ -289,25 +404,31 @@ export default {
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
-      const id = row.id || this.ids
-      getFeatures(id).then(response => {
+      const id = row.id || this.ids;
+      getFeatures(id).then((response) => {
         this.form = response.data;
         this.open = true;
         this.title = "修改特征提取";
       });
     },
+    handleRun(row) {
+      const id = row.id;
+      run(id).then((response) => {
+        alert("任务开始运行!");
+      });
+    },
     /** 提交按钮 */
     submitForm() {
-      this.$refs["form"].validate(valid => {
+      this.$refs["form"].validate((valid) => {
         if (valid) {
           if (this.form.id != null) {
-            updateFeatures(this.form).then(response => {
+            updateFeatures(this.form).then((response) => {
               this.$modal.msgSuccess("修改成功");
               this.open = false;
               this.getList();
             });
           } else {
-            addFeatures(this.form).then(response => {
+            addFeatures(this.form).then((response) => {
               this.$modal.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -319,19 +440,50 @@ export default {
     /** 删除按钮操作 */
     handleDelete(row) {
       const ids = row.id || this.ids;
-      this.$modal.confirm('是否确认删除特征提取编号为"' + ids + '"的数据项?').then(function() {
-        return delFeatures(ids);
-      }).then(() => {
-        this.getList();
-        this.$modal.msgSuccess("删除成功");
-      }).catch(() => {});
+      this.$modal
+        .confirm('是否确认删除特征提取编号为"' + ids + '"的数据项?')
+        .then(function () {
+          return delFeatures(ids);
+        })
+        .then(() => {
+          this.getList();
+          this.$modal.msgSuccess("删除成功");
+        })
+        .catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
-      this.download('biz/features/export', {
-        ...this.queryParams
-      }, `features_${new Date().getTime()}.xlsx`)
-    }
-  }
+      this.download(
+        "biz/features/export",
+        {
+          ...this.queryParams,
+        },
+        `features_${new Date().getTime()}.xlsx`
+      );
+    },
+    getOptions() {
+      getOptionsByType("2").then((response) => {
+        this.configOptions = response.data;
+      });
+    },
+    changeAlgorithmId() {
+      const algorithmId = this.form.algorithmId;
+      const config = this.configOptions.find((item) => item.id === algorithmId);
+      if (config && config.params) {
+        this.form.algorithmParams = config.params;
+      } else {
+        this.form.algorithmParams = "";
+      }
+    },
+    handleGetResult(row) {
+      this.resultDetails = {};
+      this.selectFileName = "";
+      const id = row.id;
+      getResultDetails(id).then((response) => {
+        this.resultDetails = response.data;
+        this.detailsOpen = true;
+      });
+    },
+  },
 };
 </script>

+ 52 - 11
ips-ui/src/views/biz/preprocessed/index.vue

@@ -17,12 +17,19 @@
         />
       </el-form-item>
       <el-form-item label="算法" prop="algorithmId">
-        <el-input
+        <el-select
           v-model="queryParams.algorithmId"
-          placeholder="请输入算法"
-          clearable
+          placeholder="请选择算法"
           @keyup.enter.native="handleQuery"
-        />
+          clearable
+        >
+          <el-option
+            v-for="option in configOptions"
+            :key="option.id"
+            :label="option.name"
+            :value="option.id"
+          />
+        </el-select>
       </el-form-item>
       <el-form-item label="状态" prop="status">
         <el-select
@@ -38,7 +45,7 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="开始时间" prop="startTime">
+      <!-- <el-form-item label="开始时间" prop="startTime">
         <el-date-picker
           clearable
           v-model="queryParams.startTime"
@@ -57,7 +64,7 @@
           placeholder="请选择结束时间"
         >
         </el-date-picker>
-      </el-form-item>
+      </el-form-item> -->
       <el-form-item>
         <el-button
           type="primary"
@@ -133,7 +140,7 @@
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="编号" align="center" prop="id" />
       <el-table-column label="任务名称" align="center" prop="taskName" />
-      <el-table-column label="算法" align="center" prop="algorithmId" />
+      <el-table-column label="算法" align="center" prop="algorithmName" />
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
           <dict-tag :options="dict.type.biz_status" :value="scope.row.status" />
@@ -146,7 +153,7 @@
         width="180"
       >
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.startTime, "{y}-{m}-{d}") }}</span>
+          <span>{{ parseTime(scope.row.startTime) }}</span>
         </template>
       </el-table-column>
       <el-table-column
@@ -156,7 +163,7 @@
         width="180"
       >
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.endTime, "{y}-{m}-{d}") }}</span>
+          <span>{{ parseTime(scope.row.endTime) }}</span>
         </template>
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remark" />
@@ -182,6 +189,13 @@
             v-hasPermi="['biz:preprocessed:add']"
             >查看结果</el-button
           >
+          <el-button
+            type="text"
+            icon="el-icon-edit"
+            @click="showLogViewer(scope.row)"
+          >
+            日志
+          </el-button>
           <el-button
             size="mini"
             type="text"
@@ -211,7 +225,13 @@
     />
 
     <!-- 添加或修改数据预处理对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+    <el-dialog
+      :title="title"
+      :visible.sync="open"
+      width="500px"
+      append-to-body
+      :close-on-click-modal="false"
+    >
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="任务名称" prop="taskName">
           <el-input v-model="form.taskName" placeholder="请输入任务名称" />
@@ -425,6 +445,11 @@
         </el-col>
       </el-row>
     </el-dialog>
+    <log-viewer
+      :currentLogUrl="currentLogUrl"
+      :dialogTitle="dialogTitle"
+      :logDialogVisible="logDialogVisible"
+    />
   </div>
 </template>
 
@@ -440,9 +465,13 @@ import {
 } from "@/api/biz/preprocessed";
 import { getStatic } from "@/api/biz/common";
 import { getOptionsByType } from "@/api/biz/config";
+import LogViewer from "@/components/LogViewer";
 export default {
   name: "Preprocessed",
   dicts: ["biz_status"],
+  components: {
+    LogViewer,
+  },
   data() {
     return {
       staticsUrl: process.env.VUE_APP_BASE_API + "/biz/common/getStatic",
@@ -484,12 +513,20 @@ export default {
       detailsOpen: false,
       jsonResult: {},
       selectFileName: "",
+      // 日志查看器
+      logDialogVisible: false,
+      currentLogUrl: "",
+      dialogTitle: "",
     };
   },
   created() {
     this.getList();
     this.getOptions();
   },
+  activated() {
+    this.getList();
+    this.getOptions();
+  },
   methods: {
     /** 查询数据预处理列表 */
     getList() {
@@ -636,7 +673,11 @@ export default {
       getStatic({ filePath }).then((response) => {
         this.jsonResult = response;
       });
-      //selectRowImage
+    },
+    showLogViewer(row) {
+      this.currentLogUrl = row.outputPath + "\\" + "log.log";
+      this.dialogTitle = "日志";
+      this.logDialogVisible = true;
     },
   },
 };

+ 215 - 60
ips-ui/src/views/biz/test/index.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      size="small"
+      :inline="true"
+      v-show="showSearch"
+      label-width="68px"
+    >
       <el-form-item label="任务名称" prop="taskName">
         <el-input
           v-model="queryParams.taskName"
@@ -10,15 +17,26 @@
         />
       </el-form-item>
       <el-form-item label="算法" prop="algorithmId">
-        <el-input
+        <el-select
           v-model="queryParams.algorithmId"
-          placeholder="请输入算法"
-          clearable
+          placeholder="请选择算法"
           @keyup.enter.native="handleQuery"
-        />
+          clearable
+        >
+          <el-option
+            v-for="option in configOptions"
+            :key="option.id"
+            :label="option.name"
+            :value="option.id"
+          />
+        </el-select>
       </el-form-item>
       <el-form-item label="状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择状态"
+          clearable
+        >
           <el-option
             v-for="dict in dict.type.biz_status"
             :key="dict.value"
@@ -27,25 +45,37 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="开始时间" prop="startTime">
-        <el-date-picker clearable
+      <!-- <el-form-item label="开始时间" prop="startTime">
+        <el-date-picker
+          clearable
           v-model="queryParams.startTime"
           type="date"
           value-format="yyyy-MM-dd"
-          placeholder="请选择开始时间">
+          placeholder="请选择开始时间"
+        >
         </el-date-picker>
       </el-form-item>
       <el-form-item label="结束时间" prop="endTime">
-        <el-date-picker clearable
+        <el-date-picker
+          clearable
           v-model="queryParams.endTime"
           type="date"
           value-format="yyyy-MM-dd"
-          placeholder="请选择结束时间">
+          placeholder="请选择结束时间"
+        >
         </el-date-picker>
-      </el-form-item>
+      </el-form-item> -->
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="handleQuery"
+          >搜索</el-button
+        >
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置</el-button
+        >
       </el-form-item>
     </el-form>
 
@@ -58,7 +88,8 @@
           size="mini"
           @click="handleAdd"
           v-hasPermi="['biz:test:add']"
-        >新增</el-button>
+          >新增</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -69,7 +100,8 @@
           :disabled="single"
           @click="handleUpdate"
           v-hasPermi="['biz:test:edit']"
-        >修改</el-button>
+          >修改</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -80,7 +112,8 @@
           :disabled="multiple"
           @click="handleDelete"
           v-hasPermi="['biz:test:remove']"
-        >删除</el-button>
+          >删除</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -90,54 +123,94 @@
           size="mini"
           @click="handleExport"
           v-hasPermi="['biz:test:export']"
-        >导出</el-button>
+          >导出</el-button
+        >
       </el-col>
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
     </el-row>
 
-    <el-table v-loading="loading" :data="testList" @selection-change="handleSelectionChange">
+    <el-table
+      v-loading="loading"
+      :data="testList"
+      @selection-change="handleSelectionChange"
+    >
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="编号" align="center" prop="id" />
       <el-table-column label="任务名称" align="center" prop="taskName" />
-      <el-table-column label="算法" align="center" prop="algorithmId" />
+      <el-table-column label="算法" align="center" prop="algorithmName" />
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="dict.type.biz_status" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.biz_status" :value="scope.row.status" />
         </template>
       </el-table-column>
-      <el-table-column label="开始时间" align="center" prop="startTime" width="180">
+      <el-table-column
+        label="开始时间"
+        align="center"
+        prop="startTime"
+        width="180"
+      >
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ parseTime(scope.row.startTime) }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="结束时间" align="center" prop="endTime" width="180">
+      <el-table-column
+        label="结束时间"
+        align="center"
+        prop="endTime"
+        width="180"
+      >
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ parseTime(scope.row.endTime) }}</span>
         </template>
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remark" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column
+        label="操作"
+        align="center"
+        class-name="small-padding fixed-width"
+      >
         <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleRun(scope.row)"
+            v-hasPermi="['biz:preprocessed:add']"
+            >运行</el-button
+          >
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleGetResult(scope.row)"
+            v-hasPermi="['biz:preprocessed:add']"
+            >查看结果</el-button
+          >
           <el-button
             size="mini"
             type="text"
             icon="el-icon-edit"
             @click="handleUpdate(scope.row)"
             v-hasPermi="['biz:test:edit']"
-          >修改</el-button>
+            >修改</el-button
+          >
           <el-button
             size="mini"
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
             v-hasPermi="['biz:test:remove']"
-          >删除</el-button>
+            >删除</el-button
+          >
         </template>
       </el-table-column>
     </el-table>
 
     <pagination
-      v-show="total>0"
+      v-show="total > 0"
       :total="total"
       :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize"
@@ -145,13 +218,31 @@
     />
 
     <!-- 添加或修改分类测试对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+    <el-dialog
+      :title="title"
+      :visible.sync="open"
+      width="500px"
+      append-to-body
+      :close-on-click-modal="false"
+    >
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="任务名称" prop="taskName">
           <el-input v-model="form.taskName" placeholder="请输入任务名称" />
         </el-form-item>
         <el-form-item label="算法" prop="algorithmId">
-          <el-input v-model="form.algorithmId" placeholder="请输入算法" />
+          <el-select
+            v-model="form.algorithmId"
+            placeholder="请选择算法"
+            @change="changeAlgorithmId"
+            clearable
+          >
+            <el-option
+              v-for="option in configOptions"
+              :key="option.id"
+              :label="option.name"
+              :value="option.id"
+            />
+          </el-select>
         </el-form-item>
         <el-form-item label="输入路径" prop="inputPath">
           <el-input v-model="form.inputPath" placeholder="请输入输入路径" />
@@ -160,10 +251,18 @@
           <el-input v-model="form.outputPath" placeholder="请输入输出路径" />
         </el-form-item>
         <el-form-item label="算法参数" prop="algorithmParams">
-          <el-input v-model="form.algorithmParams" type="textarea" placeholder="请输入内容" />
+          <el-input
+            v-model="form.algorithmParams"
+            type="textarea"
+            placeholder="请输入内容"
+          />
         </el-form-item>
         <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
+          <el-input
+            v-model="form.remark"
+            type="textarea"
+            placeholder="请输入内容"
+          />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -175,13 +274,23 @@
 </template>
 
 <script>
-import { listTest, getTest, delTest, addTest, updateTest } from "@/api/biz/test";
-
+import {
+  listTest,
+  getTest,
+  delTest,
+  addTest,
+  updateTest,
+  run,
+  getResultDetails,
+} from "@/api/biz/test";
+import { getStatic } from "@/api/biz/common";
+import { getOptionsByType } from "@/api/biz/config";
 export default {
   name: "Test",
-  dicts: ['biz_status'],
+  dicts: ["biz_status"],
   data() {
     return {
+      staticsUrl: process.env.VUE_APP_BASE_API + "/biz/common/getStatic",
       // 遮罩层
       loading: true,
       // 选中数组
@@ -214,18 +323,27 @@ export default {
       // 表单参数
       form: {},
       // 表单校验
-      rules: {
-      }
+      rules: {},
+      configOptions: [],
+      resultDetails: {},
+      detailsOpen: false,
+      jsonResult: {},
+      selectFileName: "",
     };
   },
   created() {
     this.getList();
+    this.getOptions();
+  },
+  activated() {
+    this.getList();
+    this.getOptions();
   },
   methods: {
     /** 查询分类测试列表 */
     getList() {
       this.loading = true;
-      listTest(this.queryParams).then(response => {
+      listTest(this.queryParams).then((response) => {
         this.testList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -252,7 +370,7 @@ export default {
         createBy: null,
         createTime: null,
         updateBy: null,
-        updateTime: null
+        updateTime: null,
       };
       this.resetForm("form");
     },
@@ -268,9 +386,9 @@ export default {
     },
     // 多选框选中数据
     handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
-      this.multiple = !selection.length
+      this.ids = selection.map((item) => item.id);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
     },
     /** 新增按钮操作 */
     handleAdd() {
@@ -281,25 +399,31 @@ export default {
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
-      const id = row.id || this.ids
-      getTest(id).then(response => {
+      const id = row.id || this.ids;
+      getTest(id).then((response) => {
         this.form = response.data;
         this.open = true;
         this.title = "修改分类测试";
       });
     },
+    handleRun(row) {
+      const id = row.id;
+      run(id).then((response) => {
+        alert("任务开始运行!");
+      });
+    },
     /** 提交按钮 */
     submitForm() {
-      this.$refs["form"].validate(valid => {
+      this.$refs["form"].validate((valid) => {
         if (valid) {
           if (this.form.id != null) {
-            updateTest(this.form).then(response => {
+            updateTest(this.form).then((response) => {
               this.$modal.msgSuccess("修改成功");
               this.open = false;
               this.getList();
             });
           } else {
-            addTest(this.form).then(response => {
+            addTest(this.form).then((response) => {
               this.$modal.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -311,19 +435,50 @@ export default {
     /** 删除按钮操作 */
     handleDelete(row) {
       const ids = row.id || this.ids;
-      this.$modal.confirm('是否确认删除分类测试编号为"' + ids + '"的数据项?').then(function() {
-        return delTest(ids);
-      }).then(() => {
-        this.getList();
-        this.$modal.msgSuccess("删除成功");
-      }).catch(() => {});
+      this.$modal
+        .confirm('是否确认删除分类测试编号为"' + ids + '"的数据项?')
+        .then(function () {
+          return delTest(ids);
+        })
+        .then(() => {
+          this.getList();
+          this.$modal.msgSuccess("删除成功");
+        })
+        .catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
-      this.download('biz/test/export', {
-        ...this.queryParams
-      }, `test_${new Date().getTime()}.xlsx`)
-    }
-  }
+      this.download(
+        "biz/test/export",
+        {
+          ...this.queryParams,
+        },
+        `test_${new Date().getTime()}.xlsx`
+      );
+    },
+    getOptions() {
+      getOptionsByType("5").then((response) => {
+        this.configOptions = response.data;
+      });
+    },
+    changeAlgorithmId() {
+      const algorithmId = this.form.algorithmId;
+      const config = this.configOptions.find((item) => item.id === algorithmId);
+      if (config && config.params) {
+        this.form.algorithmParams = config.params;
+      } else {
+        this.form.algorithmParams = "";
+      }
+    },
+    handleGetResult(row) {
+      this.resultDetails = {};
+      this.selectFileName = "";
+      const id = row.id;
+      getResultDetails(id).then((response) => {
+        this.resultDetails = response.data;
+        this.detailsOpen = true;
+      });
+    },
+  },
 };
 </script>

+ 215 - 60
ips-ui/src/views/biz/training/index.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      size="small"
+      :inline="true"
+      v-show="showSearch"
+      label-width="68px"
+    >
       <el-form-item label="任务名称" prop="taskName">
         <el-input
           v-model="queryParams.taskName"
@@ -10,15 +17,26 @@
         />
       </el-form-item>
       <el-form-item label="算法" prop="algorithmId">
-        <el-input
+        <el-select
           v-model="queryParams.algorithmId"
-          placeholder="请输入算法"
-          clearable
+          placeholder="请选择算法"
           @keyup.enter.native="handleQuery"
-        />
+          clearable
+        >
+          <el-option
+            v-for="option in configOptions"
+            :key="option.id"
+            :label="option.name"
+            :value="option.id"
+          />
+        </el-select>
       </el-form-item>
       <el-form-item label="状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择状态"
+          clearable
+        >
           <el-option
             v-for="dict in dict.type.biz_status"
             :key="dict.value"
@@ -27,25 +45,37 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="开始时间" prop="startTime">
-        <el-date-picker clearable
+      <!-- <el-form-item label="开始时间" prop="startTime">
+        <el-date-picker
+          clearable
           v-model="queryParams.startTime"
           type="date"
           value-format="yyyy-MM-dd"
-          placeholder="请选择开始时间">
+          placeholder="请选择开始时间"
+        >
         </el-date-picker>
       </el-form-item>
       <el-form-item label="结束时间" prop="endTime">
-        <el-date-picker clearable
+        <el-date-picker
+          clearable
           v-model="queryParams.endTime"
           type="date"
           value-format="yyyy-MM-dd"
-          placeholder="请选择结束时间">
+          placeholder="请选择结束时间"
+        >
         </el-date-picker>
-      </el-form-item>
+      </el-form-item> -->
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="handleQuery"
+          >搜索</el-button
+        >
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置</el-button
+        >
       </el-form-item>
     </el-form>
 
@@ -58,7 +88,8 @@
           size="mini"
           @click="handleAdd"
           v-hasPermi="['biz:training:add']"
-        >新增</el-button>
+          >新增</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -69,7 +100,8 @@
           :disabled="single"
           @click="handleUpdate"
           v-hasPermi="['biz:training:edit']"
-        >修改</el-button>
+          >修改</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -80,7 +112,8 @@
           :disabled="multiple"
           @click="handleDelete"
           v-hasPermi="['biz:training:remove']"
-        >删除</el-button>
+          >删除</el-button
+        >
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -90,54 +123,94 @@
           size="mini"
           @click="handleExport"
           v-hasPermi="['biz:training:export']"
-        >导出</el-button>
+          >导出</el-button
+        >
       </el-col>
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
     </el-row>
 
-    <el-table v-loading="loading" :data="trainingList" @selection-change="handleSelectionChange">
+    <el-table
+      v-loading="loading"
+      :data="trainingList"
+      @selection-change="handleSelectionChange"
+    >
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="编号" align="center" prop="id" />
       <el-table-column label="任务名称" align="center" prop="taskName" />
-      <el-table-column label="算法" align="center" prop="algorithmId" />
+      <el-table-column label="算法" align="center" prop="algorithmName" />
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="dict.type.biz_status" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.biz_status" :value="scope.row.status" />
         </template>
       </el-table-column>
-      <el-table-column label="开始时间" align="center" prop="startTime" width="180">
+      <el-table-column
+        label="开始时间"
+        align="center"
+        prop="startTime"
+        width="180"
+      >
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ parseTime(scope.row.startTime) }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="结束时间" align="center" prop="endTime" width="180">
+      <el-table-column
+        label="结束时间"
+        align="center"
+        prop="endTime"
+        width="180"
+      >
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ parseTime(scope.row.endTime) }}</span>
         </template>
       </el-table-column>
       <el-table-column label="备注" align="center" prop="remark" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column
+        label="操作"
+        align="center"
+        class-name="small-padding fixed-width"
+      >
         <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleRun(scope.row)"
+            v-hasPermi="['biz:preprocessed:add']"
+            >运行</el-button
+          >
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleGetResult(scope.row)"
+            v-hasPermi="['biz:preprocessed:add']"
+            >查看结果</el-button
+          >
           <el-button
             size="mini"
             type="text"
             icon="el-icon-edit"
             @click="handleUpdate(scope.row)"
             v-hasPermi="['biz:training:edit']"
-          >修改</el-button>
+            >修改</el-button
+          >
           <el-button
             size="mini"
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
             v-hasPermi="['biz:training:remove']"
-          >删除</el-button>
+            >删除</el-button
+          >
         </template>
       </el-table-column>
     </el-table>
 
     <pagination
-      v-show="total>0"
+      v-show="total > 0"
       :total="total"
       :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize"
@@ -145,13 +218,31 @@
     />
 
     <!-- 添加或修改模型训练对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+    <el-dialog
+      :title="title"
+      :visible.sync="open"
+      width="500px"
+      append-to-body
+      :close-on-click-modal="false"
+    >
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="任务名称" prop="taskName">
           <el-input v-model="form.taskName" placeholder="请输入任务名称" />
         </el-form-item>
         <el-form-item label="算法" prop="algorithmId">
-          <el-input v-model="form.algorithmId" placeholder="请输入算法" />
+          <el-select
+            v-model="form.algorithmId"
+            placeholder="请选择算法"
+            @change="changeAlgorithmId"
+            clearable
+          >
+            <el-option
+              v-for="option in configOptions"
+              :key="option.id"
+              :label="option.name"
+              :value="option.id"
+            />
+          </el-select>
         </el-form-item>
         <el-form-item label="输入路径" prop="inputPath">
           <el-input v-model="form.inputPath" placeholder="请输入输入路径" />
@@ -160,10 +251,18 @@
           <el-input v-model="form.outputPath" placeholder="请输入输出路径" />
         </el-form-item>
         <el-form-item label="算法参数" prop="algorithmParams">
-          <el-input v-model="form.algorithmParams" type="textarea" placeholder="请输入内容" />
+          <el-input
+            v-model="form.algorithmParams"
+            type="textarea"
+            placeholder="请输入内容"
+          />
         </el-form-item>
         <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
+          <el-input
+            v-model="form.remark"
+            type="textarea"
+            placeholder="请输入内容"
+          />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -175,13 +274,23 @@
 </template>
 
 <script>
-import { listTraining, getTraining, delTraining, addTraining, updateTraining } from "@/api/biz/training";
-
+import {
+  listTraining,
+  getTraining,
+  delTraining,
+  addTraining,
+  updateTraining,
+  run,
+  getResultDetails,
+} from "@/api/biz/training";
+import { getStatic } from "@/api/biz/common";
+import { getOptionsByType } from "@/api/biz/config";
 export default {
   name: "Training",
-  dicts: ['biz_status'],
+  dicts: ["biz_status"],
   data() {
     return {
+      staticsUrl: process.env.VUE_APP_BASE_API + "/biz/common/getStatic",
       // 遮罩层
       loading: true,
       // 选中数组
@@ -214,18 +323,27 @@ export default {
       // 表单参数
       form: {},
       // 表单校验
-      rules: {
-      }
+      rules: {},
+      configOptions: [],
+      resultDetails: {},
+      detailsOpen: false,
+      jsonResult: {},
+      selectFileName: "",
     };
   },
   created() {
     this.getList();
+    this.getOptions();
+  },
+  activated() {
+    this.getList();
+    this.getOptions();
   },
   methods: {
     /** 查询模型训练列表 */
     getList() {
       this.loading = true;
-      listTraining(this.queryParams).then(response => {
+      listTraining(this.queryParams).then((response) => {
         this.trainingList = response.rows;
         this.total = response.total;
         this.loading = false;
@@ -252,7 +370,7 @@ export default {
         createBy: null,
         createTime: null,
         updateBy: null,
-        updateTime: null
+        updateTime: null,
       };
       this.resetForm("form");
     },
@@ -268,9 +386,9 @@ export default {
     },
     // 多选框选中数据
     handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
-      this.multiple = !selection.length
+      this.ids = selection.map((item) => item.id);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
     },
     /** 新增按钮操作 */
     handleAdd() {
@@ -281,25 +399,31 @@ export default {
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
-      const id = row.id || this.ids
-      getTraining(id).then(response => {
+      const id = row.id || this.ids;
+      getTraining(id).then((response) => {
         this.form = response.data;
         this.open = true;
         this.title = "修改模型训练";
       });
     },
+    handleRun(row) {
+      const id = row.id;
+      run(id).then((response) => {
+        alert("任务开始运行!");
+      });
+    },
     /** 提交按钮 */
     submitForm() {
-      this.$refs["form"].validate(valid => {
+      this.$refs["form"].validate((valid) => {
         if (valid) {
           if (this.form.id != null) {
-            updateTraining(this.form).then(response => {
+            updateTraining(this.form).then((response) => {
               this.$modal.msgSuccess("修改成功");
               this.open = false;
               this.getList();
             });
           } else {
-            addTraining(this.form).then(response => {
+            addTraining(this.form).then((response) => {
               this.$modal.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -311,19 +435,50 @@ export default {
     /** 删除按钮操作 */
     handleDelete(row) {
       const ids = row.id || this.ids;
-      this.$modal.confirm('是否确认删除模型训练编号为"' + ids + '"的数据项?').then(function() {
-        return delTraining(ids);
-      }).then(() => {
-        this.getList();
-        this.$modal.msgSuccess("删除成功");
-      }).catch(() => {});
+      this.$modal
+        .confirm('是否确认删除模型训练编号为"' + ids + '"的数据项?')
+        .then(function () {
+          return delTraining(ids);
+        })
+        .then(() => {
+          this.getList();
+          this.$modal.msgSuccess("删除成功");
+        })
+        .catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
-      this.download('biz/training/export', {
-        ...this.queryParams
-      }, `training_${new Date().getTime()}.xlsx`)
-    }
-  }
+      this.download(
+        "biz/training/export",
+        {
+          ...this.queryParams,
+        },
+        `training_${new Date().getTime()}.xlsx`
+      );
+    },
+    getOptions() {
+      getOptionsByType("3").then((response) => {
+        this.configOptions = response.data;
+      });
+    },
+    changeAlgorithmId() {
+      const algorithmId = this.form.algorithmId;
+      const config = this.configOptions.find((item) => item.id === algorithmId);
+      if (config && config.params) {
+        this.form.algorithmParams = config.params;
+      } else {
+        this.form.algorithmParams = "";
+      }
+    },
+    handleGetResult(row) {
+      this.resultDetails = {};
+      this.selectFileName = "";
+      const id = row.id;
+      getResultDetails(id).then((response) => {
+        this.resultDetails = response.data;
+        this.detailsOpen = true;
+      });
+    },
+  },
 };
 </script>

+ 24 - 1
sql/biz.sql

@@ -257,4 +257,27 @@ insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame
 values('模型训练删除', @parentId, '4',  '#', '', 1, 0, 'F', '0', '0', 'biz:training:remove',       '#', 'admin', sysdate(), '', null, '');
 
 insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
-values('模型训练导出', @parentId, '5',  '#', '', 1, 0, 'F', '0', '0', 'biz:training:export',       '#', 'admin', sysdate(), '', null, '');
+values('模型训练导出', @parentId, '5',  '#', '', 1, 0, 'F', '0', '0', 'biz:training:export',       '#', 'admin', sysdate(), '', null, '');
+
+-- 菜单 SQL
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('知识蒸馏', '0', '1', 'distillation', 'biz/distillation/index', 1, 0, 'C', '0', '0', 'biz:distillation:list', '#', 'admin', sysdate(), '', null, '知识蒸馏菜单');
+
+-- 按钮父菜单ID
+SELECT @parentId := LAST_INSERT_ID();
+
+-- 按钮 SQL
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('知识蒸馏查询', @parentId, '1',  '#', '', 1, 0, 'F', '0', '0', 'biz:distillation:query',        '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('知识蒸馏新增', @parentId, '2',  '#', '', 1, 0, 'F', '0', '0', 'biz:distillation:add',          '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('知识蒸馏修改', @parentId, '3',  '#', '', 1, 0, 'F', '0', '0', 'biz:distillation:edit',         '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('知识蒸馏删除', @parentId, '4',  '#', '', 1, 0, 'F', '0', '0', 'biz:distillation:remove',       '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('知识蒸馏导出', @parentId, '5',  '#', '', 1, 0, 'F', '0', '0', 'biz:distillation:export',       '#', 'admin', sysdate(), '', null, '');