yxk-20260520-流程bug修复:发布新版本流程的时候,内嵌子流程的流程配置会被删除
This commit is contained in:
+100
-15
@@ -7,6 +7,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StreamUtils;
|
||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.bpmn.model.FlowElementsContainer;
|
||||
import org.flowable.bpmn.model.Task;
|
||||
import org.flowable.common.engine.api.FlowableException;
|
||||
import org.flowable.engine.IdentityService;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
@@ -51,6 +56,11 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.util.*;
|
||||
@@ -183,6 +193,11 @@ public class ExtActProcessServiceImpl extends ServiceImpl<ExtActProcessMapper, E
|
||||
processnodeDeployment.setNodeConfigJson(node.getNodeConfigJson());
|
||||
processnodeDeployment.setDeploymentId(deployment.getId());
|
||||
processnodeDeployment.setFormId(node.getFormId());
|
||||
// 发布版本快照必须带上开关字段,否则运行时会回退到默认配置。
|
||||
processnodeDeployment.setFormEditStatus(node.getFormEditStatus());
|
||||
processnodeDeployment.setCcStatus(node.getCcStatus());
|
||||
processnodeDeployment.setSelnextUserStatus(node.getSelnextUserStatus());
|
||||
processnodeDeployment.setMsgStatus(node.getMsgStatus());
|
||||
processnodeDeployment.setModelAndView(node.getModelAndView());
|
||||
processnodeDeployment.setModelAndViewMobile(node.getModelAndViewMobile());
|
||||
processnodeDeployment.setNodeTimeout(node.getNodeTimeout());
|
||||
@@ -1263,7 +1278,9 @@ public class ExtActProcessServiceImpl extends ServiceImpl<ExtActProcessMapper, E
|
||||
log.info(" 流程开始节点类型 startType :" + startType);
|
||||
log.info(" 乐观锁 updateCount :" + updateCount);
|
||||
|
||||
DesUtils.checkNodeDuplicate(nodes);
|
||||
// 以前端提交的 BPMN XML 为准解析节点,避免 nodes 字符串漏传内嵌子流程节点后误删配置。
|
||||
Map<String, ProcessNodeInfo> processNodeInfoMap = parseProcessNodeInfoMap(processDescriptor);
|
||||
DesUtils.checkNodeDuplicate(toDesignerNodeString(processNodeInfoMap.values()));
|
||||
ExtActProcess process = extActProcessMapper.selectById(processDefinitionId);
|
||||
//第一次进入设计流程的时候,processDefinitionId始终为零,导致流程保存多份
|
||||
if ("0".equals(processDefinitionId) && process == null) {
|
||||
@@ -1351,19 +1368,16 @@ public class ExtActProcessServiceImpl extends ServiceImpl<ExtActProcessMapper, E
|
||||
//同步修改流程节点配置
|
||||
// 1.查出原来的流程节点
|
||||
List<ExtActProcessNode> oldNodeList = extActProcessNodeMapper.queryAllNodesByProcessKey(processkey);
|
||||
List<String> newNodeList = new ArrayList<>();
|
||||
if (nodes != null && nodes.length() > 3) {
|
||||
String[] temp = nodes.split("@@@");
|
||||
for (int i = 0; i < temp.length; i++) {
|
||||
ExtActProcessNode processnode = null;
|
||||
String[] fileds = temp[i].split("###");
|
||||
String tid = fileds[0].substring(3);
|
||||
String name = fileds[1].substring(9);
|
||||
newNodeList.add(tid);
|
||||
Map<String, ExtActProcessNode> oldNodeMap = oldNodeList.stream()
|
||||
.collect(Collectors.toMap(ExtActProcessNode::getProcessNodeCode, node -> node, (left, right) -> left));
|
||||
// newNodeList 是 XML 中真实存在的可配置任务节点,后续只删除不在此清单中的旧配置。
|
||||
List<String> newNodeList = new ArrayList<>(processNodeInfoMap.keySet());
|
||||
for (ProcessNodeInfo nodeInfo : processNodeInfoMap.values()) {
|
||||
String tid = nodeInfo.getId();
|
||||
String name = nodeInfo.getName();
|
||||
ExtActProcessNode processnode = oldNodeMap.get(tid);
|
||||
|
||||
// 2.查询节点是否存在
|
||||
processnode = oldNodeList.stream().filter(node -> node.getProcessNodeCode().equals(tid)).findFirst().orElse(null);
|
||||
//processnode = extActProcessNodeMapper.queryByNodeCodeAndProcessKey(processkey, tid);
|
||||
if (processnode == null) {
|
||||
processnode = new ExtActProcessNode();
|
||||
processnode.setProcessNodeCode(tid);
|
||||
@@ -1385,7 +1399,6 @@ public class ExtActProcessServiceImpl extends ServiceImpl<ExtActProcessMapper, E
|
||||
processnode.setMsgStatus(CommonConstant.STATUS_1);
|
||||
extActProcessNodeMapper.insert(processnode);
|
||||
} else {
|
||||
processnode.setProcessNodeCode(tid);
|
||||
processnode.setProcessNodeName(name);
|
||||
processnode.setProcessId(process.getId());
|
||||
extActProcessNodeMapper.updateById(processnode);
|
||||
@@ -1393,15 +1406,87 @@ public class ExtActProcessServiceImpl extends ServiceImpl<ExtActProcessMapper, E
|
||||
}
|
||||
|
||||
// 3.筛选出需要删除的节点【TV360X-1119 自定义start节点不能删】
|
||||
List<String> needToDeleteNodes = oldNodeList.stream().filter(element -> !newNodeList.contains(element.getProcessNodeCode()) && !element.getProcessNodeCode().toLowerCase().contains("start"))
|
||||
List<String> needToDeleteNodes = oldNodeList.stream().filter(element -> !newNodeList.contains(element.getProcessNodeCode()))
|
||||
.map(ExtActProcessNode::getProcessNodeCode).collect(Collectors.toList());
|
||||
if(!CollectionUtils.isEmpty(needToDeleteNodes)){
|
||||
extActProcessNodeMapper.deleteNodeByProcessId(process.getId(), needToDeleteNodes);
|
||||
}
|
||||
}
|
||||
//update-end---author:scott ---date::2023-11-18 for:【QQYUN-7020】流程设计器里面节点删除了,但是配置里面节点未删除
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 BPMN XML 解析流程配置节点。XML 解析失败时直接中断保存,避免按不完整节点清单删除已有配置。
|
||||
*/
|
||||
private Map<String, ProcessNodeInfo> parseProcessNodeInfoMap(String processDescriptor) throws Exception {
|
||||
if (oConvertUtils.isEmpty(processDescriptor)) {
|
||||
throw new Exception("Process XML cannot be empty");
|
||||
}
|
||||
XMLInputFactory xif = XMLInputFactory.newInstance();
|
||||
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|
||||
xif.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
|
||||
try (InputStreamReader xmlIn = new InputStreamReader(new ByteArrayInputStream(processDescriptor.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)) {
|
||||
XMLStreamReader xtr = xif.createXMLStreamReader(xmlIn);
|
||||
BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
|
||||
Map<String, ProcessNodeInfo> nodeInfoMap = new LinkedHashMap<>();
|
||||
for (org.flowable.bpmn.model.Process process : bpmnModel.getProcesses()) {
|
||||
collectProcessNodeInfos(process, nodeInfoMap);
|
||||
}
|
||||
return nodeInfoMap;
|
||||
} catch (Exception e) {
|
||||
log.error("Parse BPMN XML process nodes failed", e);
|
||||
throw new Exception("Parse BPMN XML process nodes failed, please check process designer XML", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void collectProcessNodeInfos(FlowElementsContainer container, Map<String, ProcessNodeInfo> nodeInfoMap) {
|
||||
if (container == null || CollectionUtils.isEmpty(container.getFlowElements())) {
|
||||
return;
|
||||
}
|
||||
for (FlowElement flowElement : container.getFlowElements()) {
|
||||
if (isConfigurableProcessNode(flowElement) && oConvertUtils.isNotEmpty(flowElement.getId())) {
|
||||
nodeInfoMap.put(flowElement.getId(), new ProcessNodeInfo(flowElement.getId(), oConvertUtils.getString(flowElement.getName(), "")));
|
||||
}
|
||||
// 子流程本身不作为配置节点保存,但要递归进入子流程内部收集任务节点。
|
||||
if (flowElement instanceof FlowElementsContainer) {
|
||||
collectProcessNodeInfos((FlowElementsContainer) flowElement, nodeInfoMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isConfigurableProcessNode(FlowElement flowElement) {
|
||||
// 只同步任务节点,排除开始、结束事件以及 bpmn:SubProcess 容器。
|
||||
return flowElement instanceof Task;
|
||||
}
|
||||
|
||||
private String toDesignerNodeString(Collection<ProcessNodeInfo> nodeInfos) {
|
||||
if (CollectionUtils.isEmpty(nodeInfos)) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder nodes = new StringBuilder();
|
||||
for (ProcessNodeInfo nodeInfo : nodeInfos) {
|
||||
nodes.append("id=").append(nodeInfo.getId()).append("###nodeName=").append(nodeInfo.getName()).append("@@@");
|
||||
}
|
||||
return nodes.toString();
|
||||
}
|
||||
|
||||
private static class ProcessNodeInfo {
|
||||
private final String id;
|
||||
private final String name;
|
||||
|
||||
private ProcessNodeInfo(String id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user