Commit a13b58200948bc269c1746073f79e7473cfbafe1

Authored by Lesan
1 parent 8b91b471

feat: Simple设计器-路由分支

yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeType.java
... ... @@ -33,6 +33,7 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable {
33 33 CONDITION_BRANCH_NODE(51, "条件分支", "exclusiveGateway"),
34 34 PARALLEL_BRANCH_NODE(52, "并行分支", "parallelGateway"),
35 35 INCLUSIVE_BRANCH_NODE(53, "包容分支", "inclusiveGateway"),
  36 + ROUTE_BRANCH_NODE(54, "路由分支", "exclusiveGateway")
36 37 ;
37 38  
38 39 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmSimpleModelNodeType::getType).toArray();
... ... @@ -49,7 +50,8 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable {
49 50 public static boolean isBranchNode(Integer type) {
50 51 return Objects.equals(CONDITION_BRANCH_NODE.getType(), type)
51 52 || Objects.equals(PARALLEL_BRANCH_NODE.getType(), type)
52   - || Objects.equals(INCLUSIVE_BRANCH_NODE.getType(), type);
  53 + || Objects.equals(INCLUSIVE_BRANCH_NODE.getType(), type)
  54 + || Objects.equals(ROUTE_BRANCH_NODE.getType(), type);
53 55 }
54 56  
55 57 public static BpmSimpleModelNodeType valueOf(Integer type) {
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
... ... @@ -226,4 +226,31 @@ public class BpmSimpleModelNodeVO {
226 226 private String delayTime;
227 227 }
228 228  
  229 + @Schema(description = "路由分支组", example = "[]")
  230 + private List<RouteCondition> routeGroup;
  231 +
  232 + @Schema(description = "默认分支id", example = "Flow_xxx")
  233 + private String defaultFlowId; // 仅用于路由分支节点 BpmSimpleModelNodeType.ROUTE_BRANCH_NODE
  234 +
  235 + @Schema(description = "路由分支")
  236 + @Data
  237 + @Valid
  238 + public static class RouteCondition {
  239 +
  240 + @Schema(description = "节点Id", example = "Activity_xxx")
  241 + @NotEmpty(message = "节点Id不能为空")
  242 + private String nodeId;
  243 +
  244 + @Schema(description = "条件类型", example = "1")
  245 + @InEnum(BpmSimpleModeConditionType.class)
  246 + @NotNull(message = "条件类型不能为空")
  247 + private Integer conditionType;
  248 +
  249 + @Schema(description = "条件表达式", example = "${day>3}")
  250 + private String conditionExpression;
  251 +
  252 + @Schema(description = "条件组", example = "{}")
  253 + private ConditionGroups conditionGroups;
  254 + }
  255 +
229 256 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
... ... @@ -38,7 +38,8 @@ public class SimpleModelUtils {
38 38 List<NodeConvert> converts = asList(new StartNodeConvert(), new EndNodeConvert(),
39 39 new StartUserNodeConvert(), new ApproveNodeConvert(), new CopyNodeConvert(),
40 40 new DelayTimerNodeConvert(),
41   - new ConditionBranchNodeConvert(), new ParallelBranchNodeConvert(), new InclusiveBranchNodeConvert());
  41 + new ConditionBranchNodeConvert(), new ParallelBranchNodeConvert(), new InclusiveBranchNodeConvert(),
  42 + new RouteBranchNodeConvert());
42 43 converts.forEach(convert -> NODE_CONVERTS.put(convert.getType(), convert));
43 44 }
44 45  
... ... @@ -180,10 +181,12 @@ public class SimpleModelUtils {
180 181 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType());
181 182 BpmSimpleModelNodeVO childNode = node.getChildNode();
182 183 List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes();
183   - Assert.notEmpty(conditionNodes, "分支节点的条件节点不能为空");
  184 + // TODO @芋艿 路由分支没有conditionNodes 这里注释会影响吗?
  185 +// Assert.notEmpty(conditionNodes, "分支节点的条件节点不能为空");
184 186 // 分支终点节点 ID
185 187 String branchEndNodeId = null;
186   - if (nodeType == BpmSimpleModelNodeType.CONDITION_BRANCH_NODE) { // 条件分支
  188 + if (nodeType == BpmSimpleModelNodeType.CONDITION_BRANCH_NODE
  189 + || nodeType == BpmSimpleModelNodeType.ROUTE_BRANCH_NODE) { // 条件分支或路由分支
187 190 // 分两种情况 1. 分支节点有孩子节点为孩子节点 Id 2. 分支节点孩子为无效节点时 (分支嵌套且为分支最后一个节点) 为分支终点节点 ID
188 191 branchEndNodeId = isValidNode(childNode) ? childNode.getId() : targetNodeId;
189 192 } else if (nodeType == BpmSimpleModelNodeType.PARALLEL_BRANCH_NODE
... ... @@ -194,31 +197,45 @@ public class SimpleModelUtils {
194 197 Assert.notEmpty(branchEndNodeId, "分支终点节点 Id 不能为空");
195 198  
196 199 // 3. 遍历分支节点
197   - // 下面的注释,以如下情况举例子。分支 1:A->B->C->D->E,分支 2:A->D->E。其中,A 为分支节点, D 为 A 孩子节点
198   - for (BpmSimpleModelNodeVO item : conditionNodes) {
199   - Assert.isTrue(Objects.equals(item.getType(), BpmSimpleModelNodeType.CONDITION_NODE.getType()),
200   - "条件节点类型({})不符合", item.getType());
201   - BpmSimpleModelNodeVO conditionChildNode = item.getChildNode();
202   - // 3.1 分支有后续节点。即分支 1: A->B->C->D 的情况
203   - if (isValidNode(conditionChildNode)) {
204   - // 3.1.1 建立与后续的节点的连线。例如说,建立 A->B 的连线
205   - SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), conditionChildNode.getId(), item);
206   - process.addFlowElement(sequenceFlow);
207   - // 3.1.2 递归调用后续节点连线。例如说,建立 B->C->D 的连线
208   - traverseNodeToBuildSequenceFlow(process, conditionChildNode, branchEndNodeId);
209   - } else {
210   - // 3.2 分支没有后续节点。例如说,建立 A->D 的连线
211   - SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), branchEndNodeId, item);
212   - process.addFlowElement(sequenceFlow);
  200 + if (nodeType == BpmSimpleModelNodeType.ROUTE_BRANCH_NODE) {
  201 + // 路由分支遍历
  202 + for (BpmSimpleModelNodeVO.RouteCondition route : node.getRouteGroup()) {
  203 + SequenceFlow sFlow = RouteBranchNodeConvert.buildSequenceFlow(node.getId(), route);
  204 + process.addFlowElement(sFlow);
  205 + }
  206 + } else {
  207 + // 下面的注释,以如下情况举例子。分支 1:A->B->C->D->E,分支 2:A->D->E。其中,A 为分支节点, D 为 A 孩子节点
  208 + for (BpmSimpleModelNodeVO item : conditionNodes) {
  209 + Assert.isTrue(Objects.equals(item.getType(), BpmSimpleModelNodeType.CONDITION_NODE.getType()),
  210 + "条件节点类型({})不符合", item.getType());
  211 + BpmSimpleModelNodeVO conditionChildNode = item.getChildNode();
  212 + // 3.1 分支有后续节点。即分支 1: A->B->C->D 的情况
  213 + if (isValidNode(conditionChildNode)) {
  214 + // 3.1.1 建立与后续的节点的连线。例如说,建立 A->B 的连线
  215 + SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), conditionChildNode.getId(), item);
  216 + process.addFlowElement(sequenceFlow);
  217 + // 3.1.2 递归调用后续节点连线。例如说,建立 B->C->D 的连线
  218 + traverseNodeToBuildSequenceFlow(process, conditionChildNode, branchEndNodeId);
  219 + } else {
  220 + // 3.2 分支没有后续节点。例如说,建立 A->D 的连线
  221 + SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), branchEndNodeId, item);
  222 + process.addFlowElement(sequenceFlow);
  223 + }
