allen 1 月之前
父節點
當前提交
f6bae3b00a

+ 14 - 0
ips-admin/src/main/java/com/ips/system/controller/TimeFrequencyImagesController.java

@@ -2,6 +2,9 @@ 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 org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -101,4 +104,15 @@ public class TimeFrequencyImagesController extends BaseController
     {
         return toAjax(timeFrequencyImagesService.deleteTimeFrequencyImagesByIds(ids));
     }
+
+    @PreAuthorize("@ss.hasPermi('biz:images:add')")
+    @GetMapping(value = "/run/{id}")
+    public AjaxResult run(@PathVariable("id") Long id) throws JsonProcessingException {
+        String errorMsg = timeFrequencyImagesService.run(id);
+        if(StringUtils.isEmpty(errorMsg)){
+            return success(errorMsg);
+        } else {
+            return error(errorMsg);
+        }
+    }
 }

+ 1 - 1
ips-admin/src/main/java/com/ips/system/service/IPreprocessedService.java

@@ -61,7 +61,7 @@ public interface IPreprocessedService
      */
     public int deletePreprocessedById(Long id);
 
-    String run(Long id) throws JsonProcessingException;
+    String run(Long id);
 
     Preprocessed getResultDetails(Long id);
 }

+ 2 - 0
ips-admin/src/main/java/com/ips/system/service/ITimeFrequencyImagesService.java

@@ -58,4 +58,6 @@ public interface ITimeFrequencyImagesService
      * @return 结果
      */
     public int deleteTimeFrequencyImagesById(Long id);
+
+    String run(Long id);
 }

+ 1 - 2
ips-admin/src/main/java/com/ips/system/service/impl/BizTrainingServiceImpl.java

@@ -12,7 +12,6 @@ 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;
@@ -150,7 +149,7 @@ public class BizTrainingServiceImpl implements IBizTrainingService {
             // 对象 → JSON 字符串
             String json = objectMapper.writeValueAsString(algorithmParamsDto);
             // 处理算法
-            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmConfig.getAlgorithmName(),algorithmPath, json);
         } catch (JsonProcessingException e) {
             logger.error("格式化失败", e);
             errorMsg = "格式化失败";

+ 1 - 3
ips-admin/src/main/java/com/ips/system/service/impl/ClassifyTestServiceImpl.java

@@ -12,8 +12,6 @@ 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;
@@ -157,7 +155,7 @@ public class ClassifyTestServiceImpl implements IClassifyTestService
             // 对象 → JSON 字符串
             String json = objectMapper.writeValueAsString(algorithmParamsDto);
             // 处理算法
-            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmConfig.getAlgorithmName(),algorithmPath, json);
         } catch (JsonProcessingException e) {
             logger.error("格式化失败", e);
             errorMsg = "格式化失败";

+ 1 - 2
ips-admin/src/main/java/com/ips/system/service/impl/DistillationServiceImpl.java

@@ -6,7 +6,6 @@ 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.ClassifyTest;
 import com.ips.system.domain.Distillation;
 import com.ips.system.dto.AlgorithmParamsDto;
 import com.ips.system.mapper.DistillationMapper;
@@ -156,7 +155,7 @@ public class DistillationServiceImpl implements IDistillationService
             // 对象 → JSON 字符串
             String json = objectMapper.writeValueAsString(algorithmParamsDto);
             // 处理算法
-            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmConfig.getAlgorithmName(),algorithmPath, json);
         } catch (JsonProcessingException e) {
             logger.error("格式化失败", e);
             errorMsg = "格式化失败";

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

@@ -1,6 +1,5 @@
 package com.ips.system.service.impl;
 
-import java.io.IOException;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 
@@ -10,10 +9,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.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;
@@ -159,7 +155,7 @@ public class ExtractedFeaturesServiceImpl implements IExtractedFeaturesService
             // 对象 → JSON 字符串
             String json = objectMapper.writeValueAsString(algorithmParamsDto);
             // 处理算法
-            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmConfig.getAlgorithmName(),algorithmPath, json);
         } catch (JsonProcessingException e) {
             logger.error("格式化失败", e);
             errorMsg = "格式化失败";

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

@@ -121,7 +121,7 @@ public class PreprocessedServiceImpl implements IPreprocessedService
     }
 
     @Override
