Commit 1684706e9aa70df8675b4b6bba212b7f5541d078

Authored by jason
1 parent 76d89067

feat: [BPM 工作流] 增加跳过表达式判断。

yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
@@ -71,6 +71,9 @@ public class BpmSimpleModelNodeVO { @@ -71,6 +71,9 @@ public class BpmSimpleModelNodeVO {
71 @Schema(description = "是否填写审批意见", example = "false") 71 @Schema(description = "是否填写审批意见", example = "false")
72 private Boolean reasonRequire; 72 private Boolean reasonRequire;
73 73
  74 + @Schema(description = "跳过表达式", example = "{true}")
  75 + private String skipExpression; // 用于审批节点
  76 +
74 /** 77 /**
75 * 审批节点拒绝处理 78 * 审批节点拒绝处理
76 */ 79 */
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java
@@ -13,7 +13,7 @@ import lombok.Getter; @@ -13,7 +13,7 @@ import lombok.Getter;
13 @Getter 13 @Getter
14 @AllArgsConstructor 14 @AllArgsConstructor
15 public enum BpmTaskStatusEnum { 15 public enum BpmTaskStatusEnum {
16 - 16 + SKIP(-2, "跳过"),
17 NOT_START(-1, "未开始"), 17 NOT_START(-1, "未开始"),
18 RUNNING(1, "审批中"), 18 RUNNING(1, "审批中"),
19 APPROVE(2, "审批通过"), 19 APPROVE(2, "审批通过"),
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
@@ -800,9 +800,10 @@ public class BpmnModelUtils { @@ -800,9 +800,10 @@ public class BpmnModelUtils {
800 || currentElement instanceof EndEvent 800 || currentElement instanceof EndEvent
801 || currentElement instanceof UserTask 801 || currentElement instanceof UserTask
802 || currentElement instanceof ServiceTask) { 802 || currentElement instanceof ServiceTask) {
803 - // 添加元素 803 + // 添加节点
804 FlowNode flowNode = (FlowNode) currentElement; 804 FlowNode flowNode = (FlowNode) currentElement;
805 resultElements.add(flowNode); 805 resultElements.add(flowNode);
  806 +
806 // 遍历子节点 807 // 遍历子节点
807 flowNode.getOutgoingFlows().forEach( 808 flowNode.getOutgoingFlows().forEach(
808 nextElement -> simulateNextFlowElements(nextElement.getTargetFlowElement(), variables, resultElements, visitElements)); 809 nextElement -> simulateNextFlowElements(nextElement.getTargetFlowElement(), variables, resultElements, visitElements));
@@ -836,6 +837,31 @@ public class BpmnModelUtils { @@ -836,6 +837,31 @@ public class BpmnModelUtils {
836 } 837 }
837 838
838 /** 839 /**
  840 + * 判断是否跳过此节点
  841 + *
  842 + * @param flowNode 节点
  843 + * @param variables 流程变量
  844 + */
  845 + public static boolean isSkipNode(FlowElement flowNode, Map<String, Object> variables) {
  846 + // 1. 检查节点是否有跳过表达式(支持多种任务节点类型)
  847 + String skipExpression = null;
  848 + if (flowNode instanceof UserTask) {
  849 + skipExpression = ((UserTask) flowNode).getSkipExpression();
  850 + } else if (flowNode instanceof ServiceTask) {
  851 + skipExpression = ((ServiceTask) flowNode).getSkipExpression();
  852 + } else if (flowNode instanceof ScriptTask) {
  853 + skipExpression = ((ScriptTask) flowNode).getSkipExpression();
  854 + }
  855 +
  856 + if (StrUtil.isEmpty(skipExpression)) {
  857 + return false;
  858 + }
  859 +
  860 + // 2. 计算跳过表达式的值
  861 + return evalConditionExpress(variables, skipExpression);
  862 + }
  863 +
  864 + /**
839 * 根据当前节点,获取下一个节点 865 * 根据当前节点,获取下一个节点
840 * 866 *
841 * @param currentElement 当前节点 867 * @param currentElement 当前节点
@@ -997,7 +1023,7 @@ public class BpmnModelUtils { @@ -997,7 +1023,7 @@ public class BpmnModelUtils {
997 * @return 是否满足条件 1023 * @return 是否满足条件
998 */ 1024 */
999 public static boolean evalConditionExpress(Map<String, Object> variables, String expression) { 1025 public static boolean evalConditionExpress(Map<String, Object> variables, String expression) {
1000 - if (expression == null) { 1026 + if (StrUtil.isEmpty(expression)) {
1001 return Boolean.FALSE; 1027 return Boolean.FALSE;
1002 } 1028 }
1003 // 如果 variables 为空,则创建一个的原因?可能 expression 的计算,不依赖于 variables 1029 // 如果 variables 为空,则创建一个的原因?可能 expression 的计算,不依赖于 variables
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
@@ -464,9 +464,15 @@ public class SimpleModelUtils { @@ -464,9 +464,15 @@ public class SimpleModelUtils {
464 addReasonRequire(node.getReasonRequire(), userTask); 464 addReasonRequire(node.getReasonRequire(), userTask);
465 // 节点类型 465 // 节点类型
466 addNodeType(node.getType(), userTask); 466 addNodeType(node.getType(), userTask);
  467 + // 添加跳过表达式
  468 + if (StrUtil.isNotEmpty(node.getSkipExpression())) {
  469 + userTask.setSkipExpression(node.getSkipExpression());
  470 + }
467 return userTask; 471 return userTask;
468 } 472 }
469 473
  474 +
  475 +
470 private void addUserTaskListener(BpmSimpleModelNodeVO node, UserTask userTask) { 476 private void addUserTaskListener(BpmSimpleModelNodeVO node, UserTask userTask) {
471 List<FlowableListener> flowableListeners = new ArrayList<>(3); 477 List<FlowableListener> flowableListeners = new ArrayList<>(3);
472 if (node.getTaskCreateListener() != null 478 if (node.getTaskCreateListener() != null
@@ -967,7 +973,7 @@ public class SimpleModelUtils { @@ -967,7 +973,7 @@ public class SimpleModelUtils {
967 || nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE 973 || nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE
968 || nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS 974 || nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS
969 || nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) { 975 || nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) {
970 - // 添加元素 976 + // 添加此节点
971 resultNodes.add(currentNode); 977 resultNodes.add(currentNode);
972 } 978 }
973 979
@@ -1013,6 +1019,16 @@ public class SimpleModelUtils { @@ -1013,6 +1019,16 @@ public class SimpleModelUtils {
1013 simulateNextNode(currentNode.getChildNode(), variables, resultNodes); 1019 simulateNextNode(currentNode.getChildNode(), variables, resultNodes);
1014 } 1020 }
1015 1021
  1022 + /**
  1023 + * 根据跳过表达式,判断是否跳过此节点。
  1024 + */
  1025 + public static boolean isSkipNode(BpmSimpleModelNodeVO currentNode, Map<String, Object> variables) {
  1026 + if (StrUtil.isEmpty(currentNode.getSkipExpression())) {
  1027 + return false;
  1028 + }
  1029 + return BpmnModelUtils.evalConditionExpress(variables, currentNode.getSkipExpression());
  1030 + }
  1031 +
1016 public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { 1032 public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) {
1017 return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting)); 1033 return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting));
1018 } 1034 }
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
@@ -398,7 +398,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -398,7 +398,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
398 ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType() 398 ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()
399 : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别 399 : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别
400 BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())) 400 BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()))
401 - .setStatus(FlowableUtils.getTaskStatus(task)) 401 + .setStatus(getEndActivityNodeStatus(task))
402 .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) 402 .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
403 .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime())) 403 .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime()))
404 .setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task))); 404 .setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task)));
@@ -462,6 +462,15 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -462,6 +462,15 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
462 return approvalNodes; 462 return approvalNodes;
463 } 463 }
464 464
  465 +
  466 + /**
  467 + * 获取结束节点的状态
  468 + */
  469 + private Integer getEndActivityNodeStatus(HistoricTaskInstance task) {
  470 + Integer status = FlowableUtils.getTaskStatus(task);
  471 + return status == null ? BpmTaskStatusEnum.SKIP.getStatus() : status; // 结束节点未获取到状态,为跳过状态
  472 + }
  473 +
