1
This commit is contained in:
parent
296b5d3b9e
commit
f0c964ea43
@ -34,67 +34,54 @@ public class ShellTaskDelegate implements JavaDelegate {
|
|||||||
private ManagementService managementService;
|
private ManagementService managementService;
|
||||||
|
|
||||||
private Expression script;
|
private Expression script;
|
||||||
|
|
||||||
private Expression workDir;
|
private Expression workDir;
|
||||||
|
|
||||||
private Expression env;
|
private Expression env;
|
||||||
|
|
||||||
// 用于存储实时输出的Map
|
// 用于存储实时输出的Map
|
||||||
private static final Map<String, StringBuilder> outputMap = new ConcurrentHashMap<>();
|
private static final Map<String, StringBuilder> outputMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static final Map<String, StringBuilder> errorMap = new ConcurrentHashMap<>();
|
private static final Map<String, StringBuilder> errorMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private void processInputStream(InputStream inputStream, String processInstanceId, NodeLogTypeEnums logType) {
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
// 发布日志事件
|
|
||||||
eventPublisher.publishEvent(new ShellLogEvent(processInstanceId, line, logType));
|
|
||||||
|
|
||||||
// 同时保存到StringBuilder中
|
|
||||||
if (logType == NodeLogTypeEnums.STDOUT) {
|
|
||||||
StringBuilder output = outputMap.get(processInstanceId);
|
|
||||||
synchronized (output) {
|
|
||||||
output.append(line).append("\n");
|
|
||||||
}
|
|
||||||
log.info("Shell output: {}", line);
|
|
||||||
} else {
|
|
||||||
StringBuilder error = errorMap.get(processInstanceId);
|
|
||||||
synchronized (error) {
|
|
||||||
error.append(line).append("\n");
|
|
||||||
}
|
|
||||||
log.error("Shell error: {}", line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Error reading process output", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(DelegateExecution execution) {
|
public void execute(DelegateExecution execution) {
|
||||||
|
log.info("ShellTaskDelegate开始执行, processInstanceId={}, executionId={}",
|
||||||
|
execution.getProcessInstanceId(), execution.getId());
|
||||||
|
|
||||||
// 从字段注入中获取值
|
// 从字段注入中获取值
|
||||||
String scriptValue = script != null ? script.getValue(execution).toString() : null;
|
String scriptValue = script != null ? script.getValue(execution).toString() : null;
|
||||||
String workDirValue = workDir != null ? workDir.getValue(execution).toString() : null;
|
String workDirValue = workDir != null ? workDir.getValue(execution).toString() : null;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, String> envValue = env != null ? (Map<String, String>) env.getValue(execution) : null;
|
Map<String, String> envValue = env != null ? (Map<String, String>) env.getValue(execution) : null;
|
||||||
|
|
||||||
|
log.info("字段注入的值: script={}, workDir={}, env={}", scriptValue, workDirValue, envValue);
|
||||||
|
|
||||||
// 如果流程变量中有值,优先使用流程变量
|
// 如果流程变量中有值,优先使用流程变量
|
||||||
if (execution.hasVariable("script")) {
|
if (execution.hasVariable("script")) {
|
||||||
scriptValue = (String) execution.getVariable("script");
|
scriptValue = (String) execution.getVariable("script");
|
||||||
|
log.info("从流程变量获取到script={}", scriptValue);
|
||||||
}
|
}
|
||||||
if (execution.hasVariable("workDir")) {
|
if (execution.hasVariable("workDir")) {
|
||||||
workDirValue = (String) execution.getVariable("workDir");
|
workDirValue = (String) execution.getVariable("workDir");
|
||||||
|
log.info("从流程变量获取到workDir={}", workDirValue);
|
||||||
}
|
}
|
||||||
if (execution.hasVariable("env")) {
|
if (execution.hasVariable("env")) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, String> envFromVar = (Map<String, String>) execution.getVariable("env");
|
Map<String, String> envFromVar = (Map<String, String>) execution.getVariable("env");
|
||||||
envValue = envFromVar;
|
envValue = envFromVar;
|
||||||
|
log.info("从流程变量获取到env={}", envValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scriptValue == null) {
|
if (scriptValue == null) {
|
||||||
|
log.error("脚本内容为空,执行失败");
|
||||||
handleFailure(execution, "Script is required but not provided");
|
handleFailure(execution, "Script is required but not provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
log.info("准备执行脚本: {}", scriptValue);
|
||||||
// 使用processInstanceId而不是executionId
|
// 使用processInstanceId而不是executionId
|
||||||
String processInstanceId = execution.getProcessInstanceId();
|
String processInstanceId = execution.getProcessInstanceId();
|
||||||
outputMap.put(processInstanceId, new StringBuilder());
|
outputMap.put(processInstanceId, new StringBuilder());
|
||||||
@ -137,7 +124,7 @@ public class ShellTaskDelegate implements JavaDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 执行命令
|
// 执行命令
|
||||||
log.info("Executing shell script: {}", scriptValue);
|
log.info("执行shell脚本: {}", scriptValue);
|
||||||
Process process = processBuilder.start();
|
Process process = processBuilder.start();
|
||||||
|
|
||||||
// 使用BufferedReader实时读取输出
|
// 使用BufferedReader实时读取输出
|
||||||
@ -178,28 +165,56 @@ public class ShellTaskDelegate implements JavaDelegate {
|
|||||||
errorMap.remove(processInstanceId);
|
errorMap.remove(processInstanceId);
|
||||||
|
|
||||||
if (exitCode != 0) {
|
if (exitCode != 0) {
|
||||||
log.error("Shell script execution failed with exit code: {}", exitCode);
|
log.error("Shell脚本执行失败,退出码: {}", exitCode);
|
||||||
log.error("Error output: {}", finalError);
|
log.error("错误输出: {}", finalError);
|
||||||
handleFailure(execution, "Shell script execution failed with exit code: " + exitCode);
|
handleFailure(execution, "Shell脚本执行失败,退出码: " + exitCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("Shell script executed successfully");
|
log.info("Shell脚本执行成功");
|
||||||
log.debug("Script output: {}", finalOutput);
|
log.debug("脚本输出: {}", finalOutput);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Shell script execution failed", e);
|
log.error("Shell脚本执行失败", e);
|
||||||
handleFailure(execution, "Shell script execution failed: " + e.getMessage());
|
handleFailure(execution, "Shell脚本执行失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processInputStream(InputStream inputStream, String processInstanceId, NodeLogTypeEnums logType) {
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
// 发布日志事件
|
||||||
|
eventPublisher.publishEvent(new ShellLogEvent(processInstanceId, line, logType));
|
||||||
|
|
||||||
|
// 同时保存到StringBuilder中
|
||||||
|
if (logType == NodeLogTypeEnums.STDOUT) {
|
||||||
|
StringBuilder output = outputMap.get(processInstanceId);
|
||||||
|
synchronized (output) {
|
||||||
|
output.append(line).append("\n");
|
||||||
|
}
|
||||||
|
log.info("Shell output: {}", line);
|
||||||
|
} else {
|
||||||
|
StringBuilder error = errorMap.get(processInstanceId);
|
||||||
|
synchronized (error) {
|
||||||
|
error.append(line).append("\n");
|
||||||
|
}
|
||||||
|
log.error("Shell error: {}", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error reading process output", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void handleFailure(DelegateExecution execution, String errorMessage) {
|
private void handleFailure(DelegateExecution execution, String errorMessage) {
|
||||||
String processInstanceId = execution.getProcessInstanceId();
|
String processInstanceId = execution.getProcessInstanceId();
|
||||||
try {
|
try {
|
||||||
// 直接终止流程实例
|
// 直接终止流程实例
|
||||||
runtimeService.deleteProcessInstance(processInstanceId, errorMessage);
|
runtimeService.deleteProcessInstance(processInstanceId, errorMessage);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Error while handling shell task failure for process instance: {}", processInstanceId, e);
|
log.error("处理Shell任务失败时出现错误,流程实例: {}", processInstanceId, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,33 +1,79 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.enums;
|
package com.qqchen.deploy.backend.workflow.enums;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.flowable.bpmn.model.EndEvent;
|
||||||
|
import org.flowable.bpmn.model.ExclusiveGateway;
|
||||||
|
import org.flowable.bpmn.model.ScriptTask;
|
||||||
|
import org.flowable.bpmn.model.ServiceTask;
|
||||||
|
import org.flowable.bpmn.model.StartEvent;
|
||||||
|
import org.flowable.bpmn.model.UserTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BPMN节点类型枚举
|
* BPMN节点类型枚举
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public enum BpmnNodeTypeEnums {
|
public enum BpmnNodeTypeEnums {
|
||||||
START("start", "startEvent"),
|
|
||||||
END("end", "endEvent"),
|
|
||||||
USER_TASK("userTask", "userTask"),
|
|
||||||
SERVICE_TASK("serviceTask", "serviceTask"),
|
|
||||||
SHELL_TASK("shellTask", "serviceTask"),
|
|
||||||
EXCLUSIVE_GATEWAY("exclusiveGateway", "exclusiveGateway");
|
|
||||||
|
|
||||||
private final String shape;
|
START_EVENT("startEvent", StartEvent.class),
|
||||||
|
|
||||||
|
END_EVENT("endEvent", EndEvent.class),
|
||||||
|
|
||||||
|
USER_TASK("userTask", UserTask.class),
|
||||||
|
|
||||||
|
SERVICE_TASK("serviceTask", ServiceTask.class),
|
||||||
|
|
||||||
|
SCRIPT_TASK("scriptTask", ScriptTask.class),
|
||||||
|
|
||||||
|
EXCLUSIVE_GATEWAY("exclusiveGateway", ExclusiveGateway.class);
|
||||||
|
|
||||||
private final String bpmnType;
|
private final String bpmnType;
|
||||||
|
|
||||||
BpmnNodeTypeEnums(String shape, String bpmnType) {
|
private final Object instance;
|
||||||
this.shape = shape;
|
|
||||||
|
BpmnNodeTypeEnums(String bpmnType, Object instance) {
|
||||||
this.bpmnType = bpmnType;
|
this.bpmnType = bpmnType;
|
||||||
|
this.instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BpmnNodeTypeEnums fromShape(String shape) {
|
|
||||||
for (BpmnNodeTypeEnums type : values()) {
|
/**
|
||||||
if (type.getShape().equals(shape)) {
|
* Flowable 主要的节点类型包括:
|
||||||
return type;
|
*
|
||||||
}
|
* 事件类型:
|
||||||
}
|
* StartEvent (开始事件)
|
||||||
return null;
|
* EndEvent (结束事件)
|
||||||
}
|
* TimerStartEvent (定时开始事件)
|
||||||
|
* ErrorStartEvent (错误开始事件)
|
||||||
|
* MessageStartEvent (消息开始事件)
|
||||||
|
* SignalStartEvent (信号开始事件)
|
||||||
|
* IntermediateCatchEvent (中间捕获事件)
|
||||||
|
* IntermediateThrowEvent (中间抛出事件)
|
||||||
|
* 任务类型:
|
||||||
|
* UserTask (用户任务)
|
||||||
|
* ServiceTask (服务任务)
|
||||||
|
* ScriptTask (脚本任务)
|
||||||
|
* MailTask (邮件任务)
|
||||||
|
* ManualTask (手动任务)
|
||||||
|
* ReceiveTask (接收任务)
|
||||||
|
* BusinessRuleTask (业务规则任务)
|
||||||
|
* CallActivity (调用活动)
|
||||||
|
* 网关类型:
|
||||||
|
* ExclusiveGateway (排他网关)
|
||||||
|
* ParallelGateway (并行网关)
|
||||||
|
* InclusiveGateway (包容网关)
|
||||||
|
* EventBasedGateway (事件网关)
|
||||||
|
* ComplexGateway (复杂网关)
|
||||||
|
* 子流程:
|
||||||
|
* SubProcess (子流程)
|
||||||
|
* EventSubProcess (事件子流程)
|
||||||
|
* Transaction (事务子流程)
|
||||||
|
* 边界事件:
|
||||||
|
* BoundaryEvent (边界事件)
|
||||||
|
* ErrorBoundaryEvent (错误边界事件)
|
||||||
|
* TimerBoundaryEvent (定时边界事件)
|
||||||
|
* SignalBoundaryEvent (信号边界事件)
|
||||||
|
* 连线:
|
||||||
|
* SequenceFlow (顺序流)
|
||||||
|
* MessageFlow (消息流)
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
@ -23,6 +23,7 @@ public enum NodeTypeEnums {
|
|||||||
START_EVENT(
|
START_EVENT(
|
||||||
"START_EVENT", // 节点类型编码
|
"START_EVENT", // 节点类型编码
|
||||||
"开始节点", // 节点显示名称
|
"开始节点", // 节点显示名称
|
||||||
|
BpmnNodeTypeEnums.START_EVENT,
|
||||||
NodeCategoryEnums.EVENT,
|
NodeCategoryEnums.EVENT,
|
||||||
"工作流的起点", // 节点简要描述
|
"工作流的起点", // 节点简要描述
|
||||||
new WorkflowNodeGraph() // UI配置
|
new WorkflowNodeGraph() // UI配置
|
||||||
@ -42,6 +43,7 @@ public enum NodeTypeEnums {
|
|||||||
END_EVENT(
|
END_EVENT(
|
||||||
"END_EVENT",
|
"END_EVENT",
|
||||||
"结束节点",
|
"结束节点",
|
||||||
|
BpmnNodeTypeEnums.END_EVENT,
|
||||||
NodeCategoryEnums.EVENT,
|
NodeCategoryEnums.EVENT,
|
||||||
"工作流的终点",
|
"工作流的终点",
|
||||||
new WorkflowNodeGraph()
|
new WorkflowNodeGraph()
|
||||||
@ -53,6 +55,7 @@ public enum NodeTypeEnums {
|
|||||||
SCRIPT_TASK(
|
SCRIPT_TASK(
|
||||||
"SCRIPT_TASK",
|
"SCRIPT_TASK",
|
||||||
"脚本任务",
|
"脚本任务",
|
||||||
|
BpmnNodeTypeEnums.SERVICE_TASK,
|
||||||
NodeCategoryEnums.TASK,
|
NodeCategoryEnums.TASK,
|
||||||
"脚本执行任务",
|
"脚本执行任务",
|
||||||
new WorkflowNodeGraph()
|
new WorkflowNodeGraph()
|
||||||
@ -200,6 +203,8 @@ public enum NodeTypeEnums {
|
|||||||
|
|
||||||
private final String name; // 节点显示名称
|
private final String name; // 节点显示名称
|
||||||
|
|
||||||
|
private final BpmnNodeTypeEnums bpmnType; // 对应的BPMN类型
|
||||||
|
|
||||||
private final NodeCategoryEnums category; //分类
|
private final NodeCategoryEnums category; //分类
|
||||||
|
|
||||||
private final String description; // 节点详细描述
|
private final String description; // 节点详细描述
|
||||||
@ -209,11 +214,13 @@ public enum NodeTypeEnums {
|
|||||||
NodeTypeEnums(
|
NodeTypeEnums(
|
||||||
String code,
|
String code,
|
||||||
String name,
|
String name,
|
||||||
|
BpmnNodeTypeEnums bpmnType,
|
||||||
NodeCategoryEnums category,
|
NodeCategoryEnums category,
|
||||||
String description,
|
String description,
|
||||||
WorkflowNodeGraph uiConfig) {
|
WorkflowNodeGraph uiConfig) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.bpmnType = bpmnType;
|
||||||
this.category = category;
|
this.category = category;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.uiConfig = uiConfig;
|
this.uiConfig = uiConfig;
|
||||||
|
|||||||
@ -10,7 +10,11 @@ import lombok.Getter;
|
|||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ShellLogEvent {
|
public class ShellLogEvent {
|
||||||
|
|
||||||
private String processInstanceId;
|
private String processInstanceId;
|
||||||
|
|
||||||
private String logMessage;
|
private String logMessage;
|
||||||
|
|
||||||
private NodeLogTypeEnums logType;
|
private NodeLogTypeEnums logType;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,44 +0,0 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.handler;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.qqchen.deploy.backend.workflow.enums.BpmnNodeTypeEnums;
|
|
||||||
import com.qqchen.deploy.backend.workflow.model.BpmnNodeConfig;
|
|
||||||
import org.flowable.bpmn.model.FlowElement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BPMN节点处理器接口
|
|
||||||
*
|
|
||||||
* @param <T> 流程元素类型
|
|
||||||
*/
|
|
||||||
public interface BpmnNodeHandler<T extends FlowElement> {
|
|
||||||
/**
|
|
||||||
* 处理节点数据
|
|
||||||
*
|
|
||||||
* @param nodeData JSON节点数据
|
|
||||||
* @param element 流程元素
|
|
||||||
* @param config 节点配置
|
|
||||||
*/
|
|
||||||
void handle(JsonNode nodeData, T element, BpmnNodeConfig config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建流程元素
|
|
||||||
*
|
|
||||||
* @param config 节点配置
|
|
||||||
* @return 流程元素
|
|
||||||
*/
|
|
||||||
T createElement(BpmnNodeConfig config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取处理器类型
|
|
||||||
*
|
|
||||||
* @return 节点类型
|
|
||||||
*/
|
|
||||||
BpmnNodeTypeEnums getType();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取处理的元素类型
|
|
||||||
*
|
|
||||||
* @return 元素类型Class
|
|
||||||
*/
|
|
||||||
Class<T> getElementType();
|
|
||||||
}
|
|
||||||
@ -1,132 +0,0 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.handler.impl;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.qqchen.deploy.backend.workflow.annotation.BpmnNode;
|
|
||||||
import com.qqchen.deploy.backend.workflow.enums.BpmnNodeTypeEnums;
|
|
||||||
import com.qqchen.deploy.backend.workflow.handler.BpmnNodeHandler;
|
|
||||||
import com.qqchen.deploy.backend.workflow.model.BpmnNodeConfig;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.flowable.bpmn.model.FieldExtension;
|
|
||||||
import org.flowable.bpmn.model.ServiceTask;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shell任务处理器
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
@BpmnNode(
|
|
||||||
type = "shellTask",
|
|
||||||
name = "Shell脚本",
|
|
||||||
async = true,
|
|
||||||
requiredFields = {"script", "workDir"},
|
|
||||||
delegateExpression = "${shellTaskDelegate}"
|
|
||||||
)
|
|
||||||
public class ShellTaskHandler implements BpmnNodeHandler<ServiceTask> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(JsonNode nodeData, ServiceTask element, BpmnNodeConfig config) {
|
|
||||||
// 设置任务委托表达式
|
|
||||||
setupTaskDelegate(element);
|
|
||||||
|
|
||||||
// 设置任务属性
|
|
||||||
setupTaskProperties(element, config);
|
|
||||||
|
|
||||||
// 验证必需字段
|
|
||||||
validateRequiredFields(element, config);
|
|
||||||
|
|
||||||
// 处理扩展字段
|
|
||||||
handleExtensionFields(element, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ServiceTask createElement(BpmnNodeConfig config) {
|
|
||||||
ServiceTask task = new ServiceTask();
|
|
||||||
task.setId(config.getId());
|
|
||||||
task.setName(config.getName());
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BpmnNodeTypeEnums getType() {
|
|
||||||
return BpmnNodeTypeEnums.SHELL_TASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<ServiceTask> getElementType() {
|
|
||||||
return ServiceTask.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置任务委托表达式
|
|
||||||
*/
|
|
||||||
private void setupTaskDelegate(ServiceTask element) {
|
|
||||||
BpmnNode annotation = this.getClass().getAnnotation(BpmnNode.class);
|
|
||||||
element.setImplementationType("delegateExpression");
|
|
||||||
element.setImplementation(annotation.delegateExpression());
|
|
||||||
element.setAsynchronous(annotation.async());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置任务属性
|
|
||||||
*/
|
|
||||||
private void setupTaskProperties(ServiceTask element, BpmnNodeConfig config) {
|
|
||||||
Map<String, Object> properties = config.getProperties();
|
|
||||||
properties.forEach((key, value) -> {
|
|
||||||
if (value != null) {
|
|
||||||
addFieldExtension(element, key, value.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证必需字段
|
|
||||||
*/
|
|
||||||
private void validateRequiredFields(ServiceTask element, BpmnNodeConfig config) {
|
|
||||||
BpmnNode annotation = this.getClass().getAnnotation(BpmnNode.class);
|
|
||||||
for (String requiredField : annotation.requiredFields()) {
|
|
||||||
boolean fieldExists = element.getFieldExtensions().stream()
|
|
||||||
.anyMatch(field -> field.getFieldName().equals(requiredField));
|
|
||||||
if (!fieldExists) {
|
|
||||||
log.warn("Required field '{}' is missing for shell task '{}'",
|
|
||||||
requiredField, element.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理扩展字段
|
|
||||||
*/
|
|
||||||
private void handleExtensionFields(ServiceTask element, BpmnNodeConfig config) {
|
|
||||||
Map<String, String> extensions = config.getExtensions();
|
|
||||||
extensions.forEach((key, value) -> {
|
|
||||||
if (value != null) {
|
|
||||||
addFieldExtension(element, key, value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加字段扩展
|
|
||||||
*/
|
|
||||||
private void addFieldExtension(ServiceTask serviceTask, String name, String value) {
|
|
||||||
// 检查字段是否已存在
|
|
||||||
Optional<FieldExtension> existingField = serviceTask.getFieldExtensions().stream()
|
|
||||||
.filter(field -> field.getFieldName().equals(name))
|
|
||||||
.findFirst();
|
|
||||||
|
|
||||||
if (existingField.isPresent()) {
|
|
||||||
// 更新现有字段
|
|
||||||
existingField.get().setStringValue(value);
|
|
||||||
} else {
|
|
||||||
// 添加新字段
|
|
||||||
FieldExtension field = new FieldExtension();
|
|
||||||
field.setFieldName(name);
|
|
||||||
field.setStringValue(value);
|
|
||||||
serviceTask.getFieldExtensions().add(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,76 +0,0 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.parser;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.qqchen.deploy.backend.workflow.enums.BpmnNodeTypeEnums;
|
|
||||||
import com.qqchen.deploy.backend.workflow.model.BpmnNodeConfig;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BPMN节点配置解析器
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class BpmnNodeConfigParser {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析节点配置
|
|
||||||
*
|
|
||||||
* @param node JSON节点数据
|
|
||||||
* @return 节点配置
|
|
||||||
*/
|
|
||||||
public BpmnNodeConfig parse(JsonNode node) {
|
|
||||||
BpmnNodeConfig config = new BpmnNodeConfig();
|
|
||||||
config.setId(node.path("id").asText());
|
|
||||||
config.setName(node.path("data").path("label").asText());
|
|
||||||
config.setType(BpmnNodeTypeEnums.fromShape(node.path("shape").asText()));
|
|
||||||
|
|
||||||
// 解析属性
|
|
||||||
JsonNode data = node.path("data");
|
|
||||||
|
|
||||||
// 处理通用属性
|
|
||||||
Map<String, Object> properties = new HashMap<>();
|
|
||||||
if (data.has("properties")) {
|
|
||||||
data.path("properties").fields()
|
|
||||||
.forEachRemaining(entry -> properties.put(
|
|
||||||
entry.getKey(),
|
|
||||||
parseValue(entry.getValue())
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理特定任务属性
|
|
||||||
if (data.has("serviceTask") && data.path("serviceTask").has("fields")) {
|
|
||||||
JsonNode fields = data.path("serviceTask").path("fields");
|
|
||||||
fields.fields().forEachRemaining(entry ->
|
|
||||||
properties.put(entry.getKey(), parseValue(entry.getValue()))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
config.setProperties(properties);
|
|
||||||
|
|
||||||
// 解析扩展字段
|
|
||||||
Map<String, String> extensions = new HashMap<>();
|
|
||||||
if (data.has("extensions")) {
|
|
||||||
data.path("extensions").fields()
|
|
||||||
.forEachRemaining(entry -> extensions.put(
|
|
||||||
entry.getKey(),
|
|
||||||
entry.getValue().asText()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
config.setExtensions(extensions);
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析JSON值
|
|
||||||
*/
|
|
||||||
private Object parseValue(JsonNode value) {
|
|
||||||
if (value.isTextual()) return value.asText();
|
|
||||||
if (value.isNumber()) return value.numberValue();
|
|
||||||
if (value.isBoolean()) return value.asBoolean();
|
|
||||||
if (value.isObject() || value.isArray()) return value.toString();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -24,7 +24,7 @@ public interface IWorkflowDefinitionService extends IBaseService<WorkflowDefinit
|
|||||||
* @param dto 工作流定义DTO
|
* @param dto 工作流定义DTO
|
||||||
* @return 工作流定义DTO
|
* @return 工作流定义DTO
|
||||||
*/
|
*/
|
||||||
WorkflowDefinitionDTO deployWorkflow(WorkflowDefinitionDTO dto);
|
void deployWorkflow(WorkflowDefinition workflowDefinition);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动工作流实例
|
* 启动工作流实例
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
|||||||
import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO;
|
import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO;
|
||||||
import com.qqchen.deploy.backend.workflow.dto.WorkflowExecutionDTO;
|
import com.qqchen.deploy.backend.workflow.dto.WorkflowExecutionDTO;
|
||||||
import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceCreateDTO;
|
import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceCreateDTO;
|
||||||
|
import com.qqchen.deploy.backend.workflow.dto.graph.WorkflowDefinitionGraph;
|
||||||
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
|
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
|
||||||
import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnums;
|
import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnums;
|
||||||
import com.qqchen.deploy.backend.workflow.enums.WorkflowStatusEnums;
|
import com.qqchen.deploy.backend.workflow.enums.WorkflowStatusEnums;
|
||||||
@ -13,6 +14,7 @@ import com.qqchen.deploy.backend.workflow.util.BpmnConverter;
|
|||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flowable.bpmn.model.SequenceFlow;
|
import org.flowable.bpmn.model.SequenceFlow;
|
||||||
|
import org.flowable.bpmn.model.StartEvent;
|
||||||
import org.flowable.engine.HistoryService;
|
import org.flowable.engine.HistoryService;
|
||||||
import org.flowable.engine.ManagementService;
|
import org.flowable.engine.ManagementService;
|
||||||
import org.flowable.engine.RepositoryService;
|
import org.flowable.engine.RepositoryService;
|
||||||
@ -69,64 +71,23 @@ public class WorkflowDefinitionServiceImpl extends BaseServiceImpl<WorkflowDefin
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public WorkflowDefinitionDTO saveWorkflowDesign(WorkflowDefinitionDTO dto) throws Exception {
|
public WorkflowDefinitionDTO saveWorkflowDesign(WorkflowDefinitionDTO dto) throws Exception {
|
||||||
// 转换图形JSON为BPMN XML
|
|
||||||
String bpmnXml = bpmnConverter.convertToXml(null, dto.getKey());
|
|
||||||
dto.setFlowVersion(1);
|
|
||||||
dto.setBpmnXml(bpmnXml);
|
|
||||||
// // 创建工作流定义
|
|
||||||
// WorkflowDefinition definition = new WorkflowDefinition();
|
|
||||||
// definition.setName(dto.getName());
|
|
||||||
// definition.setKey(dto.getKey());
|
|
||||||
// definition.setDescription(dto.getDescription());
|
|
||||||
// definition.setGraphJson(dto.getGraphJson());
|
|
||||||
// definition.setBpmnXml(bpmnXml);
|
|
||||||
// definition.setFlowVersion(1); // 设置初始版本为1
|
|
||||||
//
|
|
||||||
// // 保存工作流定义
|
|
||||||
WorkflowDefinition definition = super.converter.toEntity(dto);
|
WorkflowDefinition definition = super.converter.toEntity(dto);
|
||||||
workflowDefinitionRepository.save(definition);
|
workflowDefinitionRepository.save(definition);
|
||||||
//
|
|
||||||
// // 部署工作流
|
|
||||||
// WorkflowDefinitionDTO deployDto = new WorkflowDefinitionDTO();
|
|
||||||
// deployDto.setId(definition.getId());
|
|
||||||
// deployDto.setName(definition.getName());
|
|
||||||
// deployDto.setKey(definition.getKey());
|
|
||||||
// deployDto.setBpmnXml(definition.getBpmnXml());
|
|
||||||
// deployDto.setDescription(definition.getDescription());
|
|
||||||
//// workflowDefinitionService.deployWorkflow(deployDto);
|
|
||||||
//
|
|
||||||
// // 手动转换为 WorkflowDesignDTO
|
|
||||||
// WorkflowDesignDTO result = new WorkflowDesignDTO();
|
|
||||||
// result.setId(definition.getId());
|
|
||||||
// result.setName(definition.getName());
|
|
||||||
// result.setKey(definition.getKey());
|
|
||||||
// result.setDescription(definition.getDescription());
|
|
||||||
// result.setGraphJson(definition.getGraphJson());
|
|
||||||
return super.converter.toDto(definition);
|
return super.converter.toDto(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public WorkflowDefinitionDTO deployWorkflow(WorkflowDefinitionDTO dto) {
|
public void deployWorkflow(WorkflowDefinition workflowDefinition) {
|
||||||
try {
|
try {
|
||||||
// 部署流程
|
// 部署流程
|
||||||
Deployment deployment = repositoryService.createDeployment()
|
repositoryService.createDeployment()
|
||||||
.addString(dto.getName() + ".bpmn20.xml", dto.getBpmnXml())
|
.addString(workflowDefinition.getKey() + ".bpmn20.xml", workflowDefinition.getBpmnXml())
|
||||||
.name(dto.getName())
|
.name(workflowDefinition.getName())
|
||||||
.deploy();
|
.deploy();
|
||||||
|
log.info("Successfully deployed workflow: {}", workflowDefinition.getName());
|
||||||
log.info("Successfully deployed workflow: {}", dto.getName());
|
|
||||||
|
|
||||||
// 查找已存在的工作流定义
|
|
||||||
WorkflowDefinition definition = workflowDefinitionRepository.findById(dto.getId())
|
|
||||||
.orElseThrow(() -> new RuntimeException("Workflow definition not found: " + dto.getId()));
|
|
||||||
|
|
||||||
// 转换为DTO
|
|
||||||
dto.setFlowVersion(definition.getFlowVersion());
|
|
||||||
return dto;
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to deploy workflow: {}", dto.getName(), e);
|
log.error("Failed to deploy workflow: {}", workflowDefinition.getName(), e);
|
||||||
throw new RuntimeException("Failed to deploy workflow", e);
|
throw new RuntimeException("Failed to deploy workflow", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,6 +260,20 @@ public class WorkflowDefinitionServiceImpl extends BaseServiceImpl<WorkflowDefin
|
|||||||
stages.add(stage);
|
stages.add(stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 按开始时间排序
|
||||||
|
stages.sort((a, b) -> {
|
||||||
|
if (a.getStartTime() == null && b.getStartTime() == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (a.getStartTime() == null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (b.getStartTime() == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return a.getStartTime().compareTo(b.getStartTime());
|
||||||
|
});
|
||||||
|
|
||||||
executionDTO.setStages(stages);
|
executionDTO.setStages(stages);
|
||||||
return executionDTO;
|
return executionDTO;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -368,7 +343,11 @@ public class WorkflowDefinitionServiceImpl extends BaseServiceImpl<WorkflowDefin
|
|||||||
public void publishedWorkflowDesign(Long workflowDefinitionId) {
|
public void publishedWorkflowDesign(Long workflowDefinitionId) {
|
||||||
WorkflowDefinition definition = workflowDefinitionRepository.findById(workflowDefinitionId)
|
WorkflowDefinition definition = workflowDefinitionRepository.findById(workflowDefinitionId)
|
||||||
.orElseThrow(() -> new RuntimeException("Workflow definition not found: " + workflowDefinitionId));
|
.orElseThrow(() -> new RuntimeException("Workflow definition not found: " + workflowDefinitionId));
|
||||||
|
WorkflowDefinitionGraph graph = definition.getGraph();
|
||||||
|
definition.setBpmnXml(bpmnConverter.convertToXml(graph, definition.getKey()));
|
||||||
definition.setStatus(WorkflowStatusEnums.PUBLISHED);
|
definition.setStatus(WorkflowStatusEnums.PUBLISHED);
|
||||||
|
this.deployWorkflow(definition);
|
||||||
|
definition.setFlowVersion(1);
|
||||||
workflowDefinitionRepository.save(definition);
|
workflowDefinitionRepository.save(definition);
|
||||||
log.info("Successfully published workflow definition: {}", workflowDefinitionId);
|
log.info("Successfully published workflow definition: {}", workflowDefinitionId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,302 +1,163 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.util;
|
package com.qqchen.deploy.backend.workflow.util;
|
||||||
|
|
||||||
import com.qqchen.deploy.backend.workflow.dto.graph.*;
|
import com.qqchen.deploy.backend.workflow.dto.graph.*;
|
||||||
|
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnums;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.bpmn.BpmnAutoLayout;
|
||||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||||
import org.flowable.bpmn.model.*;
|
import org.flowable.bpmn.model.*;
|
||||||
import org.flowable.bpmn.model.Process;
|
import org.flowable.bpmn.model.Process;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BPMN 模型转换工具
|
* BPMN 模型转换工具
|
||||||
* @author cascade
|
* @author cascade
|
||||||
* @date 2024-12-11
|
* @date 2024-12-11
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class BpmnConverter {
|
public class BpmnConverter {
|
||||||
|
|
||||||
private final BpmnXMLConverter bpmnXmlConverter = new BpmnXMLConverter();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将工作流图转换为BPMN XML
|
* 将工作流定义图转换为Flowable XML
|
||||||
* @param graph 工作流图数据
|
*
|
||||||
* @param processKey 流程标识
|
* @param graph 工作流定义图
|
||||||
* @return BPMN XML字符串
|
* @param processKey 流程定义的唯一标识
|
||||||
|
* @return Flowable XML字符串
|
||||||
|
* @throws RuntimeException 当转换失败时抛出
|
||||||
*/
|
*/
|
||||||
public String convertToXml(WorkflowDefinitionGraph graph, String processKey) {
|
public String convertToXml(WorkflowDefinitionGraph graph, String processKey) {
|
||||||
BpmnModel bpmnModel = convertToBpmnModel(graph, processKey);
|
try {
|
||||||
byte[] xmlBytes = bpmnXmlConverter.convertToXML(bpmnModel);
|
log.debug("开始转换工作流定义为XML, processKey: {}", processKey);
|
||||||
return new String(xmlBytes, StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// 创建BPMN模型
|
||||||
* 将工作流图转换为BPMN模型
|
BpmnModel bpmnModel = new BpmnModel();
|
||||||
* @param graph 工作流图数据
|
Process process = new Process();
|
||||||
* @param processKey 流程标识
|
// 确保processKey符合NCName规则
|
||||||
* @return BPMN模型
|
String validProcessKey = processKey.replaceAll("[^a-zA-Z0-9-_.]", "_");
|
||||||
*/
|
process.setId(validProcessKey);
|
||||||
public BpmnModel convertToBpmnModel(WorkflowDefinitionGraph graph, String processKey) {
|
process.setName(processKey); // 保持原始processKey作为显示名称
|
||||||
BpmnModel bpmnModel = new BpmnModel();
|
process.setExecutable(true);
|
||||||
Process process = new Process();
|
bpmnModel.addProcess(process);
|
||||||
|
|
||||||
// 设置流程属性
|
// 创建节点ID到规范化ID的映射
|
||||||
process.setId(processKey);
|
Map<String, String> idMapping = new HashMap<>();
|
||||||
// if (graph.getProperties() != null) {
|
|
||||||
// Map<String, Object> properties = graph.getProperties();
|
|
||||||
// process.setName(properties.get("name") != null ? properties.get("name").toString() : null);
|
|
||||||
// process.setDocumentation(properties.get("description") != null ? properties.get("description").toString() : null);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 转换节点
|
// 转换节点
|
||||||
// for (WorkflowDefinitionNode node : graph.getNodes()) {
|
for (WorkflowDefinitionNode node : graph.getNodes()) {
|
||||||
// FlowElement element = convertNode(node);
|
log.debug("转换节点: {}, 类型: {}", node.getName(), node.getCode());
|
||||||
// if (element != null) {
|
|
||||||
// process.addFlowElement(element);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 转换边
|
|
||||||
// for (WorkflowDefinitionEdge edge : graph.getEdges()) {
|
|
||||||
// SequenceFlow flow = convertEdge(edge);
|
|
||||||
// if (flow != null) {
|
|
||||||
// process.addFlowElement(flow);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
bpmnModel.addProcess(process);
|
// 通过NodeTypeEnums获取对应的BpmnTypeEnums中定义的实例类型
|
||||||
return bpmnModel;
|
@SuppressWarnings("unchecked")
|
||||||
}
|
Class<? extends FlowElement> instanceClass = (Class<? extends FlowElement>) NodeTypeEnums.valueOf(node.getCode())
|
||||||
|
.getBpmnType()
|
||||||
|
.getInstance();
|
||||||
|
|
||||||
/**
|
// 创建节点实例
|
||||||
* 将工作流图转换为BPMN模型
|
FlowElement element = instanceClass.getDeclaredConstructor().newInstance();
|
||||||
* @param graph 工作流图数据
|
String validId = sanitizeId(node.getId());
|
||||||
* @return BPMN模型
|
idMapping.put(node.getId(), validId);
|
||||||
*/
|
element.setId(validId);
|
||||||
public BpmnModel convertToBpmnModel(WorkflowDefinitionGraph graph) {
|
element.setName(node.getName());
|
||||||
String processKey = null;
|
|
||||||
// if (graph.getProperties() != null) {
|
|
||||||
// Object key = graph.getProperties().get("key");
|
|
||||||
// processKey = key != null ? key.toString() : null;
|
|
||||||
// }
|
|
||||||
// if (processKey == null) {
|
|
||||||
// processKey = "process_" + System.currentTimeMillis();
|
|
||||||
// }
|
|
||||||
return convertToBpmnModel(graph, processKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// 设置节点特定属性
|
||||||
* 转换节点
|
configureFlowElement(element, node);
|
||||||
* @param node 工作流节点
|
|
||||||
* @return 流程元素
|
|
||||||
*/
|
|
||||||
private FlowElement convertNode(WorkflowDefinitionNode node) {
|
|
||||||
if (node.getType() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (node.getType()) {
|
process.addFlowElement(element);
|
||||||
case START_EVENT:
|
|
||||||
return createStartEvent(node);
|
|
||||||
case END_EVENT:
|
|
||||||
return createEndEvent(node);
|
|
||||||
// case SERVICE_TASK:
|
|
||||||
// return createServiceTask(node);
|
|
||||||
// case USER_TASK:
|
|
||||||
// return createUserTask(node);
|
|
||||||
// case SCRIPT_TASK:
|
|
||||||
// return createScriptTask(node);
|
|
||||||
// case EXCLUSIVE_GATEWAY:
|
|
||||||
// return createExclusiveGateway(node);
|
|
||||||
// case PARALLEL_GATEWAY:
|
|
||||||
// return createParallelGateway(node);
|
|
||||||
// case SUBPROCESS:
|
|
||||||
// return createSubProcess(node);
|
|
||||||
// case CALL_ACTIVITY:
|
|
||||||
// return createCallActivity(node);
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建开始事件
|
|
||||||
* @param node 节点数据
|
|
||||||
* @return 开始事件
|
|
||||||
*/
|
|
||||||
private StartEvent createStartEvent(WorkflowDefinitionNode node) {
|
|
||||||
StartEvent startEvent = new StartEvent();
|
|
||||||
startEvent.setId(node.getId());
|
|
||||||
startEvent.setName(node.getName());
|
|
||||||
return startEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建结束事件
|
|
||||||
* @param node 节点数据
|
|
||||||
* @return 结束事件
|
|
||||||
*/
|
|
||||||
private EndEvent createEndEvent(WorkflowDefinitionNode node) {
|
|
||||||
EndEvent endEvent = new EndEvent();
|
|
||||||
endEvent.setId(node.getId());
|
|
||||||
endEvent.setName(node.getName());
|
|
||||||
return endEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建服务任务
|
|
||||||
* @param node 节点数据
|
|
||||||
* @return 服务任务
|
|
||||||
*/
|
|
||||||
private ServiceTask createServiceTask(WorkflowDefinitionNode node) {
|
|
||||||
ServiceTask serviceTask = new ServiceTask();
|
|
||||||
serviceTask.setId(node.getId());
|
|
||||||
serviceTask.setName(node.getName());
|
|
||||||
|
|
||||||
if (node.getConfig() != null) {
|
|
||||||
// WorkflowDefinitionEdgeNodeConfig config = node.getConfig();
|
|
||||||
// serviceTask.setImplementation(config.getImplementation());
|
|
||||||
// if (config.getFields() != null) {
|
|
||||||
// config.getFields().forEach((key, value) -> {
|
|
||||||
// FieldExtension field = new FieldExtension();
|
|
||||||
// field.setFieldName(key);
|
|
||||||
// field.setStringValue(value != null ? value.toString() : null);
|
|
||||||
// serviceTask.getFieldExtensions().add(field);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
return serviceTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建用户任务
|
|
||||||
* @param node 节点数据
|
|
||||||
* @return 用户任务
|
|
||||||
*/
|
|
||||||
private UserTask createUserTask(WorkflowDefinitionNode node) {
|
|
||||||
UserTask userTask = new UserTask();
|
|
||||||
userTask.setId(node.getId());
|
|
||||||
userTask.setName(node.getName());
|
|
||||||
|
|
||||||
if (node.getConfig() != null) {
|
|
||||||
// NodeConfig config = node.getConfig();
|
|
||||||
// userTask.setAssignee(config.getAssignee());
|
|
||||||
// userTask.setCandidateUsers(config.getCandidateUsers());
|
|
||||||
// userTask.setCandidateGroups(config.getCandidateGroups());
|
|
||||||
// userTask.setDueDate(config.getDueDate());
|
|
||||||
// userTask.setPriority(config.getPriority() != null ? config.getPriority().toString() : null);
|
|
||||||
// userTask.setFormKey(config.getFormKey());
|
|
||||||
// userTask.setSkipExpression(config.getSkipExpression());
|
|
||||||
}
|
|
||||||
|
|
||||||
return userTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建脚本任务
|
|
||||||
* @param node 节点数据
|
|
||||||
* @return 脚本任务
|
|
||||||
*/
|
|
||||||
private ScriptTask createScriptTask(WorkflowDefinitionNode node) {
|
|
||||||
ScriptTask scriptTask = new ScriptTask();
|
|
||||||
scriptTask.setId(node.getId());
|
|
||||||
scriptTask.setName(node.getName());
|
|
||||||
|
|
||||||
if (node.getConfig() != null) {
|
|
||||||
// NodeConfig config = node.getConfig();
|
|
||||||
// scriptTask.setScriptFormat(config.getImplementation());
|
|
||||||
// if (config.getFields() != null && config.getFields().containsKey("script")) {
|
|
||||||
// scriptTask.setScript(config.getFields().get("script").toString());
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
return scriptTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建排他网关
|
|
||||||
* @param node 节点数据
|
|
||||||
* @return 排他网关
|
|
||||||
*/
|
|
||||||
private ExclusiveGateway createExclusiveGateway(WorkflowDefinitionNode node) {
|
|
||||||
ExclusiveGateway gateway = new ExclusiveGateway();
|
|
||||||
gateway.setId(node.getId());
|
|
||||||
gateway.setName(node.getName());
|
|
||||||
return gateway;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建并行网关
|
|
||||||
* @param node 节点数据
|
|
||||||
* @return 并行网关
|
|
||||||
*/
|
|
||||||
private ParallelGateway createParallelGateway(WorkflowDefinitionNode node) {
|
|
||||||
ParallelGateway gateway = new ParallelGateway();
|
|
||||||
gateway.setId(node.getId());
|
|
||||||
gateway.setName(node.getName());
|
|
||||||
return gateway;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建子流程
|
|
||||||
* @param node 节点数据
|
|
||||||
* @return 子流程
|
|
||||||
*/
|
|
||||||
private SubProcess createSubProcess(WorkflowDefinitionNode node) {
|
|
||||||
SubProcess subProcess = new SubProcess();
|
|
||||||
subProcess.setId(node.getId());
|
|
||||||
subProcess.setName(node.getName());
|
|
||||||
return subProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建调用活动
|
|
||||||
* @param node 节点数据
|
|
||||||
* @return 调用活动
|
|
||||||
*/
|
|
||||||
private CallActivity createCallActivity(WorkflowDefinitionNode node) {
|
|
||||||
CallActivity callActivity = new CallActivity();
|
|
||||||
callActivity.setId(node.getId());
|
|
||||||
callActivity.setName(node.getName());
|
|
||||||
|
|
||||||
if (node.getConfig() != null) {
|
|
||||||
// WorkflowDefinitionEdgeNodeConfig config = node.getConfig();
|
|
||||||
// callActivity.setCalledElement(config.getImplementation());
|
|
||||||
// if (config.getFields() != null) {
|
|
||||||
// config.getFields().forEach((key, value) -> {
|
|
||||||
// IOParameter parameter = new IOParameter();
|
|
||||||
// parameter.setSource(key);
|
|
||||||
// parameter.setTarget(value != null ? value.toString() : null);
|
|
||||||
// callActivity.getInParameters().add(parameter);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
return callActivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转换边
|
|
||||||
* @param edge 工作流边
|
|
||||||
* @return 序列流
|
|
||||||
*/
|
|
||||||
private SequenceFlow convertEdge(WorkflowDefinitionEdge edge) {
|
|
||||||
SequenceFlow flow = new SequenceFlow();
|
|
||||||
flow.setId(edge.getId());
|
|
||||||
flow.setName(edge.getName());
|
|
||||||
// flow.setSourceRef(edge.getSource());
|
|
||||||
// flow.setTargetRef(edge.getTarget());
|
|
||||||
|
|
||||||
if (edge.getConfig() != null) {
|
|
||||||
WorkflowDefinitionEdgeConfig config = edge.getConfig();
|
|
||||||
if ("sequence".equals(config.getType())) {
|
|
||||||
if (config.getCondition() != null) {
|
|
||||||
((SequenceFlow) flow).setConditionExpression(config.getCondition());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return flow;
|
// 转换连线
|
||||||
|
for (WorkflowDefinitionEdge edge : graph.getEdges()) {
|
||||||
|
log.debug("转换连线: from {} to {}", edge.getFrom(), edge.getTo());
|
||||||
|
|
||||||
|
SequenceFlow flow = new SequenceFlow();
|
||||||
|
flow.setId("flow_" + edge.getId().replaceAll("[^a-zA-Z0-9-_.]", "_"));
|
||||||
|
flow.setName(edge.getName());
|
||||||
|
flow.setSourceRef(idMapping.get(edge.getFrom()));
|
||||||
|
flow.setTargetRef(idMapping.get(edge.getTo()));
|
||||||
|
process.addFlowElement(flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动布局
|
||||||
|
new BpmnAutoLayout(bpmnModel).execute();
|
||||||
|
|
||||||
|
// 转换为XML
|
||||||
|
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||||
|
byte[] bytes = converter.convertToXML(bpmnModel);
|
||||||
|
String xml = new String(bytes, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
log.debug("工作流定义转换完成");
|
||||||
|
return xml;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("转换工作流定义为XML失败", e);
|
||||||
|
throw new RuntimeException("转换工作流定义为XML失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sanitizeId(String id) {
|
||||||
|
return "node_" + id.replaceAll("[^a-zA-Z0-9-_.]", "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置流程节点的特定属性
|
||||||
|
* @param element 流程节点元素
|
||||||
|
* @param node 工作流节点定义
|
||||||
|
*/
|
||||||
|
private void configureFlowElement(FlowElement element, WorkflowDefinitionNode node) {
|
||||||
|
if (element instanceof ServiceTask) {
|
||||||
|
ServiceTask serviceTask = (ServiceTask) element;
|
||||||
|
// 设置委托表达式
|
||||||
|
String delegate = (String) node.getConfig().get("delegate");
|
||||||
|
serviceTask.setImplementationType("delegateExpression");
|
||||||
|
serviceTask.setImplementation(delegate);
|
||||||
|
serviceTask.setAsynchronous(true); // 设置为异步执行
|
||||||
|
|
||||||
|
// 添加字段注入和扩展属性
|
||||||
|
List<FieldExtension> fieldExtensions = new ArrayList<>();
|
||||||
|
Map<String, List<ExtensionElement>> extensionElements = new HashMap<>();
|
||||||
|
|
||||||
|
// 遍历所有配置项
|
||||||
|
node.getConfig().forEach((key, value) -> {
|
||||||
|
if (value != null && !"delegate".equals(key)) {
|
||||||
|
// 添加为字段注入
|
||||||
|
FieldExtension fieldExtension = new FieldExtension();
|
||||||
|
fieldExtension.setFieldName(key);
|
||||||
|
fieldExtension.setStringValue(String.valueOf(value));
|
||||||
|
fieldExtensions.add(fieldExtension);
|
||||||
|
|
||||||
|
// 同时也添加为扩展属性(用于兼容性和可视化)
|
||||||
|
addExtensionElement(extensionElements, key, String.valueOf(value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
serviceTask.setFieldExtensions(fieldExtensions);
|
||||||
|
serviceTask.setExtensionElements(extensionElements);
|
||||||
|
}
|
||||||
|
// 后续可以添加其他类型的节点配置
|
||||||
|
// else if (element instanceof UserTask) { ... }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加扩展属性
|
||||||
|
*/
|
||||||
|
private void addExtensionElement(Map<String, List<ExtensionElement>> extensionElements, String name, String value) {
|
||||||
|
if (value != null && !value.trim().isEmpty()) {
|
||||||
|
ExtensionElement extensionElement = new ExtensionElement();
|
||||||
|
extensionElement.setName(name);
|
||||||
|
extensionElement.setNamespace("http://flowable.org/bpmn");
|
||||||
|
extensionElement.setNamespacePrefix("flowable");
|
||||||
|
|
||||||
|
// 直接设置文本值,让Flowable自己处理XML转义
|
||||||
|
extensionElement.setElementText(value);
|
||||||
|
|
||||||
|
extensionElements.computeIfAbsent(name, k -> new ArrayList<>()).add(extensionElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,232 +1,229 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.util;
|
//package com.qqchen.deploy.backend.workflow.util;
|
||||||
|
//
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
//import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
//import com.qqchen.deploy.backend.workflow.dto.graph.*;
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
//import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnums;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
//import lombok.Data;
|
||||||
import com.qqchen.deploy.backend.workflow.dto.graph.*;
|
//import lombok.extern.slf4j.Slf4j;
|
||||||
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnums;
|
//
|
||||||
import lombok.Data;
|
//import java.util.ArrayList;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
//import java.util.HashMap;
|
||||||
|
//import java.util.List;
|
||||||
import java.util.ArrayList;
|
//import java.util.Map;
|
||||||
import java.util.HashMap;
|
//
|
||||||
import java.util.List;
|
///**
|
||||||
import java.util.Map;
|
// * 工作流定义图形生成工具类
|
||||||
|
// * 用于生成示例工作流定义,包括:
|
||||||
/**
|
// * 1. 简单工作流:开始 -> 脚本任务 -> 结束
|
||||||
* 工作流定义图形生成工具类
|
// * 2. 复杂工作流:开始 -> 脚本任务A -> 脚本任务B -> 结束
|
||||||
* 用于生成示例工作流定义,包括:
|
// */
|
||||||
* 1. 简单工作流:开始 -> 脚本任务 -> 结束
|
//@Data
|
||||||
* 2. 复杂工作流:开始 -> 脚本任务A -> 脚本任务B -> 结束
|
//@Slf4j
|
||||||
*/
|
//public class WorkflowDefinitionGraph {
|
||||||
@Data
|
// private static final ObjectMapper mapper = new ObjectMapper();
|
||||||
@Slf4j
|
//
|
||||||
public class WorkflowDefinitionGraph {
|
// /**
|
||||||
private static final ObjectMapper mapper = new ObjectMapper();
|
// * 节点列表
|
||||||
|
// */
|
||||||
/**
|
// private List<WorkflowDefinitionNode> nodes;
|
||||||
* 节点列表
|
//
|
||||||
*/
|
// /**
|
||||||
private List<WorkflowDefinitionNode> nodes;
|
// * 边列表
|
||||||
|
// */
|
||||||
/**
|
// private List<WorkflowDefinitionEdge> edges;
|
||||||
* 边列表
|
//
|
||||||
*/
|
// /**
|
||||||
private List<WorkflowDefinitionEdge> edges;
|
// * 生成简单工作流
|
||||||
|
// * 开始 -> 脚本任务 -> 结束
|
||||||
/**
|
// */
|
||||||
* 生成简单工作流
|
// public static WorkflowDefinitionGraph generateSimpleWorkflow() {
|
||||||
* 开始 -> 脚本任务 -> 结束
|
// WorkflowDefinitionGraph graph = new WorkflowDefinitionGraph();
|
||||||
*/
|
// List<WorkflowDefinitionNode> nodes = new ArrayList<>();
|
||||||
public static WorkflowDefinitionGraph generateSimpleWorkflow() {
|
// List<WorkflowDefinitionEdge> edges = new ArrayList<>();
|
||||||
WorkflowDefinitionGraph graph = new WorkflowDefinitionGraph();
|
//
|
||||||
List<WorkflowDefinitionNode> nodes = new ArrayList<>();
|
// // 开始节点
|
||||||
List<WorkflowDefinitionEdge> edges = new ArrayList<>();
|
// WorkflowDefinitionNode startNode = createNode(
|
||||||
|
// "startEvent1",
|
||||||
// 开始节点
|
// NodeTypeEnums.START_EVENT,
|
||||||
WorkflowDefinitionNode startNode = createNode(
|
// "开始",
|
||||||
"startEvent1",
|
// 100, 100,
|
||||||
NodeTypeEnums.START_EVENT,
|
// createNodeConfig("开始节点", "启动流程")
|
||||||
"开始",
|
// );
|
||||||
100, 100,
|
// nodes.add(startNode);
|
||||||
createNodeConfig("开始节点", "启动流程")
|
//
|
||||||
);
|
// // 脚本任务节点
|
||||||
nodes.add(startNode);
|
// Map<String, Object> scriptConfig = createNodeConfig("脚本任务", "执行一个简单的Shell脚本");
|
||||||
|
// scriptConfig.put("script", "echo 'Hello World'");
|
||||||
// 脚本任务节点
|
// scriptConfig.put("language", "shell");
|
||||||
Map<String, Object> scriptConfig = createNodeConfig("脚本任务", "执行一个简单的Shell脚本");
|
//
|
||||||
scriptConfig.put("script", "echo 'Hello World'");
|
// WorkflowDefinitionNode scriptNode = createNode(
|
||||||
scriptConfig.put("language", "shell");
|
// "scriptTask1",
|
||||||
|
// NodeTypeEnums.SCRIPT_TASK,
|
||||||
WorkflowDefinitionNode scriptNode = createNode(
|
// "执行脚本",
|
||||||
"scriptTask1",
|
// 300, 100,
|
||||||
NodeTypeEnums.SCRIPT_TASK,
|
// scriptConfig
|
||||||
"执行脚本",
|
// );
|
||||||
300, 100,
|
// nodes.add(scriptNode);
|
||||||
scriptConfig
|
//
|
||||||
);
|
// // 结束节点
|
||||||
nodes.add(scriptNode);
|
// WorkflowDefinitionNode endNode = createNode(
|
||||||
|
// "endEvent1",
|
||||||
// 结束节点
|
// NodeTypeEnums.END_EVENT,
|
||||||
WorkflowDefinitionNode endNode = createNode(
|
// "结束",
|
||||||
"endEvent1",
|
// 500, 100,
|
||||||
NodeTypeEnums.END_EVENT,
|
// createNodeConfig("结束节点", "流程结束")
|
||||||
"结束",
|
// );
|
||||||
500, 100,
|
// nodes.add(endNode);
|
||||||
createNodeConfig("结束节点", "流程结束")
|
//
|
||||||
);
|
// // 添加连线
|
||||||
nodes.add(endNode);
|
// edges.add(createEdge("flow1", "startEvent1", "scriptTask1", "开始到脚本"));
|
||||||
|
// edges.add(createEdge("flow2", "scriptTask1", "endEvent1", "脚本到结束"));
|
||||||
// 添加连线
|
//
|
||||||
edges.add(createEdge("flow1", "startEvent1", "scriptTask1", "开始到脚本"));
|
// graph.setNodes(nodes);
|
||||||
edges.add(createEdge("flow2", "scriptTask1", "endEvent1", "脚本到结束"));
|
// graph.setEdges(edges);
|
||||||
|
// return graph;
|
||||||
graph.setNodes(nodes);
|
// }
|
||||||
graph.setEdges(edges);
|
//
|
||||||
return graph;
|
// /**
|
||||||
}
|
// * 生成复杂工作流
|
||||||
|
// * 开始 -> 脚本任务A -> 脚本任务B -> 结束
|
||||||
/**
|
// */
|
||||||
* 生成复杂工作流
|
// public static WorkflowDefinitionGraph generateComplexWorkflow() {
|
||||||
* 开始 -> 脚本任务A -> 脚本任务B -> 结束
|
// WorkflowDefinitionGraph graph = new WorkflowDefinitionGraph();
|
||||||
*/
|
// List<WorkflowDefinitionNode> nodes = new ArrayList<>();
|
||||||
public static WorkflowDefinitionGraph generateComplexWorkflow() {
|
// List<WorkflowDefinitionEdge> edges = new ArrayList<>();
|
||||||
WorkflowDefinitionGraph graph = new WorkflowDefinitionGraph();
|
//
|
||||||
List<WorkflowDefinitionNode> nodes = new ArrayList<>();
|
// // 开始节点
|
||||||
List<WorkflowDefinitionEdge> edges = new ArrayList<>();
|
// WorkflowDefinitionNode startNode = createNode(
|
||||||
|
// "startEvent1",
|
||||||
// 开始节点
|
// NodeTypeEnums.START_EVENT,
|
||||||
WorkflowDefinitionNode startNode = createNode(
|
// "开始",
|
||||||
"startEvent1",
|
// 100, 100,
|
||||||
NodeTypeEnums.START_EVENT,
|
// createNodeConfig("开始节点", "启动流程")
|
||||||
"开始",
|
// );
|
||||||
100, 100,
|
// nodes.add(startNode);
|
||||||
createNodeConfig("开始节点", "启动流程")
|
//
|
||||||
);
|
// // 脚本任务A
|
||||||
nodes.add(startNode);
|
// Map<String, Object> scriptConfigA = createNodeConfig("脚本任务A", "数据处理");
|
||||||
|
// scriptConfigA.put("script", "process_data.sh");
|
||||||
// 脚本任务A
|
// scriptConfigA.put("language", "shell");
|
||||||
Map<String, Object> scriptConfigA = createNodeConfig("脚本任务A", "数据处理");
|
//
|
||||||
scriptConfigA.put("script", "process_data.sh");
|
// WorkflowDefinitionNode scriptNodeA = createNode(
|
||||||
scriptConfigA.put("language", "shell");
|
// "scriptTask1",
|
||||||
|
// NodeTypeEnums.SCRIPT_TASK,
|
||||||
WorkflowDefinitionNode scriptNodeA = createNode(
|
// "数据处理",
|
||||||
"scriptTask1",
|
// 300, 100,
|
||||||
NodeTypeEnums.SCRIPT_TASK,
|
// scriptConfigA
|
||||||
"数据处理",
|
// );
|
||||||
300, 100,
|
// nodes.add(scriptNodeA);
|
||||||
scriptConfigA
|
//
|
||||||
);
|
// // 脚本任务B
|
||||||
nodes.add(scriptNodeA);
|
// Map<String, Object> scriptConfigB = createNodeConfig("脚本任务B", "生成报告");
|
||||||
|
// scriptConfigB.put("script", "generate_report.sh");
|
||||||
// 脚本任务B
|
// scriptConfigB.put("language", "shell");
|
||||||
Map<String, Object> scriptConfigB = createNodeConfig("脚本任务B", "生成报告");
|
//
|
||||||
scriptConfigB.put("script", "generate_report.sh");
|
// WorkflowDefinitionNode scriptNodeB = createNode(
|
||||||
scriptConfigB.put("language", "shell");
|
// "scriptTask2",
|
||||||
|
// NodeTypeEnums.SCRIPT_TASK,
|
||||||
WorkflowDefinitionNode scriptNodeB = createNode(
|
// "生成报告",
|
||||||
"scriptTask2",
|
// 500, 100,
|
||||||
NodeTypeEnums.SCRIPT_TASK,
|
// scriptConfigB
|
||||||
"生成报告",
|
// );
|
||||||
500, 100,
|
// nodes.add(scriptNodeB);
|
||||||
scriptConfigB
|
//
|
||||||
);
|
// // 结束节点
|
||||||
nodes.add(scriptNodeB);
|
// WorkflowDefinitionNode endNode = createNode(
|
||||||
|
// "endEvent1",
|
||||||
// 结束节点
|
// NodeTypeEnums.END_EVENT,
|
||||||
WorkflowDefinitionNode endNode = createNode(
|
// "结束",
|
||||||
"endEvent1",
|
// 700, 100,
|
||||||
NodeTypeEnums.END_EVENT,
|
// createNodeConfig("结束节点", "流程结束")
|
||||||
"结束",
|
// );
|
||||||
700, 100,
|
// nodes.add(endNode);
|
||||||
createNodeConfig("结束节点", "流程结束")
|
//
|
||||||
);
|
// // 添加连线
|
||||||
nodes.add(endNode);
|
// edges.add(createEdge("flow1", "startEvent1", "scriptTask1", "开始到处理"));
|
||||||
|
// edges.add(createEdge("flow2", "scriptTask1", "scriptTask2", "处理到报告"));
|
||||||
// 添加连线
|
// edges.add(createEdge("flow3", "scriptTask2", "endEvent1", "报告到结束"));
|
||||||
edges.add(createEdge("flow1", "startEvent1", "scriptTask1", "开始到处理"));
|
//
|
||||||
edges.add(createEdge("flow2", "scriptTask1", "scriptTask2", "处理到报告"));
|
// graph.setNodes(nodes);
|
||||||
edges.add(createEdge("flow3", "scriptTask2", "endEvent1", "报告到结束"));
|
// graph.setEdges(edges);
|
||||||
|
// return graph;
|
||||||
graph.setNodes(nodes);
|
// }
|
||||||
graph.setEdges(edges);
|
//
|
||||||
return graph;
|
// /**
|
||||||
}
|
// * 创建节点
|
||||||
|
// */
|
||||||
/**
|
// private static WorkflowDefinitionNode createNode(String id, NodeTypeEnums type, String name, int x, int y, Map<String, Object> config) {
|
||||||
* 创建节点
|
// WorkflowDefinitionNode node = new WorkflowDefinitionNode();
|
||||||
*/
|
// node.setId(id);
|
||||||
private static WorkflowDefinitionNode createNode(String id, NodeTypeEnums type, String name, int x, int y, Map<String, Object> config) {
|
// node.setCode(type.getCode());
|
||||||
WorkflowDefinitionNode node = new WorkflowDefinitionNode();
|
// node.setType(type);
|
||||||
node.setId(id);
|
// node.setName(name);
|
||||||
node.setCode(type.getCode());
|
// node.setConfig(config);
|
||||||
node.setType(type);
|
//
|
||||||
node.setName(name);
|
// // 从枚举的uiConfig中获取配置并创建新的图形配置
|
||||||
node.setConfig(config);
|
// WorkflowNodeGraph originalConfig = type.getUiConfig();
|
||||||
|
// WorkflowNodeGraph nodeGraph = new WorkflowNodeGraph()
|
||||||
// 从枚举的uiConfig中获取配置并创建新的图形配置
|
// .setShape(originalConfig.getShape())
|
||||||
WorkflowNodeGraph originalConfig = type.getUiConfig();
|
// .setSize(originalConfig.getSize().getWidth(), originalConfig.getSize().getHeight())
|
||||||
WorkflowNodeGraph nodeGraph = new WorkflowNodeGraph()
|
// .setStyle(originalConfig.getStyle().getFill(),
|
||||||
.setShape(originalConfig.getShape())
|
// originalConfig.getStyle().getStroke(),
|
||||||
.setSize(originalConfig.getSize().getWidth(), originalConfig.getSize().getHeight())
|
// originalConfig.getStyle().getIcon())
|
||||||
.setStyle(originalConfig.getStyle().getFill(),
|
// .configPorts(originalConfig.getPorts().getTypes())
|
||||||
originalConfig.getStyle().getStroke(),
|
// .setPosition(x, y);
|
||||||
originalConfig.getStyle().getIcon())
|
//
|
||||||
.configPorts(originalConfig.getPorts().getTypes())
|
// node.setGraph(nodeGraph);
|
||||||
.setPosition(x, y);
|
// return node;
|
||||||
|
// }
|
||||||
node.setGraph(nodeGraph);
|
//
|
||||||
return node;
|
// /**
|
||||||
}
|
// * 创建节点配置
|
||||||
|
// */
|
||||||
/**
|
// private static Map<String, Object> createNodeConfig(String name, String description) {
|
||||||
* 创建节点配置
|
// Map<String, Object> config = new HashMap<>();
|
||||||
*/
|
// config.put("name", name);
|
||||||
private static Map<String, Object> createNodeConfig(String name, String description) {
|
// config.put("description", description);
|
||||||
Map<String, Object> config = new HashMap<>();
|
// return config;
|
||||||
config.put("name", name);
|
// }
|
||||||
config.put("description", description);
|
//
|
||||||
return config;
|
// /**
|
||||||
}
|
// * 创建连线
|
||||||
|
// */
|
||||||
/**
|
// private static WorkflowDefinitionEdge createEdge(String id, String from, String to, String name) {
|
||||||
* 创建连线
|
// return createEdge(id, from, to, name, null);
|
||||||
*/
|
// }
|
||||||
private static WorkflowDefinitionEdge createEdge(String id, String from, String to, String name) {
|
//
|
||||||
return createEdge(id, from, to, name, null);
|
// /**
|
||||||
}
|
// * 创建带条件的连线
|
||||||
|
// */
|
||||||
/**
|
// private static WorkflowDefinitionEdge createEdge(String id, String from, String to, String name, String condition) {
|
||||||
* 创建带条件的连线
|
// WorkflowDefinitionEdge edge = new WorkflowDefinitionEdge();
|
||||||
*/
|
// edge.setId(id);
|
||||||
private static WorkflowDefinitionEdge createEdge(String id, String from, String to, String name, String condition) {
|
// edge.setFrom(from);
|
||||||
WorkflowDefinitionEdge edge = new WorkflowDefinitionEdge();
|
// edge.setTo(to);
|
||||||
edge.setId(id);
|
// edge.setName(name);
|
||||||
edge.setFrom(from);
|
//
|
||||||
edge.setTo(to);
|
// // 设置边配置
|
||||||
edge.setName(name);
|
// WorkflowDefinitionEdgeConfig config = new WorkflowDefinitionEdgeConfig();
|
||||||
|
// config.setType("sequence");
|
||||||
// 设置边配置
|
// if (condition != null) {
|
||||||
WorkflowDefinitionEdgeConfig config = new WorkflowDefinitionEdgeConfig();
|
// config.setCondition(condition);
|
||||||
config.setType("sequence");
|
// config.setConditionExpression(condition);
|
||||||
if (condition != null) {
|
// }
|
||||||
config.setCondition(condition);
|
// edge.setConfig(config);
|
||||||
config.setConditionExpression(condition);
|
//
|
||||||
}
|
// return edge;
|
||||||
edge.setConfig(config);
|
// }
|
||||||
|
//
|
||||||
return edge;
|
// public static void main(String[] args) {
|
||||||
}
|
// try {
|
||||||
|
// System.out.println("=== 简单工作流 ===");
|
||||||
public static void main(String[] args) {
|
// System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(generateSimpleWorkflow()));
|
||||||
try {
|
// System.out.println("\n=== 复杂工作流 ===");
|
||||||
System.out.println("=== 简单工作流 ===");
|
// System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(generateComplexWorkflow()));
|
||||||
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(generateSimpleWorkflow()));
|
// } catch (Exception e) {
|
||||||
System.out.println("\n=== 复杂工作流 ===");
|
// log.error("生成工作流定义失败", e);
|
||||||
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(generateComplexWorkflow()));
|
// }
|
||||||
} catch (Exception e) {
|
// }
|
||||||
log.error("生成工作流定义失败", e);
|
//}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user