Commit d88718071d649146b428485fe02e51d40f72a47b

Authored by jason
1 parent 1b708ccd

仿钉钉流程设计-排他网关实现

yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeType.java
... ... @@ -18,8 +18,7 @@ import java.util.Objects;
18 18 public enum BpmSimpleModelNodeType implements IntArrayValuable {
19 19  
20 20 // TODO @jaosn:-1、0、1、4、-2 是前端已经定义好的么?感觉未来可以考虑搞成和 BPMN 尽量一致的单词哈;类似 usertask 用户审批;
21   - START_NODE(-1, "开始节点"),
22   - START_USER_NODE(0, "发起人结点"),
  21 + START_EVENT_NODE(0, "开始节点"),
23 22 APPROVE_USER_NODE (1, "审批人节点"),
24 23 EXCLUSIVE_GATEWAY_NODE(4, "排他网关"),
25 24 END_NODE(-2, "结束节点");
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
... ... @@ -358,44 +358,72 @@ public class BpmnModelUtils {
358 358 // 单独添加 end event 节点
359 359 addBpmnEndEventNode(mainProcess);
360 360 // 添加节点之间的连线 Sequence Flow
361   - addBpmnSequenceFlow(mainProcess, simpleModelNode);
  361 + addBpmnSequenceFlow(mainProcess, simpleModelNode, BpmnModelConstants.END_EVENT_ID);
362 362 // 自动布局
363 363 new BpmnAutoLayout(bpmnModel).execute();
364 364 return bpmnModel;
365 365 }
366 366  
367   - private static void addBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node) {
  367 + private static void addBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node, String endId) {
368 368 // 节点为 null 退出
369 369 if (node == null || node.getId() == null) {
370 370 return;
371 371 }
372 372 BpmSimpleModelNodeVO childNode = node.getChildNode();
373   - // 如果后续节点为 null. 添加与结束节点的连线
374   - if (childNode == null || childNode.getId() == null) {
375   - addBpmnSequenceFlowElement(mainProcess, node.getId(), BpmnModelConstants.END_EVENT_ID, null);
  373 + // 如果不是网关节点、且后续节点为 null. 添加与结束节点的连线
  374 + if (!BpmSimpleModelNodeType.isGatewayNode(node.getType()) && (childNode == null || childNode.getId() == null)) {
  375 + addBpmnSequenceFlowElement(mainProcess, node.getId(), endId, null, null);
376 376 return;
377 377 }
378 378 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType());
379 379 Assert.notNull(nodeType, "模型节点类型不支持");
380 380 switch (nodeType) {
381   - case START_NODE:
382   - case START_USER_NODE:
383   - case APPROVE_USER_NODE:
384   - addBpmnSequenceFlowElement(mainProcess, node.getId(), childNode.getId(), null);
  381 + case START_EVENT_NODE:
  382 + case APPROVE_USER_NODE: {
  383 + addBpmnSequenceFlowElement(mainProcess, node.getId(), childNode.getId(), null, null);
  384 + // 递归调用后续节点
  385 + addBpmnSequenceFlow(mainProcess, childNode,endId);
  386 + break;
  387 + }
  388 + case EXCLUSIVE_GATEWAY_NODE: {
  389 + String gateWayEndId = ( childNode == null || childNode.getId() == null ) ? BpmnModelConstants.END_EVENT_ID : childNode.getId();
  390 + List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes();
  391 + Assert.notEmpty(conditionNodes, "网关节点的条件节点不能为空");
  392 + for (int i = 0; i < conditionNodes.size(); i++) {
  393 + BpmSimpleModelNodeVO item = conditionNodes.get(i);
  394 + BpmSimpleModelNodeVO nextNodeOnCondition = getNextNodeOnCondition(item);
  395 + if (nextNodeOnCondition != null && nextNodeOnCondition.getId() != null) {
  396 + addBpmnSequenceFlowElement(mainProcess, node.getId(), nextNodeOnCondition.getId(),
  397 + String.format("%s_SequenceFlow_%d", node.getId(), i+1), null);
  398 + addBpmnSequenceFlow(mainProcess, nextNodeOnCondition, gateWayEndId);
  399 + } else {
  400 + addBpmnSequenceFlowElement(mainProcess, node.getId(), gateWayEndId,
  401 + String.format("%s_SequenceFlow_%d", node.getId(), i+1), null);
  402 + }
  403 + }
  404 + // 递归调用后续节点
  405 + addBpmnSequenceFlow(mainProcess, childNode, endId);
385 406 break;
  407 + }
386 408 default: {
387 409 // TODO 其它节点类型的实现
388 410 }
389 411 }
390   - // 递归调用后续节点
391   - addBpmnSequenceFlow(mainProcess, childNode);
  412 +
392 413 }
393 414  
394   - private static void addBpmnSequenceFlowElement(Process mainProcess, String sourceId, String targetId, String conditionExpression) {
  415 + private static BpmSimpleModelNodeVO getNextNodeOnCondition(BpmSimpleModelNodeVO conditionNode) {
  416 + return conditionNode.getChildNode();
  417 + }
  418 +
  419 + private static void addBpmnSequenceFlowElement(Process mainProcess, String sourceId, String targetId, String seqFlowId, String conditionExpression) {
395 420 SequenceFlow sequenceFlow = new SequenceFlow(sourceId, targetId);
396 421 if (StrUtil.isNotEmpty(conditionExpression)) {
397 422 sequenceFlow.setConditionExpression(conditionExpression);
398 423 }
  424 + if (StrUtil.isNotEmpty(seqFlowId)) {
  425 + sequenceFlow.setId(seqFlowId);
  426 + }
399 427 mainProcess.addFlowElement(sequenceFlow);
400 428 }
401 429  
... ... @@ -407,13 +435,15 @@ public class BpmnModelUtils {
407 435 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType());
408 436 Assert.notNull(nodeType, "模型节点类型不支持");
409 437 switch (nodeType) {
410   - case START_NODE:
  438 + case START_EVENT_NODE:
411 439 addBpmnStartEventNode(mainProcess, simpleModelNode);
412 440 break;
413   - case START_USER_NODE:
414 441 case APPROVE_USER_NODE:
415 442 addBpmnUserTaskEventNode(mainProcess, simpleModelNode);
416 443 break;
  444 + case EXCLUSIVE_GATEWAY_NODE:
  445 + addBpmnExclusiveGatewayNode(mainProcess, simpleModelNode);
  446 + break;
417 447 default: {
418 448 // TODO 其它节点类型的实现
419 449 }
... ... @@ -427,7 +457,7 @@ public class BpmnModelUtils {
427 457 // 如果是网关类型接口. 递归添加条件节点
428 458 if (BpmSimpleModelNodeType.isGatewayNode(simpleModelNode.getType()) && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) {
429 459 for (BpmSimpleModelNodeVO node : simpleModelNode.getConditionNodes()) {
430   - addBpmnFlowNode(mainProcess, node);
  460 + addBpmnFlowNode(mainProcess, node.getChildNode());
431 461 }
432 462 }
433 463  
... ... @@ -437,6 +467,15 @@ public class BpmnModelUtils {
437 467 }
438 468 }
439 469  
  470 + private static void addBpmnExclusiveGatewayNode(Process mainProcess, BpmSimpleModelNodeVO node) {
  471 + Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空");
  472 + ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
  473 + exclusiveGateway.setId(node.getId());
  474 + // 条件节点的最后一个条件为 网关的 default sequence flow
  475 + exclusiveGateway.setDefaultFlow(String.format("%s_SequenceFlow_%d", node.getId(), node.getConditionNodes().size()));
  476 + mainProcess.addFlowElement(exclusiveGateway);
  477 + }
  478 +
440 479 private static void addBpmnEndEventNode(Process mainProcess) {
441 480 EndEvent endEvent = new EndEvent();
442 481 endEvent.setId(BpmnModelConstants.END_EVENT_ID);
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmSimpleModelServiceImpl.java
... ... @@ -20,7 +20,7 @@ import java.util.Map;
20 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
21 21 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT;
22 22 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_NOT_EXISTS;
23   -import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.START_NODE;
  23 +import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.START_EVENT_NODE;
24 24 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_PARAM;
25 25 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY;
26 26  
... ... @@ -85,7 +85,7 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService {
85 85 return null;
86 86 }
87 87 BpmSimpleModelNodeVO rootNode = new BpmSimpleModelNodeVO();
88   - rootNode.setType(START_NODE.getType());
  88 + rootNode.setType(START_EVENT_NODE.getType());
89 89 rootNode.setId(startEvent.getId());
90 90 rootNode.setName(startEvent.getName());
91 91 recursiveBuildSimpleModelNode(startEvent, rootNode);
... ... @@ -129,7 +129,7 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService {
129 129  
130 130 private List<SequenceFlow> validateCanConvertSimpleNode(BpmSimpleModelNodeType nodeType, FlowNode currentFlowNode) {
131 131 switch (nodeType) {
132   - case START_NODE:
  132 + case START_EVENT_NODE:
133 133 case APPROVE_USER_NODE: {
134 134 List<SequenceFlow> outgoingFlows = currentFlowNode.getOutgoingFlows();
135 135 if (CollUtil.isNotEmpty(outgoingFlows) && outgoingFlows.size() > 1) {
... ...