-    public String run(Long id) throws JsonProcessingException {
+    public String run(Long id) {
         Preprocessed preprocessed = preprocessedMapper.selectPreprocessedById(id);
         if(preprocessed == null || preprocessed.getAlgorithmId() == null){
             return "无法找到该任务,id:"+id;
@@ -162,7 +162,7 @@ public class PreprocessedServiceImpl implements IPreprocessedService
             // 对象 → JSON 字符串
             String json = objectMapper.writeValueAsString(algorithmParamsDto);
             // 处理算法
-            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmPath, json);
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmConfig.getAlgorithmName(),algorithmPath, json);
         } catch (JsonProcessingException e) {
             logger.error("格式化失败", e);
             errorMsg = "格式化失败";

+ 77 - 0
ips-admin/src/main/java/com/ips/system/service/impl/TimeFrequencyImagesServiceImpl.java

@@ -1,7 +1,22 @@
 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.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.TimeFrequencyImagesMapper;
@@ -17,9 +32,14 @@ import com.ips.system.service.ITimeFrequencyImagesService;
 @Service
 public class TimeFrequencyImagesServiceImpl implements ITimeFrequencyImagesService 
 {
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
     @Autowired
     private TimeFrequencyImagesMapper timeFrequencyImagesMapper;
 
+    @Autowired
+    private IAlgorithmConfigService algorithmConfigService;
+
+
     /**
      * 查询时频图生成
      * 
@@ -93,4 +113,61 @@ public class TimeFrequencyImagesServiceImpl implements ITimeFrequencyImagesServi
     {
         return timeFrequencyImagesMapper.deleteTimeFrequencyImagesById(id);
     }
+
+    @Override
+    public String run(Long id)  {
+        TimeFrequencyImages timeFrequencyImages = timeFrequencyImagesMapper.selectTimeFrequencyImagesById(id);
+        if(timeFrequencyImages == null || timeFrequencyImages.getAlgorithmId() == null){
+            return "无法找到该任务,id:"+id;
+        }
+        Long algorithmId = timeFrequencyImages.getAlgorithmId();
+        AlgorithmConfig algorithmConfig = algorithmConfigService.selectAlgorithmConfigById(algorithmId);
+        timeFrequencyImages.setStartTime(new Date());
+        timeFrequencyImages.setStatus("1");
+        this.updateTimeFrequencyImages(timeFrequencyImages);
+
+        CompletableFuture.runAsync(() -> {
+            // 异步逻辑
+            doRun(algorithmConfig, timeFrequencyImages);
+        });
+        return null;
+    }
+
+    private void doRun(AlgorithmConfig algorithmConfig, TimeFrequencyImages timeFrequencyImages) {
+        String algorithmPath = algorithmConfig.getAlgorithmPath();
+
+        // 组装json
+        String inputPath = timeFrequencyImages.getInputPath();
+        String outputPath = timeFrequencyImages.getOutputPath();
+        ObjectMapper objectMapper = new ObjectMapper();
+        Map<String, Object> params = new HashMap<>(0);
+
+        String errorMsg = "";
+        try {
+            if (StringUtils.isNotEmpty(timeFrequencyImages.getAlgorithmParams())) {
+
+                params = objectMapper.readValue(
+                        timeFrequencyImages.getAlgorithmParams(),
+                        new TypeReference<Map<String, Object>>() {
+                        }
+                );
+            }
+            AlgorithmParamsDto algorithmParamsDto = new AlgorithmParamsDto(inputPath, outputPath, params);
+            // 对象 → JSON 字符串
+            String json = objectMapper.writeValueAsString(algorithmParamsDto);
+            // 处理算法
+            errorMsg = AlgorithmCaller.executeAlgorithm(algorithmConfig.getAlgorithmName(),algorithmPath, json);
+        } catch (JsonProcessingException e) {
+            logger.error("格式化失败", e);
+            errorMsg = "格式化失败";
+        }
+        //处理结果
+        if (StringUtils.isEmpty(errorMsg)) {
+            timeFrequencyImages.setStatus("2");
+        } else {
+            timeFrequencyImages.setStatus("3");
+        }
+        timeFrequencyImages.setEndTime(new Date());
+        this.updateTimeFrequencyImages(timeFrequencyImages);
+    }
 }

+ 10 - 6
ips-admin/src/main/java/com/ips/system/utils/AlgorithmCaller.java

@@ -38,11 +38,13 @@ public class AlgorithmCaller {
 
     /**
      * 根据json字符串生成input.json文件到指定目录(解决中文乱码问题)
-     * @param directory 目标目录
+     *
+     * @param jsonName input_xxx.json的xxx部分(算法的名称)
+     * @param directory   目标目录
      * @param jsonContent JSON内容字符串
      * @return 生成的JSON文件路径
      */
-    public static String generateInputJsonFile(String directory, String jsonContent) throws IOException {
+    public static String generateInputJsonFile(String jsonName, String directory, String jsonContent) throws IOException {
         if (directory == null || directory.isEmpty()) {
             throw new IllegalArgumentException("Directory cannot be null or empty");
         }
@@ -61,7 +63,7 @@ public class AlgorithmCaller {
         }
 
         // 创建input.json文件(使用UTF-8编码写入)
-        File jsonFile = new File(directory, "input.json");
+        File jsonFile = new File(directory, "input_" + jsonName + ".json");
         try (OutputStreamWriter writer = new OutputStreamWriter(
                 Files.newOutputStream(jsonFile.toPath()), StandardCharsets.UTF_8)) {
             writer.write(jsonContent);
@@ -147,19 +149,21 @@ public class AlgorithmCaller {
 
     /**
      * 完整调用流程
+     *
      * @param programPath 程序路径(可以是.py或.exe)
      * @param jsonContent 输入JSON内容
+     * @param json
      * @return 执行结果
      */
-    public static String executeAlgorithm(String programPath, String jsonContent) {
-        logger.info("调用算法开始,programPath:{},jsonContent:{}", programPath, jsonContent);
+    public static String executeAlgorithm(String jsonName,String programPath, String jsonContent) {
+        logger.info("调用算法开始,jsonName:{},programPath:{},jsonContent:{}", jsonName, programPath, jsonContent);
         String errorMsg = "";
         try {
             // 1. 获取工作目录
             String workingDirectory = getAlgorithmRootPath(programPath);
 
             // 2. 生成输入文件
-            generateInputJsonFile(workingDirectory, jsonContent);
+            generateInputJsonFile(jsonName,workingDirectory, jsonContent);
 
             // 3. 根据文件类型调用相应程序
             if (programPath.toLowerCase().endsWith(".py")) {

+ 27 - 19
ips-ui/src/api/biz/images.js

@@ -1,44 +1,52 @@
-import request from '@/utils/request'
+import request from "@/utils/request";
 
 // 查询时频图生成列表
 export function listImages(query) {
   return request({
-    url: '/biz/images/list',
-    method: 'get',
-    params: query
-  })
+    url: "/biz/images/list",
+    method: "get",
+    params: query,
+  });
 }
 
 // 查询时频图生成详细
 export function getImages(id) {
   return request({
-    url: '/biz/images/' + id,
-    method: 'get'
-  })
+    url: "/biz/images/" + id,
+    method: "get",
+  });
 }
 
 // 新增时频图生成
 export function addImages(data) {
   return request({
-    url: '/biz/images',
-    method: 'post',
-    data: data
-  })
+    url: "/biz/images",
+    method: "post",
+    data: data,
+  });
 }
 
 // 修改时频图生成
 export function updateImages(data) {
   return request({
-    url: '/biz/images',
-    method: 'put',
-    data: data
-  })
+    url: "/biz/images",
+    method: "put",
+    data: data,
+  });
 }
 
 // 删除时频图生成
 export function delImages(id) {
   return request({
-    url: '/biz/images/' + id,
-    method: 'delete'
-  })
+    url: "/biz/images/" + id,
+    method: "delete",
+  });
+}
+
+// 运行时频图生成
+export function run(id) {
+  return request({
+    url: "/biz/images/run/" + id,
+    method: "get",
+  });
 }

