feat:任务执行算例初始化流程节点/启动流程实例/查询流程节点

This commit is contained in:
2025-11-28 18:09:56 +08:00
parent 4d8497c366
commit 6bc4c7401e
30 changed files with 655 additions and 87 deletions

View File

@@ -178,4 +178,12 @@ public class SimulationRunController {
runService.generateReport(req,response);
}
/**
* 任务执行 一键执行 启动流程
*/
@PostMapping("/startProcessInstance")
public SdmResponse startProcessInstance(@RequestBody SpdmTaskRunReq req) {
return runService.startProcessInstance(req);
}
}

View File

@@ -141,4 +141,8 @@ public class SimulationRun implements Serializable {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
@Schema(description= "流程实例id流程引擎返回的")
@TableField("flowInstanceId")
private String flowInstanceId;
}

View File

@@ -17,5 +17,8 @@ public class SpdmTaskRunReq {
@Schema(description = "任务uuid")
private String taskId;
@Schema(description = "流程模板id")
private String templateId;
}

View File

@@ -57,4 +57,6 @@ public interface ISimulationRunService extends IService<SimulationRun> {
SdmResponse deleteSimulationKeyResult(KeyResultReq req);
void generateReport(SpdmReportReq req, HttpServletResponse response);
SdmResponse startProcessInstance(SpdmTaskRunReq req);
}

View File