465 /** 474 /**
466 * 获得【进行中】的活动节点们 475 * 获得【进行中】的活动节点们
467 */ 476 */
@@ -565,10 +574,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -565,10 +574,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
565 if (runActivityIds.contains(node.getId())) { 574 if (runActivityIds.contains(node.getId())) {
566 return null; 575 return null;
567 } 576 }
568 - 577 + Integer status = BpmTaskStatusEnum.NOT_START.getStatus();
  578 + // 如果节点被跳过。设置状态为跳过
  579 + if (SimpleModelUtils.isSkipNode(node, processVariables)) {
  580 + status = BpmTaskStatusEnum.SKIP.getStatus();
  581 + }
569 ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName()) 582 ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName())
570 .setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy()) 583 .setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy())
571 - .setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); 584 + .setStatus(status);
572 585
573 // 1. 开始节点/审批节点 586 // 1. 开始节点/审批节点
574 if (ObjectUtils.equalsAny(node.getType(), 587 if (ObjectUtils.equalsAny(node.getType(),
@@ -608,8 +621,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -608,8 +621,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
608 if (runActivityIds.contains(node.getId())) { 621 if (runActivityIds.contains(node.getId())) {
609 return null; 622 return null;
610 } 623 }
  624 + Integer status = BpmTaskStatusEnum.NOT_START.getStatus();
  625 + // 如果节点被跳过,状态设置为跳过
  626 + if(BpmnModelUtils.isSkipNode(node, processVariables)){
  627 + status = BpmTaskStatusEnum.SKIP.getStatus();
  628 + }
611 ActivityNode activityNode = new ActivityNode().setId(node.getId()) 629 ActivityNode activityNode = new ActivityNode().setId(node.getId())
612 - .setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); 630 + .setStatus(status);
613 631
614 // 1. 开始节点 632 // 1. 开始节点
615 if (node instanceof StartEvent) { 633 if (node instanceof StartEvent) {