添加通知管理功能
This commit is contained in:
parent
3140456ee0
commit
9c8065dd53
@ -1,6 +1,7 @@
|
|||||||
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.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants;
|
import com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants;
|
||||||
import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraphEdge;
|
import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraphEdge;
|
||||||
import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraph;
|
import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraph;
|
||||||
@ -31,6 +32,8 @@ import java.util.Map;
|
|||||||
@Component
|
@Component
|
||||||
public class BpmnConverter {
|
public class BpmnConverter {
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将工作流定义图转换为Flowable XML
|
* 将工作流定义图转换为Flowable XML
|
||||||
*
|
*
|
||||||
@ -144,8 +147,8 @@ public class BpmnConverter {
|
|||||||
element.setName(node.getNodeName());
|
element.setName(node.getNodeName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 步骤2.5:配置节点的特定属性
|
// 步骤2.5:配置节点的特定属性(传递原始节点ID和sanitized ID)
|
||||||
configureFlowElement(element, node, process);
|
configureFlowElement(element, node, process, validId);
|
||||||
|
|
||||||
// 步骤2.6:将节点添加到流程中
|
// 步骤2.6:将节点添加到流程中
|
||||||
process.addFlowElement(element);
|
process.addFlowElement(element);
|
||||||
@ -155,8 +158,15 @@ public class BpmnConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接使用前端生成的节点 ID
|
||||||
|
* 前端已经生成了符合 NCName 规范的 ID(如 sid_265bc83e_9e7f_4acf_bd25_cf04c868a5da)
|
||||||
|
*
|
||||||
|
* @param id 前端生成的节点 ID
|
||||||
|
* @return 节点 ID(直接返回)
|
||||||
|
*/
|
||||||
private String sanitizeId(String id) {
|
private String sanitizeId(String id) {
|
||||||
return "NODE_" + id.replaceAll("[^a-zA-Z0-9-_.]", "_");
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,14 +175,15 @@ public class BpmnConverter {
|
|||||||
* @param element 流程节点元素
|
* @param element 流程节点元素
|
||||||
* @param node 工作流节点定义
|
* @param node 工作流节点定义
|
||||||
* @param process 当前流程
|
* @param process 当前流程
|
||||||
|
* @param validId sanitized 后的节点 ID
|
||||||
*/
|
*/
|
||||||
private void configureFlowElement(FlowElement element, WorkflowDefinitionGraphNode node, Process process) {
|
private void configureFlowElement(FlowElement element, WorkflowDefinitionGraphNode node, Process process, String validId) {
|
||||||
// 步骤1:配置执行监听器
|
// 步骤1:配置执行监听器
|
||||||
Map<String, List<ExtensionElement>> extensionElements = configureExecutionListeners(element);
|
Map<String, List<ExtensionElement>> extensionElements = configureExecutionListeners(element);
|
||||||
|
|
||||||
// 步骤2:根据节点类型进行特定配置
|
// 步骤2:根据节点类型进行特定配置
|
||||||
if (element instanceof ServiceTask) {
|
if (element instanceof ServiceTask) {
|
||||||
configureServiceTask((ServiceTask) element, node, process, extensionElements);
|
configureServiceTask((ServiceTask) element, node, process, extensionElements, validId);
|
||||||
} else {
|
} else {
|
||||||
element.setExtensionElements(extensionElements);
|
element.setExtensionElements(extensionElements);
|
||||||
}
|
}
|
||||||
@ -229,20 +240,50 @@ public class BpmnConverter {
|
|||||||
* @param node 工作流节点定义
|
* @param node 工作流节点定义
|
||||||
* @param process 当前流程
|
* @param process 当前流程
|
||||||
* @param extensionElements 扩展元素
|
* @param extensionElements 扩展元素
|
||||||
|
* @param validId sanitized 后的节点 ID
|
||||||
*/
|
*/
|
||||||
private void configureServiceTask(ServiceTask serviceTask, WorkflowDefinitionGraphNode node, Process process, Map<String, List<ExtensionElement>> extensionElements) {
|
private void configureServiceTask(ServiceTask serviceTask, WorkflowDefinitionGraphNode node, Process process, Map<String, List<ExtensionElement>> extensionElements, String validId) {
|
||||||
// if (node.getPanelVariables() != null && node.getPanelVariables().has("delegate")) {
|
// ✅ 设置 delegateExpression(根据节点类型映射)
|
||||||
// String delegate = node.getPanelVariables().get("delegate").asText();
|
String delegateExpression = getDelegateExpression(node.getNodeCode());
|
||||||
// serviceTask.setImplementationType("delegateExpression");
|
if (delegateExpression != null && !delegateExpression.isEmpty()) {
|
||||||
// serviceTask.setImplementation(delegate);
|
serviceTask.setImplementationType("delegateExpression");
|
||||||
// }
|
serviceTask.setImplementation(delegateExpression);
|
||||||
|
}
|
||||||
|
|
||||||
addExecutionVariables(extensionElements, node);
|
// ✅ 添加 field 字段(nodeId, configs, inputMapping)
|
||||||
|
addExecutionVariables(extensionElements, node, validId);
|
||||||
|
|
||||||
|
// ✅ 添加重试策略
|
||||||
addRetryStrategy(extensionElements);
|
addRetryStrategy(extensionElements);
|
||||||
|
|
||||||
serviceTask.setExtensionElements(extensionElements);
|
serviceTask.setExtensionElements(extensionElements);
|
||||||
addErrorBoundaryEventHandler(process, serviceTask);
|
addErrorBoundaryEventHandler(process, serviceTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据节点类型获取对应的 delegateExpression
|
||||||
|
*
|
||||||
|
* @param nodeCode 节点类型编码
|
||||||
|
* @return delegateExpression 字符串
|
||||||
|
*/
|
||||||
|
private String getDelegateExpression(String nodeCode) {
|
||||||
|
switch (nodeCode) {
|
||||||
|
case "JENKINS_BUILD":
|
||||||
|
return "${jenkinsBuildDelegate}";
|
||||||
|
case "NOTIFICATION":
|
||||||
|
return "${notificationDelegate}";
|
||||||
|
case "SCRIPT_NODE":
|
||||||
|
return "${shellDelegate}";
|
||||||
|
case "APPROVAL_NODE":
|
||||||
|
return "${approvalDelegate}";
|
||||||
|
case "DEPLOY_NODE":
|
||||||
|
return "${deployDelegate}";
|
||||||
|
default:
|
||||||
|
log.warn("未知的节点类型: {}, 将不设置 delegateExpression", nodeCode);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建扩展属性
|
* 创建扩展属性
|
||||||
*
|
*
|
||||||
@ -258,65 +299,67 @@ public class BpmnConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加执行实例级变量
|
* 添加执行实例级变量(field 字段)
|
||||||
*
|
*
|
||||||
* @param extensionElements 扩展元素
|
* @param extensionElements 扩展元素
|
||||||
* @param node 工作流节点定义
|
* @param node 工作流节点定义
|
||||||
|
* @param validId sanitized 后的节点 ID
|
||||||
*/
|
*/
|
||||||
private void addExecutionVariables(Map<String, List<ExtensionElement>> extensionElements, WorkflowDefinitionGraphNode node) {
|
private void addExecutionVariables(Map<String, List<ExtensionElement>> extensionElements, WorkflowDefinitionGraphNode node, String validId) {
|
||||||
// 添加panelVariables变量
|
try {
|
||||||
// if (node.getPanelVariables() != null) {
|
// ✅ 1. 添加 nodeId field
|
||||||
// ExtensionElement fieldElement = new ExtensionElement();
|
extensionElements.computeIfAbsent("field", k -> new ArrayList<>())
|
||||||
// fieldElement.setName("field");
|
.add(createFieldElement("nodeId", validId));
|
||||||
// fieldElement.setNamespace("http://flowable.org/bpmn");
|
|
||||||
// fieldElement.setNamespacePrefix("flowable");
|
|
||||||
//
|
|
||||||
// // 创建field的子元素string
|
|
||||||
// ExtensionElement stringElement = new ExtensionElement();
|
|
||||||
// stringElement.setName("string");
|
|
||||||
// stringElement.setNamespace("http://flowable.org/bpmn");
|
|
||||||
// stringElement.setNamespacePrefix("flowable");
|
|
||||||
// // 直接设置JSON内容,不使用CDATA
|
|
||||||
// stringElement.setElementText(node.getPanelVariables().toString());
|
|
||||||
//
|
|
||||||
// // 设置field的name属性
|
|
||||||
// Map<String, List<ExtensionAttribute>> fieldAttributes = new HashMap<>();
|
|
||||||
// fieldAttributes.put("name", Collections.singletonList(createAttribute("name", "panelVariables")));
|
|
||||||
// fieldElement.setAttributes(fieldAttributes);
|
|
||||||
//
|
|
||||||
// // 添加string子元素到field
|
|
||||||
// fieldElement.addChildElement(stringElement);
|
|
||||||
//
|
|
||||||
// // 添加field到extensionElements
|
|
||||||
// extensionElements.computeIfAbsent("field", k -> new ArrayList<>()).add(fieldElement);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 添加localVariables变量
|
// ✅ 2. 添加 configs field
|
||||||
// if (node.getLocalVariables() != null) {
|
if (node.getConfigs() != null) {
|
||||||
// ExtensionElement fieldElement = new ExtensionElement();
|
String configsJson = objectMapper.writeValueAsString(node.getConfigs());
|
||||||
// fieldElement.setName("field");
|
extensionElements.computeIfAbsent("field", k -> new ArrayList<>())
|
||||||
// fieldElement.setNamespace("http://flowable.org/bpmn");
|
.add(createFieldElement("configs", configsJson));
|
||||||
// fieldElement.setNamespacePrefix("flowable");
|
}
|
||||||
//
|
|
||||||
// // 创建field的子元素string
|
// ✅ 3. 添加 inputMapping field
|
||||||
// ExtensionElement stringElement = new ExtensionElement();
|
if (node.getInputMapping() != null) {
|
||||||
// stringElement.setName("string");
|
String inputMappingJson = objectMapper.writeValueAsString(node.getInputMapping());
|
||||||
// stringElement.setNamespace("http://flowable.org/bpmn");
|
extensionElements.computeIfAbsent("field", k -> new ArrayList<>())
|
||||||
// stringElement.setNamespacePrefix("flowable");
|
.add(createFieldElement("inputMapping", inputMappingJson));
|
||||||
// // 直接设置JSON内容,不使用CDATA
|
}
|
||||||
// stringElement.setElementText(node.getLocalVariables().toString());
|
} catch (Exception e) {
|
||||||
//
|
log.error("添加执行变量失败: {}", node.getNodeName(), e);
|
||||||
// // 设置field的name属性
|
throw new RuntimeException("添加执行变量失败: " + e.getMessage(), e);
|
||||||
// Map<String, List<ExtensionAttribute>> fieldAttributes = new HashMap<>();
|
}
|
||||||
// fieldAttributes.put("name", Collections.singletonList(createAttribute("name", "localVariables")));
|
}
|
||||||
// fieldElement.setAttributes(fieldAttributes);
|
|
||||||
//
|
/**
|
||||||
// // 添加string子元素到field
|
* 创建 field 扩展元素
|
||||||
// fieldElement.addChildElement(stringElement);
|
*
|
||||||
//
|
* @param fieldName 字段名
|
||||||
// // 添加field到extensionElements
|
* @param fieldValue 字段值
|
||||||
// extensionElements.computeIfAbsent("field", k -> new ArrayList<>()).add(fieldElement);
|
* @return field 扩展元素
|
||||||
// }
|
*/
|
||||||
|
private ExtensionElement createFieldElement(String fieldName, String fieldValue) {
|
||||||
|
// 创建 field 元素
|
||||||
|
ExtensionElement fieldElement = new ExtensionElement();
|
||||||
|
fieldElement.setName("field");
|
||||||
|
fieldElement.setNamespace("http://flowable.org/bpmn");
|
||||||
|
fieldElement.setNamespacePrefix("flowable");
|
||||||
|
|
||||||
|
// 设置 field 的 name 属性
|
||||||
|
Map<String, List<ExtensionAttribute>> fieldAttributes = new HashMap<>();
|
||||||
|
fieldAttributes.put("name", Collections.singletonList(createAttribute("name", fieldName)));
|
||||||
|
fieldElement.setAttributes(fieldAttributes);
|
||||||
|
|
||||||
|
// 创建 string 子元素
|
||||||
|
ExtensionElement stringElement = new ExtensionElement();
|
||||||
|
stringElement.setName("string");
|
||||||
|
stringElement.setNamespace("http://flowable.org/bpmn");
|
||||||
|
stringElement.setNamespacePrefix("flowable");
|
||||||
|
stringElement.setElementText(fieldValue);
|
||||||
|
|
||||||
|
// 添加 string 子元素到 field
|
||||||
|
fieldElement.addChildElement(stringElement);
|
||||||
|
|
||||||
|
return fieldElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -494,8 +537,8 @@ public class BpmnConverter {
|
|||||||
log.debug("转换连线: from {} to {}", edge.getFrom(), edge.getTo());
|
log.debug("转换连线: from {} to {}", edge.getFrom(), edge.getTo());
|
||||||
|
|
||||||
SequenceFlow flow = new SequenceFlow();
|
SequenceFlow flow = new SequenceFlow();
|
||||||
String flowId = "FLOW_" + edge.getId().replaceAll("[^a-zA-Z0-9-_.]", "_");
|
// ✅ 直接使用前端生成的 edge ID(前端已经生成了 eid_ 开头的 ID)
|
||||||
flow.setId(flowId);
|
flow.setId(edge.getId());
|
||||||
flow.setName(edge.getName());
|
flow.setName(edge.getName());
|
||||||
flow.setSourceRef(idMapping.get(edge.getFrom()));
|
flow.setSourceRef(idMapping.get(edge.getFrom()));
|
||||||
flow.setTargetRef(idMapping.get(edge.getTo()));
|
flow.setTargetRef(idMapping.get(edge.getTo()));
|
||||||
@ -508,13 +551,6 @@ public class BpmnConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// // 添加 take 事件监听器
|
|
||||||
// Map<String, List<ExtensionElement>> extensionElements = new HashMap<>();
|
|
||||||
// List<ExtensionElement> executionListeners = new ArrayList<>();
|
|
||||||
// executionListeners.add(createExecutionListener("take", "${sequenceFlowTakeListener}"));
|
|
||||||
// extensionElements.put("executionListener", executionListeners);
|
|
||||||
// flow.setExtensionElements(extensionElements);
|
|
||||||
|
|
||||||
process.addFlowElement(flow);
|
process.addFlowElement(flow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user