diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModeConditionType.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModeConditionType.java new file mode 100644 index 000000000..042119346 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModeConditionType.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.bpm.enums.definition; + +import cn.hutool.core.util.ArrayUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 仿钉钉的流程器设计器条件节点的条件类型 + * + * @author jason + */ +@Getter +@AllArgsConstructor +public enum BpmSimpleModeConditionType { + + CUSTOM_EXPRESSION(1, "自定义条件表达式"); + + + private final Integer type; + private final String name; + + public static BpmSimpleModeConditionType valueOf(Integer type) { + return ArrayUtil.firstMatch(nodeType -> nodeType.getType().equals(type), values()); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/SimpleModelConstants.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/SimpleModelConstants.java index dd7e6a520..32dae5a8f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/SimpleModelConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/SimpleModelConstants.java @@ -12,4 +12,19 @@ public interface SimpleModelConstants { * 审批方式属性 */ String APPROVE_METHOD_ATTRIBUTE = "approveMethod"; + + /** + * 网关节点默认序列流属性 + */ + String DEFAULT_FLOW_ATTRIBUTE = "defaultFlow"; + + /** + * 条件节点的条件类型属性 + */ + String CONDITION_TYPE_ATTRIBUTE = "conditionType"; + + /** + * 条件节点条件表达式属性 + */ + String CONDITION_EXPRESSION_ATTRIBUTE = "conditionExpression"; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 2e44d5286..6e5c042e8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -5,9 +5,11 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.TypeReference; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModeConditionType; import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants; @@ -20,6 +22,7 @@ import java.util.Map; import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.END_EVENT; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.FORM_FIELD_PERMISSION_ELEMENT; +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*; import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_NAMESPACE; import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_PREFIX; @@ -57,16 +60,15 @@ public class SimpleModelUtils { mainProcess.setName(processName); mainProcess.setExecutable(Boolean.TRUE); bpmnModel.addProcess(mainProcess); - // 前端模型数据结构。 有 start event 节点. 没有 end event 节点。 + // 前端模型数据结构。 // 从 SimpleModel 构建 FlowNode 并添加到 Main Process buildAndAddBpmnFlowNode(simpleModelNode, mainProcess); // 找到 end event EndEvent endEvent = (EndEvent) CollUtil.findOne(mainProcess.getFlowElements(), item -> item instanceof EndEvent); if (endEvent == null) { - // 暂时为了兼容 单独构建 end event 节点 + // TODO 暂时为了兼容 单独构建 end event 节点. 后面去掉 endEvent = buildAndAddBpmnEndEvent(mainProcess); } - // 构建并添加节点之间的连线 Sequence Flow buildAndAddBpmnSequenceFlow(mainProcess, simpleModelNode, endEvent.getId()); // 自动布局 @@ -75,14 +77,14 @@ public class SimpleModelUtils { } private static void buildAndAddBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node, String targetId) { - // 节点为 null 退出 + // 节点为 null 或者 为END_EVENT 退出 if (node == null || node.getId() == null || END_EVENT.getType().equals(node.getType())) { return; } BpmSimpleModelNodeVO childNode = node.getChildNode(); - // 如果不是网关节点、且后续节点为 null. 添加与结束节点的连线 + // 如果是网关分支节点. 后续节点可能为 null。但不是 END_EVENT 节点 if (!BpmSimpleModelNodeType.isBranchNode(node.getType()) && (childNode == null || childNode.getId() == null)) { - SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), targetId, null, null); + SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), targetId, null, null, null); mainProcess.addFlowElement(sequenceFlow); return; } @@ -94,7 +96,7 @@ public class SimpleModelUtils { case COPY_TASK: case PARALLEL_GATEWAY_JOIN: case INCLUSIVE_GATEWAY_JOIN: { - SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), childNode.getId(), null, null); + SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), childNode.getId(), null, null, null); mainProcess.addFlowElement(sequenceFlow); // 递归调用后续节点 buildAndAddBpmnSequenceFlow(mainProcess, childNode, targetId); @@ -103,21 +105,21 @@ public class SimpleModelUtils { case PARALLEL_GATEWAY_FORK: case EXCLUSIVE_GATEWAY: case INCLUSIVE_GATEWAY_FORK: { - String sequenceFlowTargetId = (childNode == null || childNode.getId() == null) ? BpmnModelConstants.END_EVENT_ID : childNode.getId(); + String sequenceFlowTargetId = (childNode == null || childNode.getId() == null) ? targetId : childNode.getId(); List conditionNodes = node.getConditionNodes(); Assert.notEmpty(conditionNodes, "网关节点的条件节点不能为空"); - for (int i = 0; i < conditionNodes.size(); i++) { - BpmSimpleModelNodeVO item = conditionNodes.get(i); + for (BpmSimpleModelNodeVO item : conditionNodes) { + String conditionExpression = buildConditionExpression(item); BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode(); if (nextNodeOnCondition != null && nextNodeOnCondition.getId() != null) { SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), nextNodeOnCondition.getId(), - String.format("%s_SequenceFlow_%d", node.getId(), i + 1), null); + item.getId(), item.getName(), conditionExpression); mainProcess.addFlowElement(sequenceFlow); // 递归调用后续节点 buildAndAddBpmnSequenceFlow(mainProcess, nextNodeOnCondition, sequenceFlowTargetId); } else { SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), sequenceFlowTargetId, - String.format("%s_SequenceFlow_%d", node.getId(), i + 1), null); + item.getId(), item.getName(), conditionExpression); mainProcess.addFlowElement(sequenceFlow); } } @@ -132,7 +134,24 @@ public class SimpleModelUtils { } - private static SequenceFlow buildBpmnSequenceFlow(String sourceId, String targetId, String seqFlowId, String conditionExpression) { + /** + * 构造条件表达式 + * + * @param conditionNode 条件节点 + */ + private static String buildConditionExpression(BpmSimpleModelNodeVO conditionNode) { + Integer conditionType = MapUtil.getInt(conditionNode.getAttributes(), CONDITION_TYPE_ATTRIBUTE); + BpmSimpleModeConditionType conditionTypeEnum = BpmSimpleModeConditionType.valueOf(conditionType); + String conditionExpression = null; + if (conditionTypeEnum == BpmSimpleModeConditionType.CUSTOM_EXPRESSION) { + conditionExpression = MapUtil.getStr(conditionNode.getAttributes(), CONDITION_EXPRESSION_ATTRIBUTE); + } + // TODO 待增加其它类型 + return conditionExpression; + + } + + private static SequenceFlow buildBpmnSequenceFlow(String sourceId, String targetId, String seqFlowId, String seqName, String conditionExpression) { SequenceFlow sequenceFlow = new SequenceFlow(sourceId, targetId); if (StrUtil.isNotEmpty(conditionExpression)) { sequenceFlow.setConditionExpression(conditionExpression); @@ -140,6 +159,9 @@ public class SimpleModelUtils { if (StrUtil.isNotEmpty(seqFlowId)) { sequenceFlow.setId(seqFlowId); } + if (StrUtil.isNotEmpty(seqName)) { + sequenceFlow.setName(seqName); + } return sequenceFlow; } @@ -249,8 +271,12 @@ public class SimpleModelUtils { Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空"); ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); exclusiveGateway.setId(node.getId()); - // 网关的最后一个条件为 网关的 default sequence flow - exclusiveGateway.setDefaultFlow(String.format("%s_SequenceFlow_%d", node.getId(), node.getConditionNodes().size())); + // 寻找默认的序列流 + BpmSimpleModelNodeVO defaultSeqFlow = CollUtil.findOne(node.getConditionNodes(), + item -> BooleanUtil.isTrue(MapUtil.getBool(item.getAttributes(), DEFAULT_FLOW_ATTRIBUTE))); + if (defaultSeqFlow != null) { + exclusiveGateway.setDefaultFlow(defaultSeqFlow.getId()); + } return exclusiveGateway; }