fix:支持任意节点开始执行
This commit is contained in:
@@ -21,10 +21,10 @@ public class FlowableClientFeignClientImpl implements IFlowableFeignClient {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IFlowableFeignClient flowableFeignClient;
|
private IFlowableFeignClient flowableFeignClient;
|
||||||
|
|
||||||
public SdmResponse<ProcessInstanceResp> startByProcessDefinitionId(String processDefinitionId, Map<String, Object> variables) {
|
public SdmResponse<ProcessInstanceResp> startByProcessDefinitionId(String processDefinitionId,String targetNodeId, Map<String, Object> variables) {
|
||||||
SdmResponse<ProcessInstanceResp> response;
|
SdmResponse<ProcessInstanceResp> response;
|
||||||
try {
|
try {
|
||||||
response = flowableFeignClient.startByProcessDefinitionId(processDefinitionId, variables);
|
response = flowableFeignClient.startByProcessDefinitionId(processDefinitionId,targetNodeId, variables);
|
||||||
log.info("启动流程实例:"+ response);
|
log.info("启动流程实例:"+ response);
|
||||||
return response;
|
return response;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import java.util.Map;
|
|||||||
public interface IFlowableFeignClient {
|
public interface IFlowableFeignClient {
|
||||||
|
|
||||||
@GetMapping("/process/startByProcessDefinitionId")
|
@GetMapping("/process/startByProcessDefinitionId")
|
||||||
SdmResponse<ProcessInstanceResp> startByProcessDefinitionId(@RequestParam String processDefinitionId, @RequestBody(required = false) Map<String, Object> variables);
|
SdmResponse<ProcessInstanceResp> startByProcessDefinitionId(@RequestParam String processDefinitionId, @RequestParam(required = false) String targetNodeId, @RequestBody(required = false) Map<String, Object> variables);
|
||||||
|
|
||||||
@PostMapping("/process/deploy")
|
@PostMapping("/process/deploy")
|
||||||
SdmResponse<DeployFlowableResp> deploy(@RequestBody ProcessDefinitionDTO processDTO);
|
SdmResponse<DeployFlowableResp> deploy(@RequestBody ProcessDefinitionDTO processDTO);
|
||||||
|
|||||||
@@ -119,14 +119,23 @@ public class ProcessController implements IFlowableFeignClient {
|
|||||||
* 根据流程定义ID启动流程实例
|
* 根据流程定义ID启动流程实例
|
||||||
*
|
*
|
||||||
* @param processDefinitionId 流程定义ID(指定版本)
|
* @param processDefinitionId 流程定义ID(指定版本)
|
||||||
|
* @param targetNodeId 可选,指定从该节点启动(内部会智能修正到真实入口节点)
|
||||||
* @param variables 可选的流程启动变量
|
* @param variables 可选的流程启动变量
|
||||||
*/
|
*/
|
||||||
@PostMapping("/startByProcessDefinitionId")
|
@PostMapping("/startByProcessDefinitionId")
|
||||||
public SdmResponse startByProcessDefinitionId(
|
public SdmResponse startByProcessDefinitionId(
|
||||||
@RequestParam String processDefinitionId,
|
@RequestParam String processDefinitionId,
|
||||||
|
@RequestParam(required = false) String targetNodeId,
|
||||||
@RequestBody(required = false) Map<String, Object> variables) {
|
@RequestBody(required = false) Map<String, Object> variables) {
|
||||||
log.info("开始启动流程定义: {}",processDefinitionId);
|
log.info("开始启动流程定义: {}, targetNodeId: {}", processDefinitionId, targetNodeId);
|
||||||
ProcessInstance processInstance = processService.startByProcessDefinitionId(processDefinitionId, variables);
|
|
||||||
|
ProcessInstance processInstance;
|
||||||
|
if (targetNodeId != null && !targetNodeId.isBlank()) {
|
||||||
|
processInstance = processService.startProcessAtNode(processDefinitionId, targetNodeId, variables);
|
||||||
|
} else {
|
||||||
|
processInstance = processService.startByProcessDefinitionId(processDefinitionId, variables);
|
||||||
|
}
|
||||||
|
|
||||||
ProcessInstanceResp processInstanceResp = new ProcessInstanceResp();
|
ProcessInstanceResp processInstanceResp = new ProcessInstanceResp();
|
||||||
processInstanceResp.setProcessInstanceId(processInstance.getId());
|
processInstanceResp.setProcessInstanceId(processInstance.getId());
|
||||||
processInstanceResp.setProcessDefinitionId(processInstance.getProcessDefinitionId());
|
processInstanceResp.setProcessDefinitionId(processInstance.getProcessDefinitionId());
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import org.flowable.validation.ProcessValidatorFactory;
|
|||||||
import org.flowable.validation.ValidationError;
|
import org.flowable.validation.ValidationError;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
@@ -149,14 +150,71 @@ public class ProcessService implements Iprocess{
|
|||||||
if (variables == null) {
|
if (variables == null) {
|
||||||
variables = Collections.emptyMap();
|
variables = Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("根据流程定义ID启动流程实例, 流程定义ID: {}, 变量数量: {}", processDefinitionId, variables.size());
|
log.info("根据流程定义ID启动流程实例, 流程定义ID: {}, 变量数量: {}", processDefinitionId, variables.size());
|
||||||
|
|
||||||
ProcessInstance instance = runtimeService.startProcessInstanceById(processDefinitionId, variables);
|
ProcessInstance instance = runtimeService.startProcessInstanceById(processDefinitionId, variables);
|
||||||
|
|
||||||
log.info("流程实例启动成功, 实例ID: {}, 流程定义ID: {}, 业务Key: {}",
|
log.info("流程实例启动成功, 实例ID: {}, 流程定义ID: {}, 业务Key: {}",
|
||||||
instance.getId(), instance.getProcessDefinitionId(), instance.getBusinessKey());
|
instance.getId(), instance.getProcessDefinitionId(), instance.getBusinessKey());
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从任意节点启动流程(利用 StartEvent 异步特性,在同事务内启动 + 跳转)
|
||||||
|
*
|
||||||
|
* @param processDefinitionId 流程定义ID
|
||||||
|
* @param targetNodeId 目标节点ID(可传原始节点ID或复合节点ID)
|
||||||
|
* @param variables 流程变量
|
||||||
|
* @return 启动后的流程实例
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ProcessInstance startProcessAtNode(String processDefinitionId, String targetNodeId, Map<String, Object> variables) {
|
||||||
|
log.info("开始从指定节点启动流程. 流程定义: {}, 目标节点: {}", processDefinitionId, targetNodeId);
|
||||||
|
|
||||||
|
// 1. 获取 BPMN 模型
|
||||||
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
|
||||||
|
if (bpmnModel == null || bpmnModel.getMainProcess() == null) {
|
||||||
|
throw new RuntimeException("流程定义不存在: " + processDefinitionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 找 StartEvent
|
||||||
|
StartEvent startEvent = bpmnModel.getMainProcess().findFlowElementsOfType(StartEvent.class).stream()
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new RuntimeException("流程模型中缺少 StartEvent"));
|
||||||
|
String startEventId = startEvent.getId();
|
||||||
|
|
||||||
|
// 3. 智能修正目标节点(复用现有复合节点规则)
|
||||||
|
String realTargetNodeId = targetNodeId;
|
||||||
|
String originalNodeId = FlowNodeIdUtils.parseOriginalNodeId(targetNodeId);
|
||||||
|
|
||||||
|
String registerNodeId = FlowNodeIdUtils.generateRegisterTaskId(originalNodeId);
|
||||||
|
String waitUserNodeId = FlowNodeIdUtils.generateWaitUserTaskId(originalNodeId);
|
||||||
|
|
||||||
|
if (bpmnModel.getMainProcess().getFlowElement(registerNodeId) != null) {
|
||||||
|
realTargetNodeId = registerNodeId;
|
||||||
|
} else if (bpmnModel.getMainProcess().getFlowElement(waitUserNodeId) != null) {
|
||||||
|
realTargetNodeId = waitUserNodeId;
|
||||||
|
} else if (bpmnModel.getMainProcess().getFlowElement(realTargetNodeId) == null) {
|
||||||
|
throw new RuntimeException("目标节点不存在: " + targetNodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("原始目标节点: {}, 智能修正后的真实入口: {}", targetNodeId, realTargetNodeId);
|
||||||
|
|
||||||
|
// 4. 启动流程(StartEvent 异步,流程会先停在 StartEvent)
|
||||||
|
if (variables == null) {
|
||||||
|
variables = new HashMap<>();
|
||||||
|
}
|
||||||
|
ProcessInstance instance = runtimeService.startProcessInstanceById(processDefinitionId, variables);
|
||||||
|
|
||||||
|
// 5. 同事务内立刻跳转到目标节点
|
||||||
|
runtimeService.createChangeActivityStateBuilder()
|
||||||
|
.processInstanceId(instance.getId())
|
||||||
|
.moveActivityIdTo(startEventId, realTargetNodeId)
|
||||||
|
.changeState();
|
||||||
|
|
||||||
|
log.info("流程已成功从节点 [{}] 启动,实例ID: {}", realTargetNodeId, instance.getId());
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,5 +18,8 @@ public class SpdmTaskRunReq {
|
|||||||
@Schema(description = "流程模板id")
|
@Schema(description = "流程模板id")
|
||||||
private String templateId;
|
private String templateId;
|
||||||
|
|
||||||
|
@Schema(description = "指定启动节点")
|
||||||
|
private String targetNodeId;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2512,7 +2512,7 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
|
|||||||
variables.put("userName", ThreadLocalContext.getUserName());
|
variables.put("userName", ThreadLocalContext.getUserName());
|
||||||
variables.put("tenantId", ThreadLocalContext.getTenantId());
|
variables.put("tenantId", ThreadLocalContext.getTenantId());
|
||||||
// 启动流程实例 多次执行会生成多个流程实例id,更新算例run表、同时更新flowable流程参数的流程实例id
|
// 启动流程实例 多次执行会生成多个流程实例id,更新算例run表、同时更新flowable流程参数的流程实例id
|
||||||
SdmResponse<ProcessInstanceResp> sdmResponse = flowableFeignClient.startByProcessDefinitionId(simulationRun.getProcessDefinitionId(), variables);
|
SdmResponse<ProcessInstanceResp> sdmResponse = flowableFeignClient.startByProcessDefinitionId(simulationRun.getProcessDefinitionId(),req.getTargetNodeId(), variables);
|
||||||
if (sdmResponse.getData() != null) {
|
if (sdmResponse.getData() != null) {
|
||||||
this.lambdaUpdate()
|
this.lambdaUpdate()
|
||||||
.set(SimulationRun::getFlowInstanceId, sdmResponse.getData().getProcessInstanceId())
|
.set(SimulationRun::getFlowInstanceId, sdmResponse.getData().getProcessInstanceId())
|
||||||
|
|||||||
Reference in New Issue
Block a user