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,8 +18,7 @@ import java.util.Objects;
18 public enum BpmSimpleModelNodeType implements IntArrayValuable { 18 public enum BpmSimpleModelNodeType implements IntArrayValuable {
19 19
20 // TODO @jaosn:-1、0、1、4、-2 是前端已经定义好的么?感觉未来可以考虑搞成和 BPMN 尽量一致的单词哈;类似 usertask 用户审批; 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 APPROVE_USER_NODE (1, "审批人节点"), 22 APPROVE_USER_NODE (1, "审批人节点"),
24 EXCLUSIVE_GATEWAY_NODE(4, "排他网关"), 23 EXCLUSIVE_GATEWAY_NODE(4, "排他网关"),
25 END_NODE(-2, "结束节点"); 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,44 +358,72 @@ public class BpmnModelUtils {
358 // 单独添加 end event 节点 358 // 单独添加 end event 节点
359 addBpmnEndEventNode(mainProcess); 359 addBpmnEndEventNode(mainProcess);
360 // 添加节点之间的连线 Sequence Flow 360 // 添加节点之间的连线 Sequence Flow
361 - addBpmnSequenceFlow(mainProcess, simpleModelNode); 361 + addBpmnSequenceFlow(mainProcess, simpleModelNode, BpmnModelConstants.END_EVENT_ID);
362 // 自动布局 362 // 自动布局
363 new BpmnAutoLayout(bpmnModel).execute(); 363 new BpmnAutoLayout(bpmnModel).execute();
364 return bpmnModel; 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 // 节点为 null 退出 368 // 节点为 null 退出
369 if (node == null || node.getId() == null) { 369 if (node == null || node.getId() == null) {
370 return; 370 return;
371 } 371 }
372 BpmSimpleModelNodeVO childNode = node.getChildNode(); 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 return; 376 return;
377 } 377 }
378 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType()); 378 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType());
379 Assert.notNull(nodeType, "模型节点类型不支持"); 379 Assert.notNull(nodeType, "模型节点类型不支持");
380 switch (nodeType) { 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 break; 406 break;
  407 + }
386 default: { 408 default: {
387 // TODO 其它节点类型的实现 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 SequenceFlow sequenceFlow = new SequenceFlow(sourceId, targetId); 420 SequenceFlow sequenceFlow = new SequenceFlow(sourceId, targetId);
396 if (StrUtil.isNotEmpty(conditionExpression)) { 421 if (StrUtil.isNotEmpty(conditionExpression)) {
397 sequenceFlow.setConditionExpression(conditionExpression); 422 sequenceFlow.setConditionExpression(conditionExpression);
398 } 423 }
  424 + if (StrUtil.isNotEmpty(seqFlowId)) {
  425 + sequenceFlow.setId(seqFlowId);
  426 + }
399 mainProcess.addFlowElement(sequenceFlow); 427 mainProcess.addFlowElement(sequenceFlow);
400 } 428 }
401 429
@@ -407,13 +435,15 @@ public class BpmnModelUtils { @@ -407,13 +435,15 @@ public class BpmnModelUtils {
407 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType()); 435 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType());
408 Assert.notNull(nodeType, "模型节点类型不支持"); 436 Assert.notNull(nodeType, "模型节点类型不支持");
409 switch (nodeType) { 437 switch (nodeType) {
410 - case START_NODE: 438 + case START_EVENT_NODE:
411 addBpmnStartEventNode(mainProcess, simpleModelNode); 439 addBpmnStartEventNode(mainProcess, simpleModelNode);
412 break; 440 break;
413 - case START_USER_NODE:  
414 case APPROVE_USER_NODE: 441 case APPROVE_USER_NODE:
415 addBpmnUserTaskEventNode(mainProcess, simpleModelNode); 442 addBpmnUserTaskEventNode(mainProcess, simpleModelNode);
416 break; 443 break;
  444 + case EXCLUSIVE_GATEWAY_NODE:
  445 + addBpmnExclusiveGatewayNode(mainProcess, simpleModelNode);
  446 + break;
417 default: { 447 default: {
418 // TODO 其它节点类型的实现 448 // TODO 其它节点类型的实现
419 } 449 }
@@ -427,7 +457,7 @@ public class BpmnModelUtils { @@ -427,7 +457,7 @@ public class BpmnModelUtils {
427 // 如果是网关类型接口. 递归添加条件节点 457 // 如果是网关类型接口. 递归添加条件节点
428 if (BpmSimpleModelNodeType.isGatewayNode(simpleModelNode.getType()) && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) { 458 if (BpmSimpleModelNodeType.isGatewayNode(simpleModelNode.getType()) && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) {
429 for (BpmSimpleModelNodeVO node : simpleModelNode.getConditionNodes()) { 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,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 private static void addBpmnEndEventNode(Process mainProcess) { 479 private static void addBpmnEndEventNode(Process mainProcess) {
441 EndEvent endEvent = new EndEvent(); 480 EndEvent endEvent = new EndEvent();
442 endEvent.setId(BpmnModelConstants.END_EVENT_ID); 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,7 +20,7 @@ import java.util.Map;
20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
21 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT; 21 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT;
22 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_NOT_EXISTS; 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 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_PARAM; 24 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_PARAM;
25 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY; 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,7 +85,7 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService {
85 return null; 85 return null;
86 } 86 }
87 BpmSimpleModelNodeVO rootNode = new BpmSimpleModelNodeVO(); 87 BpmSimpleModelNodeVO rootNode = new BpmSimpleModelNodeVO();
88 - rootNode.setType(START_NODE.getType()); 88 + rootNode.setType(START_EVENT_NODE.getType());
89 rootNode.setId(startEvent.getId()); 89 rootNode.setId(startEvent.getId());
90 rootNode.setName(startEvent.getName()); 90 rootNode.setName(startEvent.getName());
91 recursiveBuildSimpleModelNode(startEvent, rootNode); 91 recursiveBuildSimpleModelNode(startEvent, rootNode);
@@ -129,7 +129,7 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService { @@ -129,7 +129,7 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService {
129 129
130 private List<SequenceFlow> validateCanConvertSimpleNode(BpmSimpleModelNodeType nodeType, FlowNode currentFlowNode) { 130 private List<SequenceFlow> validateCanConvertSimpleNode(BpmSimpleModelNodeType nodeType, FlowNode currentFlowNode) {
131 switch (nodeType) { 131 switch (nodeType) {
132 - case START_NODE: 132 + case START_EVENT_NODE:
133 case APPROVE_USER_NODE: { 133 case APPROVE_USER_NODE: {
134 List<SequenceFlow> outgoingFlows = currentFlowNode.getOutgoingFlows(); 134 List<SequenceFlow> outgoingFlows = currentFlowNode.getOutgoingFlows();
135 if (CollUtil.isNotEmpty(outgoingFlows) && outgoingFlows.size() > 1) { 135 if (CollUtil.isNotEmpty(outgoingFlows) && outgoingFlows.size() > 1) {