From 8e94a466400736081bc6c7be4998f38ac3970ec5 Mon Sep 17 00:00:00 2001 From: yangyang01000846 <15195822163@163.com> Date: Fri, 9 Jan 2026 13:56:02 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9Ahpc=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E5=91=BD=E4=BB=A4=E5=8F=82=E6=95=B0=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E6=96=B0=E5=A2=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-sql/2026-01-06/simulation_job.sql | 2 +- 1-sql/2026-01-09/yang.sql | 94 +++++ 1-sql/spdmbaseline/base.sql | 2 +- .../executeConfig/HPCExecuteConfig.java | 5 +- .../req/pbs/SubmitHpcTaskRemoteReq.java | 7 + .../sdm/common/utils/CommandReplaceUtil.java | 108 ++++++ .../flowable/delegate/handler/HpcHandler.java | 28 +- .../com/sdm/pbs/controller/TaskAdapter.java | 33 +- .../sdm/pbs/controller/TaskController.java | 6 +- .../SimulationCommandPlaceholderMapper.java | 4 +- .../pbs/dao/SimulationSoftConfigMapper.java | 4 +- .../com/sdm/pbs/model/bo/CommandResult.java | 11 + .../entity/SimulationCommandPlaceholder.java | 74 ---- ...tConfig.java => SimulationHpcCommand.java} | 45 ++- .../SimulationHpcCommandPlaceholder.java | 99 +++++ .../sdm/pbs/model/entity/SimulationJob.java | 2 +- .../sdm/pbs/model/req/SubmitHpcTaskReq.java | 6 +- .../ISimulationCommandPlaceholderService.java | 4 +- .../service/ISimulationSoftConfigService.java | 4 +- ...mulationCommandPlaceholderServiceImpl.java | 4 +- .../pbs/service/impl/PbsServiceDecorator.java | 355 ++++++++++++++---- .../impl/SimulationSoftConfigServiceImpl.java | 4 +- 22 files changed, 709 insertions(+), 192 deletions(-) create mode 100644 1-sql/2026-01-09/yang.sql create mode 100644 common/src/main/java/com/sdm/common/utils/CommandReplaceUtil.java create mode 100644 pbs/src/main/java/com/sdm/pbs/model/bo/CommandResult.java delete mode 100644 pbs/src/main/java/com/sdm/pbs/model/entity/SimulationCommandPlaceholder.java rename pbs/src/main/java/com/sdm/pbs/model/entity/{SimulationSoftConfig.java => SimulationHpcCommand.java} (51%) create mode 100644 pbs/src/main/java/com/sdm/pbs/model/entity/SimulationHpcCommandPlaceholder.java diff --git a/1-sql/2026-01-06/simulation_job.sql b/1-sql/2026-01-06/simulation_job.sql index 1c0a29c8..513e87a7 100644 --- a/1-sql/2026-01-06/simulation_job.sql +++ b/1-sql/2026-01-06/simulation_job.sql @@ -15,7 +15,7 @@ CREATE TABLE `simulation_job` ( `taskName` varchar(255) DEFAULT NULL COMMENT '计算任务所属任务名称', `runId` varchar(64) DEFAULT NULL COMMENT '计算任务所属算力ID', `runName` varchar(255) DEFAULT NULL COMMENT '计算任务所属算力名称', - `softwareId` bigint DEFAULT NULL COMMENT '使用软件的id', + `softwareId` varchar(128) DEFAULT NULL COMMENT '使用软件的id', `inputFileId` bigint DEFAULT NULL COMMENT '求解文件对应的文件Id', `jobId` varchar(255) DEFAULT NULL COMMENT '计算任务Id,job new 生成', `jobDetailId` varchar(255) DEFAULT NULL COMMENT '计算任务添加时Id,job add 生成', diff --git a/1-sql/2026-01-09/yang.sql b/1-sql/2026-01-09/yang.sql new file mode 100644 index 00000000..15147379 --- /dev/null +++ b/1-sql/2026-01-09/yang.sql @@ -0,0 +1,94 @@ +drop table simulation_soft_config; +drop table simulation_command_placeholder; +-- 下面的表和app注册表 simulation_app_repository 主键id关联 +CREATE TABLE `spdm_baseline`.`simulation_hpc_command` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `appUuid` varchar(128) NOT NULL COMMENT 'app注册的uuId', + `softName` varchar(255) NOT NULL COMMENT '软件名称,对应的simulation_app_repository的appName,名字建议格式appName_v1', + `softVersion` varchar(32) DEFAULT NULL COMMENT '软件版本号', + `functionDsc` varchar(255) DEFAULT NULL COMMENT '功能描述(如:电池仿真)', + `command` text NOT NULL COMMENT '功能对应的CMD命令', + `postFileRegular` varchar(512) DEFAULT NULL COMMENT '预留-软件执行完成后筛选回传文件正则,用于过滤回传文件', + `creatorId` bigint DEFAULT NULL COMMENT '创建者ID', + `createTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updaterId` bigint DEFAULT NULL COMMENT '更新者ID', + `updateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', + PRIMARY KEY (`id`), + KEY `simulation_command_soft_name` (`softName`) COMMENT '按软件名称查询', + KEY `simulation_command_appUuid` (`appUuid`) COMMENT '按appid查询' +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='仿真软件hpc命令配置表'; + +CREATE TABLE `spdm_baseline`.`simulation_hpc_command_placeholder` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `appUuid` varchar(128)NOT NULL COMMENT 'app注册的uuId', + `keyEnName` varchar(255) NOT NULL COMMENT '占位符英文名称', + `keyCnName` varchar(255) NOT NULL COMMENT '占位符中文名称', + `valueType` varchar(50) NOT NULL COMMENT '占位符值的类型(file:共享云盘文件;input:用户自定义输入)', + `isDisplay` varchar(1) NOT NULL DEFAULT 'Y' COMMENT '是否展示(Y:是,N:否),N时必须填写默认值', + `featchType` varchar(16) NOT NULL DEFAULT 'input' COMMENT '动态参数获取值的来源,input:用户自定义,default:默认值,param:从参数里取', + `defaultValue` varchar(512) DEFAULT NULL COMMENT '默认值:valueType为Input且isDisplay为N时必填', + `fileRegular` varchar(512) DEFAULT NULL COMMENT '文件正则表达式:valueType为file时必填,用于过滤对应的求解文件', + `creatorId` bigint DEFAULT NULL COMMENT '创建者ID', + `createTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updaterId` bigint DEFAULT NULL COMMENT '更新者ID', + `updateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', + PRIMARY KEY (`id`), + KEY `placeholder_appUuid` (`appUuid`) COMMENT 'app表hpc求解器id查询' +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='仿真工具hpc命令占位符配置表'; + +-- 记得仿真任务执行的时候也记录 appRepositoryId +-- isDisplay 是N 假如 defaultValue是null,则在从提交对象的参数获取数据赋值 +-- 回传的正则没有就是全部所有的文件 +-- file类型的,先收集正则,把文件先上传到工作目录 + + +-- job 表修改 +drop table simulation_job; +CREATE TABLE `simulation_job` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID,自增', + `jobName` varchar(255) NOT NULL COMMENT '计算任务名称', + `coreNum` int DEFAULT NULL COMMENT '计算所需要核数', + `software` varchar(100) DEFAULT NULL COMMENT '计算软件的名称', + `jobType` varchar(255) DEFAULT NULL COMMENT '计算任务类型', + `independence` tinyint(1) NOT NULL DEFAULT '0' COMMENT '计算任务是否独立存在 0:非独立任务 1:独立任务', + `inputFiles` text COMMENT '求解文件(JSON格式存储文件UUID列表)', + `masterFile` varchar(255) DEFAULT NULL COMMENT '计算主文件(文件UUID)', + `taskId` varchar(64) DEFAULT NULL COMMENT '计算任务所属任务ID', + `taskName` varchar(255) DEFAULT NULL COMMENT '计算任务所属任务名称', + `runId` varchar(64) DEFAULT NULL COMMENT '计算任务所属算力ID', + `runName` varchar(255) DEFAULT NULL COMMENT '计算任务所属算力名称', + `softwareId` varchar(128) DEFAULT NULL COMMENT '使用软件的uuid', + `inputFileId` bigint DEFAULT NULL COMMENT '求解文件对应的文件Id', + `jobId` varchar(255) DEFAULT NULL COMMENT '计算任务Id,job new 生成', + `jobDetailId` varchar(255) DEFAULT NULL COMMENT '计算任务添加时Id,job add 生成', + `stdoutHpcFilePath` varchar(512) DEFAULT NULL COMMENT '任务执行输出的文件在Hpc的绝对路径,共享目录+jobName(文件回传)+uuid,下面可能有多个文件', + `stdoutSpdmMinoFilePath` varchar(1024) DEFAULT NULL COMMENT '任务执行输出的文件在 MinIO 上的路径(baseDir+jobName+uuid,可能包含多个文件)', + `nodeName` varchar(256) DEFAULT NULL COMMENT '节点名称', + `executCommand` text COMMENT '记录最终执行的执行对应工具命令', + `startTime` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '任务开始时间', + `endTime` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '任务结束时间', + `jobStatus` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '任务状态,spdm,+hpc返回的其他状态(定时任务维护)', + `solverName` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '求解器名称', + `totalKernelTime` bigint DEFAULT NULL COMMENT '总内核态时间(单位:毫秒)', + `totalUserTime` bigint DEFAULT NULL COMMENT '总用户态时间(单位:毫秒)', + `totalElapsedTime` bigint DEFAULT NULL COMMENT '作业耗费总秒数(单位:秒)', + `uuid` varchar(64) DEFAULT NULL COMMENT '配置提交前端生成不带横线的uuid', + `fileStatus` varchar(16) DEFAULT NULL COMMENT '任务结果回传状态,generating,uploading,finished', + `creatorId` bigint DEFAULT NULL COMMENT '创建者ID', + `createTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updaterId` bigint DEFAULT NULL COMMENT '更新者ID', + `updateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', + `stdoutSpdmNasFilePath` varchar(1024) DEFAULT NULL COMMENT '任务执行输出的文件在 NAS 上的路径(baseDir+jobName+uuid,可能包含多个文件)', + `tenantId` bigint DEFAULT NULL COMMENT '租户ID', + PRIMARY KEY (`id`), + KEY `idx_task_id` (`taskId`) COMMENT '按所属任务ID查询', + KEY `idx_run_id` (`runId`) COMMENT '按所属算力ID查询', + KEY `idx_job_name` (`jobName`) COMMENT '按任务名称查询', + KEY `idx_job_status` (`jobStatus`) COMMENT '按任务状态查询', + KEY `idx_softwareId` (`softwareId`) COMMENT '按软件id查询', + KEY `idx_node_name` (`nodeName`) COMMENT '按节点名称查询' +) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='仿真计算任务表'; + +-- 家里修改 +-- 修改softwareId字段类型为varchar(128) +ALTER TABLE `simulation_job` MODIFY COLUMN `softwareId` varchar(128) DEFAULT NULL COMMENT '使用软件的id'; diff --git a/1-sql/spdmbaseline/base.sql b/1-sql/spdmbaseline/base.sql index 63fb94b6..2cc17e36 100644 --- a/1-sql/spdmbaseline/base.sql +++ b/1-sql/spdmbaseline/base.sql @@ -531,7 +531,7 @@ CREATE TABLE `simulation_job` ( `taskName` varchar(255) DEFAULT NULL COMMENT '计算任务所属任务名称', `runId` varchar(64) DEFAULT NULL COMMENT '计算任务所属算力ID', `runName` varchar(255) DEFAULT NULL COMMENT '计算任务所属算力名称', - `softwareId` bigint DEFAULT NULL COMMENT '使用软件的id', + `softwareId` varchar(128) DEFAULT NULL COMMENT '使用软件的id', `inputFileId` bigint NOT NULL COMMENT '求解文件对应的文件Id', `jobId` varchar(255) DEFAULT NULL COMMENT '计算任务Id,job new 生成', `jobDetailId` varchar(255) DEFAULT NULL COMMENT '计算任务添加时Id,job add 生成', diff --git a/common/src/main/java/com/sdm/common/entity/flowable/executeConfig/HPCExecuteConfig.java b/common/src/main/java/com/sdm/common/entity/flowable/executeConfig/HPCExecuteConfig.java index 8ee3a91f..350a6ff6 100644 --- a/common/src/main/java/com/sdm/common/entity/flowable/executeConfig/HPCExecuteConfig.java +++ b/common/src/main/java/com/sdm/common/entity/flowable/executeConfig/HPCExecuteConfig.java @@ -10,7 +10,10 @@ public class HPCExecuteConfig extends BaseExecuteConfig { private String masterFileRegularStr = "^.*\\.xml$"; // 先默认写死一个,后面前端配置传递 private String inputFilesRegularStr="^.+\\.json$"; - // 节点的命令 + // 节点的命令 这个不用传递了,配置在后台表里的 private String nodeExeCommand; + // app注册表的uuid + private String uuid; + } diff --git a/common/src/main/java/com/sdm/common/entity/req/pbs/SubmitHpcTaskRemoteReq.java b/common/src/main/java/com/sdm/common/entity/req/pbs/SubmitHpcTaskRemoteReq.java index cd145345..5e4d7c51 100644 --- a/common/src/main/java/com/sdm/common/entity/req/pbs/SubmitHpcTaskRemoteReq.java +++ b/common/src/main/java/com/sdm/common/entity/req/pbs/SubmitHpcTaskRemoteReq.java @@ -5,6 +5,7 @@ import lombok.Data; import java.io.Serializable; import java.util.List; +import java.util.Map; @Data public class SubmitHpcTaskRemoteReq implements Serializable { @@ -19,6 +20,9 @@ public class SubmitHpcTaskRemoteReq implements Serializable { @Schema(description = "计算软件") public String software; + @Schema(description = "计算软件uuid") + public String softwareId; + @Schema(description = "计算任务类型") public String jobType; @@ -70,4 +74,7 @@ public class SubmitHpcTaskRemoteReq implements Serializable { @Schema(description = "任务求解文件从文件路径,adapter里使用,executeMode=MANUAL") public List manualInputFilePaths; + @Schema(description = "任务流用户传递的参数,用于动态替换命令") + private Map params; + } diff --git a/common/src/main/java/com/sdm/common/utils/CommandReplaceUtil.java b/common/src/main/java/com/sdm/common/utils/CommandReplaceUtil.java new file mode 100644 index 00000000..f915b068 --- /dev/null +++ b/common/src/main/java/com/sdm/common/utils/CommandReplaceUtil.java @@ -0,0 +1,108 @@ +package com.sdm.common.utils; + +import cn.hutool.core.util.ObjectUtil; +import com.sdm.common.entity.req.pbs.SubmitHpcTaskRemoteReq; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Field; +@Slf4j +public class CommandReplaceUtil { + /** + * 通用替换方法:将命令字符串中的 %key 占位符替换为指定值 + * @param command 原始命令字符串(包含%key形式的占位符) + * @param key 要替换的占位符键名(不需要带%) + * @param value 替换后的值 + * @return 替换完成后的命令字符串 + */ + public static String replaceCommandPlaceholder(String command, String key, Object value) { + // 1. 空值校验,避免空指针异常 + if (command == null) { + throw new IllegalArgumentException("命令字符串(command)不能为null"); + } + if (key == null || key.trim().isEmpty()) { + throw new IllegalArgumentException("占位符键名(key)不能为null或空字符串"); + } + // value允许为空,空值时直接替换成空字符串 + String replaceValue = ObjectUtil.isEmpty(value) ? "" : value.toString(); + + // 2. 构建要替换的占位符(% + key) + String placeholder = "%" + key.trim(); + + // 3. 替换所有匹配的占位符 + return command.replace(placeholder, replaceValue); + } + + /** + * 根据字段名动态获取对象的字段值 + * @param obj 目标对象 + * @param fieldName 字段名(如 masterFileRegularStr) + * @return 字段值 + * @throws NoSuchFieldException 字段不存在 + * @throws IllegalAccessException 访问权限不足 + */ + public static Object getFieldValue(Object obj, String fieldName) { + if (obj == null || fieldName == null || fieldName.isEmpty()) { + log.warn("获取对象为空,或者字段名为空"); + return null; + } + // 1. 获取对象的Class对象 + Class clazz = obj.getClass(); + // 2. 获取字段(包括public/private/protected) + Field field = null; + try { + field = clazz.getDeclaredField(fieldName); + } catch (Exception e) { + log.warn("反射获取字段{}异常,{}", fieldName,e.getMessage()); + return null; + } + // 3. 设置访问权限(即使字段是private也能访问) + field.setAccessible(true); + // 4. 获取字段值 + try { + Object o = field.get(obj); + return o; + } catch (Exception e) { + log.warn("反射获取字段值{}异常,{}", fieldName,e.getMessage()); + return null; + } + } + + public static void main(String[] args) { + // 1. 创建测试对象 + SubmitHpcTaskRemoteReq req = new SubmitHpcTaskRemoteReq(); + req.setJobName("流体力学计算"); + req.setCoreNum(8); + req.setMasterFileRegularStr("/data/input/file.txt"); + req.setSoftwareId("softwareId11"); + // 获取String类型字段 + String jobName = (String) getFieldValue(req, "jobName"); + System.out.println("jobName = " + jobName); // 输出:流体力学计算 + + // 获取int类型字段 + Integer coreNum = (Integer) getFieldValue(req, "coreNum"); + System.out.println("coreNum = " + coreNum); // 输出:8 + + // 获取private字段(appRepositoryId) + String appId = (String) getFieldValue(req, "softwareId"); + System.out.println("softwareId = " + appId); // 输出:1001 + + } + + +// // 测试示例 +// public static void main(String[] args) { +// // 测试用的原始命令 +// String command = "\\\\CARSAFE\\share\\solver\\RLithium\\reta.exe -i %masterFilePath -t %coreNum -m %memory"; +// // 替换coreNum为4 +// String newCommand = replaceCommandPlaceholder(command, "coreNum", "4"); +// System.out.println("替换后命令:"); +// System.out.println(newCommand); +// +// // 继续替换其他占位符示例 +// newCommand = replaceCommandPlaceholder(newCommand, "memory", "8G"); +// System.out.println("\n继续替换memory后:"); +// System.out.println(newCommand); +// +// +// } +} diff --git a/flowable/src/main/java/com/sdm/flowable/delegate/handler/HpcHandler.java b/flowable/src/main/java/com/sdm/flowable/delegate/handler/HpcHandler.java index dc3a76de..d0054bf2 100644 --- a/flowable/src/main/java/com/sdm/flowable/delegate/handler/HpcHandler.java +++ b/flowable/src/main/java/com/sdm/flowable/delegate/handler/HpcHandler.java @@ -63,7 +63,10 @@ public class HpcHandler implements ExecutionHandler,HPCExecu @Override public void execute(DelegateExecution execution, Map params, HPCExecuteConfig config) { CoreLogger.info("hpc process excute,params:{},config:{}",JSONObject.toJSONString(params),JSONObject.toJSONString(config)); - SubmitHpcTaskRemoteReq submitHpcTaskRemoteReq = convertParamsToReq(params,config.getNodeExeCommand()); + SubmitHpcTaskRemoteReq submitHpcTaskRemoteReq = convertParamsToReq(params); + submitHpcTaskRemoteReq.setParams(params); + // 设置软件id + submitHpcTaskRemoteReq.setSoftwareId(config.getUuid()); String beforeNodeId = config.getBeforeNodeId(); String currentNodeId =execution.getCurrentActivityId(); String masterFileRegularStr = config.getMasterFileRegularStr(); @@ -89,6 +92,7 @@ public class HpcHandler implements ExecutionHandler,HPCExecu } // 处理hpc求解文件路径 dealHpcFile(submitHpcTaskRemoteReq,beforeNodeId,currentNodeId, processDefinitionId,processInstanceId,executeMode,params); + // // 实现HPC处理逻辑... // INIT(初始化)/RUNNING(执行中)/SUCCESS(执行成功)/FAIL(执行失败) String status = AsyncTaskStatusEnum.INIT.getCode(); @@ -226,10 +230,10 @@ public class HpcHandler implements ExecutionHandler,HPCExecu } /** - * 将参数Map转换为SubmitHpcTaskRemoteReq对象的工具方法 + * 将参数Map转换为SubmitHpcTaskRemoteReq对象的工具方法 String command */ - private SubmitHpcTaskRemoteReq convertParamsToReq(Map params,String command) { - CoreLogger.error("convertParamsToReq start command:{}",command); + private SubmitHpcTaskRemoteReq convertParamsToReq(Map params) { + CoreLogger.error("convertParamsToReq start "); SubmitHpcTaskRemoteReq req = new SubmitHpcTaskRemoteReq(); if (params == null) { return req; @@ -258,14 +262,14 @@ public class HpcHandler implements ExecutionHandler,HPCExecu // String command =(params.get("command")==null||StringUtils.isBlank(params.get("command").toString()))? // "\\\\CARSAFE\\share\\solver\\RLithium\\reta.exe -i %s" : params.get("command").toString(); // 只是测试环境用于兜底mock - if(StringUtils.isBlank(command)){ - command = mockCommand; - } - if(StringUtils.isBlank(command)){ - CoreLogger.error("command is empty!!!!!"); - throw new RuntimeException("command is empty"); - } - req.setCommand(command); +// if(StringUtils.isBlank(command)){ +// command = mockCommand; +// } +// if(StringUtils.isBlank(command)){ +// CoreLogger.error("command is empty!!!!!"); +// throw new RuntimeException("command is empty"); +// } +// req.setCommand(command); req.setProjectname(params.get("projectname").toString()); // req.setFeatchFileType(params.get("featchFileType").toString()); // req.setBeforeNodeId(params.get("beforeNodeId").toString()); diff --git a/pbs/src/main/java/com/sdm/pbs/controller/TaskAdapter.java b/pbs/src/main/java/com/sdm/pbs/controller/TaskAdapter.java index 52a61a66..9e2de9f2 100644 --- a/pbs/src/main/java/com/sdm/pbs/controller/TaskAdapter.java +++ b/pbs/src/main/java/com/sdm/pbs/controller/TaskAdapter.java @@ -12,15 +12,11 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.concurrent.atomic.AtomicReference; @Slf4j @@ -35,6 +31,29 @@ public class TaskAdapter implements ITaskFeignClient { @Autowired private TaskController taskController; + + @Value("${testEnStr:}") + private String enStr; + @Value("${testEnStr2:}") + private String testEnStr2; + + @Value("${pbs.task.impl}") + private String pbsImpl; + + @GetMapping("/testEn") + @Operation(summary = "作业提交") + public SdmResponse> testEn() { + Map map = new HashMap<>(); + map.put("enStr", enStr); + map.put("pbsImpl", pbsImpl); + map.put("testEnStr2", testEnStr2); + return SdmResponse.success(map); + } + + + + + @PostMapping("/adapterSubmitHpcJob") @Operation(summary = "作业提交") public SdmResponse adapterSubmitHpcJob(@RequestBody SubmitHpcTaskRemoteReq req) { 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 3154cf2b..9ea944e9 100644 --- a/pbs/src/main/java/com/sdm/pbs/controller/TaskController.java +++ b/pbs/src/main/java/com/sdm/pbs/controller/TaskController.java @@ -14,7 +14,7 @@ import com.sdm.common.utils.HpcCommandExcuteUtil; import com.sdm.pbs.model.bo.HpcJobStatusInfo; import com.sdm.pbs.model.bo.HpcResouceInfo; import com.sdm.pbs.model.entity.SimulationJob; -import com.sdm.pbs.model.entity.SimulationSoftConfig; +import com.sdm.pbs.model.entity.SimulationHpcCommand; import com.sdm.pbs.model.req.JobFileCallBackReq; import com.sdm.pbs.model.req.QueryJobReq; import com.sdm.pbs.model.req.SubmitHpcTaskReq; @@ -114,8 +114,8 @@ public class TaskController { @GetMapping("/querySoftConfig") @Operation(summary = "spdm系统查询hpc求解器指令配置") - SdmResponse>> querySoftConfig (@RequestParam String softName) { - return pbsServiceDecorator.querySoftConfig(softName); + SdmResponse querySoftConfig (@RequestParam String appUuid) { + return pbsServiceDecorator.querySoftConfig(appUuid); } diff --git a/pbs/src/main/java/com/sdm/pbs/dao/SimulationCommandPlaceholderMapper.java b/pbs/src/main/java/com/sdm/pbs/dao/SimulationCommandPlaceholderMapper.java index ee4c0c30..8a7ee543 100644 --- a/pbs/src/main/java/com/sdm/pbs/dao/SimulationCommandPlaceholderMapper.java +++ b/pbs/src/main/java/com/sdm/pbs/dao/SimulationCommandPlaceholderMapper.java @@ -1,7 +1,7 @@ package com.sdm.pbs.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.sdm.pbs.model.entity.SimulationCommandPlaceholder; +import com.sdm.pbs.model.entity.SimulationHpcCommandPlaceholder; /** *

@@ -11,6 +11,6 @@ import com.sdm.pbs.model.entity.SimulationCommandPlaceholder; * @author author * @since 2025-11-05 */ -public interface SimulationCommandPlaceholderMapper extends BaseMapper { +public interface SimulationCommandPlaceholderMapper extends BaseMapper { } diff --git a/pbs/src/main/java/com/sdm/pbs/dao/SimulationSoftConfigMapper.java b/pbs/src/main/java/com/sdm/pbs/dao/SimulationSoftConfigMapper.java index c1dfa711..dd0c720f 100644 --- a/pbs/src/main/java/com/sdm/pbs/dao/SimulationSoftConfigMapper.java +++ b/pbs/src/main/java/com/sdm/pbs/dao/SimulationSoftConfigMapper.java @@ -1,7 +1,7 @@ package com.sdm.pbs.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.sdm.pbs.model.entity.SimulationSoftConfig; +import com.sdm.pbs.model.entity.SimulationHpcCommand; /** *

@@ -11,6 +11,6 @@ import com.sdm.pbs.model.entity.SimulationSoftConfig; * @author author * @since 2025-11-05 */ -public interface SimulationSoftConfigMapper extends BaseMapper { +public interface SimulationSoftConfigMapper extends BaseMapper { } diff --git a/pbs/src/main/java/com/sdm/pbs/model/bo/CommandResult.java b/pbs/src/main/java/com/sdm/pbs/model/bo/CommandResult.java new file mode 100644 index 00000000..3305ca26 --- /dev/null +++ b/pbs/src/main/java/com/sdm/pbs/model/bo/CommandResult.java @@ -0,0 +1,11 @@ +package com.sdm.pbs.model.bo; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class CommandResult { + private String command; + private String formatCommand; +} diff --git a/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationCommandPlaceholder.java b/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationCommandPlaceholder.java deleted file mode 100644 index b7507737..00000000 --- a/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationCommandPlaceholder.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.sdm.pbs.model.entity; - - -import com.baomidou.mybatisplus.annotation.*; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonIgnore; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -import java.io.Serializable; -import java.time.LocalDateTime; - -/** - *

- * 仿真工具命令占位符配置表 - *

- * - * @author author - * @since 2025-12-01 - */ -@Data -@EqualsAndHashCode(callSuper = false) -@Accessors(chain = true) -@TableName("simulation_command_placeholder") -@Schema(description = "仿真工具命令占位符配置表") -public class SimulationCommandPlaceholder implements Serializable { - - private static final long serialVersionUID = 1L; - - @Schema(description = "自增主键") - @TableId(value = "id", type = IdType.AUTO) - private Long id; - - @Schema(description = "占位符英文名称") - @TableField("keyEnName") - private String keyEnName; - - @Schema(description = "占位符中文名称") - @TableField("keyCnName") - private String keyCnName; - - @Schema(description = "占位符值的类型(file_exact_match:文件完全匹配;file_regex_match:文件正则匹配," + - "hpc_file_select:Hpc节点文件选择,hpc_file_regex_match:Hpc节点目录正则,local_file_select:本地文件选择,custom_input:用户自定义输入值") - @TableField("valueType") - private String valueType; - - @Schema(description = "占位符的值,用户输入后赋值传递") - @TableField(exist = false) - private String inputValue=""; - - @Schema(description = "创建者ID") - @TableField("creatorId") - @JsonIgnore - private Long creatorId; - - @Schema(description = "创建时间") - @TableField(value = "createTime", fill = FieldFill.INSERT) - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @JsonIgnore - private LocalDateTime createTime; - - @Schema(description = "更新者ID") - @TableField("updaterId") - @JsonIgnore - private Long updaterId; - - @Schema(description = "修改时间") - @TableField(value = "updateTime", fill = FieldFill.INSERT_UPDATE) - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @JsonIgnore - private LocalDateTime updateTime; -} \ No newline at end of file diff --git a/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationSoftConfig.java b/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationHpcCommand.java similarity index 51% rename from pbs/src/main/java/com/sdm/pbs/model/entity/SimulationSoftConfig.java rename to pbs/src/main/java/com/sdm/pbs/model/entity/SimulationHpcCommand.java index 50a052d2..6d01234c 100644 --- a/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationSoftConfig.java +++ b/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationHpcCommand.java @@ -2,6 +2,7 @@ package com.sdm.pbs.model.entity; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -9,6 +10,7 @@ import lombok.experimental.Accessors; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.HashMap; import java.util.Map; /** @@ -22,9 +24,9 @@ import java.util.Map; @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) -@TableName("simulation_soft_config") -@Schema(description = "仿真软件命令配置表") -public class SimulationSoftConfig implements Serializable { +@TableName("simulation_hpc_command") +@Schema(description = "仿真软件hpc命令配置表") +public class SimulationHpcCommand implements Serializable { private static final long serialVersionUID = 1L; @@ -32,42 +34,55 @@ public class SimulationSoftConfig implements Serializable { @TableId(value = "id", type = IdType.AUTO) private Long id; - @Schema(description = "软件名称") - @TableField("softName") + @Schema(description = "app注册的Id") + @TableField(value = "appUuid",select = true) + private String appUuid; + + @Schema(description = "软件名称,对应的simulation_app_repository的appName,名字建议格式appName_v1") + @TableField(value = "softName",select = true) private String softName; @Schema(description = "软件版本号") - @TableField("softVersion") + @TableField(value = "softVersion",select = true) private String softVersion; @Schema(description = "功能描述(如:电池仿真)") - @TableField("functionDsc") + @TableField(value = "functionDsc",select = true) private String functionDsc; @Schema(description = "功能对应的CMD命令") - @TableField("command") + @TableField(value = "command",select = true) private String command; + @Schema(description = "预留-软件执行完成后筛选回传文件正则,用于过滤回传文件") + @TableField(value = "postFileRegular",select = true) + @JsonIgnore + private String postFileRegular; + @Schema(description = "创建者ID") - @TableField("creatorId") + @TableField(value = "creatorId",select = true) + @JsonIgnore private Long creatorId; @Schema(description = "创建时间") - @TableField(value = "createTime", fill = FieldFill.INSERT) + @TableField(value = "createTime", fill = FieldFill.INSERT,select = true) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonIgnore private LocalDateTime createTime; @Schema(description = "更新者ID") - @TableField("updaterId") + @TableField(value = "updaterId",select = false) + @JsonIgnore private Long updaterId; @Schema(description = "修改时间") - @TableField(value = "updateTime", fill = FieldFill.INSERT_UPDATE) + @TableField(value = "updateTime", fill = FieldFill.INSERT_UPDATE,select = false) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonIgnore private LocalDateTime updateTime; - @Schema(description= "自定义占位符,只有列表展示使用,key 就是占位符") - @TableField(value = "commandExpand", insertStrategy = FieldStrategy.NEVER,select = false,updateStrategy = FieldStrategy.NEVER) - private Map commandExpand; + @Schema(description = "命令动态扩展的数据,SimulationHpcCommandPlaceholder对象") + @TableField(exist = false) + private MapcommandExpand = new HashMap<>(); } \ No newline at end of file diff --git a/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationHpcCommandPlaceholder.java b/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationHpcCommandPlaceholder.java new file mode 100644 index 00000000..688de393 --- /dev/null +++ b/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationHpcCommandPlaceholder.java @@ -0,0 +1,99 @@ +package com.sdm.pbs.model.entity; + + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 仿真工具命令占位符配置表 + *

+ * + * @author author + * @since 2025-12-01 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("simulation_hpc_command_placeholder") +@Schema(description = "仿真工具hpc命令占位符配置表") +public class SimulationHpcCommandPlaceholder implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "自增主键") + @TableId(value = "id", type = IdType.AUTO) + @JsonIgnore + private Long id; + + @Schema(description = "app注册的Id") + @TableField(value = "appUuid",select = true) + private String appUuid; + + @Schema(description = "占位符英文名称") + @TableField(value = "keyEnName",select = true) + private String keyEnName; + + @Schema(description = "占位符中文名称") + @TableField(value = "keyCnName",select = true) + private String keyCnName; + + @Schema(description = "占位符值的类型(file:共享云盘文件;input:用户自定义输入)") + @TableField(value = "valueType",select = true) + private String valueType; + + @Schema(description = "是否展示(Y:是,N:否),N时必须填写默认值") + @TableField(value = "isDisplay",select = true) + @JsonIgnore + private String isDisplay; + + @Schema(description = "是否拼接(Y:是,N:否),N时不用拼接到命令") + @TableField(value = "featchType",select = true) + @JsonIgnore + private String featchType; + + @Schema(description = "默认值:valueType为file且isDisplay为N时必填") + @TableField(value = "defaultValue",select = true) + @JsonIgnore + private String defaultValue; + + @Schema(description = "文件正则表达式:valueType为file时必填,用于过滤对应的求解文件") + @TableField(value = "fileRegular",select = true) + @JsonIgnore + private String fileRegular; + + @Schema(description = "创建者ID") + @TableField(value = "creatorId",select = false) + @JsonIgnore + private Long creatorId; + + @Schema(description = "创建时间") + @TableField(value = "createTime", fill = FieldFill.INSERT,select = false) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonIgnore + private LocalDateTime createTime; + + @Schema(description = "更新者ID") + @TableField(value = "updaterId",select = false) + @JsonIgnore + private Long updaterId; + + @Schema(description = "修改时间") + @TableField(value = "updateTime", fill = FieldFill.INSERT_UPDATE,select = false) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonIgnore + private LocalDateTime updateTime; + + @Schema(description = "占位符的值,显示给用户的字段,用户输入后赋值传递") + @TableField(exist = false) + private String inputValue = ""; + +} \ No newline at end of file diff --git a/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationJob.java b/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationJob.java index e69d6928..6f77bff4 100644 --- a/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationJob.java +++ b/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationJob.java @@ -77,7 +77,7 @@ public class SimulationJob implements Serializable { @Schema(description = "使用软件的id") @TableField("softwareId") - private Long softwareId; + private String softwareId; @Schema(description = "求解文件对应的文件Id") @TableField("inputFileId") diff --git a/pbs/src/main/java/com/sdm/pbs/model/req/SubmitHpcTaskReq.java b/pbs/src/main/java/com/sdm/pbs/model/req/SubmitHpcTaskReq.java index 614003a2..cc39c1e9 100644 --- a/pbs/src/main/java/com/sdm/pbs/model/req/SubmitHpcTaskReq.java +++ b/pbs/src/main/java/com/sdm/pbs/model/req/SubmitHpcTaskReq.java @@ -7,6 +7,8 @@ import org.springframework.web.multipart.MultipartFile; import java.util.ArrayList; import java.util.List; +import java.util.Map; + @Data public class SubmitHpcTaskReq { @@ -64,7 +66,7 @@ public class SubmitHpcTaskReq { public String projectname; @Schema(description = "软件的id") - public Long softwareId; + public String softwareId; @Schema(description = "计算任务回传minio的路径") public String stdoutSpdmMinoFilePath; @@ -78,5 +80,7 @@ public class SubmitHpcTaskReq { @Schema(description = "求解文件本地路径,spdm工作流引擎会传递过来") public List inputFileLocalPaths = new ArrayList<>(); + @Schema(description = "任务流用户传递的参数,用于动态替换命令") + private Map params; } diff --git a/pbs/src/main/java/com/sdm/pbs/service/ISimulationCommandPlaceholderService.java b/pbs/src/main/java/com/sdm/pbs/service/ISimulationCommandPlaceholderService.java index eeaf6228..7da297f8 100644 --- a/pbs/src/main/java/com/sdm/pbs/service/ISimulationCommandPlaceholderService.java +++ b/pbs/src/main/java/com/sdm/pbs/service/ISimulationCommandPlaceholderService.java @@ -1,7 +1,7 @@ package com.sdm.pbs.service; import com.baomidou.mybatisplus.extension.service.IService; -import com.sdm.pbs.model.entity.SimulationCommandPlaceholder; +import com.sdm.pbs.model.entity.SimulationHpcCommandPlaceholder; -public interface ISimulationCommandPlaceholderService extends IService { +public interface ISimulationCommandPlaceholderService extends IService { } diff --git a/pbs/src/main/java/com/sdm/pbs/service/ISimulationSoftConfigService.java b/pbs/src/main/java/com/sdm/pbs/service/ISimulationSoftConfigService.java index c17b3765..0d2e2ff4 100644 --- a/pbs/src/main/java/com/sdm/pbs/service/ISimulationSoftConfigService.java +++ b/pbs/src/main/java/com/sdm/pbs/service/ISimulationSoftConfigService.java @@ -1,7 +1,7 @@ package com.sdm.pbs.service; import com.baomidou.mybatisplus.extension.service.IService; -import com.sdm.pbs.model.entity.SimulationSoftConfig; +import com.sdm.pbs.model.entity.SimulationHpcCommand; -public interface ISimulationSoftConfigService extends IService { +public interface ISimulationSoftConfigService extends IService { } diff --git a/pbs/src/main/java/com/sdm/pbs/service/SimulationCommandPlaceholderServiceImpl.java b/pbs/src/main/java/com/sdm/pbs/service/SimulationCommandPlaceholderServiceImpl.java index 45f3284c..acc695a3 100644 --- a/pbs/src/main/java/com/sdm/pbs/service/SimulationCommandPlaceholderServiceImpl.java +++ b/pbs/src/main/java/com/sdm/pbs/service/SimulationCommandPlaceholderServiceImpl.java @@ -2,9 +2,9 @@ package com.sdm.pbs.service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.sdm.pbs.dao.SimulationCommandPlaceholderMapper; -import com.sdm.pbs.model.entity.SimulationCommandPlaceholder; +import com.sdm.pbs.model.entity.SimulationHpcCommandPlaceholder; import org.springframework.stereotype.Service; @Service -public class SimulationCommandPlaceholderServiceImpl extends ServiceImpl implements ISimulationCommandPlaceholderService { +public class SimulationCommandPlaceholderServiceImpl extends ServiceImpl implements ISimulationCommandPlaceholderService { } 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 5ae97c8f..618bebaf 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 @@ -1,5 +1,6 @@ package com.sdm.pbs.service.impl; +import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; @@ -15,17 +16,20 @@ 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; import com.sdm.common.log.CoreLogger; +import com.sdm.common.utils.CommandReplaceUtil; import com.sdm.common.utils.HpcCommandExcuteUtil; import com.sdm.common.utils.PageUtils; +import com.sdm.pbs.model.bo.CommandResult; import com.sdm.pbs.model.bo.HpcJobStatusInfo; import com.sdm.pbs.model.bo.HpcResouceInfo; -import com.sdm.pbs.model.entity.SimulationCommandPlaceholder; +import com.sdm.pbs.model.entity.SimulationHpcCommand; +import com.sdm.pbs.model.entity.SimulationHpcCommandPlaceholder; import com.sdm.pbs.model.entity.SimulationJob; -import com.sdm.pbs.model.entity.SimulationSoftConfig; import com.sdm.pbs.model.req.JobFileCallBackReq; import com.sdm.pbs.model.req.QueryJobReq; import com.sdm.pbs.model.req.SubmitHpcTaskReq; import com.sdm.pbs.service.*; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -37,11 +41,14 @@ import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import java.time.LocalDateTime; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; +@Slf4j @Service @Qualifier("decoratorPbsService") @ConditionalOnProperty(name = "pbs.task.impl", havingValue = "hpc") @@ -89,46 +96,139 @@ public class PbsServiceDecorator implements IPbsServiceDecorator { public SdmResponse submitHpcJob(SubmitHpcTaskReq req) { //1. 上传hpc主文件 及 其他文件 MultipartFile masterFile = req.getMasterFile(); - // hpc共享机器+ subDir 这个就确定是工作目录了 - String subDir = req.getJobName()+"\\"+System.currentTimeMillis(); + // 获取hpc的工作目录 + String subDir = generateHpcSubDir(req); // webClient 调用上传,这个是主文件,求解算出的文件,及stdout文件都指定这个文件夹下面 - String masterFilePath = hpcCommandExcuteUtil.uploaHpcFile(masterFile,subDir); - dealInputFiles(req,subDir); + String masterFilePath = hpcCommandExcuteUtil.uploaHpcFile(masterFile, subDir); + req.setMasterFilePath(masterFilePath); + // 上传从文件 + dealInputFiles(req, subDir); // 任务输出的文件夹 String hpcOutPutDir = extractDirectory(masterFilePath); req.setWorkDir(hpcOutPutDir); - // 前置处理 替换求解文件 - String command=""; - if(StringUtils.isNotBlank(req.getCommand())) { - command=req.getCommand(); - }else { - SimulationSoftConfig simulationSoftConfig = simulationSoftConfigService.lambdaQuery(). - eq(SimulationSoftConfig::getSoftName,req.getSoftware()).one(); - command = simulationSoftConfig.getCommand(); + // 2.处理命令拼接和参数替换 + CommandResult commandResult = buildAndReplaceHpcCommand(req, masterFilePath); + if (StringUtils.isBlank(commandResult.getCommand())) { + log.error("Hpc执行失败,command命令不能为空{}",JSONObject.toJSONString(req)); + throw new RuntimeException("Hpc执行失败,command命令不能为空"); } - if(StringUtils.isBlank(command)) { - return SdmResponse.failed("command命令不能为空,软件名称:"+req.getSoftware()); - } - // 处理 拼接命令 \\CARSAFE\share\solver\RLithium\reta.exe -i %s - String formatCommand = String.format(command, masterFilePath); - req.setCommand(formatCommand); - req.setMasterFilePath(masterFilePath); + req.setCommand(commandResult.getFormatCommand()); + + // 3. 提交 SdmResponse response = pbsService.submitHpcJob(req); - String jobId=""; - if(response.isSuccess()&&StringUtils.isNotEmpty(response.getData())) { + String jobId = ""; + if (response.isSuccess() && StringUtils.isNotEmpty(response.getData())) { jobId = response.getData(); } - if(StringUtils.isNotEmpty(jobId)) { + if(StringUtils.isNotEmpty(jobId)){ + log.error("Hpc执行失败返回结果:{}",JSONObject.toJSONString(response)); + throw new RuntimeException("Hpc执行失败,返回jobId空"); + } + // 4. 保存任务信息到数据库 + saveSimulationJobToDb(req, jobId, hpcOutPutDir, commandResult.getCommand()); + return SdmResponse.success(jobId); + } + + /** + * 生成HPC任务的工作子目录路径(简化版) + * 目录规则:用户ID(非空时)\任务名称\时间戳 + * @param req 提交HPC任务的请求参数 + * @return 拼接好的子目录字符串 + */ + private String generateHpcSubDir(SubmitHpcTaskReq req) { + Long userId = ThreadLocalContext.getUserId(); + log.info("Hpc任务执行开始,用户id:{}", userId); + // 拼接逻辑 + String subDirPrefix = Objects.isNull(userId) ? "" : (String.valueOf(userId) + "\\"); + String subDir = subDirPrefix + req.getJobName() + "\\" + System.currentTimeMillis(); + return subDir; + } + + /** + * 构建并替换HPC命令中的动态参数 + * @param req 任务请求参数 + * @param masterFilePath 主文件路径 + * @return 包含原始命令和格式化命令的结果对象 + */ + private CommandResult buildAndReplaceHpcCommand(SubmitHpcTaskReq req, String masterFilePath) { + String command = ""; + String formatCommand = ""; + + // 优先使用传递的command,然后替换求解文件即可 + if (StringUtils.isNotBlank(req.getCommand())) { + command = req.getCommand(); + // 处理 拼接命令 \\CARSAFE\share\solver\RLithium\reta.exe -i %s + formatCommand = String.format(command, masterFilePath); + } else { + // 命令 + SimulationHpcCommand simulationHpcCommand = simulationSoftConfigService.lambdaQuery() + .eq(SimulationHpcCommand::getAppUuid, req.getSoftwareId()).one(); + // 动态参数 + List placeholders = simulationCommandPlaceholderService.lambdaQuery() + .eq(SimulationHpcCommandPlaceholder::getAppUuid, req.getSoftwareId()) + .list(); + // 配置在表中的包含动态参数的命令 + if (ObjectUtil.isNull(simulationHpcCommand) || StringUtils.isBlank(simulationHpcCommand.getCommand())) { + throw new RuntimeException("该应用没有初始化配置command"); + } + command = simulationHpcCommand.getCommand(); + + // 命令中动态参数的处理替换 + for (SimulationHpcCommandPlaceholder placeholder : placeholders) { + String keyEnName = placeholder.getKeyEnName(); + Object replaceValue = null; + + // 用户手动输入 + if (Objects.equals(placeholder.getFeatchType(), "input")) { + replaceValue = req.getParams().get(keyEnName); + // 用户输入是空就使用配置的默认值 + if (ObjectUtil.isNull(replaceValue)) { // 修复原代码的判断逻辑错误 + log.warn("Hpc命令动态参数替换,用户输入是空,参数名:{}", keyEnName); + replaceValue = placeholder.getDefaultValue(); + } + } + // 入参 + else if (Objects.equals(placeholder.getFeatchType(), "param")) { + replaceValue = CommandReplaceUtil.getFieldValue(req, keyEnName); + if (ObjectUtil.isNull(replaceValue)) { // 修复原代码的判断逻辑错误 + log.warn("Hpc命令动态参数替换,入参反射是空,参数名:{}", keyEnName); + replaceValue = placeholder.getDefaultValue(); + } + } + // 默认兜底,比如从文件 就是null,最后命令就不拼接从文件 + else if (Objects.equals(placeholder.getFeatchType(), "default")) { + replaceValue = placeholder.getDefaultValue(); + if (ObjectUtil.isNull(replaceValue)) { // 修复原代码的判断逻辑错误 + log.warn("Hpc命令动态参数替换,默认值是空,参数名:{}", keyEnName); + } + } + + command = CommandReplaceUtil.replaceCommandPlaceholder(command, keyEnName, replaceValue); + } + } + + return new CommandResult(command, formatCommand); + } + + /** + * 保存模拟任务信息到数据库 + * @param req 任务请求参数 + * @param jobId 任务ID + * @param hpcOutPutDir 输出目录 + * @param command 执行命令 + */ + private void saveSimulationJobToDb(SubmitHpcTaskReq req, String jobId, String hpcOutPutDir, String command) { + if (StringUtils.isNotEmpty(jobId)) { // 数据入库 SimulationJob simulationJob = new SimulationJob(); // 基础字段 -// simulationJob.setId(1L); + // simulationJob.setId(1L); simulationJob.setJobName(req.getJobName()); simulationJob.setCoreNum(req.getCoreNum()); simulationJob.setSoftware(req.getSoftware()); simulationJob.setJobType(req.getJobType()); simulationJob.setIndependence(req.isIndependence()); -// simulationJob.setInputFiles(JSONObject.toJSONString(req.getInputFiles())); + // simulationJob.setInputFiles(JSONObject.toJSONString(req.getInputFiles())); // 主文件位置 simulationJob.setMasterFile(req.getMasterFilePath()); // 求解文件集合 @@ -140,20 +240,20 @@ public class PbsServiceDecorator implements IPbsServiceDecorator { // 软件及文件关联 simulationJob.setSoftwareId(req.getSoftwareId()); // 下面的待定 -// simulationJob.setInputFileId(null); + // simulationJob.setInputFileId(null); simulationJob.setJobId(jobId); // 没必要要 -// simulationJob.setJobDetailId(""); + // simulationJob.setJobDetailId(""); // 文件路径 共享目录+jobName(文件回传)+uuid,下面可能有多个文件 simulationJob.setStdoutHpcFilePath(hpcOutPutDir); simulationJob.setStdoutSpdmMinoFilePath(req.getStdoutSpdmMinoFilePath()); simulationJob.setStdoutSpdmNasFilePath(req.getStdoutSpdmNasFilePath()); // 执行信息 定时任务回传的时候修改 -// simulationJob.setNodeName(""); + // simulationJob.setNodeName(""); simulationJob.setExecutCommand(command); // 执行信息 定时任务回传的时候修改 -// simulationJob.setStartTime("2025-11-30 10:00:00"); -// simulationJob.setEndTime("2025-11-30 12:30:00"); + // simulationJob.setStartTime("2025-11-30 10:00:00"); + // simulationJob.setEndTime("2025-11-30 12:30:00"); simulationJob.setJobStatus("Configuring"); // 求解器名称 simulationJob.setSolverName(req.getSoftware()); @@ -162,12 +262,12 @@ public class PbsServiceDecorator implements IPbsServiceDecorator { simulationJob.setTotalUserTime(null); simulationJob.setTotalElapsedTime(null); // 标识及状态 -// simulationJob.setUuid(null); + // simulationJob.setUuid(null); simulationJob.setFileStatus("generating"); // 审计字段 Long userId = ThreadLocalContext.getUserId(); Long tenantId = ThreadLocalContext.getTenantId(); - CoreLogger.info("submitHpcJob save db userId:{},tenantId:{}",userId,tenantId); + CoreLogger.info("submitHpcJob save db userId:{},tenantId:{}", userId, tenantId); simulationJob.setCreatorId(userId); simulationJob.setTenantId(tenantId); simulationJob.setCreateTime(LocalDateTime.now()); @@ -175,9 +275,147 @@ public class PbsServiceDecorator implements IPbsServiceDecorator { simulationJob.setUpdateTime(LocalDateTime.now()); simulationJobService.save(simulationJob); } - return SdmResponse.success(jobId); } +// @Override +// public SdmResponse submitHpcJob(SubmitHpcTaskReq req) { +// //1. 上传hpc主文件 及 其他文件 +// MultipartFile masterFile = req.getMasterFile(); +// // hpc共享机器+ subDir 这个就确定是工作目录了 todo 加上用户目录 +// String subDir = req.getJobName()+"\\"+System.currentTimeMillis(); +// // webClient 调用上传,这个是主文件,求解算出的文件,及stdout文件都指定这个文件夹下面 +// String masterFilePath = hpcCommandExcuteUtil.uploaHpcFile(masterFile,subDir); +// req.setMasterFilePath(masterFilePath); +// // 上传从文件 +// dealInputFiles(req,subDir); +// // 任务输出的文件夹 +// String hpcOutPutDir = extractDirectory(masterFilePath); +// req.setWorkDir(hpcOutPutDir); +// // 前置处理 替换求解文件 +// String command=""; +// String formatCommand=""; +// // 优先使用传递的command,然后替换求解文件即可 +// if(StringUtils.isNotBlank(req.getCommand())) { +// command=req.getCommand(); +// // 处理 拼接命令 \\CARSAFE\share\solver\RLithium\reta.exe -i %s +// formatCommand = String.format(command, masterFilePath); +// }else { +// // 命令 +// SimulationHpcCommand simulationHpcCommand = simulationSoftConfigService.lambdaQuery(). +// eq(SimulationHpcCommand::getAppRepositoryId,req.getAppRepositoryId()).one(); +// // 动态参数 +// List placeholders = simulationCommandPlaceholderService.lambdaQuery() +// .eq(SimulationHpcCommandPlaceholder::getAppRepositoryId, req.getAppRepositoryId()) +// .list(); +// // 配置在表中的包含动态参数的命令 +// if(ObjectUtil.isNull(simulationHpcCommand)||StringUtils.isBlank(simulationHpcCommand.getCommand())) { +// throw new RuntimeException("该应用没有初始化配置command"); +// } +// command = simulationHpcCommand.getCommand(); +// // 命令中动态参数的处理替换 +// for(SimulationHpcCommandPlaceholder placeholder : placeholders) { +// String keyEnName = placeholder.getKeyEnName(); +// // 用户手动输入 +// if(Objects.equals(placeholder.getFeatchType(),"input")) { +// Object value = req.getParams().get(keyEnName); +// // 用户输入是空就使用配置的默认值 +// if(ObjectUtil.isNotNull(value)) { +// log.warn("Hpc命令动态参数替换,用户输入是空,参数名:{}",keyEnName); +// value=placeholder.getDefaultValue(); +// } +// command = CommandReplaceUtil.replaceCommandPlaceholder(command, keyEnName, value); +// } +// // 入参 +// if(Objects.equals(placeholder.getFeatchType(),"param")) { +// Object fieldValue = CommandReplaceUtil.getFieldValue(req, keyEnName); +// if(ObjectUtil.isNotNull(fieldValue)) { +// log.warn("Hpc命令动态参数替换,入参反射是空,参数名:{}",keyEnName); +// fieldValue=placeholder.getDefaultValue(); +// } +// command = CommandReplaceUtil.replaceCommandPlaceholder(command, keyEnName, fieldValue); +// } +// // 默认兜底,比如从文件 就是null,最后命令就不拼接从文件 +// if(Objects.equals(placeholder.getFeatchType(),"default")) { +// Object defaultValue = placeholder.getDefaultValue(); +// if(ObjectUtil.isNotNull(defaultValue)) { +// log.warn("Hpc命令动态参数替换,默认值是空,参数名:{}",keyEnName); +// } +// command = CommandReplaceUtil.replaceCommandPlaceholder(command, keyEnName, defaultValue); +// } +// +// } +// } +// +// if(StringUtils.isBlank(command)) { +// return SdmResponse.failed("command命令不能为空,软件名称:"+req.getSoftware()); +// } +// +// req.setCommand(formatCommand); +// SdmResponse response = pbsService.submitHpcJob(req); +// String jobId=""; +// if(response.isSuccess()&&StringUtils.isNotEmpty(response.getData())) { +// jobId = response.getData(); +// } +// if(StringUtils.isNotEmpty(jobId)) { +// // 数据入库 +// SimulationJob simulationJob = new SimulationJob(); +// // 基础字段 +//// simulationJob.setId(1L); +// simulationJob.setJobName(req.getJobName()); +// simulationJob.setCoreNum(req.getCoreNum()); +// simulationJob.setSoftware(req.getSoftware()); +// simulationJob.setJobType(req.getJobType()); +// simulationJob.setIndependence(req.isIndependence()); +//// simulationJob.setInputFiles(JSONObject.toJSONString(req.getInputFiles())); +// // 主文件位置 +// simulationJob.setMasterFile(req.getMasterFilePath()); +// // 求解文件集合 +// simulationJob.setInputFiles(JSONObject.toJSONString(req.getInputFilePaths())); +// simulationJob.setTaskId(req.getTaskId()); +// simulationJob.setTaskName(req.getTaskName()); +// simulationJob.setRunId(req.getRunId()); +// simulationJob.setRunName(req.getRunName()); +// // 软件及文件关联 +// simulationJob.setSoftwareId(req.getSoftwareId()); +// // 下面的待定 +//// simulationJob.setInputFileId(null); +// simulationJob.setJobId(jobId); +// // 没必要要 +//// simulationJob.setJobDetailId(""); +// // 文件路径 共享目录+jobName(文件回传)+uuid,下面可能有多个文件 +// simulationJob.setStdoutHpcFilePath(hpcOutPutDir); +// simulationJob.setStdoutSpdmMinoFilePath(req.getStdoutSpdmMinoFilePath()); +// simulationJob.setStdoutSpdmNasFilePath(req.getStdoutSpdmNasFilePath()); +// // 执行信息 定时任务回传的时候修改 +//// simulationJob.setNodeName(""); +// simulationJob.setExecutCommand(command); +// // 执行信息 定时任务回传的时候修改 +//// simulationJob.setStartTime("2025-11-30 10:00:00"); +//// simulationJob.setEndTime("2025-11-30 12:30:00"); +// simulationJob.setJobStatus("Configuring"); +// // 求解器名称 +// simulationJob.setSolverName(req.getSoftware()); +// // 执行信息 定时任务回传的时候修改 +// simulationJob.setTotalKernelTime(null); +// simulationJob.setTotalUserTime(null); +// simulationJob.setTotalElapsedTime(null); +// // 标识及状态 +//// simulationJob.setUuid(null); +// simulationJob.setFileStatus("generating"); +// // 审计字段 +// Long userId = ThreadLocalContext.getUserId(); +// Long tenantId = ThreadLocalContext.getTenantId(); +// CoreLogger.info("submitHpcJob save db userId:{},tenantId:{}",userId,tenantId); +// simulationJob.setCreatorId(userId); +// simulationJob.setTenantId(tenantId); +// simulationJob.setCreateTime(LocalDateTime.now()); +// simulationJob.setUpdaterId(userId); +// simulationJob.setUpdateTime(LocalDateTime.now()); +// simulationJobService.save(simulationJob); +// } +// return SdmResponse.success(jobId); +// } + private void dealInputFiles(SubmitHpcTaskReq req, String subDir) { if(req.getInputFiles()==null|| CollectionUtils.isEmpty(req.getInputFiles())) { return; @@ -276,35 +514,24 @@ public class PbsServiceDecorator implements IPbsServiceDecorator { return PageUtils.getJsonObjectSdmResponse(results, page); } - public SdmResponse>> querySoftConfig(String softName) { - List configs = simulationSoftConfigService.lambdaQuery() - .eq(SimulationSoftConfig::getSoftName, softName) - .orderByDesc(SimulationSoftConfig::getCreateTime) + public SdmResponse querySoftConfig(String appUuid) { + // app对应hpc命令,一个只会有一个 + SimulationHpcCommand hpcCommand = simulationSoftConfigService.lambdaQuery() + .eq(SimulationHpcCommand::getAppUuid, appUuid).one(); + // 查询显示用户的动态参数 + List placeholders = simulationCommandPlaceholderService.lambdaQuery() + .eq(SimulationHpcCommandPlaceholder::getAppUuid, appUuid) + .eq(SimulationHpcCommandPlaceholder::getValueType,"input") .list(); - List placeholders = simulationCommandPlaceholderService.lambdaQuery().list(); - Map placeholderMap = placeholders.stream() - .collect(Collectors.toMap( - SimulationCommandPlaceholder::getKeyEnName, // 键:keyEnName - placeholder -> placeholder, - (existing, replacement) -> existing - )); - configs.forEach(config -> { - HashMap map = new HashMap<>(); - String command = config.getCommand(); - List placeholderKeys = extractPlaceholders(command); - placeholderKeys.stream().forEach(placeholderKey -> { - SimulationCommandPlaceholder simulationCommandPlaceholder = placeholderMap.get(placeholderKey); - if (simulationCommandPlaceholder != null) { - map.put(placeholderKey, simulationCommandPlaceholder); - } - }); - config.setCommandExpand(placeholderMap); - }); - // 一个softName --》一个版本--》有多个命令 - Map> softConfigs = configs.stream() - .collect(Collectors.groupingBy(SimulationSoftConfig::getSoftVersion)); - return SdmResponse.success(softConfigs); - + if(Objects.isNull(hpcCommand)){ + return SdmResponse.failed("该应用未配置hpc命令!"); + } + for(SimulationHpcCommandPlaceholder placeholder : placeholders){ + Map commandExpandMap = hpcCommand.getCommandExpand(); + String keyEnName = placeholder.getKeyEnName(); + commandExpandMap.put(keyEnName,placeholder); + } + return SdmResponse.success(hpcCommand); } /** diff --git a/pbs/src/main/java/com/sdm/pbs/service/impl/SimulationSoftConfigServiceImpl.java b/pbs/src/main/java/com/sdm/pbs/service/impl/SimulationSoftConfigServiceImpl.java index bcc2a375..8e778742 100644 --- a/pbs/src/main/java/com/sdm/pbs/service/impl/SimulationSoftConfigServiceImpl.java +++ b/pbs/src/main/java/com/sdm/pbs/service/impl/SimulationSoftConfigServiceImpl.java @@ -2,10 +2,10 @@ package com.sdm.pbs.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.sdm.pbs.dao.SimulationSoftConfigMapper; -import com.sdm.pbs.model.entity.SimulationSoftConfig; +import com.sdm.pbs.model.entity.SimulationHpcCommand; import com.sdm.pbs.service.ISimulationSoftConfigService; import org.springframework.stereotype.Service; @Service -public class SimulationSoftConfigServiceImpl extends ServiceImpl implements ISimulationSoftConfigService { +public class SimulationSoftConfigServiceImpl extends ServiceImpl implements ISimulationSoftConfigService { } From fc007fd0d8c478f6cfbb0f1b3ded2d340bee714b Mon Sep 17 00:00:00 2001 From: zhuxinru Date: Fri, 9 Jan 2026 14:05:56 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/entity/req/system/SendMsgReq.java | 5 ++ .../entity/resp/task/PerformanceResp.java | 2 + project/get_curve_params.py | 64 +++++++++++++++++++ .../sdm/project/model/bo/CurveParamDto.java | 19 +++++- .../service/handle/LyricMessageSender.java | 31 +++++---- 5 files changed, 105 insertions(+), 16 deletions(-) create mode 100644 project/get_curve_params.py diff --git a/common/src/main/java/com/sdm/common/entity/req/system/SendMsgReq.java b/common/src/main/java/com/sdm/common/entity/req/system/SendMsgReq.java index 63b8250b..4a0e46eb 100644 --- a/common/src/main/java/com/sdm/common/entity/req/system/SendMsgReq.java +++ b/common/src/main/java/com/sdm/common/entity/req/system/SendMsgReq.java @@ -24,4 +24,9 @@ public class SendMsgReq { * 是否发送cid消息 */ private boolean sendCid = true; + + // 即时通发送人工号 + private String sendJobNo; + // 即时通接收人工号 + private String receiveJobNo; } diff --git a/common/src/main/java/com/sdm/common/entity/resp/task/PerformanceResp.java b/common/src/main/java/com/sdm/common/entity/resp/task/PerformanceResp.java index 0134a365..9fb1ed1e 100644 --- a/common/src/main/java/com/sdm/common/entity/resp/task/PerformanceResp.java +++ b/common/src/main/java/com/sdm/common/entity/resp/task/PerformanceResp.java @@ -1,6 +1,7 @@ package com.sdm.common.entity.resp.task; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -56,6 +57,7 @@ public class PerformanceResp { private String tenantId; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; private Long creator; diff --git a/project/get_curve_params.py b/project/get_curve_params.py new file mode 100644 index 00000000..b34cecc6 --- /dev/null +++ b/project/get_curve_params.py @@ -0,0 +1,64 @@ +import os +import re +import sys +import json + +# def is_number(str): +# try: +# float(str) +# return True +# except ValueError: +# return False + +def is_number(string): + """ 判断字符串是否为数字类型 """ + pattern = re.compile(r'^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$') + return bool(pattern.match(string)) + +def get_curve_unit(string): + xUnit = '' + yUnit = '' + xPhysics = '' + yPhysics = '' + + try: + unit_dict = json.loads(string) + xUnit = unit_dict.get('xUnit') + yUnit = unit_dict.get('yUnit') + xPhysics = unit_dict.get('xPhysics') + yPhysics = unit_dict.get('yPhysics') + except: + pass + + return xUnit, yUnit, xPhysics, yPhysics + + +def get_curve_params(curvePath, decimal): + """ 获取曲线文件最大最小值 """ + valueList = [] + with open(curvePath, 'r+', encoding='utf-8') as fr: + lines = fr.readlines() + for line in lines: + if line.__contains__(','): + yValue = line.split(',')[1] + if(is_number(yValue)): + valueList.append(float(yValue)) + + maxValue = round(max(valueList), decimal) + minValue = round(min(valueList), decimal) + + xUnit, yUnit, xPhysics, yPhysics = get_curve_unit(lines[0]) + curve_params = {"max":maxValue, "min":minValue, "xUnit":xUnit, "yUnit":yUnit, "xPhysics":xPhysics, "yPhysics":yPhysics} + print(json.dumps(curve_params, ensure_ascii=False)) + + +if __name__=='__main__': + # 曲线文件路径 + curvePath = sys.argv[1] + # 保留小数点位数 + try: + decimal = int(sys.argv[2]) + except: + decimal = 3 + + get_curve_params(curvePath, decimal) diff --git a/project/src/main/java/com/sdm/project/model/bo/CurveParamDto.java b/project/src/main/java/com/sdm/project/model/bo/CurveParamDto.java index fcab5115..bb66d78f 100644 --- a/project/src/main/java/com/sdm/project/model/bo/CurveParamDto.java +++ b/project/src/main/java/com/sdm/project/model/bo/CurveParamDto.java @@ -21,7 +21,20 @@ public class CurveParamDto { @Schema(description = "最小值") private Double min; - @JsonProperty("unit") - @Schema(description = "单位") - private String unit; + @JsonProperty("xUnit") + @Schema(description = "x轴单位") + private String xUnit; + + @JsonProperty("xPhysics") + @Schema(description = "x轴物理量") + private String xPhysics; + + @JsonProperty("yUnit") + @Schema(description = "y轴单位") + private String yUnit; + + @JsonProperty("yPhysics") + @Schema(description = "y轴物理量") + private String yPhysics; + } diff --git a/system/src/main/java/com/sdm/system/service/handle/LyricMessageSender.java b/system/src/main/java/com/sdm/system/service/handle/LyricMessageSender.java index bad1440a..95e5119b 100644 --- a/system/src/main/java/com/sdm/system/service/handle/LyricMessageSender.java +++ b/system/src/main/java/com/sdm/system/service/handle/LyricMessageSender.java @@ -45,6 +45,21 @@ public class LyricMessageSender implements IMessageSender { // 1、先调用基础发送 basicSender.send(req); + // 根据userId查询发送人工号 + UserQueryReq userReq = new UserQueryReq(); + userReq.setUserId(ThreadLocalContext.getUserId()); + userReq.setTenantId(ThreadLocalContext.getTenantId()); + SdmResponse sdmResponse = sysUserFeignClient.queryUserDetail(userReq); + if (sdmResponse.getData() != null) { + req.setSendJobNo(sdmResponse.getData().getUsername()); + } + // 根据userId查询接收人工号 + userReq.setUserId(Long.valueOf(req.getUserId())); + SdmResponse response = sysUserFeignClient.queryUserDetail(userReq); + if (response.getData() != null) { + req.setReceiveJobNo(response.getData().getUsername()); + } + // 2、异步发送即时通消息通知 CompletableFuture.runAsync(() -> { sendMsgToFreelink(req); @@ -53,21 +68,11 @@ public class LyricMessageSender implements IMessageSender { private void sendMsgToFreelink(SendMsgReq req) { FreelinkAndDingdingInformReq param = new FreelinkAndDingdingInformReq(); - // 根据userId查询工号 - UserQueryReq userReq = new UserQueryReq(); - userReq.setUserId(ThreadLocalContext.getUserId()); - userReq.setTenantId(ThreadLocalContext.getTenantId()); - SdmResponse sdmResponse = sysUserFeignClient.queryUserDetail(userReq); - if (sdmResponse.getData() != null) { - param.setJobNo(sdmResponse.getData().getUsername()); - } + param.setJobNo(req.getSendJobNo()); + FreeLinkMsg freeLinkMsg = new FreeLinkMsg(); if (switchFlag.equals("true")) { - userReq.setUserId(Long.valueOf(req.getUserId())); - SdmResponse response = sysUserFeignClient.queryUserDetail(userReq); - if (response.getData() != null) { - freeLinkMsg.setId(response.getData().getUsername()); - } + freeLinkMsg.setId(req.getReceiveJobNo()); } else { freeLinkMsg.setId(sendUserId); }