213 224 }
214 225 }
215 226  
216   - // 4. 如果是并行分支、包容分支,由于是程序创建的聚合网关,需要手工创建聚合网关和下一个节点的连线
  227 + // 4. 各分支节点所需特殊处理
217 228 if (nodeType == BpmSimpleModelNodeType.PARALLEL_BRANCH_NODE
218 229 || nodeType == BpmSimpleModelNodeType.INCLUSIVE_BRANCH_NODE ) {
  230 + // 如果是并行分支、包容分支,由于是程序创建的聚合网关,需要手工创建聚合网关和下一个节点的连线
219 231 String nextNodeId = isValidNode(childNode) ? childNode.getId() : targetNodeId;
220 232 SequenceFlow sequenceFlow = buildBpmnSequenceFlow(branchEndNodeId, nextNodeId);
221 233 process.addFlowElement(sequenceFlow);
  234 + } else if (nodeType == BpmSimpleModelNodeType.ROUTE_BRANCH_NODE) {
  235 + // 如果是路由分支,需要连接后续节点为默认路由
  236 + SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), branchEndNodeId, node.getDefaultFlowId(),
  237 + null, null);
  238 + process.addFlowElement(sequenceFlow);
222 239 }
223 240  
224 241 // 5. 递归调用后续节点 继续递归。例如说,建立 D->E 的连线
... ... @@ -576,12 +593,20 @@ public class SimpleModelUtils {
576 593 * @param node 条件节点
577 594 */
578 595 public static String buildConditionExpression(BpmSimpleModelNodeVO node) {
579   - BpmSimpleModeConditionType conditionTypeEnum = BpmSimpleModeConditionType.valueOf(node.getConditionType());
  596 + return buildConditionExpression(node.getConditionType(), node.getConditionExpression(),
  597 + node.getConditionGroups());
  598 + }
  599 + public static String buildConditionExpression(BpmSimpleModelNodeVO.RouteCondition route) {
  600 + return buildConditionExpression(route.getConditionType(), route.getConditionExpression(),
  601 + route.getConditionGroups());
  602 + }
  603 + public static String buildConditionExpression(Integer conditionType, String conditionExpression,
  604 + ConditionGroups conditionGroups) {
  605 + BpmSimpleModeConditionType conditionTypeEnum = BpmSimpleModeConditionType.valueOf(conditionType);
580 606 if (conditionTypeEnum == BpmSimpleModeConditionType.EXPRESSION) {
581   - return node.getConditionExpression();
  607 + return conditionExpression;
582 608 }
583 609 if (conditionTypeEnum == BpmSimpleModeConditionType.RULE) {
584   - ConditionGroups conditionGroups = node.getConditionGroups();
585 610 if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) {
586 611 return null;
587 612 }
... ... @@ -644,6 +669,29 @@ public class SimpleModelUtils {
644 669 }
645 670 }
646 671  
  672 + public static class RouteBranchNodeConvert implements NodeConvert {
  673 +
  674 + @Override
  675 + public ExclusiveGateway convert(BpmSimpleModelNodeVO node) {
  676 + ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
  677 + exclusiveGateway.setId(node.getId());
  678 +
  679 + // 设置默认的序列流(条件)
  680 + exclusiveGateway.setDefaultFlow(node.getDefaultFlowId());
  681 + return exclusiveGateway;
  682 + }
  683 +
  684 + @Override
  685 + public BpmSimpleModelNodeType getType() {
  686 + return BpmSimpleModelNodeType.ROUTE_BRANCH_NODE;
  687 + }
  688 +
  689 + public static SequenceFlow buildSequenceFlow(String nodeId, BpmSimpleModelNodeVO.RouteCondition route) {
  690 + String conditionExpression = ConditionNodeConvert.buildConditionExpression(route);
  691 + return buildBpmnSequenceFlow(nodeId, route.getNodeId(), null, null, conditionExpression);
  692 + }
  693 + }
  694 +
647 695 private static String buildGatewayJoinId(String id) {
648 696 return id + "_join";
649 697 }
... ...