From 9be4b9dbcfd281607aa525134d8ddffe2692807c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A5=BF=E5=A4=A7=E9=94=90?= <1070211640@qq.com> Date: Thu, 28 Mar 2024 15:13:15 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=E5=A2=9E=E5=8A=A0global=5Fparam=E5=AD=97?= =?UTF-8?q?=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../experiment/ExperimentController.java | 6 ++-- .../experiment/ExperimentInsController.java | 2 +- .../ruoyi/platform/domain/ExperimentIns.java | 17 +++++++++++ .../com/ruoyi/platform/domain/Workflow.java | 12 ++++++++ .../impl/ExperimentInsServiceImpl.java | 2 +- .../service/impl/ExperimentServiceImpl.java | 3 ++ .../service/impl/WorkflowServiceImpl.java | 3 ++ .../ExperimentInsDaoMapper.xml | 28 +++++++++++++------ .../managementPlatform/WorkflowDaoMapper.xml | 28 +++++++++++++------ .../WorkflowParamDaoMapper.xml | 2 +- 10 files changed, 80 insertions(+), 23 deletions(-) diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentController.java index 30603eab..cc8fff85 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentController.java @@ -45,7 +45,7 @@ public class ExperimentController extends BaseController { return genericsSuccess(this.experimentService.queryByPage(experiment, pageRequest)); } - @GetMapping(("/status")) + @GetMapping("/status") @ApiOperation("查询实验状态") public GenericsAjaxResult> selectStatus(@RequestBody Experiment experiment, PageRequest pageRequest) throws IOException { return genericsSuccess(this.experimentService.selectStatus(experiment, pageRequest)); @@ -53,8 +53,8 @@ public class ExperimentController extends BaseController { - @GetMapping(("/configuration")) - @ApiOperation("查询实验配置") + @GetMapping("/configuration") + @ApiOperation("查询实验配置参数") public GenericsAjaxResult> showExperimentConfig(@RequestBody Experiment experiment){ return genericsSuccess(this.experimentService.showExperimentConfig(experiment)); } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java index 2db90e05..b31e1316 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java @@ -138,7 +138,7 @@ public class ExperimentInsController extends BaseController { @GetMapping("/pods/log") @ApiOperation("获取pod实时日志请求") - public GenericsAjaxResult getRealtimePodLog(@RequestParam("pod_name") String podName, + public GenericsAjaxResult> getRealtimePodLog(@RequestParam("pod_name") String podName, @RequestParam("start_time") String startTime){ return genericsSuccess(this.experimentInsService.getRealtimePodLog(podName,startTime)); } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java index 1ec09234..6d3736c7 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java @@ -15,6 +15,7 @@ import java.util.Date; * @since 2023-11-09 09:48:36 */ @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +@ApiModel("实验实例对象") public class ExperimentIns implements Serializable { private static final long serialVersionUID = 623464560240790680L; @ApiModelProperty(name = "id") @@ -46,6 +47,14 @@ public class ExperimentIns implements Serializable { @ApiModelProperty(name = "nodes_logs") private String nodesLogs; + + + /** + * 实验实例全局参数 + */ +// @ApiModelProperty(name = "global_param") + private String globalParam; + /** * 开始时间 */ @@ -154,6 +163,14 @@ public class ExperimentIns implements Serializable { this.nodesLogs = nodesLogs; } + public String getGlobalParam() { + return globalParam; + } + + public void setGlobalParam(String globalParam) { + this.globalParam = globalParam; + } + public void setStartTime(Date startTime) { this.startTime = startTime; } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java index 70eb8f76..a6774593 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java @@ -46,6 +46,10 @@ public class Workflow extends BaseMetaObjectHandler implements Serializable { */ @ApiModelProperty(name = "dag") private String dag; + +// @ApiModelProperty(name = "global_param") + private String globalParam; + /** * 创建者 */ @@ -105,6 +109,14 @@ public class Workflow extends BaseMetaObjectHandler implements Serializable { this.dag = dag; } + public String getGlobalParam() { + return globalParam; + } + + public void setGlobalParam(String globalParam) { + this.globalParam = globalParam; + } + public String getCreateBy() { return createBy; } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java index 1122808c..c4ffd05c 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java @@ -91,7 +91,7 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { //搞个标记,当状态改变才去改表 boolean flag = false; List result = new ArrayList(); - if (experimentInsList!=null&&experimentInsList.size()>0) { + if (experimentInsList!=null&& experimentInsList.size()>0) { for (ExperimentIns experimentIns : experimentInsList) { //当原本状态为null或非终止态时才调用argo接口 if (experimentIns != null && (StringUtils.isEmpty(experimentIns.getStatus())) || !isTerminatedState(experimentIns)) { diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java index 1c224d73..a6ac4eeb 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java @@ -243,10 +243,13 @@ public class ExperimentServiceImpl implements ExperimentService { Map metadata = (Map) data.get("metadata"); + // 插入记录到实验实例表 ExperimentIns experimentIns = new ExperimentIns(); experimentIns.setExperimentId(experiment.getId()); experimentIns.setArgoInsNs((String) metadata.get("namespace")); experimentIns.setArgoInsName((String) metadata.get("name")); + //传入实验全局参数 + experimentIns.setGlobalParam(experiment.getGlobalParam()); //替换argoInsName String outputString = JsonUtils.mapToJson(output); diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/WorkflowServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/WorkflowServiceImpl.java index 023e1a98..59cb170d 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/WorkflowServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/WorkflowServiceImpl.java @@ -153,6 +153,8 @@ public class WorkflowServiceImpl implements WorkflowService { return new PageImpl<>(this.workflowDao.queryByName(name)); } + + @Override public Workflow duplicateWorkflow(Long id) { //先去查找数据库中存在的数据 @@ -180,6 +182,7 @@ public class WorkflowServiceImpl implements WorkflowService { } duplicateWorkflow.setDag(newDag); duplicateWorkflow.setDescription(workflow.getDescription()); + duplicateWorkflow.setGlobalParam(workflow.getGlobalParam()); return this.insert(duplicateWorkflow); } catch (Exception e) { throw new RuntimeException("复制流水线失败: " + e.getMessage(), e); diff --git a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentInsDaoMapper.xml b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentInsDaoMapper.xml index 89d41d53..0c223e21 100644 --- a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentInsDaoMapper.xml +++ b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentInsDaoMapper.xml @@ -24,14 +24,14 @@ select - id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs, start_time, finish_time, create_by, create_time, update_by, update_time, state + id, experiment_id, argo_ins_name, argo_ins_ns, status, nodes_status,nodes_result, nodes_logs,global_param, start_time, finish_time, create_by, create_time, update_by, update_time, state from experiment_ins state = 1 @@ -66,6 +66,9 @@ and nodes_logs = #{experimentIns.nodesLogs} + + and global_param = #{experimentIns.globalParam} + and start_time = #{experimentIns.startTime} @@ -90,7 +93,7 @@ select - id, name, description, dag, create_by, create_time, update_by, update_time, state + id, name, description, dag, global_param, create_by, create_time, update_by, update_time, state from workflow where id = #{id} and state = 1 @@ -25,7 +26,7 @@ select - id, name, description, dag, create_by, create_time, update_by, update_time, state + id, name, description, dag, global_param, create_by, create_time, update_by, update_time, state from workflow state = 1 diff --git a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/WorkflowParamDaoMapper.xml b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/WorkflowParamDaoMapper.xml index 6ee3a384..b8c15a14 100644 --- a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/WorkflowParamDaoMapper.xml +++ b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/WorkflowParamDaoMapper.xml @@ -7,7 +7,7 @@ - + From 77cf23033571d2cca391c790b4fdb941ac50afa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A5=BF=E5=A4=A7=E9=94=90?= <1070211640@qq.com> Date: Thu, 28 Mar 2024 15:36:44 +0800 Subject: [PATCH 02/12] =?UTF-8?q?global=5Fparam=E5=AD=97=E6=AE=B5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0@Jsonrawvalue=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/ruoyi/platform/domain/Experiment.java | 2 ++ .../src/main/java/com/ruoyi/platform/domain/ExperimentIns.java | 3 +++ .../src/main/java/com/ruoyi/platform/domain/Workflow.java | 2 ++ 3 files changed, 7 insertions(+) diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Experiment.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Experiment.java index 2a775f09..cb0bb320 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Experiment.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Experiment.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; +import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.ruoyi.common.core.web.domain.BaseEntity; @@ -34,6 +35,7 @@ public class Experiment implements Serializable { * 全局参数 */ @ApiModelProperty(name = "global_param") + @JsonRawValue private String globalParam; private String statusList; diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java index 6d3736c7..edb678e7 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java @@ -1,5 +1,6 @@ package com.ruoyi.platform.domain; +import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.annotation.JsonNaming; import io.swagger.annotations.ApiModel; @@ -53,6 +54,8 @@ public class ExperimentIns implements Serializable { * 实验实例全局参数 */ // @ApiModelProperty(name = "global_param") + + @JsonRawValue private String globalParam; /** diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java index a6774593..f4ddff72 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java @@ -2,6 +2,7 @@ package com.ruoyi.platform.domain; import com.baomidou.mybatisplus.annotation.TableId; import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.ruoyi.platform.handler.BaseMetaObjectHandler; @@ -48,6 +49,7 @@ public class Workflow extends BaseMetaObjectHandler implements Serializable { private String dag; // @ApiModelProperty(name = "global_param") + @JsonRawValue private String globalParam; /** From ed08068c92c78977af553a14403f9dec67b3251d Mon Sep 17 00:00:00 2001 From: fanshuai <1141904845@qq.com> Date: Thu, 28 Mar 2024 16:36:28 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-modules/management-platform/pom.xml | 6 ++ .../platform/config/WebSocketConfig.java | 17 +++++ .../experiment/ExperimentInsController.java | 9 +++ .../com/ruoyi/platform/domain/Workflow.java | 2 + .../service/ExperimentInsService.java | 2 + .../platform/service/WorkflowService.java | 1 + .../impl/ExperimentInsServiceImpl.java | 8 +++ .../service/impl/ExperimentServiceImpl.java | 1 + .../ruoyi/platform/utils/K8sClientUtil.java | 7 +- .../ruoyi/platform/webSocket/WebSocket.java | 70 +++++++++++++++++++ 10 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/config/WebSocketConfig.java create mode 100644 ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/webSocket/WebSocket.java diff --git a/ruoyi-modules/management-platform/pom.xml b/ruoyi-modules/management-platform/pom.xml index 9eedb568..4cb1ae7d 100644 --- a/ruoyi-modules/management-platform/pom.xml +++ b/ruoyi-modules/management-platform/pom.xml @@ -201,6 +201,12 @@ 0.1.55 + + org.springframework.boot + spring-boot-starter-websocket + + + diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/config/WebSocketConfig.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/config/WebSocketConfig.java new file mode 100644 index 00000000..9f946af1 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/config/WebSocketConfig.java @@ -0,0 +1,17 @@ +package com.ruoyi.platform.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +@Configuration +public class WebSocketConfig { + /** + * 注入 ServerEndpointExporter, + * 这个 bean 会自动注册使用了 @ServerEndpoint 注解声明的 WebSocket endpoint + */ + @Bean + public ServerEndpointExporter serverEndpointExporter() { + return new ServerEndpointExporter(); + } +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java index b31e1316..4b5fc804 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java @@ -143,6 +143,15 @@ public class ExperimentInsController extends BaseController { return genericsSuccess(this.experimentInsService.getRealtimePodLog(podName,startTime)); } + + @GetMapping("/pods/realtimelog") + @ApiOperation("获取pod实时日志请求") + public GenericsAjaxResult getRealtimePodLogFromPod(@RequestParam("pod_name") String podName, + @RequestParam("workspace") String workspace){ + return genericsSuccess(this.experimentInsService.getRealtimePodLogFromPod(podName,workspace)); + } + + /** * 查询实验实例实时日志 * diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java index a6774593..f4ddff72 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Workflow.java @@ -2,6 +2,7 @@ package com.ruoyi.platform.domain; import com.baomidou.mybatisplus.annotation.TableId; import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.ruoyi.platform.handler.BaseMetaObjectHandler; @@ -48,6 +49,7 @@ public class Workflow extends BaseMetaObjectHandler implements Serializable { private String dag; // @ApiModelProperty(name = "global_param") + @JsonRawValue private String globalParam; /** diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java index 96552f83..13ff922d 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java @@ -94,4 +94,6 @@ public interface ExperimentInsService { Map getRealtimeWorkflowLog(LogRequestVo logRequest); Map getRealtimePodLog(String podName, String startTime); + + String getRealtimePodLogFromPod(String podName, String namespace); } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/WorkflowService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/WorkflowService.java index 7520c562..41397348 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/WorkflowService.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/WorkflowService.java @@ -1,5 +1,6 @@ package com.ruoyi.platform.service; +import com.fasterxml.jackson.core.JsonProcessingException; import com.ruoyi.platform.domain.Workflow; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java index c4ffd05c..ee45a36e 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java @@ -51,6 +51,9 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { private String argoWorkflowRealTimeLog; @Value("${argo.workflowPodLog}") private String argoWorkflowPodLog; + @Value("${argo.ins.logsLines}") + private int logsLines; + private final MinioUtil minioUtil; public ExperimentInsServiceImpl(MinioUtil minioUtil) { @@ -518,6 +521,11 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { } + @Override + public String getRealtimePodLogFromPod(String podName, String namespace) { + return K8sClientUtil.getPodLogs(podName, namespace, logsLines); + } + private boolean isTerminatedState(ExperimentIns ins) throws IOException { // 定义终止态的列表,例如 "Succeeded", "Failed" 等 String status = ins.getStatus(); diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java index a6ac4eeb..650598ce 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java @@ -226,6 +226,7 @@ public class ExperimentServiceImpl implements ExperimentService { Map runReqMap = new HashMap<>(); runReqMap.put("data", converMap.get("data")); runReqMap.put("params", JsonUtils.jsonToMap(StringUtils.isEmpty(experiment.getGlobalParam())?"{}":experiment.getGlobalParam())); + runReqMap.put("experiment", new HashMap().put("name", "experiment-"+experiment.getId())); Map output = (Map) converMap.get("output"); // 调argo运行接口 String runRes = HttpUtils.sendPost(argoUrl + argoWorkflowRun, JsonUtils.mapToJson(runReqMap)); diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java index 4bc187d1..c0b59127 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java @@ -1,13 +1,16 @@ package com.ruoyi.platform.utils; +import com.alibaba.nacos.shaded.com.google.gson.reflect.TypeToken; import io.kubernetes.client.Exec; import io.kubernetes.client.custom.IntOrString; import io.kubernetes.client.custom.Quantity; import io.kubernetes.client.openapi.ApiClient; import io.kubernetes.client.openapi.ApiException; +import io.kubernetes.client.openapi.ApiResponse; import io.kubernetes.client.openapi.apis.CoreV1Api; import io.kubernetes.client.openapi.models.*; import io.kubernetes.client.util.ClientBuilder; +import io.kubernetes.client.util.Watch; import io.kubernetes.client.util.credentials.AccessTokenAuthentication; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; @@ -15,7 +18,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; import java.util.LinkedHashMap; @@ -405,10 +407,11 @@ public class K8sClientUtil { public static String getPodLogs(String podName,String namespace,int line) { CoreV1Api api = new CoreV1Api(apiClient); try { - String log = api.readNamespacedPodLog(podName, namespace, null, null, null, null, null,null, null, line, null); + String log = api.readNamespacedPodLog(podName, namespace, null, null, null, null, null,null, null, line, null); return log; } catch (ApiException e) { throw new RuntimeException("获取Pod日志异常", e); } + } } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/webSocket/WebSocket.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/webSocket/WebSocket.java new file mode 100644 index 00000000..b9b60ac8 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/webSocket/WebSocket.java @@ -0,0 +1,70 @@ +package com.ruoyi.platform.webSocket; + +import javax.annotation.Resource; +import javax.websocket.*; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; + +import com.ruoyi.platform.service.ExperimentInsService; +import com.ruoyi.platform.utils.K8sClientUtil; +import org.springframework.stereotype.Component; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.ConcurrentHashMap; + +@Component +@Slf4j +@ServerEndpoint("/websocket/workflowLogs") +@RestController +public class WebSocket { + private Session session; + private String userId; + private static CopyOnWriteArraySet webSockets = new CopyOnWriteArraySet<>(); + private static ConcurrentHashMap sessionPool = new ConcurrentHashMap<>(); + + @OnOpen + public void onOpen(Session session, @PathParam("userId") String userId) { + try { + this.session = session; + this.userId = "workflowLogs"; + webSockets.add(this); + sessionPool.put(userId, session); + log.info("【WebSocket 消息】有新的连接,总数为:" + webSockets.size()); + } catch (Exception e) { + // 异常处理 + } + } + + @OnClose + public void onClose() { + try { + webSockets.remove(this); + sessionPool.remove(this.userId); + log.info("【WebSocket 消息】连接断开,总数为:" + webSockets.size()); + } catch (Exception e) { + // 异常处理 + } + } + + @OnMessage + public void onMessage(String message, Session session) { + log.info("【WebSocket 消息】收到客户端消息:" + message); + // 处理收到的消息,例如获取实时日志数据 + + // 推送日志数据给客户端 + try { + K8sClientUtil.watchPodLog("workflow-controller-7c6f89997b-9lr8z", "argo"); + session.getBasicRemote().sendText("nihao"); + } catch (Exception e) { + log.error("【WebSocket 消息】推送日志数据失败:" + e.getMessage()); + } + } + + @OnError + public void onError(Session session, Throwable error) { + log.error("【WebSocket 消息】发生错误:" + error.getMessage()); + } +} From 64b800cefa0bcea4a236826f010cb88231ce344c Mon Sep 17 00:00:00 2001 From: fanshuai <1141904845@qq.com> Date: Fri, 29 Mar 2024 11:54:30 +0800 Subject: [PATCH 04/12] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ruoyi/platform/RuoYiManagementPlatformApplication.java | 1 + .../src/main/java/com/ruoyi/platform/webSocket/WebSocket.java | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/RuoYiManagementPlatformApplication.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/RuoYiManagementPlatformApplication.java index c266e000..b3b22ac9 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/RuoYiManagementPlatformApplication.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/RuoYiManagementPlatformApplication.java @@ -32,3 +32,4 @@ public class RuoYiManagementPlatformApplication { " ''-' `'-' `-..-' "); } } + diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/webSocket/WebSocket.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/webSocket/WebSocket.java index b9b60ac8..7f2fa47e 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/webSocket/WebSocket.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/webSocket/WebSocket.java @@ -56,7 +56,6 @@ public class WebSocket { // 推送日志数据给客户端 try { - K8sClientUtil.watchPodLog("workflow-controller-7c6f89997b-9lr8z", "argo"); session.getBasicRemote().sendText("nihao"); } catch (Exception e) { log.error("【WebSocket 消息】推送日志数据失败:" + e.getMessage()); From 449d7c52c22f26e784baf81b8be3b80d5283692e Mon Sep 17 00:00:00 2001 From: fanshuai <1141904845@qq.com> Date: Fri, 29 Mar 2024 14:02:44 +0800 Subject: [PATCH 05/12] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/experiment/ExperimentInsController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java index 4b5fc804..02b752fe 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java @@ -147,8 +147,8 @@ public class ExperimentInsController extends BaseController { @GetMapping("/pods/realtimelog") @ApiOperation("获取pod实时日志请求") public GenericsAjaxResult getRealtimePodLogFromPod(@RequestParam("pod_name") String podName, - @RequestParam("workspace") String workspace){ - return genericsSuccess(this.experimentInsService.getRealtimePodLogFromPod(podName,workspace)); + @RequestParam("namespace") String namespace){ + return genericsSuccess(this.experimentInsService.getRealtimePodLogFromPod(podName,namespace)); } From d4d4d98aaa2e20595709b64de8ffe9d03b2c712a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A5=BF=E5=A4=A7=E9=94=90?= <1070211640@qq.com> Date: Fri, 29 Mar 2024 15:22:42 +0800 Subject: [PATCH 06/12] =?UTF-8?q?=E8=BF=90=E8=A1=8C=E6=8E=A5=E5=8F=A3param?= =?UTF-8?q?s=E5=AD=97=E6=AE=B5=E4=BF=AE=E6=94=B9=E4=B8=BAList?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/experiment/ExperimentInsController.java | 6 +++--- .../ruoyi/platform/service/impl/ExperimentServiceImpl.java | 6 +++++- .../mapper/managementPlatform/ExperimentDaoMapper.xml | 6 +++--- .../mapper/managementPlatform/ExperimentInsDaoMapper.xml | 2 +- .../mapper/managementPlatform/WorkflowDaoMapper.xml | 4 ++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java index 02b752fe..3547fe11 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java @@ -144,10 +144,10 @@ public class ExperimentInsController extends BaseController { } - @GetMapping("/pods/realtimelog") + @GetMapping("/pods/realTimeLog") @ApiOperation("获取pod实时日志请求") - public GenericsAjaxResult getRealtimePodLogFromPod(@RequestParam("pod_name") String podName, - @RequestParam("namespace") String namespace){ + public GenericsAjaxResult getRealtimePodLogFromPod(@PathVariable("pod_name") String podName, + @PathVariable("namespace") String namespace){ return genericsSuccess(this.experimentInsService.getRealtimePodLogFromPod(podName,namespace)); } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java index 650598ce..d94dba8f 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentServiceImpl.java @@ -10,6 +10,7 @@ import com.ruoyi.platform.service.ExperimentInsService; import com.ruoyi.platform.service.ExperimentService; import com.ruoyi.platform.service.WorkflowService; import com.ruoyi.platform.utils.HttpUtils; +import com.ruoyi.platform.utils.JacksonUtil; import com.ruoyi.platform.utils.JsonUtils; import com.ruoyi.system.api.model.LoginUser; import org.apache.commons.collections4.MapUtils; @@ -225,8 +226,11 @@ public class ExperimentServiceImpl implements ExperimentService { // 组装运行接口json Map runReqMap = new HashMap<>(); runReqMap.put("data", converMap.get("data")); - runReqMap.put("params", JsonUtils.jsonToMap(StringUtils.isEmpty(experiment.getGlobalParam())?"{}":experiment.getGlobalParam())); + List> params = JacksonUtil.parseJSONStr2MapList(StringUtils.isEmpty(experiment.getGlobalParam()) ? "[]" : experiment.getGlobalParam()); + runReqMap.put("params", params); + //runReqMap.put("params", JsonUtils.jsonToMap(StringUtils.isEmpty(experiment.getGlobalParam())?"{}":experiment.getGlobalParam())); runReqMap.put("experiment", new HashMap().put("name", "experiment-"+experiment.getId())); + Map output = (Map) converMap.get("output"); // 调argo运行接口 String runRes = HttpUtils.sendPost(argoUrl + argoWorkflowRun, JsonUtils.mapToJson(runReqMap)); diff --git a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentDaoMapper.xml b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentDaoMapper.xml index b4df6caf..ccf5bd1f 100644 --- a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentDaoMapper.xml +++ b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentDaoMapper.xml @@ -84,7 +84,7 @@ and global_param = #{experiment.globalParam} - status_list = #{experiment.statusList}, + status_list = #{experiment.statusList} and description = #{experiment.description} @@ -125,7 +125,7 @@ and global_param = #{experiment.globalParam} - status_list = #{experiment.statusList}, + status_list = #{experiment.statusList} and description = #{experiment.description} @@ -148,7 +148,7 @@ insert into experiment(name,workflow_id, global_param, status_list, description, create_by, create_time, update_by, update_time, state) - values (#{experiment.name},#{experiment.workflowId}, #{experiment.globalParam},#{experiment.statusList}, #{experiment.description}, #{experiment.createBy}, #{experiment.createTime}, #{experiment.updateBy}, #{experiment.updateTime}, #{experiment.state}) + values (#{experiment.name},#{experiment.workflowId}, #{experiment.globalParam},#{experiment.statusList}, #{experiment.description}, #{experiment.createBy}, #{experiment.createTime}, #{experiment.updateBy}, #{experiment.updateTime}, #{experiment.state}) diff --git a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentInsDaoMapper.xml b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentInsDaoMapper.xml index 0c223e21..1f6aa194 100644 --- a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentInsDaoMapper.xml +++ b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ExperimentInsDaoMapper.xml @@ -248,7 +248,7 @@ nodes_logs = #{experimentIns.nodesLogs}, - global_param = #{experimentIns.globalParam} + global_param = #{experimentIns.globalParam}, start_time = #{experimentIns.startTime}, diff --git a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/WorkflowDaoMapper.xml b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/WorkflowDaoMapper.xml index 0b63fdca..c1c6bb9e 100644 --- a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/WorkflowDaoMapper.xml +++ b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/WorkflowDaoMapper.xml @@ -18,7 +18,7 @@ @@ -147,7 +147,7 @@ dag = #{workflow.dag}, - global_param = #{workflow.globalParam} + global_param = #{workflow.globalParam}, create_by = #{workflow.createBy}, From 6fba822c18d35f5e0abe88afc161a175375a50a3 Mon Sep 17 00:00:00 2001 From: fanshuai <1141904845@qq.com> Date: Fri, 29 Mar 2024 15:26:41 +0800 Subject: [PATCH 07/12] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/experiment/ExperimentInsController.java | 4 ++-- .../java/com/ruoyi/platform/service/ExperimentInsService.java | 2 +- .../ruoyi/platform/service/impl/ExperimentInsServiceImpl.java | 4 ++-- .../src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java index 3547fe11..ede76079 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java @@ -147,8 +147,8 @@ public class ExperimentInsController extends BaseController { @GetMapping("/pods/realTimeLog") @ApiOperation("获取pod实时日志请求") public GenericsAjaxResult getRealtimePodLogFromPod(@PathVariable("pod_name") String podName, - @PathVariable("namespace") String namespace){ - return genericsSuccess(this.experimentInsService.getRealtimePodLogFromPod(podName,namespace)); + @PathVariable("namespace") String namespace,@PathVariable("container_name") String containerName){ + return genericsSuccess(this.experimentInsService.getRealtimePodLogFromPod(podName,namespace,containerName)); } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java index 13ff922d..8293dec1 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java @@ -95,5 +95,5 @@ public interface ExperimentInsService { Map getRealtimePodLog(String podName, String startTime); - String getRealtimePodLogFromPod(String podName, String namespace); + String getRealtimePodLogFromPod(String podName, String namespace,String container); } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java index ee45a36e..19f4ddf5 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java @@ -522,8 +522,8 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { } @Override - public String getRealtimePodLogFromPod(String podName, String namespace) { - return K8sClientUtil.getPodLogs(podName, namespace, logsLines); + public String getRealtimePodLogFromPod(String podName, String namespace,String container) { + return K8sClientUtil.getPodLogs(podName, namespace,container, logsLines); } private boolean isTerminatedState(ExperimentIns ins) throws IOException { diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java index c0b59127..04a2d4bd 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java @@ -404,10 +404,10 @@ public class K8sClientUtil { return pod.getStatus().getPhase(); } - public static String getPodLogs(String podName,String namespace,int line) { + public static String getPodLogs(String podName,String namespace,String container,int line) { CoreV1Api api = new CoreV1Api(apiClient); try { - String log = api.readNamespacedPodLog(podName, namespace, null, null, null, null, null,null, null, line, null); + String log = api.readNamespacedPodLog(podName, namespace, StringUtils.isEmpty(container)?null:container, null, null, null, null,null, null, line, null); return log; } catch (ApiException e) { throw new RuntimeException("获取Pod日志异常", e); From 32fe9b48990a62965ce27aff6aca042bc1e280bb Mon Sep 17 00:00:00 2001 From: fanshuai <1141904845@qq.com> Date: Fri, 29 Mar 2024 16:18:07 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/experiment/ExperimentInsController.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java index ede76079..6e55db2b 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java @@ -144,10 +144,9 @@ public class ExperimentInsController extends BaseController { } - @GetMapping("/pods/realTimeLog") + @PostMapping("/pods/realTimeLog") @ApiOperation("获取pod实时日志请求") - public GenericsAjaxResult getRealtimePodLogFromPod(@PathVariable("pod_name") String podName, - @PathVariable("namespace") String namespace,@PathVariable("container_name") String containerName){ + public GenericsAjaxResult getRealtimePodLogFromPod(@RequestParam("namespace") String namespace, @RequestParam("container_name") String containerName,@RequestParam("pod_name") String podName){ return genericsSuccess(this.experimentInsService.getRealtimePodLogFromPod(podName,namespace,containerName)); } From 7afddb91bdf0855ff7ff69729765994ddef033d7 Mon Sep 17 00:00:00 2001 From: fanshuai <1141904845@qq.com> Date: Fri, 29 Mar 2024 17:04:03 +0800 Subject: [PATCH 09/12] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../experiment/ExperimentInsController.java | 5 ++- .../service/ExperimentInsService.java | 4 +- .../impl/ExperimentInsServiceImpl.java | 5 ++- .../java/com/ruoyi/platform/vo/PodLogVo.java | 37 +++++++++++++++++++ 4 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/PodLogVo.java diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java index 6e55db2b..f2bd4688 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java @@ -5,6 +5,7 @@ import com.ruoyi.common.core.web.domain.GenericsAjaxResult; import com.ruoyi.platform.domain.ExperimentIns; import com.ruoyi.platform.service.ExperimentInsService; import com.ruoyi.platform.vo.LogRequestVo; +import com.ruoyi.platform.vo.PodLogVo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.data.domain.Page; @@ -146,8 +147,8 @@ public class ExperimentInsController extends BaseController { @PostMapping("/pods/realTimeLog") @ApiOperation("获取pod实时日志请求") - public GenericsAjaxResult getRealtimePodLogFromPod(@RequestParam("namespace") String namespace, @RequestParam("container_name") String containerName,@RequestParam("pod_name") String podName){ - return genericsSuccess(this.experimentInsService.getRealtimePodLogFromPod(podName,namespace,containerName)); + public GenericsAjaxResult getRealtimePodLogFromPod(@RequestBody PodLogVo podLogVo){ + return genericsSuccess(this.experimentInsService.getRealtimePodLogFromPod(podLogVo)); } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java index 8293dec1..56f5303d 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java @@ -2,6 +2,7 @@ package com.ruoyi.platform.service; import com.ruoyi.platform.domain.ExperimentIns; import com.ruoyi.platform.vo.LogRequestVo; +import com.ruoyi.platform.vo.PodLogVo; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -95,5 +96,6 @@ public interface ExperimentInsService { Map getRealtimePodLog(String podName, String startTime); - String getRealtimePodLogFromPod(String podName, String namespace,String container); + String getRealtimePodLogFromPod(PodLogVo podLogVo); + } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java index 19f4ddf5..8633f47a 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ExperimentInsServiceImpl.java @@ -9,6 +9,7 @@ import com.ruoyi.platform.service.ExperimentInsService; import com.ruoyi.platform.service.WorkflowService; import com.ruoyi.platform.utils.*; import com.ruoyi.platform.vo.LogRequestVo; +import com.ruoyi.platform.vo.PodLogVo; import com.ruoyi.system.api.model.LoginUser; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; @@ -522,8 +523,8 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { } @Override - public String getRealtimePodLogFromPod(String podName, String namespace,String container) { - return K8sClientUtil.getPodLogs(podName, namespace,container, logsLines); + public String getRealtimePodLogFromPod(PodLogVo podLogVo) { + return K8sClientUtil.getPodLogs(podLogVo.getPodName(), podLogVo.getNamespace(),podLogVo.getContainerName(), logsLines); } private boolean isTerminatedState(ExperimentIns ins) throws IOException { diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/PodLogVo.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/PodLogVo.java new file mode 100644 index 00000000..87574a4e --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/PodLogVo.java @@ -0,0 +1,37 @@ +package com.ruoyi.platform.vo; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import java.io.Serializable; + +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class PodLogVo implements Serializable { + private String podName; + private String namespace; + private String containerName; + + public String getPodName() { + return podName; + } + + public void setPodName(String podName) { + this.podName = podName; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getContainerName() { + return containerName; + } + + public void setContainerName(String containerName) { + this.containerName = containerName; + } +} From 54be56a559ffd93f6e0a90acb9e4a18530fb54e0 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Mon, 1 Apr 2024 14:37:19 +0800 Subject: [PATCH 10/12] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/.eslintrc.js | 3 + react-ui/config/proxy.ts | 4 +- react-ui/config/routes.ts | 35 +- react-ui/src/app.tsx | 91 +- react-ui/src/dayjsConfig.ts | 3 + react-ui/src/enums/status.d.ts | 1 + react-ui/src/hooks/dict.ts | 6 + react-ui/src/hooks/index.ts | 12 + react-ui/src/hooks/net/dict.ts | 7 - .../DatasetAnnotation/index.less | 10 + .../DatasetAnnotation/index.tsx | 11 + .../Experiment/experimentText/LogList.tsx | 18 + .../experimentText/addExperimentModal.less | 51 + .../experimentText/addExperimentModal.tsx | 127 +++ .../pages/Experiment/experimentText/index.jsx | 716 +++++++------- .../Experiment/experimentText/logGroup.less | 34 + .../Experiment/experimentText/logGroup.tsx | 127 +++ .../pages/Experiment/experimentText/props.jsx | 714 ++++++++------ react-ui/src/pages/Experiment/index.jsx | 889 +++++++++--------- react-ui/src/pages/Experiment/index.less | 143 +-- react-ui/src/pages/Experiment/status.ts | 59 ++ react-ui/src/pages/Experiment/types.ts | 0 react-ui/src/pages/Model/modelIntro.jsx | 399 ++++---- react-ui/src/pages/Model/personalData.jsx | 526 ++++++----- react-ui/src/pages/Model/publicData.jsx | 464 +++++---- react-ui/src/pages/User/Center/index.tsx | 48 +- react-ui/src/requestConfig.ts | 57 ++ react-ui/src/requestErrorConfig.ts | 109 --- react-ui/src/services/experiment/index.js | 129 +-- react-ui/src/services/session.ts | 26 +- react-ui/src/utils/date.ts | 38 + react-ui/src/utils/promise.ts | 20 + react-ui/tsconfig.json | 40 +- 33 files changed, 2787 insertions(+), 2130 deletions(-) create mode 100644 react-ui/src/dayjsConfig.ts create mode 100644 react-ui/src/enums/status.d.ts create mode 100644 react-ui/src/hooks/dict.ts create mode 100644 react-ui/src/hooks/index.ts delete mode 100644 react-ui/src/hooks/net/dict.ts create mode 100644 react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.less create mode 100644 react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.tsx create mode 100644 react-ui/src/pages/Experiment/experimentText/LogList.tsx create mode 100644 react-ui/src/pages/Experiment/experimentText/addExperimentModal.less create mode 100644 react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx create mode 100644 react-ui/src/pages/Experiment/experimentText/logGroup.less create mode 100644 react-ui/src/pages/Experiment/experimentText/logGroup.tsx create mode 100644 react-ui/src/pages/Experiment/status.ts create mode 100644 react-ui/src/pages/Experiment/types.ts create mode 100644 react-ui/src/requestConfig.ts delete mode 100644 react-ui/src/requestErrorConfig.ts create mode 100644 react-ui/src/utils/date.ts create mode 100644 react-ui/src/utils/promise.ts diff --git a/react-ui/.eslintrc.js b/react-ui/.eslintrc.js index 3ac39ef6..ad3e7590 100644 --- a/react-ui/.eslintrc.js +++ b/react-ui/.eslintrc.js @@ -4,4 +4,7 @@ module.exports = { page: true, REACT_APP_ENV: true, }, + rules: { + "@typescript-eslint/no-use-before-define": "off" + } }; diff --git a/react-ui/config/proxy.ts b/react-ui/config/proxy.ts index 911db70b..cbdd6337 100644 --- a/react-ui/config/proxy.ts +++ b/react-ui/config/proxy.ts @@ -16,8 +16,8 @@ export default { '/api/': { // 要代理的地址 // target: 'http://172.20.32.181:31205', - // target: 'http://172.20.32.98:8082', - target: 'http://172.20.32.150:8082', + target: 'http://172.20.32.98:8082', + // target: 'http://172.20.32.150:8082', // 配置了这个可以从 http 代理到 https // 依赖 origin 的功能可能需要这个,比如 cookie changeOrigin: true, diff --git a/react-ui/config/routes.ts b/react-ui/config/routes.ts index 9dd26c3e..9c30003d 100644 --- a/react-ui/config/routes.ts +++ b/react-ui/config/routes.ts @@ -46,18 +46,34 @@ export default [ }, ], }, + { + name: 'datasetPreparation', + path: '/datasetPreparation', + routes: [ + { + name: 'datasetAnnotation', + path: 'datasetAnnotation', + component: './DatasetPreparation/DatasetAnnotation/index', + }, + { + name: '训练', + path: 'pytorchtext/:id/:name', + component: './Pipeline/editPipeline/index', + }, + ], + }, { name: 'pipeline', path: '/pipeline', routes: [ { name: '流水线', - path: '/pipeline', + path: '', component: './Pipeline/index', }, { name: '训练', - path: '/pipeline/pytorchtext/:id/:name', + path: 'pytorchtext/:id/:name', component: './Pipeline/editPipeline/index', }, ], @@ -68,12 +84,12 @@ export default [ routes: [ { name: '实验', - path: '/experiment', + path: '', component: './Experiment/index', }, { name: '实验训练', - path: '/experiment/pytorchtext/:workflowId/:id', + path: 'pytorchtext/:workflowId/:id', component: './Experiment/experimentText/index', }, ], @@ -84,7 +100,7 @@ export default [ routes: [ { name: '开发环境', - path: '/developmentEnvironment', + path: '', component: './DevelopmentEnvironment/index', }, ], @@ -103,7 +119,7 @@ export default [ path: '/system/role-auth/user/:id', component: './System/Role/authUser', }, - ] + ], }, { name: 'dataset', @@ -123,14 +139,13 @@ export default [ name: '模型管理', path: '/dataset/modelIndex', component: './Model/index', - }, { name: '模型简介', path: '/dataset/modelIntro/:id', component: './Model/modelIntro', }, - ] + ], }, { name: 'monitor', @@ -141,7 +156,7 @@ export default [ path: '/monitor/job-log/index/:id', component: './Monitor/JobLog', }, - ] + ], }, { name: 'tool', @@ -157,6 +172,6 @@ export default [ path: '/tool/gen/edit', component: './Tool/Gen/edit', }, - ] + ], }, ]; diff --git a/react-ui/src/app.tsx b/react-ui/src/app.tsx index de4c7db2..07fa0094 100644 --- a/react-ui/src/app.tsx +++ b/react-ui/src/app.tsx @@ -1,23 +1,25 @@ - import RightContent from '@/components/RightContent'; -import { LinkOutlined } from '@ant-design/icons'; import type { Settings as LayoutSettings } from '@ant-design/pro-components'; -import { SettingDrawer } from '@ant-design/pro-components'; import type { RunTimeLayoutConfig } from '@umijs/max'; -import { history, Link } from '@umijs/max'; +import { history } from '@umijs/max'; +import axios from 'axios'; import defaultSettings from '../config/defaultSettings'; -import { errorConfig } from './requestErrorConfig'; -import { clearSessionToken, getAccessToken, getRefreshToken, getTokenExpireTime } from './access'; -import { getRemoteMenu, getRoutersInfo, getUserInfo, patchRouteWithRemoteMenus, setRemoteMenu } from './services/session'; +import '../public/fonts/font.css'; +import { getAccessToken } from './access'; +import './dayjsConfig'; import { PageEnum } from './enums/pagesEnums'; -import '../public/fonts/font.css' -import './global.less' -import axios from 'axios' -axios.defaults.baseUrl='http://172.20.32.150:8082' +import './global.less'; +import { + getRemoteMenu, + getRoutersInfo, + getUserInfo, + patchRouteWithRemoteMenus, + setRemoteMenu, +} from './services/session'; +export { requestConfig as request } from './requestConfig'; +axios.defaults.baseUrl = 'http://172.20.32.150:8082'; const isDev = process.env.NODE_ENV === 'development'; - - /** * @see https://umijs.org/zh-CN/plugins/plugin-initial-state * */ @@ -155,9 +157,9 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) = export async function onRouteChange({ clientRoutes, location }) { const menus = getRemoteMenu(); - // console.log('onRouteChange', clientRoutes, location, menus); - if(menus === null && location.pathname !== PageEnum.LOGIN) { - console.log('refresh') + // console.log('onRouteChange', clientRoutes, location, menus); + if (menus === null && location.pathname !== PageEnum.LOGIN) { + console.log('refresh'); history.go(0); } } @@ -166,7 +168,6 @@ export async function onRouteChange({ clientRoutes, location }) { // console.log('patchRoutes', routes, routeComponents); // } - export async function patchClientRoutes({ routes }) { // console.log('patchClientRoutes', routes); patchRouteWithRemoteMenus(routes); @@ -175,62 +176,12 @@ export async function patchClientRoutes({ routes }) { export function render(oldRender: () => void) { // console.log('render get routers', oldRender) const token = getAccessToken(); - if(!token || token?.length === 0) { + if (!token || token?.length === 0) { oldRender(); return; } - getRoutersInfo().then(res => { + getRoutersInfo().then((res) => { setRemoteMenu(res); - oldRender() + oldRender(); }); } - -/** - * @name request 配置,可以配置错误处理 - * 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。 - * @doc https://umijs.org/docs/max/request#配置 - */ -const checkRegion = 5 * 60 * 1000; - -export const request = { - ...errorConfig, - requestInterceptors: [ - (url: any, options: { headers: any }) => { - const headers = options.headers ? options.headers : []; - console.log('request ====>:', url); - const authHeader = headers['Authorization']; - const isToken = headers['isToken']; - if (!authHeader && isToken !== false) { - const expireTime = getTokenExpireTime(); - if (expireTime) { - const left = Number(expireTime) - new Date().getTime(); - const refreshToken = getRefreshToken(); - if (left < checkRegion && refreshToken) { - if (left < 0) { - clearSessionToken(); - } - } else { - const accessToken = getAccessToken(); - if (accessToken) { - headers['Authorization'] = `Bearer ${accessToken}`; - } - } - } else { - clearSessionToken(); - } - } - return { url, options }; - }, - ], - responseInterceptors: [ - // (response) => - // { - // // // 不再需要异步处理读取返回体内容,可直接在data中读出,部分字段可在 config 中找到 - // // const { data = {} as any, config } = response; - // // // do something - // // console.log('data: ', data) - // // console.log('config: ', config) - // return response - // }, - ], -}; diff --git a/react-ui/src/dayjsConfig.ts b/react-ui/src/dayjsConfig.ts new file mode 100644 index 00000000..199db3db --- /dev/null +++ b/react-ui/src/dayjsConfig.ts @@ -0,0 +1,3 @@ +import dayjs from 'dayjs'; +import duration from 'dayjs/plugin/duration'; +dayjs.extend(duration); diff --git a/react-ui/src/enums/status.d.ts b/react-ui/src/enums/status.d.ts new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/react-ui/src/enums/status.d.ts @@ -0,0 +1 @@ + diff --git a/react-ui/src/hooks/dict.ts b/react-ui/src/hooks/dict.ts new file mode 100644 index 00000000..e474b9f2 --- /dev/null +++ b/react-ui/src/hooks/dict.ts @@ -0,0 +1,6 @@ +import { getDictValueEnum } from '@/services/system/dict'; + +export function useDictEnum(name: string) { + const data = getDictValueEnum(name); + return data; +} diff --git a/react-ui/src/hooks/index.ts b/react-ui/src/hooks/index.ts new file mode 100644 index 00000000..d0c7705a --- /dev/null +++ b/react-ui/src/hooks/index.ts @@ -0,0 +1,12 @@ +import { useEffect, useRef, useState } from 'react'; +export function useStateRef(initialValue: T) { + const [value, setValue] = useState(initialValue); + + const ref = useRef(value); + + useEffect(() => { + ref.current = value; + }, [value]); + + return [value, setValue, ref] as const; +} diff --git a/react-ui/src/hooks/net/dict.ts b/react-ui/src/hooks/net/dict.ts deleted file mode 100644 index 9c2c41c5..00000000 --- a/react-ui/src/hooks/net/dict.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { getDictValueEnum } from "@/services/system/dict"; - -export function useDictEnum(name: string) -{ - const data = getDictValueEnum(name); - return data; -} \ No newline at end of file diff --git a/react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.less b/react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.less new file mode 100644 index 00000000..d0d8b09b --- /dev/null +++ b/react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.less @@ -0,0 +1,10 @@ +.container { + width: 100%; + height: 100%; + + .frame { + width: 100%; + height: 100%; + border: none; + } +} diff --git a/react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.tsx b/react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.tsx new file mode 100644 index 00000000..e5c03dbc --- /dev/null +++ b/react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.tsx @@ -0,0 +1,11 @@ +import styles from './index.less'; + +function DatasetAnnotation() { + return ( +
+ +
+ ); +} + +export default DatasetAnnotation; diff --git a/react-ui/src/pages/Experiment/experimentText/LogList.tsx b/react-ui/src/pages/Experiment/experimentText/LogList.tsx new file mode 100644 index 00000000..57e7a7e1 --- /dev/null +++ b/react-ui/src/pages/Experiment/experimentText/LogList.tsx @@ -0,0 +1,18 @@ +import LogGroup from './logGroup'; + +type LogListProps = { + list: any[]; + status: string; +}; + +function LogList({ list = [], status }: LogListProps) { + return ( +
+ {list.map((v) => ( + + ))} +
+ ); +} + +export default LogList; diff --git a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less new file mode 100644 index 00000000..a7bb2af8 --- /dev/null +++ b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less @@ -0,0 +1,51 @@ +.modal { + :global { + .ant-modal-content { + width: 825px; + padding: 20px 67px; + background: linear-gradient(180deg, #cfdfff 0%, #d4e2ff 9.77%, #ffffff 40%, #ffffff 100%); + border-radius: 21px; + } + .ant-modal-header { + margin: 20px 0; + background-color: transparent; + } + .ant-input { + height: 40px; + border-color: #e6e6e6; + } + .ant-select-single { + height: 40px; + } + .ant-form-item .ant-form-item-label > label { + color: rgba(29, 29, 32, 0.8); + } + .ant-modal-footer { + display: flex; + justify-content: center; + margin: 40px 0 30px 0; + } + .ant-btn { + width: 110px; + height: 40px; + font-size: 18px; + background: rgba(22, 100, 255, 0.06); + border-color: transparent; + border-radius: 10px; + } + .ant-btn-primary { + background: #1664ff; + } + } + + .title { + display: flex; + align-items: center; + font-weight: 500; + + .image { + width: 20px; + margin-right: 10px; + } + } +} diff --git a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx new file mode 100644 index 00000000..89148473 --- /dev/null +++ b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx @@ -0,0 +1,127 @@ +import { Form, Input, Modal, Select } from 'antd'; +import { useState } from 'react'; +import styles from './addExperimentModal.less'; + +type FormData = { + name?: string; + description?: string; + workflow_id?: string | number; +}; + +type AddExperimentModalProps = { + isAdd: boolean; + open: boolean; + onCancel: () => void; + onFinish: () => void; + workflowList: Workflow[]; + initialValues: FormData; +}; + +interface GlobalParam { + param_name: string; + param_value: string; +} + +interface Workflow { + id: string | number; + name: string; + global_param?: GlobalParam[] | null; +} + +function AddExperimentModal({ + isAdd, + open, + onCancel, + onFinish, + workflowList = [], + initialValues = {}, +}: AddExperimentModalProps) { + const dialogTitle = isAdd ? '新建实验' : '编辑实验'; + const workflowDisabled = isAdd ? false : true; + const [globalParam, setGlobalParam] = useState([]); + const [form] = Form.useForm(); + // 除了流水线选择发生变化 + const handleWorkflowChange = (id: string) => { + const pipeline: Workflow | undefined = workflowList.find((v) => v.id === id); + if (pipeline && pipeline.global_param) { + setGlobalParam(pipeline.global_param); + const fields = pipeline.global_param.reduce((acc, item) => { + acc[item.param_name] = item.param_value; + return acc; + }, {} as Record); + form.setFieldsValue(fields); + } else { + setGlobalParam([]); + } + }; + return ( + + + {dialogTitle} + + } + open={open} + okButtonProps={{ + htmlType: 'submit', + form: 'form', + }} + onCancel={onCancel} + destroyOnClose={true} + > +
+ + + + + + + + + + {globalParam.map((item) => ( + + + + ))} +
+
+ ); +} + +export default AddExperimentModal; diff --git a/react-ui/src/pages/Experiment/experimentText/index.jsx b/react-ui/src/pages/Experiment/experimentText/index.jsx index 51b0f21f..37dbb4b3 100644 --- a/react-ui/src/pages/Experiment/experimentText/index.jsx +++ b/react-ui/src/pages/Experiment/experimentText/index.jsx @@ -1,375 +1,405 @@ -import React ,{ useState,useEffect,useRef }from 'react'; -import { useParams } from 'react-router-dom' -import Props from './props'; +import { getExperimentIns } from '@/services/experiment/index.js'; +import { getWorkflowById } from '@/services/pipeline/index.js'; +import { elapsedTime } from '@/utils/date'; import { useEmotionCss } from '@ant-design/use-emotion-css'; import G6 from '@antv/g6'; -import Styles from './editPipeline.less' +import momnet from 'moment'; +import { useEffect, useRef, useState } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; import { s8 } from '../../../utils'; -import { Button, message} from 'antd'; -import {SaveOutlined} from '@ant-design/icons'; -import {saveWorkflow,getWorkflowById,} from '@/services/pipeline/index.js' -import {getExperimentIns,} from '@/services/experiment/index.js' -import { useNavigate} from 'react-router-dom'; -import momnet from 'moment' -const ExperimentText = React.FC = () => { - const propsRef=useRef() - const navgite=useNavigate(); - const locationParams =useParams () //新版本获取路由参数接口 - let graph=null - const [experimentStatusObj,setExperimentStatusObj]=useState({}) - const [experimentAllMessage,setExperimentAllMessage]=useState({}) - const statusObj={ - "Running":'运行中', - "Succeeded":'成功', - "Pending":'等待中', - "Failed":'失败', - "Error":'错误', - "Terminated":'终止', - "Skipped":'未执行', - "Omitted":'未执行', - } - const statusColorObj={ - "Running":'#165bff', - "Succeeded":'#63a728', - "Pending":'#f981eb', - "Failed":'#c73131', - "Error":'#c73131', - "Terminated":'#8a8a8a', - "Skipped":'#8a8a8a', - "Omitted":'#8a8a8ae', +import { experimentStatusInfo } from '../status'; +import Styles from './editPipeline.less'; +import Props from './props'; + +function ExperimentText() { + const [message, setMessage] = useState({}); + const messageRef = useRef(message); + const propsRef = useRef(); + const navgite = useNavigate(); + const locationParams = useParams(); //新版本获取路由参数接口 + let graph = null; + + const timers = (time) => { + let timer = new Date(time); + let hours = timer.getHours(); //转换成时 + let minutes = timer.getMinutes(); //转换成分 + let secend = timer.getSeconds(); //转换成秒 + + let str = `${minutes}分${secend}秒`; + return str; + }; + const pipelineContainer = useEmotionCss(() => { + return { + display: 'flex', + backgroundColor: '#fff', + height: '98vh', + }; + }); + const graphStyle = useEmotionCss(() => { + return { + width: '100%', + backgroundColor: '#f9fafb', + flex: 1, + }; + }); + const graphRef = useRef(); + const onDragEnd = (val) => { + console.log(val, 'eee'); + const _x = val.x; + const _y = val.y; + const point = graph.getPointByClient(_x, _y); + let model = {}; + // 元模型 + model = { + ...val, + x: point.x, + y: point.y, + id: val.component_name + '-' + s8(), + isCluster: false, + }; + console.log(graph, model); + + graph.addItem('node', model, true); + console.log(graph); + }; + const formChange = (val) => {}; + const handlerClick = (e) => { + console.log(propsRef, graph, messageRef.current); + // let cache = []; + // let json_str = JSON.stringify(graph, function(key, value) { + // if (typeof value === 'object' && value !== null) { + // if (cache.indexOf(value) !== -1) { + // return; + // } + // cache.push(value); + // } + // return value; + // }); + // console.log(json_str); + propsRef.current.showDrawer(e, locationParams.id, messageRef.current); + }; + const getGraphData = (data) => { + if (graph) { + console.log(graph); + graph.data(data); + graph.render(); + } else { + setTimeout(() => { + getGraphData(data); + }, 500); } - const timers=(time)=>{ - let timer=new Date(time) - let hours = timer.getHours(); //转换成时 - let minutes = timer.getMinutes(); //转换成分 - let secend = timer.getSeconds(); //转换成秒 - - let str = `${minutes}分${secend}秒`; - return str; - } - const pipelineContainer = useEmotionCss(() => { - return { - display: 'flex', - backgroundColor:'#fff', - height:'98vh' - }; - }); - const graphStyle = useEmotionCss(() => { - return { - width:'100%', - backgroundColor:'#f9fafb', - flex:1 - }; - }); - const graphRef=useRef() - const onDragEnd=(val)=>{ - console.log(val,'eee'); - const _x = val.x - const _y = val.y - const point = graph.getPointByClient(_x, _y); - let model = {}; - // 元模型 - model = { - ...val, - x: point.x, - y: point.y, - id: val.component_name+'-'+s8(), - isCluster: false, - }; - console.log(graph, model); + }; + const getFirstWorkflow = (val) => { + getWorkflowById(val).then((ret) => { + console.log(ret, 'retttttttttt'); + if (ret.code == 200) { + if (graph && ret.data && ret.data.dag) { + console.log(JSON.parse(ret.data.dag)); + getExperimentIns(locationParams.id).then((res) => { + if (res.code == 200) { + console.log(ret.data, 'data'); + setMessage(res.data); + const experimentStatusObjs = JSON.parse(res.data.nodes_status); + const newNodeList = JSON.parse(ret.data.dag).nodes.map((item) => { + console.log(experimentStatusObjs); + return { + ...item, + experimentEndTime: + experimentStatusObjs && + experimentStatusObjs[item.id] && + experimentStatusObjs[item.id].finishedAt, + experimentStartTime: + experimentStatusObjs && + experimentStatusObjs[item.id] && + experimentStatusObjs[item.id].startedAt, + experimentStatus: + experimentStatusObjs && + experimentStatusObjs[item.id] && + experimentStatusObjs[item.id].phase, + component_id: + experimentStatusObjs && + experimentStatusObjs[item.id] && + experimentStatusObjs[item.id].id, + img: + experimentStatusObjs && + experimentStatusObjs[item.id] && + experimentStatusObjs[item.id].phase + ? item.img.slice(0, item.img.length - 4) + + '-' + + experimentStatusObjs[item.id].phase + + '.png' + : item.img, + }; + }); + const newData = { ...JSON.parse(ret.data.dag), nodes: newNodeList }; - graph.addItem('node', model, true); - console.log(graph); - - } - const formChange=(val)=>{ - } - const handlerClick=(e)=>{ - console.log(propsRef,graph); - // let cache = []; - // let json_str = JSON.stringify(graph, function(key, value) { - // if (typeof value === 'object' && value !== null) { - // if (cache.indexOf(value) !== -1) { - // return; - // } - // cache.push(value); - // } - // return value; - // }); - // console.log(json_str); - propsRef.current.showDrawer(e,locationParams.id) - } - const getGraphData=(data)=>{ - if(graph){ - console.log(graph); - graph.data(data) - graph.render() - } - else{ - setTimeout(()=>{ - getGraphData(data) - },500) + getGraphData(newData); + // setExperimentStatusObj(JSON.parse(ret.data.nodes_status)) + } + }); } } - const getFirstWorkflow=(val)=>{ - getWorkflowById(val).then(ret=>{ - console.log(ret,'retttttttttt'); - if(ret.code==200){ - if(graph&&ret.data&&ret.data.dag){ - console.log(JSON.parse(ret.data.dag)); - getExperimentIns(locationParams.id).then(res=>{ - if(res.code==200){ - console.log(ret.data,'data'); - const experimentStatusObjs=JSON.parse(res.data.nodes_status) - const newNodeList= JSON.parse(ret.data.dag).nodes.map(item=>{console.log(experimentStatusObjs); return {...item,experimentEndTime:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].finishedAt,experimentStartTime:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].startedAt,experimentStatus:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].phase,component_id:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].id,img:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].phase?item.img.slice(0,item.img.length-4)+'-'+experimentStatusObjs[item.id].phase+'.png':item.img}}) - const newData={...JSON.parse(ret.data.dag),nodes:newNodeList} - console.log(newData); - setExperimentAllMessage(res.data) - getGraphData(newData) - // setExperimentStatusObj(JSON.parse(ret.data.nodes_status)) - } - - }) - + // graph&&graph.data(JSON.parse(ret.dag)) + // graph.render() + }); + }; + // const getExperimentIn=(val)=>{ + // getExperimentIns(val).then(ret=>{ + // if(ret.code==200){ + // console.log(JSON.parse(ret.data.nodes_status)); + // setExperimentStatusObj(JSON.parse(ret.data.nodes_status)) + // setTimeout(() => { + // console.log(experimentStatusObj); - } - } - // graph&&graph.data(JSON.parse(ret.dag)) - // graph.render() - }) - } - // const getExperimentIn=(val)=>{ - // getExperimentIns(val).then(ret=>{ - // if(ret.code==200){ - // console.log(JSON.parse(ret.data.nodes_status)); - // setExperimentStatusObj(JSON.parse(ret.data.nodes_status)) - // setTimeout(() => { - // console.log(experimentStatusObj); - - // }, 1000); - // } - - // }) - // } - useEffect(()=>{ - - initGraph() - getFirstWorkflow(locationParams.workflowId) - },[]) - const initGraph=()=>{ - G6.registerNode( - 'rect-node', - { - // draw anchor-point circles according to the anchorPoints in afterDraw - getAnchorPoints(cfg) { - return ( - cfg.anchorPoints || [ - // 上下各3,左右各1 - [0.5, 0], - [0.5, 1], + // }, 1000); + // } - ] - ); - }, - afterDraw(cfg, group) { - // console.log(group, cfg, 12312); - const image = group.addShape('image', { - attrs: { - x: -45, - y: -10, - width: 20, - height: 20, - img: cfg.img, - cursor: 'pointer', - }, - draggable: true, - }); - // if (cfg.label) { - // group.addShape('text', { - // attrs: { - // x: 0, - // y: cfg.height / 2 - 5, - // textAlign: 'center', - // textBaseline: 'middle', - // text: cfg.label, - // fill: '#fff', - // }, - // draggable: true, - // }); - // } - const bbox = group.getBBox(); - const anchorPoints = this.getAnchorPoints(cfg); - // console.log(anchorPoints); - anchorPoints.forEach((anchorPos, i) => { - group.addShape('circle', { - attrs: { - r: 3, - x: bbox.x + bbox.width * anchorPos[0], - y: bbox.y + bbox.height * anchorPos[1], - fill: '#fff', - stroke: '#a4a4a5', - }, - name: `anchor-point`, // the name, for searching by group.find(ele => ele.get('name') === 'anchor-point') - anchorPointIdx: i, // flag the idx of the anchor-point circle - links: 0, // cache the number of edges connected to this shape - visible: false, // invisible by default, shows up when links > 1 or the node is in showAnchors state - }); - }); - return image; - }, - - // response the state changes and show/hide the link-point circles - setState(name, value, item) { - const anchorPoints = item.getContainer().findAll(ele => ele.get('name') === 'anchor-point'); - anchorPoints.forEach(point => { - if (value || point.get('links') > 0) point.show() - else point.hide() - }) - // } + // }) + // } + useEffect(() => { + initGraph(); + getFirstWorkflow(locationParams.workflowId); + }, []); + useEffect(() => { + // Update the refs whenever the state changes + messageRef.current = message; + }, [message]); + + const initGraph = () => { + G6.registerNode( + 'rect-node', + { + // draw anchor-point circles according to the anchorPoints in afterDraw + getAnchorPoints(cfg) { + return ( + cfg.anchorPoints || [ + // 上下各3,左右各1 + [0.5, 0], + [0.5, 1], + ] + ); + }, + afterDraw(cfg, group) { + // console.log(group, cfg, 12312); + const image = group.addShape('image', { + attrs: { + x: -45, + y: -10, + width: 20, + height: 20, + img: cfg.img, + cursor: 'pointer', }, - }, - 'rect' - ); - console.log(graphRef,'graphRef'); - graph = new G6.Graph({ - container: graphRef.current, - grid: true, - width: graphRef.current.clientWidth ||500, - height: graphRef.current.clientHeight||760, - animate: false, - groupByTypes: false, - enabledStack: true, - modes: { - default: [ - // config the shouldBegin for drag-node to avoid node moving while dragging on the anchor-point circles - { - type: 'drag-node', - shouldBegin: e => { - if (e.target.get('name') === 'anchor-point') return false; - return true; + draggable: true, + }); + // if (cfg.label) { + // group.addShape('text', { + // attrs: { + // x: 0, + // y: cfg.height / 2 - 5, + // textAlign: 'center', + // textBaseline: 'middle', + // text: cfg.label, + // fill: '#fff', + // }, + // draggable: true, + // }); + // } + const bbox = group.getBBox(); + const anchorPoints = this.getAnchorPoints(cfg); + // console.log(anchorPoints); + anchorPoints.forEach((anchorPos, i) => { + group.addShape('circle', { + attrs: { + r: 3, + x: bbox.x + bbox.width * anchorPos[0], + y: bbox.y + bbox.height * anchorPos[1], + fill: '#fff', + stroke: '#a4a4a5', }, - // shouldEnd: e => { - // console.log(e); - // return false; - // }, - }, - // config the shouldBegin and shouldEnd to make sure the create-edge is began and ended at anchor-point circles - 'drag-canvas', - 'zoom-canvas', - // 'brush-select', - 'drag-combo', - ], - altSelect: [ - { - type: 'brush-select', - trigger: 'drag', - }, - 'drag-node', - ], + name: `anchor-point`, // the name, for searching by group.find(ele => ele.get('name') === 'anchor-point') + anchorPointIdx: i, // flag the idx of the anchor-point circle + links: 0, // cache the number of edges connected to this shape + visible: false, // invisible by default, shows up when links > 1 or the node is in showAnchors state + }); + }); + return image; }, - defaultNode: { - type: 'rect-node', - size: [110,36], - - labelCfg: { - style: { - fill: '#000', - fontSize: 10, - - cursor: 'pointer', - x: -20, - y: 0, - textAlign: 'left', - textBaseline: 'middle', + // response the state changes and show/hide the link-point circles + setState(name, value, item) { + const anchorPoints = item + .getContainer() + .findAll((ele) => ele.get('name') === 'anchor-point'); + anchorPoints.forEach((point) => { + if (value || point.get('links') > 0) point.show(); + else point.hide(); + }); + // } + }, + }, + 'rect', + ); + console.log(graphRef, 'graphRef'); + graph = new G6.Graph({ + container: graphRef.current, + grid: true, + width: graphRef.current.clientWidth || 500, + height: graphRef.current.clientHeight || 760, + animate: false, + groupByTypes: false, + enabledStack: true, + modes: { + default: [ + // config the shouldBegin for drag-node to avoid node moving while dragging on the anchor-point circles + { + type: 'drag-node', + shouldBegin: (e) => { + if (e.target.get('name') === 'anchor-point') return false; + return true; }, + // shouldEnd: e => { + // console.log(e); + // return false; + // }, + }, + // config the shouldBegin and shouldEnd to make sure the create-edge is began and ended at anchor-point circles + 'drag-canvas', + 'zoom-canvas', + // 'brush-select', + 'drag-combo', + ], + altSelect: [ + { + type: 'brush-select', + trigger: 'drag', }, + 'drag-node', + ], + }, + + defaultNode: { + type: 'rect-node', + size: [110, 36], + + labelCfg: { style: { - fill: '#fff', - stroke: '#fff', - radius:10, - lineWidth:0.5 + fill: '#000', + fontSize: 10, + + cursor: 'pointer', + x: -20, + y: 0, + textAlign: 'left', + textBaseline: 'middle', }, }, - nodeStateStyles: { - nodeSelected: { + style: { + fill: '#fff', + stroke: '#fff', + radius: 10, + lineWidth: 0.5, + }, + }, + nodeStateStyles: { + nodeSelected: { + fill: 'red', + shadowColor: 'red', + stroke: 'red', + 'text-shape': { fill: 'red', - shadowColor: 'red', stroke: 'red', - 'text-shape': { - fill: 'red', - stroke: 'red', - }, }, }, - defaultEdge: { - // type: 'quadratic', - type: 'cubic-vertical', + }, + defaultEdge: { + // type: 'quadratic', + type: 'cubic-vertical', - style: { - endArrow: { // 设置终点箭头 - path: G6.Arrow.triangle(3, 3, 3), // 使用内置箭头路径函数,参数为箭头的 宽度、长度、偏移量(默认为 0,与 d 对应) - d: 4.5, - fill:'#a2a6b5' - }, - cursor: 'pointer', - lineWidth: 1, - opacity: 1, - stroke: '#a2a6b5', - radius: 1, - }, - nodeStateStyle: { - hover: { - opacity: 1, - stroke: '#8fe8ff', - }, + style: { + endArrow: { + // 设置终点箭头 + path: G6.Arrow.triangle(3, 3, 3), // 使用内置箭头路径函数,参数为箭头的 宽度、长度、偏移量(默认为 0,与 d 对应) + d: 4.5, + fill: '#a2a6b5', }, - labelCfg: { - autoRotate: true, - // refY: 10, - style: { - fontSize: 10, - fill: '#FFF', - }, + cursor: 'pointer', + lineWidth: 1, + opacity: 1, + stroke: '#a2a6b5', + radius: 1, + }, + nodeStateStyle: { + hover: { + opacity: 1, + stroke: '#8fe8ff', }, }, - defaultCombo: { - type: 'rect', - fixCollapseSize: 70, + labelCfg: { + autoRotate: true, + // refY: 10, style: { - fill: '#00e0ff0d', - stroke: '#00e0ff', - lineDash: [5, 10], - cursor: 'pointer', + fontSize: 10, + fill: '#FFF', }, }, - // linkCenter: true, - fitView: false, - fitViewPadding: [60, 60, 60, 80], - }); - graph.on('dblclick', handlerClick); - window.onresize = () => { - if (!graph || graph.get('destroyed')) return; - if (!graphRef.current || !graphRef.current.scrollWidth || !graphRef.current.scrollHeight) return; - graph.changeSize(graphRef.current.scrollWidth, graphRef.current.scrollHeight - 20); - }; - } - return (
-
+ }, + defaultCombo: { + type: 'rect', + fixCollapseSize: 70, + style: { + fill: '#00e0ff0d', + stroke: '#00e0ff', + lineDash: [5, 10], + cursor: 'pointer', + }, + }, + // linkCenter: true, + fitView: false, + fitViewPadding: [60, 60, 60, 80], + }); + + graph.on('dblclick', handlerClick); + window.onresize = () => { + if (!graph || graph.get('destroyed')) return; + if (!graphRef.current || !graphRef.current.scrollWidth || !graphRef.current.scrollHeight) + return; + graph.changeSize(graphRef.current.scrollWidth, graphRef.current.scrollHeight - 20); + }; + }; + return ( +
+
-
启动时间:{momnet(experimentAllMessage.create_time).format('YYYY-MM-DD HH:mm:ss')}
-
执行时长:{experimentAllMessage.finish_time?timers(new Date(experimentAllMessage.finish_time).getTime()-new Date(experimentAllMessage.create_time).getTime()):timers(new Date().getTime()-new Date(experimentAllMessage.create_time).getTime())}
-
状态: -
- {statusObj[experimentAllMessage.status]}
+
+ 启动时间:{momnet(message.create_time).format('YYYY-MM-DD HH:mm:ss')} +
+
+ 执行时长: + {message.finish_time + ? elapsedTime(new Date(message.create_time), new Date(message.finish_time)) + : elapsedTime(new Date(message.create_time), new Date())} +
+
+ 状态: +
+ + {experimentStatusInfo[message.status]?.label} + +
-
- -
)}; -export default ExperimentText; \ No newline at end of file +
+ +
+ ); +} +export default ExperimentText; diff --git a/react-ui/src/pages/Experiment/experimentText/logGroup.less b/react-ui/src/pages/Experiment/experimentText/logGroup.less new file mode 100644 index 00000000..4eee30d3 --- /dev/null +++ b/react-ui/src/pages/Experiment/experimentText/logGroup.less @@ -0,0 +1,34 @@ +.log_group { + padding-bottom: 10px; +} + +.log_group_pod { + display: flex; + align-items: center; + justify-content: space-between; + padding: 15px; + background: rgba(234, 234, 234, 0.5); + cursor: pointer; + + &_name { + margin-right: 10px; + color: #1d1d20; + font-size: 14px; + } +} + +.log_group_detail { + padding: 15px; + color: white; + font-size: 14px; + white-space: pre-line; + word-break: break-all; + background: #19253b; +} + +.log_group_more_button { + display: flex; + justify-content: center; + color: white; + background: #19253b; +} diff --git a/react-ui/src/pages/Experiment/experimentText/logGroup.tsx b/react-ui/src/pages/Experiment/experimentText/logGroup.tsx new file mode 100644 index 00000000..f50114b3 --- /dev/null +++ b/react-ui/src/pages/Experiment/experimentText/logGroup.tsx @@ -0,0 +1,127 @@ +import { useStateRef } from '@/hooks'; +import { getExperimentPodsLog } from '@/services/experiment/index.js'; +import { DoubleRightOutlined, DownOutlined, UpOutlined } from '@ant-design/icons'; +import { Button } from 'antd'; +import { useEffect, useState } from 'react'; +import styles from './logGroup.less'; + +type LogGroupProps = { + log_type?: string; + pod_name?: string; + log_content?: string; + start_time?: string; + status: string; +}; + +type Log = { + start_time: string; + log_content: string; +}; + +function LogGroup({ + log_type = '', + pod_name = '', + log_content = '', + start_time = '', + status = '', +}: LogGroupProps) { + const [collapse, setCollapse] = useState(true); + const [logList, setLogList, logListRef] = useStateRef([]); + const [completed, setCompleted] = useState(false); + + useEffect(() => { + if (status === 'Running') { + const timerId = setInterval(() => { + requestExperimentPodsLog(); + }, 5000); + return () => { + clearInterval(timerId); + }; + } + }, []); + + // 请求日志 + const requestExperimentPodsLog = async () => { + const list = logListRef.current; + const startTime = list.length > 0 ? list[list.length - 1].start_time : start_time; + const params = { + pod_name, + start_time: startTime, + }; + const res = await getExperimentPodsLog(params); + const { log_detail } = res.data; + if (log_detail && log_detail.log_content) { + setLogList((oldList) => oldList.concat(log_detail)); + } else { + setCompleted(true); + } + }; + // 请求实时日志 + // const requestExperimentPodsRealtimeLog = async () => { + // const params = { + // pod_name, + // namespace: namespace, + // container_name: log_type === 'resource' ? '' : 'main', + // }; + // const res = await getExperimentPodsRealtimeLog(params); + // const { log_detail } = res.data; + // if (log_detail && log_detail.log_content) { + // setLogList((list) => list.concat(log_detail)); + // } else { + // setCompleted(true); + // } + // }; + + // 处理折叠 + const handleCollapse = async () => { + if (!collapse) { + setCollapse(true); + return; + } + + if (logList.length === 0) { + try { + await requestExperimentPodsLog(); + setCollapse(false); + } catch (error) { + return Promise.reject(error); + } + } else { + setCollapse(false); + } + }; + + // 加载更多 + const loadMore = () => { + requestExperimentPodsLog(); + }; + + const showLog = (log_type === 'resource' && !collapse) || log_type === 'normal'; + const logText = log_content + logList.map((v) => v.log_content).join(''); + const showMoreBtn = status !== 'Running' && showLog && !completed && logText !== ''; + return ( +
+ {log_type === 'resource' && ( +
+
{pod_name}
+ {collapse ? : } +
+ )} + {showLog &&
{logText}
} +
+ {showMoreBtn && ( + + )} +
+
+ ); +} + +export default LogGroup; diff --git a/react-ui/src/pages/Experiment/experimentText/props.jsx b/react-ui/src/pages/Experiment/experimentText/props.jsx index f322cba9..1ab54930 100644 --- a/react-ui/src/pages/Experiment/experimentText/props.jsx +++ b/react-ui/src/pages/Experiment/experimentText/props.jsx @@ -1,336 +1,424 @@ -import React, { useState,useImperativeHandle ,forwardRef } from 'react'; -import { Button, Drawer,Form, Input ,Tabs,message } from 'antd'; -import Styles from './editPipeline.less' -import{getQueryByExperimentLog,getNodeResult}from '@/services/experiment/index.js' -import { ProfileOutlined, DatabaseOutlined} from '@ant-design/icons'; -import {downLoadZip} from '@/utils/downloadfile' -import momnet from 'moment' +import { getNodeResult, getQueryByExperimentLog } from '@/services/experiment/index.js'; +import { elapsedTime } from '@/utils/date'; +import { downLoadZip } from '@/utils/downloadfile'; +import { DatabaseOutlined, ProfileOutlined } from '@ant-design/icons'; +import { Drawer, Form, Input, Tabs, message } from 'antd'; +import moment from 'moment'; +import { forwardRef, useImperativeHandle, useState } from 'react'; +import LogList from './LogList'; +import Styles from './editPipeline.less'; const { TextArea } = Input; -const Props = forwardRef(({onParentChange}, ref) =>{ - const [form] = Form.useForm(); - const [stagingItem,setStagingItem]=useState({}) - const [resultObj,setResultObj]=useState([]) - const [messageItem,setMessageItem]=useState('') - const statusObj={ - "Running":'运行中', - "Succeeded":'成功', - "Pending":'等待中', - "Failed":'失败', - "Error":'错误', - "Terminated":'终止', - "Skipped":'未执行', - "Omitted":'未执行', - } - const statusColorObj={ - "Running":'#165bff', - "Succeeded":'#63a728', - "Pending":'#f981eb', - "Failed":'#c73131', - "Error":'#c73131', - "Terminated":'#8a8a8a', - "Skipped":'#8a8a8a', - "Omitted":'#8a8a8ae', - } - const exportResult=(e,val)=>{ - +const Props = forwardRef(({ onParentChange }, ref) => { + const [form] = Form.useForm(); + const [stagingItem, setStagingItem] = useState({}); + const [resultObj, setResultObj] = useState([]); + const [logList, setLogList] = useState([]); + const statusObj = { + Running: '运行中', + Succeeded: '成功', + Pending: '等待中', + Failed: '失败', + Error: '错误', + Terminated: '终止', + Skipped: '未执行', + Omitted: '未执行', + }; + const statusColorObj = { + Running: '#165bff', + Succeeded: '#63a728', + Pending: '#f981eb', + Failed: '#c73131', + Error: '#c73131', + Terminated: '#8a8a8a', + Skipped: '#8a8a8a', + Omitted: '#8a8a8ae', + }; + const exportResult = (e, val) => { const hide = message.loading('正在下载'); hide(); - downLoadZip(`/api/mmp/minioStorage/download`,{path:val}) - } - const timers=(time)=>{ - let timer=new Date(time) - let hours = timer.getHours(); //转换成时 - let minutes = timer.getMinutes(); //转换成分 - let secend = timer.getSeconds(); //转换成秒 - - let str = `${minutes}分${secend}秒`; - return str; - } - const items = [ - { - key: '1', - label: '日志详情', - children:
, - icon: - }, - { - key: '2', - label: '配置参数', - icon:, - children:
-
- - 基本信息 -
- - - - - - -
- - 任务信息 -
- - - - - - - - - - - - - - - - - { + let timer = new Date(time); + let hours = timer.getHours(); //转换成时 + let minutes = timer.getMinutes(); //转换成分 + let secend = timer.getSeconds(); //转换成秒 + + let str = `${minutes}分${secend}秒`; + return str; + }; + const items = [ + { + key: '1', + label: '日志详情', + children: , + icon: , + }, + { + key: '2', + label: '配置参数', + icon: , + children: ( + -