@@ -3,20 +3,27 @@ package com.sdm.project.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.common.ThreadLocalContext;
import com.sdm.common.entity.enums.DirTypeEnum;
import com.sdm.common.entity.enums.NodeTypeEnum;
import com.sdm.common.entity.req.capability.FlowNodeDto;
import com.sdm.common.entity.req.data.*;
import com.sdm.common.entity.req.system.UserQueryReq;
import com.sdm.common.entity.resp.PageDataResp;
import com.sdm.common.entity.resp.capability.FlowTemplateResp;
import com.sdm.common.entity.resp.data.BatchAddFileInfoResp;
import com.sdm.common.entity.resp.data.FileMetadataInfoResp;
import com.sdm.common.entity.resp.flowable.ProcessInstanceResp;
import com.sdm.common.entity.resp.system.CIDUserResp;
import com.sdm.common.feign.impl.system.SysUserFeignClientImpl;
import com.sdm.common.feign.inter.capability.ISimulationFlowFeignClient;
import com.sdm.common.feign.inter.data.IDataFeignClient;
import com.sdm.common.feign.inter.flowable.IFlowableFeignClient;
import com.sdm.common.utils.PageUtils;
import com.sdm.common.utils.RandomUtil;
import com.sdm.project.common.KeyResultTypeEnum;
@@ -50,11 +57,10 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import static com.sdm.common.service.BaseService.generateUuid;
import static com.sdm.project.service.impl.NodeServiceImpl.getTagProperty;
import static com.sdm.project.service.impl.NodeServiceImpl.setTagProperty;
@@ -91,6 +97,12 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
@Autowired
private IDataFeignClient dataFeignClient;
@Autowired
private IFlowableFeignClient flowableFeignClient;
@Autowired
private ISimulationFlowFeignClient flowFeignClient;
private static final String TEMP_REPORT_PATH = "/opt/report/";
private int getCurrentNodeDepth(NodeAllBase eachNode) {
@@ -502,13 +514,8 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
if (fileMetadataInfoResp.getData() != null) {
simulationRun.setFolderId(fileMetadataInfoResp.getData().getId());
}
BeanUtils.copyProperties(req, simulationRun);
simulationRun.setUuid(RandomUtil.generateString(32));
simulationRun.setRunName(req.getRunName());
simulationRun.setTaskId(req.getTaskId());
simulationRun.setDescription(req.getDescription());
simulationRun.setTotalStep(req.getTotalStep());
simulationRun.setParentId(req.getParentId());
simulationRun.setFlowTemplate(req.getFlowTemplate());
simulationRun.setCreator(userId);
simulationRun.setUpdater(userId);
simulationRun.setTenantId(tenantId);
@@ -538,26 +545,92 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
simulationPerformanceService.saveBatch(runPerformanceList);
}
}
CreateDirReq createDirReq = new CreateDirReq();
createDirReq.setUuId(simulationRun.getUuid());
if (fileMetadataInfoResp.getData() != null) {
createDirReq.setParDirId(fileMetadataInfoResp.getData().getId());
// 创建算例文件夹
SdmResponse runDirResponse = createDir(simulationRun.getUuid(), simulationTask.getUuid(), req.getRunName(), DirTypeEnum.PROJECT_NODE_DIR.getValue(), NodeTypeEnum.RUN.getValue());
if (!runDirResponse.isSuccess()) {
return SdmResponse.failed("创建算例文件夹失败:{}" + runDirResponse.getMessage());
}
createDirReq.setUuIdOwnType(NodeTypeEnum.RUN.getValue());
createDirReq.setDirName(req.getRunName());
createDirReq.setDirType(DirTypeEnum.PROJECT_NODE_DIR.getValue());
log.info("创建算例时,调用创建文件夹的参数为:{}", createDirReq);
SdmResponse response = dataFeignClient.createDir(createDirReq);
log.info("创建算例时,调用创建文件夹的返回值为:{}", response);
if (!response.isSuccess()) {
this.removeById(simulationRun.getUuid());
simulationPerformanceService.lambdaUpdate().eq(SimulationPerformance::getRunId, simulationRun.getUuid()).remove();
// 解析流程模板中的节点结构,初始化流程节点表
SdmResponse<FlowTemplateResp> flowTemplateResp = flowFeignClient.queryFlowTemplateInfo(simulationRun.getFlowTemplate());
if (flowTemplateResp.getData() != null) {
try {
List<FlowNodeDto> flowNodeDtoList = new ArrayList<>();
List<Map<String, String>> result = extractFlowElements(flowTemplateResp.getData().getTemplateContent());
for (Map<String, String> map : result) {
FlowNodeDto flowNodeDto = new FlowNodeDto();
flowNodeDto.setUuid(generateUuid("flow_node_"));
flowNodeDto.setNodeName(map.get("name"));
// flowNodeReq.setFlowInstanceId(simulationRun.getFlowInstanceId());
flowNodeDto.setNodeId(map.get("id"));
flowNodeDto.setTemplateId(simulationRun.getFlowTemplate());
flowNodeDto.setRunId(simulationRun.getUuid());
flowNodeDtoList.add(flowNodeDto);
}
for (FlowNodeDto flowNodeDto : flowNodeDtoList) {
// 每个流程节点建立节点文件夹
SdmResponse nodeDirResponse = createDir(flowNodeDto.getUuid(), simulationRun.getUuid(), flowNodeDto.getNodeName(), DirTypeEnum.PROJECT_NODE_DIR.getValue(), NodeTypeEnum.FLOW_NODE.getValue());
if (!nodeDirResponse.isSuccess()) {
return SdmResponse.failed("创建节点文件夹失败:{}" + nodeDirResponse.getMessage());
}
// 每个流程节点初始化输入输出两个文件夹
SdmResponse inputDir = createDir(null, flowNodeDto.getUuid(), "数据输入", DirTypeEnum.PROJECT_NODE_DIR.getValue(), null);
SdmResponse outputDir = createDir(null, flowNodeDto.getUuid(), "数据输出", DirTypeEnum.PROJECT_NODE_DIR.getValue(), null);
flowNodeDto.setInputDirId(Long.parseLong(inputDir.getData().toString()));
flowNodeDto.setOutputDirId(Long.parseLong(outputDir.getData().toString()));
}
FlowNodeDto addReq = new FlowNodeDto();
addReq.setFlowNodeDtoList(flowNodeDtoList);
if (!flowFeignClient.batchAddSimulationFlowNode(addReq).isSuccess()) {
return SdmResponse.failed("新增流程节点失败:{}");
}
} catch (Exception e) {
log.error("解析流程模板json文件失败,flowTemplateId:{}", simulationRun.getFlowTemplate(), e);
throw new RuntimeException("解析流程模板json文件失败:" + e.getMessage(), e);
}
}
}
return SdmResponse.success(simulationRun.getUuid());
}
}
private SdmResponse createDir(String uuid, String parentUuid, String dirName, Integer dirType, String uuidOwnType) {
CreateDirReq createDirReq = new CreateDirReq();
createDirReq.setUuId(uuid);
createDirReq.setParentUuId(parentUuid);
createDirReq.setUuIdOwnType(uuidOwnType);
createDirReq.setDirName(dirName);
createDirReq.setDirType(dirType);
log.info("创建算例阶段时,调用创建文件夹的参数为:{}", createDirReq);
SdmResponse response = dataFeignClient.createDir(createDirReq);
log.info("创建算例阶段时,调用创建文件夹的返回值为:{}", response);
return response;
}
/**
* 解析流程模板json结构 获取节点id和名称
* @param jsonString
* @return
* @throws Exception
*/
public static List<Map<String, String>> extractFlowElements(String jsonString) throws Exception {
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(jsonString);
JsonNode flowElements = rootNode.path("flowElements");
List<Map<String, String>> elements = new ArrayList<>();
for (JsonNode element : flowElements) {
if ("sequenceFlow".equals(element.get("type").asText())) {
continue;
}
Map<String, String> item = new HashMap<>();
item.put("id", element.path("id").asText());
item.put("name", element.path("name").asText());
elements.add(item);
}
return elements;
}
@Override
@Transactional(rollbackFor = Exception.class)
public SdmResponse deleteTaskRun(SpdmTaskRunReq req) {
@@ -681,7 +754,7 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
if (!simulationKeyResultService.save(simulationRunKeyResult)) {
return SdmResponse.failed("添加关键结果失败");
}
return SdmResponse.success();
return SdmResponse.success(simulationRunKeyResult.getUuid());
}
@Override
@@ -860,6 +933,25 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
}
@Override
@Transactional(rollbackFor = Exception.class)
public SdmResponse startProcessInstance(SpdmTaskRunReq req) {
SimulationRun simulationRun = this.lambdaQuery().eq(SimulationRun::getUuid, req.getRunId()).one();
// 启动流程实例
SdmResponse<ProcessInstanceResp> sdmResponse = flowableFeignClient.startByProcessDefinitionKey(simulationRun.getFlowTemplate());
if (sdmResponse.getData() != null) {
this.lambdaUpdate().set(SimulationRun::getFlowInstanceId, sdmResponse.getData().getId()).eq(SimulationRun::getUuid, req.getRunId()).update();
// 更新node节点的流程实例id
FlowNodeDto flowNodeDto = new FlowNodeDto();
flowNodeDto.setRunId(req.getRunId());
flowNodeDto.setFlowInstanceId(sdmResponse.getData().getId());
flowFeignClient.batchUpdateSimulationFlowNode(flowNodeDto);
} else {
return SdmResponse.failed("流程实例启动失败");
}
return sdmResponse;
}
public static void deleteFolder(File folder) {
if (folder.isDirectory()) {
File[] files = folder.listFiles();