+ 9 - 3
ips-ui/src/components/LogViewer/index.vue

@@ -110,9 +110,15 @@ export default {
     },
 
     fetchLog() {
-      getStatic({ filePath: this.currentLogUrl }).then((response) => {
-        this.logContent = response;
-      });
+      getStatic({ filePath: this.currentLogUrl })
+        .then((response) => {
+          this.logContent = response;
+        })
+        .catch((error) => {
+          console.error("获取日志失败:", error);
+          this.logContent = "无法获取日志内容,请检查文件路径或网络连接。";
+          this.stopAutoRefresh();
+        });
     },
 
     clearLog() {

+ 32 - 4
ips-ui/src/views/biz/distillation/index.vue

@@ -176,17 +176,24 @@
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-edit"
+            icon="el-icon-video-play"
             @click="handleRun(scope.row)"
-            v-hasPermi="['biz:preprocessed:add']"
+            v-hasPermi="['biz:distillation:add']"
             >运行</el-button
           >
+          <el-button
+            type="text"
+            icon="el-icon-search"
+            @click="showLogViewer(scope.row)"
+          >
+            日志
+          </el-button>
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-edit"
+            icon="el-icon-info"
             @click="handleGetResult(scope.row)"
-            v-hasPermi="['biz:preprocessed:add']"
+            v-hasPermi="['biz:distillation:add']"
             >查看结果</el-button
           >
           <el-button
@@ -274,6 +281,12 @@
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
+    <log-viewer
+      :currentLogUrl="currentLogUrl"
+      :dialogTitle="dialogTitle"
+      :logDialogVisible="logDialogVisible"
+      @updateLogDiaLlogVisible="updateLogDiaLlogVisible"
+    />
   </div>
 </template>
 
@@ -293,6 +306,7 @@ import FilePicker from "@/components/FilePicker";
 import { getStatic } from "@/api/biz/common";
 import { getOptionsByType } from "@/api/biz/config";
 import DynamicFormDialog from "@/components/DynamicFormDialog";
+import LogViewer from "@/components/LogViewer";
 export default {
   name: "Distillation",
   dicts: ["biz_status"],
@@ -300,6 +314,7 @@ export default {
     FolderPicker,
     FilePicker,
     DynamicFormDialog,
+    LogViewer,
   },
   data() {
     return {
@@ -343,6 +358,10 @@ export default {
       jsonResult: {},
       selectFileName: "",
       showParamsDialog: false,
+      // 日志查看器
+      logDialogVisible: false,
+      currentLogUrl: "",
+      dialogTitle: "",
     };
   },
   created() {
@@ -498,6 +517,15 @@ export default {
       // 这里可以添加处理配置更新的逻辑
       console.log("更新后的配置:", JSON.parse(modifiedJson));
     },
+    updateLogDiaLlogVisible(visiible) {
+      console.log("updateLogDiaLlogVisible", visiible);
+      this.logDialogVisible = visiible;
+    },
+    showLogViewer(row) {
+      this.currentLogUrl = row.outputPath + "\\" + "log.log";
+      this.dialogTitle = "日志";
+      this.logDialogVisible = true;
+    },
   },
 };
 </script>

+ 32 - 4
ips-ui/src/views/biz/features/index.vue

@@ -184,17 +184,24 @@
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-edit"
+            icon="el-icon-video-play"
             @click="handleRun(scope.row)"
-            v-hasPermi="['biz:preprocessed:add']"
+            v-hasPermi="['biz:features:add']"
             >运行</el-button
           >
+          <el-button
+            type="text"
+            icon="el-icon-search"
+            @click="showLogViewer(scope.row)"
+          >
+            日志
+          </el-button>
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-edit"
+            icon="el-icon-info"
             @click="handleGetResult(scope.row)"
-            v-hasPermi="['biz:preprocessed:add']"
+            v-hasPermi="['biz:features:add']"
             >查看结果</el-button
           >
           <el-button
@@ -275,6 +282,12 @@
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
+    <log-viewer
+      :currentLogUrl="currentLogUrl"
+      :dialogTitle="dialogTitle"
+      :logDialogVisible="logDialogVisible"
+      @updateLogDiaLlogVisible="updateLogDiaLlogVisible"
+    />
   </div>
 </template>
 
@@ -293,12 +306,14 @@ import FolderPicker from "@/components/FolderPicker";
 import { getStatic } from "@/api/biz/common";
 import { getOptionsByType } from "@/api/biz/config";
 import DynamicFormDialog from "@/components/DynamicFormDialog";
+import LogViewer from "@/components/LogViewer";
 export default {
   name: "Features",
   dicts: ["biz_status"],
   components: {
     FolderPicker,
     DynamicFormDialog,
+    LogViewer,
   },
   data() {
     return {
@@ -342,6 +357,10 @@ export default {
       jsonResult: {},
       selectFileName: "",
       showParamsDialog: false,
+      // 日志查看器
+      logDialogVisible: false,
+      currentLogUrl: "",
+      dialogTitle: "",
     };
   },
   created() {
@@ -497,6 +516,15 @@ export default {
       // 这里可以添加处理配置更新的逻辑
       console.log("更新后的配置:", JSON.parse(modifiedJson));
     },
+    updateLogDiaLlogVisible(visiible) {
+      console.log("updateLogDiaLlogVisible", visiible);
+      this.logDialogVisible = visiible;
+    },
+    showLogViewer(row) {
+      this.currentLogUrl = row.outputPath + "\\" + "log.log";
+      this.dialogTitle = "日志";
+      this.logDialogVisible = true;
+    },
   },
 };
 </script>

+ 51 - 0
ips-ui/src/views/biz/images/index.vue

@@ -141,6 +141,29 @@
         class-name="small-padding fixed-width"
       >
         <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-video-play"
+            @click="handleRun(scope.row)"
+            v-hasPermi="['biz:images:add']"
+            >运行</el-button
+          >
+          <el-button
+            type="text"
+            icon="el-icon-search"
+            @click="showLogViewer(scope.row)"
+          >
+            日志
+          </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-info"
+            @click="handleGetResult(scope.row)"
+            v-hasPermi="['biz:images:add']"
+            >查看结果</el-button
+          >
           <el-button
             size="mini"
             type="text"
@@ -213,6 +236,12 @@
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
+    <log-viewer
+      :currentLogUrl="currentLogUrl"
+      :dialogTitle="dialogTitle"
+      :logDialogVisible="logDialogVisible"
+      @updateLogDiaLlogVisible="updateLogDiaLlogVisible"
+    />
   </div>
 </template>
 
@@ -223,16 +252,19 @@ import {
   delImages,
   addImages,
   updateImages,
+  run,
 } from "@/api/biz/images";
 import { getOptionsByType } from "@/api/biz/config";
 import FolderPicker from "@/components/FolderPicker";
 import DynamicFormDialog from "@/components/DynamicFormDialog";
+import LogViewer from "@/components/LogViewer";
 export default {
   name: "Images",
   dicts: ["biz_status"],
   components: {
     FolderPicker,
     DynamicFormDialog,
+    LogViewer,
   },
   data() {
     return {
@@ -269,6 +301,10 @@ export default {
       rules: {},
       configOptions: [],
       showParamsDialog: false,
+      // 日志查看器
+      logDialogVisible: false,
+      currentLogUrl: "",
+      dialogTitle: "",
     };
   },
   created() {
@@ -409,6 +445,21 @@ export default {
         this.form.algorithmParams = "";
       }
     },
+    updateLogDiaLlogVisible(visiible) {
+      console.log("updateLogDiaLlogVisible", visiible);
+      this.logDialogVisible = visiible;
+    },
+    showLogViewer(row) {
+      this.currentLogUrl = row.outputPath + "\\" + "log.log";
+      this.dialogTitle = "日志";
+      this.logDialogVisible = true;
+    },
+    handleRun(row) {
+      const id = row.id;
+      run(id).then((response) => {
+        alert("任务开始运行!");
+      });
+    },
   },
 };
 </script>

+ 14 - 9
ips-ui/src/views/biz/preprocessed/index.vue

@@ -176,26 +176,26 @@
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-edit"
+            icon="el-icon-video-play"
             @click="handleRun(scope.row)"
             v-hasPermi="['biz:preprocessed:add']"
             >运行</el-button
           >
+          <el-button
+            type="text"
+            icon="el-icon-search"
+            @click="showLogViewer(scope.row)"
+          >
+            日志
+          </el-button>
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-edit"
+            icon="el-icon-info"
             @click="handleGetResult(scope.row)"
             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"
@@ -700,6 +700,11 @@ export default {
       console.log("updateLogDiaLlogVisible", visiible);
       this.logDialogVisible = visiible;
     },
+    showLogViewer(row) {
+      this.currentLogUrl = row.outputPath + "\\" + "log.log";
+      this.dialogTitle = "日志";
+      this.logDialogVisible = true;
+    },
   },
 };
 </script>

+ 32 - 4
ips-ui/src/views/biz/test/index.vue

@@ -176,17 +176,24 @@
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-edit"
+            icon="el-icon-video-play"
             @click="handleRun(scope.row)"
-            v-hasPermi="['biz:preprocessed:add']"
+            v-hasPermi="['biz:test:add']"
             >运行</el-button
           >
+          <el-button
+            type="text"
+            icon="el-icon-search"
+            @click="showLogViewer(scope.row)"
+          >
+            日志
+          </el-button>
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-edit"
+            icon="el-icon-info"
             @click="handleGetResult(scope.row)"
-            v-hasPermi="['biz:preprocessed:add']"
+            v-hasPermi="['biz:test:add']"
             >查看结果</el-button
           >
           <el-button
@@ -277,6 +284,12 @@
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
+    <log-viewer
+      :currentLogUrl="currentLogUrl"
+      :dialogTitle="dialogTitle"
+      :logDialogVisible="logDialogVisible"
+      @updateLogDiaLlogVisible="updateLogDiaLlogVisible"
+    />
   </div>
 </template>
 
@@ -295,6 +308,7 @@ import { getOptionsByType } from "@/api/biz/config";
 import FolderPicker from "@/components/FolderPicker";
 import FilePicker from "@/components/FilePicker";
 import DynamicFormDialog from "@/components/DynamicFormDialog";
+import LogViewer from "@/components/LogViewer";
 export default {
   name: "Test",
   dicts: ["biz_status"],
@@ -302,6 +316,7 @@ export default {
     FolderPicker,
     FilePicker,
     DynamicFormDialog,
+    LogViewer,
   },
   data() {
     return {
@@ -345,6 +360,10 @@ export default {
       jsonResult: {},
       selectFileName: "",
       showParamsDialog: false,
+      // 日志查看器
+      logDialogVisible: false,
+      currentLogUrl: "",
+      dialogTitle: "",
     };
   },
   created() {
@@ -500,6 +519,15 @@ export default {
       // 这里可以添加处理配置更新的逻辑
       console.log("更新后的配置:", JSON.parse(modifiedJson));
     },
+    updateLogDiaLlogVisible(visiible) {
+      console.log("updateLogDiaLlogVisible", visiible);
+      this.logDialogVisible = visiible;
+    },
+    showLogViewer(row) {
+      this.currentLogUrl = row.outputPath + "\\" + "log.log";
+      this.dialogTitle = "日志";
+      this.logDialogVisible = true;
+    },
   },
 };
 </script>

+ 32 - 4
ips-ui/src/views/biz/training/index.vue

@@ -176,17 +176,24 @@
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-edit"
+            icon="el-icon-video-play"
             @click="handleRun(scope.row)"
-            v-hasPermi="['biz:preprocessed:add']"
+            v-hasPermi="['biz:training:add']"
             >运行</el-button
           >
+          <el-button
+            type="text"
+            icon="el-icon-search"
+            @click="showLogViewer(scope.row)"
+          >
+            日志
+          </el-button>
           <el-button
             size="mini"
             type="text"
-            icon="el-icon-edit"
+            icon="el-icon-info"
             @click="handleGetResult(scope.row)"
-            v-hasPermi="['biz:preprocessed:add']"
+            v-hasPermi="['biz:training:add']"
             >查看结果</el-button
           >
           <el-button
@@ -274,6 +281,12 @@
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
+    <log-viewer
+      :currentLogUrl="currentLogUrl"
+      :dialogTitle="dialogTitle"
+      :logDialogVisible="logDialogVisible"
+      @updateLogDiaLlogVisible="updateLogDiaLlogVisible"
+    />
   </div>
 </template>
 
@@ -292,6 +305,7 @@ import { getOptionsByType } from "@/api/biz/config";
 import FolderPicker from "@/components/FolderPicker";
 import FilePicker from "@/components/FilePicker";
 import DynamicFormDialog from "@/components/DynamicFormDialog";
+import LogViewer from "@/components/LogViewer";
 export default {
   name: "Training",
   dicts: ["biz_status"],
@@ -299,6 +313,7 @@ export default {
     FolderPicker,
     DynamicFormDialog,
     FilePicker,
+    LogViewer,
   },
   data() {
     return {
@@ -342,6 +357,10 @@ export default {
       jsonResult: {},
       selectFileName: "",
       showParamsDialog: false,
+      // 日志查看器
+      logDialogVisible: false,
+      currentLogUrl: "",
+      dialogTitle: "",
     };
   },
   created() {
@@ -497,6 +516,15 @@ export default {
       // 这里可以添加处理配置更新的逻辑
       console.log("更新后的配置:", JSON.parse(modifiedJson));
     },
+    updateLogDiaLlogVisible(visiible) {
+      console.log("updateLogDiaLlogVisible", visiible);
+      this.logDialogVisible = visiible;
+    },
+    showLogViewer(row) {
+      this.currentLogUrl = row.outputPath + "\\" + "log.log";
+      this.dialogTitle = "日志";
+      this.logDialogVisible = true;
+    },
   },
 };
 </script>