添加通知管理功能

This commit is contained in:
dengqichen 2025-10-22 20:25:30 +08:00
parent 3140456ee0
commit 9c8065dd53

View File

@ -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);
} }
} }