From beae83c86e0bd8ade62d40c7e1e99639118fe2b1 Mon Sep 17 00:00:00 2001 From: zhuxinru Date: Tue, 10 Feb 2026 11:35:56 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=E4=BB=BB=E5=8A=A1=E4=B8=8B=E5=BD=92?= =?UTF-8?q?=E6=A1=A3=E6=8A=A5=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-sql/2026-02-10/simulation_task.sql | 2 + .../entity/req/project/EditReportReq.java | 7 + .../entity/resp/project/SpdmTaskVo.java | 7 + .../project/model/entity/SimulationTask.java | 9 + .../impl/SimulationRunServiceImpl.java | 468 ++++++++++-------- 5 files changed, 286 insertions(+), 207 deletions(-) create mode 100644 1-sql/2026-02-10/simulation_task.sql diff --git a/1-sql/2026-02-10/simulation_task.sql b/1-sql/2026-02-10/simulation_task.sql new file mode 100644 index 00000000..06f65c09 --- /dev/null +++ b/1-sql/2026-02-10/simulation_task.sql @@ -0,0 +1,2 @@ +ALTER TABLE spdm_baseline.simulation_task ADD reportTemplate varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '报告模板uuid'; +ALTER TABLE spdm_baseline.simulation_task ADD reportContent mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '报告模板填充内容'; diff --git a/common/src/main/java/com/sdm/common/entity/req/project/EditReportReq.java b/common/src/main/java/com/sdm/common/entity/req/project/EditReportReq.java index 1ea2305b..52a18e05 100644 --- a/common/src/main/java/com/sdm/common/entity/req/project/EditReportReq.java +++ b/common/src/main/java/com/sdm/common/entity/req/project/EditReportReq.java @@ -1,18 +1,25 @@ package com.sdm.common.entity.req.project; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data public class EditReportReq { + @Schema(description= "算例uuid") private String runId; + @Schema(description= "报告模板uuid") private String reportTemplate; + @Schema(description= "报告模板内容") private String reportContent; + @Schema(description= "任务uuid") + private String taskId; + } \ No newline at end of file diff --git a/common/src/main/java/com/sdm/common/entity/resp/project/SpdmTaskVo.java b/common/src/main/java/com/sdm/common/entity/resp/project/SpdmTaskVo.java index 67463d12..dc77c667 100644 --- a/common/src/main/java/com/sdm/common/entity/resp/project/SpdmTaskVo.java +++ b/common/src/main/java/com/sdm/common/entity/resp/project/SpdmTaskVo.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.sdm.common.entity.pojo.BaseEntity; import com.sdm.common.entity.resp.system.CIDUserResp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; @@ -224,4 +225,10 @@ public class SpdmTaskVo extends BaseEntity { */ private String eUserId; + @Schema(description= "报告模板内容") + private String reportContent; + + @Schema(description= "任务uuid") + private String taskId; + } diff --git a/project/src/main/java/com/sdm/project/model/entity/SimulationTask.java b/project/src/main/java/com/sdm/project/model/entity/SimulationTask.java index 28bb6b7e..0a36011d 100644 --- a/project/src/main/java/com/sdm/project/model/entity/SimulationTask.java +++ b/project/src/main/java/com/sdm/project/model/entity/SimulationTask.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import java.io.Serializable; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; @@ -210,5 +211,13 @@ public class SimulationTask implements Serializable { @TableField("discipline") private String discipline; + @Schema(description= "报告模板uuid") + @TableField("reportTemplate") + private String reportTemplate; + + @Schema(description= "报告模板填充内容") + @TableField("reportContent") + private String reportContent; + } diff --git a/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java index 6562e59f..684c7180 100644 --- a/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java @@ -915,6 +915,7 @@ public class SimulationRunServiceImpl extends ServiceImpl reportResponse = reportFeignClient.queryReportTemplateInfo(req.getReportTemplate()); - if (reportResponse.isSuccess()) { - Long reportTemplateFileId = reportResponse.getData().getFileId(); - // 获取报告模板名称 - GetFileBaseInfoReq getFileBaseInfoReq = new GetFileBaseInfoReq(); - getFileBaseInfoReq.setFileId(reportTemplateFileId); - SdmResponse fileBaseInfoResp = dataFeignClient.getFileBaseInfo(getFileBaseInfoReq); - String originalName = fileBaseInfoResp.getData().getOriginalName(); - // 下载到本地临时目录 - dataFeignClient.downloadFileToLocal(reportTemplateFileId, TEMP_REPORT_PATH + randomId); + String randomId = RandomUtil.generateString(16); + // 创建临时文件夹 + Path folder = Paths.get(TEMP_REPORT_PATH + randomId); + if (!Files.exists(folder) || !Files.isDirectory(folder)) { + if (!new File(TEMP_REPORT_PATH + randomId).mkdir()) { + log.error("创建临时文件夹:{}失败",TEMP_REPORT_PATH + randomId); + throw new RuntimeException("生成报告失败,原因为:创建临时文件夹失败"); + } + } + log.info("临时路径为:{}", randomId); - // 构建python命令 - List command = new ArrayList<>(); - command.add("python"); - command.add("/opt/script/modifyReport.py"); + // 根据文件id下载文件到临时目录 + SdmResponse reportResponse = reportFeignClient.queryReportTemplateInfo(req.getReportTemplate()); + if (reportResponse.isSuccess()) { + Long reportTemplateFileId = reportResponse.getData().getFileId(); + // 获取报告模板名称 + GetFileBaseInfoReq getFileBaseInfoReq = new GetFileBaseInfoReq(); + getFileBaseInfoReq.setFileId(reportTemplateFileId); + SdmResponse fileBaseInfoResp = dataFeignClient.getFileBaseInfo(getFileBaseInfoReq); + String originalName = fileBaseInfoResp.getData().getOriginalName(); + // 下载到本地临时目录 + dataFeignClient.downloadFileToLocal(reportTemplateFileId, TEMP_REPORT_PATH + randomId); + + // 构建python命令 + List command = new ArrayList<>(); + command.add("python"); + command.add("/opt/script/modifyReport.py"); // command.add(TEMP_REPORT_PATH + File.separator +"modifyReport.py"); - command.add(TEMP_REPORT_PATH + randomId); - command.add(TEMP_REPORT_PATH + randomId + File.separator + originalName); - String commands = String.join(" ", command); + command.add(TEMP_REPORT_PATH + randomId); + command.add(TEMP_REPORT_PATH + randomId + File.separator + originalName); + String commands = String.join(" ", command); - // 前端参数写入临时目录 - FileOutputStream projectInfoOutputStream = null; - try { - projectInfoOutputStream = new FileOutputStream(TEMP_REPORT_PATH + randomId + File.separator + "reportContent.json"); - projectInfoOutputStream.write(reportContent.getBytes(StandardCharsets.UTF_8)); - projectInfoOutputStream.flush(); - projectInfoOutputStream.close(); - } catch (Exception e) { - throw new RuntimeException(e); + // 前端参数写入临时目录 + FileOutputStream projectInfoOutputStream = null; + try { + projectInfoOutputStream = new FileOutputStream(TEMP_REPORT_PATH + randomId + File.separator + "reportContent.json"); + projectInfoOutputStream.write(reportContent.getBytes(StandardCharsets.UTF_8)); + projectInfoOutputStream.flush(); + projectInfoOutputStream.close(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + // 调用脚本 + log.info("执行 Python 命令: {}", commands); + int runningStatus = -1; + try { + log.info("开始同步执行脚本"); + Process process = Runtime.getRuntime().exec(commands); + log.info("开始获取脚本输出"); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + log.info("executePython:" + line); } + log.info("脚本执行完成"); + runningStatus = process.waitFor(); + log.info("脚本运行状态:" + runningStatus); + } catch (IOException | InterruptedException e) { + log.error("执行脚本失败:" + e); + return SdmResponse.failed("执行脚本失败"); + } + if (runningStatus != 0) { + log.error("执行脚本失败"); + return SdmResponse.failed("执行脚本失败"); + } else { + log.info(commands + "执行脚本完成!"); + } + byte[] fileData = null; + try { + // 获取临时路径中脚本生成的报告 + String reportName = "report_" + + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + + ".docx"; + FileInputStream fileInputStream = new FileInputStream(TEMP_REPORT_PATH + randomId + File.separator + reportName); + fileData = fileInputStream.readAllBytes(); - // 调用脚本 - log.info("执行 Python 命令: {}", commands); - int runningStatus = -1; - try { - log.info("开始同步执行脚本"); - Process process = Runtime.getRuntime().exec(commands); - log.info("开始获取脚本输出"); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - log.info("executePython:" + line); + // 创建临时MultipartFile + MockMultipartFile multipartFile = new MockMultipartFile( + reportName, + reportName, + "application/json", + fileData); + if (StringUtils.isNotEmpty(req.getTaskId())) { + // 上传到任务下的交付物文件夹的报告文件夹下 + Long parentId = getParentDirId(req.getTaskId(), FileBizTypeEnum.REPORT_FILE.getDirName()); + UploadFilesReq filesReq = new UploadFilesReq(); + filesReq.setFile(multipartFile); + filesReq.setFileName(reportName); + filesReq.setFileType(FileBizTypeEnum.REPORT_FILE.getValue()); + filesReq.setUuid(null); + filesReq.setDirId(parentId); + SdmResponse sdmResponse = uploadKeyResultFiles(filesReq); + if (!sdmResponse.isSuccess()) { + throw new RuntimeException("生成自动化报告上传任务报告结果目录失败"); } - log.info("脚本执行完成"); - runningStatus = process.waitFor(); - log.info("脚本运行状态:" + runningStatus); - } catch (IOException | InterruptedException e) { - log.error("执行脚本失败:" + e); - return SdmResponse.failed("执行脚本失败"); - } - if (runningStatus != 0) { - log.error("执行脚本失败"); - return SdmResponse.failed("执行脚本失败"); } else { - log.info(commands + "执行脚本完成!"); + // 上传到算例下的报告文件夹下 + KeyResultReq resultReq = new KeyResultReq(); + resultReq.setKeyResultType(KeyResultTypeEnum.DOCUMENT.getKeyResultType()); + resultReq.setRunId(req.getRunId()); + resultReq.setName(reportName); + + resultReq.setFile(multipartFile); + resultReq.setFileName(reportName); + resultReq.setFileType(FileBizTypeEnum.REPORT_FILE.getValue()); + SdmResponse sdmResponse = addSimulationKeyResult(resultReq); + if (!sdmResponse.isSuccess()) { + throw new RuntimeException("生成自动化报告上传算例报告结果目录失败"); + } } - byte[] fileData = null; + + fileInputStream.close(); + // 删除临时路径 + log.info("删除临时路径:{},中。。。。。。", randomId); + deleteFolder(new File(TEMP_REPORT_PATH + randomId)); + return SdmResponse.success(); + } catch (Exception ex) { + log.error("生成自动化报告失败:{}", ex.getMessage()); + throw new RuntimeException("生成自动化报告失败"); + } + } + return SdmResponse.failed("生成自动化报告失败"); + } + + @Override + public void editReportAndDownload(EditReportReq req, HttpServletResponse response) { + log.info("编辑报告参数为:{}", req); + String reportContent = req.getReportContent(); + if (StringUtils.isNotEmpty(req.getTaskId())) { + SimulationTask simulationTask = simulationTaskService.lambdaQuery().eq(SimulationTask::getUuid, req.getTaskId()).one(); + if (simulationTask != null) { + // 任务绑定报告模板 + simulationTask.setReportTemplate(req.getReportTemplate()); + simulationTask.setReportContent(reportContent); + simulationTaskService.updateById(simulationTask); + } + } else { + SimulationRun simulationRun = this.lambdaQuery().eq(SimulationRun::getUuid, req.getRunId()).one(); + if (simulationRun != null) { + // 算例绑定报告模板 + simulationRun.setReportTemplate(req.getReportTemplate()); + simulationRun.setReportContent(reportContent); + this.updateById(simulationRun); + } + } + + String randomId = RandomUtil.generateString(16); + // 创建临时文件夹 + Path folder = Paths.get(TEMP_REPORT_PATH + randomId); + if (!Files.exists(folder) || !Files.isDirectory(folder)) { + if (!new File(TEMP_REPORT_PATH + randomId).mkdir()) { + log.error("创建临时文件夹:{}失败",TEMP_REPORT_PATH + randomId); + throw new RuntimeException("生成报告失败,原因为:创建临时文件夹失败"); + } + } + log.info("临时路径为:{}", randomId); + + // 根据文件id下载文件到临时目录 + SdmResponse reportResponse = reportFeignClient.queryReportTemplateInfo(req.getReportTemplate()); + if (reportResponse.isSuccess()) { + Long reportTemplateFileId = reportResponse.getData().getFileId(); + // 获取报告模板名称 + GetFileBaseInfoReq getFileBaseInfoReq = new GetFileBaseInfoReq(); + getFileBaseInfoReq.setFileId(reportTemplateFileId); + SdmResponse fileBaseInfoResp = dataFeignClient.getFileBaseInfo(getFileBaseInfoReq); + String originalName = fileBaseInfoResp.getData().getOriginalName(); + // 下载到本地临时目录 + dataFeignClient.downloadFileToLocal(reportTemplateFileId, TEMP_REPORT_PATH + randomId); + + // 构建python命令 + List command = new ArrayList<>(); + command.add("python"); + command.add("/opt/script/modifyReport.py"); +// command.add(TEMP_REPORT_PATH + File.separator +"modifyReport.py"); + command.add(TEMP_REPORT_PATH + randomId); + command.add(TEMP_REPORT_PATH + randomId + File.separator + originalName); + String commands = String.join(" ", command); + + // 前端参数写入临时目录 + FileOutputStream projectInfoOutputStream = null; + try { + projectInfoOutputStream = new FileOutputStream(TEMP_REPORT_PATH + randomId + File.separator + "reportContent.json"); + projectInfoOutputStream.write(reportContent.getBytes(StandardCharsets.UTF_8)); + projectInfoOutputStream.flush(); + projectInfoOutputStream.close(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + // 调用脚本 + log.info("执行 Python 命令: {}", commands); + int runningStatus = -1; + try { + log.info("开始同步执行脚本"); + Process process = Runtime.getRuntime().exec(commands); + log.info("开始获取脚本输出"); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + log.info("executePython:" + line); + } + log.info("脚本执行完成"); + runningStatus = process.waitFor(); + log.info("脚本运行状态:" + runningStatus); + } catch (IOException | InterruptedException e) { + log.error("执行脚本失败:" + e); + return; + } + if (runningStatus != 0) { + log.error("执行脚本失败"); + return; + } else { + log.info(commands + "执行脚本完成!"); + } + byte[] fileData = null; + if (response != null) { try { // 获取临时路径中脚本生成的报告 String reportName = "report_" + @@ -1711,166 +1871,60 @@ public class SimulationRunServiceImpl extends ServiceImpl reportResponse = reportFeignClient.queryReportTemplateInfo(req.getReportTemplate()); - if (reportResponse.isSuccess()) { - Long reportTemplateFileId = reportResponse.getData().getFileId(); - // 获取报告模板名称 - GetFileBaseInfoReq getFileBaseInfoReq = new GetFileBaseInfoReq(); - getFileBaseInfoReq.setFileId(reportTemplateFileId); - SdmResponse fileBaseInfoResp = dataFeignClient.getFileBaseInfo(getFileBaseInfoReq); - String originalName = fileBaseInfoResp.getData().getOriginalName(); - // 下载到本地临时目录 - dataFeignClient.downloadFileToLocal(reportTemplateFileId, TEMP_REPORT_PATH + randomId); - - // 构建python命令 - List command = new ArrayList<>(); - command.add("python"); - command.add("/opt/script/modifyReport.py"); -// command.add(TEMP_REPORT_PATH + File.separator +"modifyReport.py"); - command.add(TEMP_REPORT_PATH + randomId); - command.add(TEMP_REPORT_PATH + randomId + File.separator + originalName); - String commands = String.join(" ", command); - - // 前端参数写入临时目录 - FileOutputStream projectInfoOutputStream = null; - try { - projectInfoOutputStream = new FileOutputStream(TEMP_REPORT_PATH + randomId + File.separator + "reportContent.json"); - projectInfoOutputStream.write(reportContent.getBytes(StandardCharsets.UTF_8)); - projectInfoOutputStream.flush(); - projectInfoOutputStream.close(); - } catch (Exception e) { - throw new RuntimeException(e); - } - - // 调用脚本 - log.info("执行 Python 命令: {}", commands); - int runningStatus = -1; - try { - log.info("开始同步执行脚本"); - Process process = Runtime.getRuntime().exec(commands); - log.info("开始获取脚本输出"); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - log.info("executePython:" + line); - } - log.info("脚本执行完成"); - runningStatus = process.waitFor(); - log.info("脚本运行状态:" + runningStatus); - } catch (IOException | InterruptedException e) { - log.error("执行脚本失败:" + e); - return; - } - if (runningStatus != 0) { - log.error("执行脚本失败"); - return; - } else { - log.info(commands + "执行脚本完成!"); - } - byte[] fileData = null; - if (response != null) { - try { - // 获取临时路径中脚本生成的报告 - String reportName = "report_" + - LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + - ".docx"; - FileInputStream fileInputStream = new FileInputStream(TEMP_REPORT_PATH + randomId + File.separator + reportName); - fileData = fileInputStream.readAllBytes(); - + if (StringUtils.isNotEmpty(req.getTaskId())) { + // 上传到任务下的交付物文件夹的报告文件夹下 + Long parentId = getParentDirId(req.getTaskId(), FileBizTypeEnum.REPORT_FILE.getDirName()); + UploadFilesReq filesReq = new UploadFilesReq(); + filesReq.setFile(multipartFile); + filesReq.setFileName(reportName); + filesReq.setFileType(FileBizTypeEnum.REPORT_FILE.getValue()); + filesReq.setUuid(null); + filesReq.setDirId(parentId); + SdmResponse sdmResponse = uploadKeyResultFiles(filesReq); + if (!sdmResponse.isSuccess()) { + throw new RuntimeException("生成自动化报告上传任务报告结果目录失败"); + } + } else { // 上传到算例下的报告文件夹下 KeyResultReq resultReq = new KeyResultReq(); resultReq.setKeyResultType(KeyResultTypeEnum.DOCUMENT.getKeyResultType()); resultReq.setRunId(req.getRunId()); resultReq.setName(reportName); - // 创建临时MultipartFile - MockMultipartFile multipartFile = new MockMultipartFile( - reportName, - reportName, - "application/json", - fileData); + resultReq.setFile(multipartFile); resultReq.setFileName(reportName); resultReq.setFileType(FileBizTypeEnum.REPORT_FILE.getValue()); SdmResponse sdmResponse = addSimulationKeyResult(resultReq); if (!sdmResponse.isSuccess()) { - throw new RuntimeException("生成自动化报告上传报告结果目录失败"); + throw new RuntimeException("生成自动化报告上传算例报告结果目录失败"); } - - // 下载到本地 - // 设置响应头 - response.reset(); - response.setContentType("application/octet-stream;charset=UTF-8"); - response.addHeader("Content-Length", String.valueOf(fileData.length)); - // 写入响应流 - OutputStream outputStream = response.getOutputStream(); - outputStream.write(fileData); - outputStream.flush(); - outputStream.close(); - fileInputStream.close(); - } catch (Exception ex) { - log.error("生成自动化报告失败:{}", ex.getMessage()); - throw new RuntimeException("生成自动化报告失败"); } + + // 下载到本地 + // 设置响应头 + response.reset(); + response.setContentType("application/octet-stream;charset=UTF-8"); + response.addHeader("Content-Length", String.valueOf(fileData.length)); + // 写入响应流 + OutputStream outputStream = response.getOutputStream(); + outputStream.write(fileData); + outputStream.flush(); + outputStream.close(); + fileInputStream.close(); + } catch (Exception ex) { + log.error("生成自动化报告失败:{}", ex.getMessage()); + throw new RuntimeException("生成自动化报告失败"); } - // 删除临时路径 - log.info("删除临时路径:{},中。。。。。。", randomId); - deleteFolder(new File(TEMP_REPORT_PATH + randomId)); } + // 删除临时路径 + log.info("删除临时路径:{},中。。。。。。", randomId); + deleteFolder(new File(TEMP_REPORT_PATH + randomId)); } } From 738751dcefabe49a92d2de2bf11b34a5ff951ba6 Mon Sep 17 00:00:00 2001 From: 15195 Date: Tue, 10 Feb 2026 14:59:16 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9Ahpc=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E6=89=B9=E9=87=8F=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/resp/pbs/hpc/DelHpcJobsResult.java | 17 +++++ .../common/utils/HpcCommandExcuteUtil.java | 22 +++++++ .../src/main/resources/application-yang.yml | 44 +++++++++++++ .../pbs/service/impl/PbsServiceDecorator.java | 64 +++++++++++++++---- .../main/resources/application-dev-190.yml | 1 + pbs/src/main/resources/application-dev-65.yml | 1 + pbs/src/main/resources/application-lyric.yml | 1 + 7 files changed, 139 insertions(+), 11 deletions(-) create mode 100644 common/src/main/java/com/sdm/common/entity/resp/pbs/hpc/DelHpcJobsResult.java create mode 100644 flowable/src/main/resources/application-yang.yml diff --git a/common/src/main/java/com/sdm/common/entity/resp/pbs/hpc/DelHpcJobsResult.java b/common/src/main/java/com/sdm/common/entity/resp/pbs/hpc/DelHpcJobsResult.java new file mode 100644 index 00000000..58215a1c --- /dev/null +++ b/common/src/main/java/com/sdm/common/entity/resp/pbs/hpc/DelHpcJobsResult.java @@ -0,0 +1,17 @@ +package com.sdm.common.entity.resp.pbs.hpc; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class DelHpcJobsResult implements Serializable { + + private static final long serialVersionUID = 1L; + + private List succJobIds; + + private List failedJobIds; + +} diff --git a/common/src/main/java/com/sdm/common/utils/HpcCommandExcuteUtil.java b/common/src/main/java/com/sdm/common/utils/HpcCommandExcuteUtil.java index 128e403b..b958d6cc 100644 --- a/common/src/main/java/com/sdm/common/utils/HpcCommandExcuteUtil.java +++ b/common/src/main/java/com/sdm/common/utils/HpcCommandExcuteUtil.java @@ -4,12 +4,15 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.TypeReference; import com.sdm.common.common.SdmResponse; +import com.sdm.common.entity.req.pbs.DelHpcJobsFileToolReq; +import com.sdm.common.entity.resp.pbs.hpc.DelHpcJobsResult; import com.sdm.common.entity.resp.pbs.hpc.FileNodeInfo; import com.sdm.common.log.CoreLogger; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferUtils; @@ -55,6 +58,9 @@ public class HpcCommandExcuteUtil { @Value("${hpc.callHpcUpload:}") private String callHpcUpload; + @Value("${hpc.delHpcJobsUrl:}") + private String delHpcJobsUrl; + @Autowired private HttpClientUtil httpClientUtil; @@ -239,4 +245,20 @@ public class HpcCommandExcuteUtil { } } + public SdmResponse batchDeleteHpcJobs(List reqs,WebClient pbsWebClient) { + // 发起POST请求,同步阻塞获取响应 + try { + SdmResponse response = pbsWebClient.post() + .uri(delHpcJobsUrl) + .bodyValue(reqs) // 传入请求体对象 + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}) // 泛型类型指定 + .block(); // 阻塞等待响应 + return response; + } catch (Exception e) { + log.error("batchDeleteHpcJobs post error:{}",e.getMessage()); + return SdmResponse.failed("发起批量删除hpc节点工作目录异常"); + } + } + } diff --git a/flowable/src/main/resources/application-yang.yml b/flowable/src/main/resources/application-yang.yml new file mode 100644 index 00000000..42ff03de --- /dev/null +++ b/flowable/src/main/resources/application-yang.yml @@ -0,0 +1,44 @@ +server: + port: 7106 +spring: + application: + name: flowable + datasource: + url: jdbc:mysql://127.0.0.1:3306/flowable?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai + username: root + password: mysql + driver-class-name: com.mysql.cj.jdbc.Driver + flowable: + # ????????? + database-schema-update: true + # ??????JOB + async-executor-activate: true + cloud: + nacos: + discovery: + server-addr: 127.0.0.1:8848 + group: YANG_GROUP + enabled: true + username: nacos + password: nacos + +logging: + level: + org: + flowable: INFO + +mybatis-plus: + mapper-locations: classpath*:/mapper/**/*.xml + type-aliases-package: com.sdm.flowable.model.entity + configuration: + map-underscore-to-camel-case: true + global-config: + db-config: + id-type: auto + +security: + whitelist: + paths: + - /process/testHpc + - /process/testHpc2 + - /process/asyncCallback \ No newline at end of file diff --git a/pbs/src/main/java/com/sdm/pbs/service/impl/PbsServiceDecorator.java b/pbs/src/main/java/com/sdm/pbs/service/impl/PbsServiceDecorator.java index 4749730c..30851e1c 100644 --- a/pbs/src/main/java/com/sdm/pbs/service/impl/PbsServiceDecorator.java +++ b/pbs/src/main/java/com/sdm/pbs/service/impl/PbsServiceDecorator.java @@ -10,9 +10,11 @@ import com.sdm.common.common.SdmResponse; import com.sdm.common.common.ThreadLocalContext; import com.sdm.common.entity.enums.MessageTemplateEnum; import com.sdm.common.entity.req.flowable.AsyncCallbackRequest; +import com.sdm.common.entity.req.pbs.DelHpcJobsFileToolReq; import com.sdm.common.entity.req.pbs.DelHpcJobsReq; import com.sdm.common.entity.req.system.SendMsgReq; import com.sdm.common.entity.resp.PageDataResp; +import com.sdm.common.entity.resp.pbs.hpc.DelHpcJobsResult; import com.sdm.common.entity.resp.pbs.hpc.FileNodeInfo; import com.sdm.common.feign.impl.system.MessageFeignClientImpl; import com.sdm.common.feign.inter.flowable.IFlowableFeignClient; @@ -55,6 +57,7 @@ import java.time.LocalDateTime; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; @Slf4j @Service @@ -579,7 +582,7 @@ public class PbsServiceDecorator implements IPbsServiceDecorator { List jobList = simulationJobService.lambdaQuery() .in(SimulationJob::getJobId, req.getHpcJobIds()) .list(); - if (jobList.isEmpty()) { + if (CollectionUtils.isEmpty(jobList)) { throw new RuntimeException("未查询到待删除的HPC任务"); } // 2. 校验任务状态(非进行中、文件非上传中) @@ -589,20 +592,59 @@ public class PbsServiceDecorator implements IPbsServiceDecorator { throw new RuntimeException("删除的任务状态和文件状态不能是未完成"); } - // 2. 调用HPC批量删除接口 todo -// boolean hpcDelSuccess = batchDeleteHpcJobs(req.getHpcJobIds()); -// if (!hpcDelSuccess) { -// return SdmResponse.fail("调用HPC批量删除接口失败"); -// } - - // 5. 逻辑删除simulation_job表数据 - boolean logicDelSuccess = logicDeleteSimulationJob(jobList); - if (!logicDelSuccess) { - return SdmResponse.failed("逻辑删除任务数据失败"); + // 3. 调用HPC批量删除接口 + SdmResponse response = batchDeleteHpcJobs(jobList); + if (!response.isSuccess()) { + return SdmResponse.failed("调用HPC文件工具服务批量删除工作目录失败:{}",JSONObject.toJSONString(response)); + } + DelHpcJobsResult data = response.getData(); + if(!Objects.isNull(data)&&CollectionUtils.isNotEmpty(data.getSuccJobIds())){ + List succJobIds = data.getSuccJobIds(); + List newJobs = filterSuccessJobs(jobList, succJobIds); + // 5. 逻辑删除simulation_job表数据 + boolean logicDelSuccess = logicDeleteSimulationJob(newJobs); + if (!logicDelSuccess) { + return SdmResponse.failed("逻辑删除任务数据失败"); + } } return SdmResponse.success("批量删除HPC任务成功"); } + /** + * 筛选出jobId在succJobIds中的SimulationJob集合 + * @param jobList 原始任务集合 + * @param succJobIds 成功的jobId集合 + * @return 筛选后的新任务集合 + */ + private List filterSuccessJobs(List jobList, List succJobIds) { + // 2. 使用Stream流筛选:jobId存在于succJobIds中的元素 + List newJobList = jobList.stream() + // 核心筛选逻辑:判断当前job的jobId是否在succJobIds中 + .filter(job -> succJobIds.contains(job.getJobId())) + // 收集筛选结果到新集合 + .collect(Collectors.toList()); + return newJobList; + } + + private SdmResponse batchDeleteHpcJobs(List jobList) { + // 远程请求filetool工具 + List reqs = new ArrayList<>(); + for (SimulationJob job : jobList) { + if(StringUtils.isNotBlank(job.getJobId())&&StringUtils.isNotBlank(job.getStdoutHpcFilePath())){ + DelHpcJobsFileToolReq req = new DelHpcJobsFileToolReq(); + req.setJobId(job.getJobId()); + req.setStdoutHpcFilePath(job.getStdoutHpcFilePath()); + reqs.add(req); + } + } + if(CollectionUtils.isEmpty(reqs)){ + log.error("batchDeleteHpcJobs get reqs null"); + return SdmResponse.failed("请求参数是null"); + } + SdmResponse response = hpcCommandExcuteUtil.batchDeleteHpcJobs(reqs, pbsWebClient); + return response; + } + private boolean logicDeleteSimulationJob(List jobList) { for (SimulationJob job : jobList) { job.setDelFlag("Y"); diff --git a/pbs/src/main/resources/application-dev-190.yml b/pbs/src/main/resources/application-dev-190.yml index 8783658a..39abeb61 100644 --- a/pbs/src/main/resources/application-dev-190.yml +++ b/pbs/src/main/resources/application-dev-190.yml @@ -121,6 +121,7 @@ hpc: remoteDownLoadFileUrl: http://192.168.190.164:9098/hpcDownload remoteUploadFileUrl: http://192.168.190.164:9098/uploadHpcFile callHpcUpload: http://192.168.190.164:9098/addJobQueue + delHpcJobsUrl: http://192.168.190.164:9098/delHpcJobs # 上传头节点文件相关的配置 fileToHpc: http: diff --git a/pbs/src/main/resources/application-dev-65.yml b/pbs/src/main/resources/application-dev-65.yml index 72e76ef5..3b1a28f9 100644 --- a/pbs/src/main/resources/application-dev-65.yml +++ b/pbs/src/main/resources/application-dev-65.yml @@ -122,6 +122,7 @@ hpc: # remoteDownLoadFileUrl: http://127.0.0.1:9097/hpcDownload remoteUploadFileUrl: http://192.168.65.55:9097/uploadHpcFile callHpcUpload: http://192.168.65.55:9097/addJobQueue + delHpcJobsUrl: http://192.168.65.55:9098/delHpcJobs # 上传头节点文件相关的配置 fileToHpc: http: diff --git a/pbs/src/main/resources/application-lyric.yml b/pbs/src/main/resources/application-lyric.yml index d2776914..0776a43e 100644 --- a/pbs/src/main/resources/application-lyric.yml +++ b/pbs/src/main/resources/application-lyric.yml @@ -122,6 +122,7 @@ hpc: # remoteDownLoadFileUrl: http://127.0.0.1:9097/hpcDownload remoteUploadFileUrl: http://10.122.38.200:9098/uploadHpcFile callHpcUpload: http://10.122.38.200:9098/addJobQueue + delHpcJobsUrl: http://10.122.38.200:9098/delHpcJobs # 上传头节点文件相关的配置 fileToHpc: http: From e34482000ad35585a66a9a32680986815774c795 Mon Sep 17 00:00:00 2001 From: zhuxinru Date: Tue, 10 Feb 2026 15:46:49 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix:=E4=BB=BB=E5=8A=A1=E4=B8=8B=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E6=8A=A5=E5=91=8A=E5=BD=92=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sdm/common/entity/resp/project/SpdmTaskVo.java | 4 ++-- .../service/impl/SimulationRunServiceImpl.java | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/com/sdm/common/entity/resp/project/SpdmTaskVo.java b/common/src/main/java/com/sdm/common/entity/resp/project/SpdmTaskVo.java index dc77c667..e3aca37d 100644 --- a/common/src/main/java/com/sdm/common/entity/resp/project/SpdmTaskVo.java +++ b/common/src/main/java/com/sdm/common/entity/resp/project/SpdmTaskVo.java @@ -228,7 +228,7 @@ public class SpdmTaskVo extends BaseEntity { @Schema(description= "报告模板内容") private String reportContent; - @Schema(description= "任务uuid") - private String taskId; + @Schema(description= "报告模板uuid") + private String reportTemplate; } diff --git a/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java index 684c7180..90433691 100644 --- a/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java @@ -1527,7 +1527,7 @@ public class SimulationRunServiceImpl extends ServiceImpl Date: Tue, 10 Feb 2026 17:18:33 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E5=90=8E?= =?UTF-8?q?=E7=BD=AE=E6=AD=A3=E5=88=99=E8=BF=87=E6=BB=A4=E6=96=87=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E4=BC=A0=E5=B0=B1=E4=BC=A0=E9=80=92=E6=89=80?= =?UTF-8?q?=E6=9C=89=EF=BC=8C=E4=BC=A0=E9=80=92=E5=B0=B1=E6=8C=89=E7=85=A7?= =?UTF-8?q?=E6=AD=A3=E5=88=99=E5=9B=9E=E4=BC=A0=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/sdm/common/utils/HpcCommandExcuteUtil.java | 3 ++- pbs/src/main/java/com/sdm/pbs/controller/TaskController.java | 2 +- .../sdm/pbs/schedule/hpc/hander/FinishedStatusHandler.java | 3 ++- .../main/java/com/sdm/pbs/service/HpcInstructionService.java | 2 +- .../com/sdm/pbs/service/impl/HpcInstructionServiceImpl.java | 4 ++-- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/com/sdm/common/utils/HpcCommandExcuteUtil.java b/common/src/main/java/com/sdm/common/utils/HpcCommandExcuteUtil.java index b958d6cc..9006d472 100644 --- a/common/src/main/java/com/sdm/common/utils/HpcCommandExcuteUtil.java +++ b/common/src/main/java/com/sdm/common/utils/HpcCommandExcuteUtil.java @@ -180,7 +180,7 @@ public class HpcCommandExcuteUtil { public SdmResponse callHpcUploadToTarget(String jobId, String workDir,String minioBucket, String callBackMinioDir,String callBackNasDir, - Long dirId,Long userId,Long tenantId) { + Long dirId,Long userId,Long tenantId,String outputFormat) { com.alibaba.fastjson2.JSONObject paramJson = new com.alibaba.fastjson2.JSONObject(); paramJson.put("jobId", jobId); paramJson.put("jobWorkDir", workDir); @@ -190,6 +190,7 @@ public class HpcCommandExcuteUtil { paramJson.put("dirId", dirId); paramJson.put("userId", userId); paramJson.put("tenantId", tenantId); + paramJson.put("outputFormat", outputFormat); Boolean call = false; String resultString = ""; try { diff --git a/pbs/src/main/java/com/sdm/pbs/controller/TaskController.java b/pbs/src/main/java/com/sdm/pbs/controller/TaskController.java index 49e70905..85725453 100644 --- a/pbs/src/main/java/com/sdm/pbs/controller/TaskController.java +++ b/pbs/src/main/java/com/sdm/pbs/controller/TaskController.java @@ -248,7 +248,7 @@ public class TaskController { return hpcInstructionService.callHpcUploadToTarget(paramMap.get("jobId").toString(), paramMap.get("jobWorkDir").toString(), paramMap.get("minioBucket").toString(), paramMap.get("callBackMinioDir").toString() ,paramMap.get("callBackNasDir").toString(), Long.valueOf(paramMap.get("dirId").toString()), - Long.valueOf(paramMap.get("userId").toString()),Long.valueOf(paramMap.get("tenantId").toString())); + Long.valueOf(paramMap.get("userId").toString()),Long.valueOf(paramMap.get("tenantId").toString()),paramMap.get("outputFormat").toString()); } } diff --git a/pbs/src/main/java/com/sdm/pbs/schedule/hpc/hander/FinishedStatusHandler.java b/pbs/src/main/java/com/sdm/pbs/schedule/hpc/hander/FinishedStatusHandler.java index cf9cf41e..4aa7088a 100644 --- a/pbs/src/main/java/com/sdm/pbs/schedule/hpc/hander/FinishedStatusHandler.java +++ b/pbs/src/main/java/com/sdm/pbs/schedule/hpc/hander/FinishedStatusHandler.java @@ -95,9 +95,10 @@ public class FinishedStatusHandler implements JobStatusHandler { String minioBucket = minioBucketPrefix + newDbJob.getTenantId(); Long userId=newDbJob.getCreatorId(); Long tenantId = newDbJob.getTenantId(); + String outputFormat = newDbJob.getOutputFormat(); // 通知工具回传文件 minio 或者 nas SdmResponse callResponse = hpcInstructionService.callHpcUploadToTarget(newDbJob.getJobId(), newDbJob.getStdoutHpcFilePath(),minioBucket, - newDbJob.getStdoutSpdmMinoFilePath(),newDbJob.getStdoutSpdmNasFilePath(),newDbJob.getDirId(),userId,tenantId); + newDbJob.getStdoutSpdmMinoFilePath(),newDbJob.getStdoutSpdmNasFilePath(),newDbJob.getDirId(),userId,tenantId,outputFormat); if (!callResponse.isSuccess()||!callResponse.getData()) { CoreLogger.error("callHpcUploadToTarget failed,jobId:{},workDir:{}",newDbJob.getJobId(),newDbJob.getStdoutHpcFilePath()); return; diff --git a/pbs/src/main/java/com/sdm/pbs/service/HpcInstructionService.java b/pbs/src/main/java/com/sdm/pbs/service/HpcInstructionService.java index 1164d605..20e60877 100644 --- a/pbs/src/main/java/com/sdm/pbs/service/HpcInstructionService.java +++ b/pbs/src/main/java/com/sdm/pbs/service/HpcInstructionService.java @@ -57,6 +57,6 @@ public interface HpcInstructionService { // 通知hpc回传文件 SdmResponse callHpcUploadToTarget(String jobId,String workDir,String minioBucket, String callBackMinioDir,String callBackNasDir,Long dirId, - Long userId,Long tenantId); + Long userId,Long tenantId,String outputFormat); } diff --git a/pbs/src/main/java/com/sdm/pbs/service/impl/HpcInstructionServiceImpl.java b/pbs/src/main/java/com/sdm/pbs/service/impl/HpcInstructionServiceImpl.java index 2037ca41..7aeaaa4c 100644 --- a/pbs/src/main/java/com/sdm/pbs/service/impl/HpcInstructionServiceImpl.java +++ b/pbs/src/main/java/com/sdm/pbs/service/impl/HpcInstructionServiceImpl.java @@ -501,9 +501,9 @@ public class HpcInstructionServiceImpl implements HpcInstructionService { @Override public SdmResponse callHpcUploadToTarget(String jobId,String workDir,String minioBucket, String callBackMinioDir,String callBackNasDir,Long dirId, - Long userId,Long tenantId) { + Long userId,Long tenantId,String outputFormat) { return hpcCommandExcuteUtil.callHpcUploadToTarget(jobId,workDir,minioBucket,callBackMinioDir, - callBackNasDir,dirId,userId,tenantId); + callBackNasDir,dirId,userId,tenantId,outputFormat); } /**