Commit d9a2849ccec0613bf55365be1048b11cd55518c1

Authored by jason
1 parent 8a3b6c3e

仿钉钉流程设计- code review 修改。新增并行分支节点

yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeType.java
... ... @@ -25,12 +25,14 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable {
25 25 APPROVE_NODE(1, "审批人节点"), // TODO @jaosn:是不是这里从 10 开始好点;相当于说,0-9 给开始和结束;10-19 给各种节点;20-29 给各种条件; TODO 后面改改
26 26 COPY_NODE(2, "抄送人节点"),
27 27  
  28 + CONDITION_NODE(3, "条件节点"), // 用于构建流转条件的表达式
28 29 CONDITION_BRANCH_NODE(4, "条件分支节点"), // TODO @jason:是不是改成叫 条件分支?
29   - PARALLEL_BRANCH_FORK_NODE(5, "并行分支分叉节点"), // TODO @jason:是不是一个 并行分支 ?就可以啦? 后面是否去掉并行网关。只用包容网关
30   - PARALLEL_BRANCH_JOIN_NODE(6, "并行分支聚合节点"),
  30 + PARALLEL_BRANCH_NODE(5, "并行分支节点"), // TODO @jason:是不是一个 并行分支 ?就可以啦? 后面是否去掉并行网关。只用包容网关
  31 +// PARALLEL_BRANCH_JOIN_NODE(6, "并行分支聚合节点"),
31 32 INCLUSIVE_BRANCH_FORK_NODE(7, "包容网关分叉节点"),
32 33 INCLUSIVE_BRANCH_JOIN_NODE(8, "包容网关聚合节点"),
33 34 // TODO @jason:建议整合 join,最终只有 条件分支、并行分支、包容分支,三种~
  35 + // TODO @芋艿。 感觉还是分开好理解一点,也好处理一点。前端结构中把聚合节点显示并传过来。
34 36 ;
35 37  
36 38 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmSimpleModelNodeType::getType).toArray();
... ... @@ -45,7 +47,7 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable {
45 47 */
46 48 public static boolean isBranchNode(Integer type) {
47 49 return Objects.equals(CONDITION_BRANCH_NODE.getType(), type)
48   - || Objects.equals(PARALLEL_BRANCH_FORK_NODE.getType(), type)
  50 + || Objects.equals(PARALLEL_BRANCH_NODE.getType(), type)
49 51 || Objects.equals(INCLUSIVE_BRANCH_FORK_NODE.getType(), type) ;
50 52 }
51 53  
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
... ... @@ -38,6 +38,11 @@ import static org.flowable.bpmn.constants.BpmnXMLConstants.*;
38 38 */
39 39 public class SimpleModelUtils {
40 40  
  41 + /**
  42 + * 聚合网关节点 Id 后缀
  43 + */
  44 + public static final String JOIN_GATE_WAY_NODE_ID_SUFFIX = "_join";
  45 +
41 46 public static final String BPMN_SIMPLE_COPY_EXECUTION_SCRIPT = "#{bpmSimpleNodeService.copy(execution)}";
42 47  
43 48 /**
... ... @@ -105,20 +110,20 @@ public class SimpleModelUtils {
105 110 // }
106 111 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType());
107 112 Assert.notNull(nodeType, "模型节点类型不支持");
  113 +
  114 + if (nodeType == END_NODE) {
  115 + return;
  116 + }
108 117 BpmSimpleModelNodeVO childNode = node.getChildNode();
109 118 // 2.1 普通节点
110 119 if (!BpmSimpleModelNodeType.isBranchNode(node.getType())) {
111   - // 2.1.1 结束节点退出递归
112   - if (nodeType == END_NODE) {
113   - return;
114   - }
115 120 if (!isValidNode(childNode)) {
116   - // 2.1.2 普通节点且无孩子节点。分两种情况
  121 + // 2.1.1 普通节点且无孩子节点。分两种情况
117 122 // a.结束节点 b. 条件分支的最后一个节点.与分支节点的孩子节点或聚合节点建立连线。
118 123 SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), targetNodeId, null, null, null);
119 124 process.addFlowElement(sequenceFlow);
120 125 } else {
121   - // 2.1.3 普通节点且有孩子节点。建立连线
  126 + // 2.1.2 普通节点且有孩子节点。建立连线
122 127 SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), childNode.getId(), null, null, null);
123 128 process.addFlowElement(sequenceFlow);
124 129 // 递归调用后续节点
... ... @@ -128,31 +133,48 @@ public class SimpleModelUtils {
128 133 // 2.2 分支节点
129 134 List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes();
130 135 Assert.notEmpty(conditionNodes, "分支节点的条件节点不能为空");
131   - // 4.1 分支节点,遍历分支节点. 如下情况:
  136 + // 分支终点节点 Id
  137 + String branchEndNodeId = null;
  138 + if (nodeType == CONDITION_BRANCH_NODE) { // 条件分支
  139 + // 分两种情况 1. 分支节点有孩子节点为孩子节点 Id 2. 分支节点孩子为无效节点时 (分支嵌套且为分支最后一个节点) 为分支终点节点Id
  140 + branchEndNodeId = isValidNode(childNode) ? childNode.getId() : targetNodeId;
  141 + } else if (nodeType == PARALLEL_BRANCH_NODE) { // 并行分支
  142 + // 分支节点:分支终点节点 Id 为程序创建的网关集合节点。目前不会从前端传入。
  143 + branchEndNodeId = node.getId() + JOIN_GATE_WAY_NODE_ID_SUFFIX;
  144 + }
  145 + // TODO 包容网关待实现
  146 + Assert.notEmpty(branchEndNodeId, "分支终点节点 Id 不能为空");
  147 + // 3.1 遍历分支节点. 如下情况:
132 148 // 分支1、A->B->C->D->E 和 分支2、A->D->E。 A为分支节点, D为A孩子节点
133   - // 分支终点节点, 1. 分支节点有孩子节点时为孩子节点 2. 当分支节点孩子为无效节点时。分支嵌套时并且为分支最后一个节点
134   - String branchEndNodeId = isValidNode(childNode) ? childNode.getId() : targetNodeId ;
135 149 for (BpmSimpleModelNodeVO item : conditionNodes) {
136 150 // TODO @jason:条件分支的情况下,需要分 item 搞的条件,和 conditionNodes 搞的条件
137   - // 构建表达式
  151 + // @芋艿 这个是啥意思。 这里的 item 的节点类型为 BpmSimpleModelNodeType.CONDITION_NODE 类型,没有对应的 bpmn 的节点。 仅仅用于构建条件表达式。
  152 + Assert.isTrue(Objects.equals(item.getType(), CONDITION_NODE.getType()), "条件节点类型不符合");
  153 + // 构建表达式,可以为空. 并行分支为空
138 154 String conditionExpression = buildConditionExpression(item);
139 155 BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode();
140   - // 4.2 分支有后续节点, 分支1: A->B->C->D
  156 + // 3.2 分支有后续节点, 分支1: A->B->C->D
141 157 if (isValidNode(nextNodeOnCondition)) {
142   - // 4.2.1 建立 A->B
  158 + // 3.2.1 建立 A->B
143 159 SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), nextNodeOnCondition.getId(),
144 160 item.getId(), item.getName(), conditionExpression);
145 161 process.addFlowElement(sequenceFlow);
146   - // 4.2.2 递归调用后续节点连线。 建立 B->C->D 的连线
  162 + // 3.2.2 递归调用后续节点连线。 建立 B->C->D 的连线
147 163 traverseNodeToBuildSequenceFlow(process, nextNodeOnCondition, branchEndNodeId);
148 164 } else {
149   - // 4.3 分支无后续节点 建立 A->D
  165 + // 3.3 分支无后续节点 建立 A->D
150 166 SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), branchEndNodeId,
151 167 item.getId(), item.getName(), conditionExpression);
152 168 process.addFlowElement(sequenceFlow);
153 169 }
154 170 }
155   - // 递归调用后续节点 继续递归建立 D->E 的连线
  171 + // 如果是并行分支。由于是程序创建的聚合网关。需要手工创建聚合网关和下一个节点的连线
  172 + if (nodeType == PARALLEL_BRANCH_NODE) {
  173 + String nextNodeId = isValidNode(childNode) ? childNode.getId() : targetNodeId;
  174 + SequenceFlow sequenceFlow = buildBpmnSequenceFlow(branchEndNodeId, nextNodeId, null, null, null);
  175 + process.addFlowElement(sequenceFlow);
  176 + }
  177 + // 4.递归调用后续节点 继续递归建立 D->E 的连线
156 178 traverseNodeToBuildSequenceFlow(process, childNode, targetNodeId);
157 179 }
158 180  
... ... @@ -328,10 +350,9 @@ public class SimpleModelUtils {
328 350 list.add(exclusiveGateway);
329 351 break;
330 352 }
331   - case PARALLEL_BRANCH_FORK_NODE:
332   - case PARALLEL_BRANCH_JOIN_NODE: {
333   - ParallelGateway parallelGateway = convertParallelBranchNode(node);
334   - list.add(parallelGateway);
  353 + case PARALLEL_BRANCH_NODE: {
  354 + List<ParallelGateway> parallelGateways = convertParallelBranchNode(node);
  355 + list.addAll(parallelGateways);
335 356 break;
336 357 }
337 358  
... ... @@ -392,14 +413,17 @@ public class SimpleModelUtils {
392 413 return boundaryEvent;
393 414 }
394 415  
395   - private static ParallelGateway convertParallelBranchNode(BpmSimpleModelNodeVO node) {
  416 + private static List<ParallelGateway> convertParallelBranchNode(BpmSimpleModelNodeVO node) {
396 417 ParallelGateway parallelGateway = new ParallelGateway();
397 418 parallelGateway.setId(node.getId());
398 419 // TODO @jason:setName
399 420  
400 421 // TODO @芋艿 + jason:合并网关;是不是要有条件啥的。微信讨论
401   - // @芋艿 貌似并行网关没有条件的
402   - return parallelGateway;
  422 + // @芋艿 感觉聚合网关(合并网关)还是从前端传过来好理解一点。
  423 + // 并行聚合网关
  424 + ParallelGateway joinParallelGateway = new ParallelGateway();
  425 + joinParallelGateway.setId(node.getId() + JOIN_GATE_WAY_NODE_ID_SUFFIX);
  426 + return CollUtil.newArrayList(parallelGateway, joinParallelGateway);
403 427 }
404 428  
405 429 private static ServiceTask convertCopyNode(BpmSimpleModelNodeVO node) {
... ...