1
0
Эх сурвалжийг харах

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

jason 3 сар өмнө
parent
commit
1684706e9a

+ 3 - 0
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 {
     @Schema(description = "是否填写审批意见", example = "false")
     private Boolean reasonRequire;
 
+    @Schema(description = "跳过表达式", example = "{true}")
+    private String skipExpression;  // 用于审批节点
+
     /**
      * 审批节点拒绝处理
      */

+ 1 - 1
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java

@@ -13,7 +13,7 @@ import lombok.Getter;
 @Getter
 @AllArgsConstructor
 public enum BpmTaskStatusEnum {
-
+    SKIP(-2, "跳过"),
     NOT_START(-1, "未开始"),
     RUNNING(1, "审批中"),
     APPROVE(2, "审批通过"),

+ 28 - 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 {
             || currentElement instanceof EndEvent
             || currentElement instanceof UserTask
             || currentElement instanceof ServiceTask) {
-            // 添加元素
+            // 添加节点
             FlowNode flowNode = (FlowNode) currentElement;
             resultElements.add(flowNode);
+
             // 遍历子节点
             flowNode.getOutgoingFlows().forEach(
                     nextElement -> simulateNextFlowElements(nextElement.getTargetFlowElement(), variables, resultElements, visitElements));
@@ -835,6 +836,31 @@ public class BpmnModelUtils {
         }
     }
 
+    /**
+     * 判断是否跳过此节点
+     *
+     * @param flowNode 节点
+     * @param variables 流程变量
+     */
+    public static boolean isSkipNode(FlowElement flowNode, Map<String, Object> variables) {
+        // 1. 检查节点是否有跳过表达式(支持多种任务节点类型)
+        String skipExpression = null;
+        if (flowNode instanceof UserTask) {
+            skipExpression = ((UserTask) flowNode).getSkipExpression();
+        } else if (flowNode instanceof ServiceTask) {
+            skipExpression = ((ServiceTask) flowNode).getSkipExpression();
+        } else if (flowNode instanceof ScriptTask) {
+            skipExpression = ((ScriptTask) flowNode).getSkipExpression();
+        }
+        
+        if (StrUtil.isEmpty(skipExpression)) {
+            return false;
+        }
+
+        // 2. 计算跳过表达式的值
+        return evalConditionExpress(variables, skipExpression);
+    }
+
     /**
      * 根据当前节点,获取下一个节点
      *
@@ -997,7 +1023,7 @@ public class BpmnModelUtils {
      * @return 是否满足条件
      */
     public static boolean evalConditionExpress(Map<String, Object> variables, String expression) {
-        if (expression == null) {
+        if (StrUtil.isEmpty(expression)) {
             return Boolean.FALSE;
         }
         // 如果 variables 为空,则创建一个的原因?可能 expression 的计算,不依赖于 variables

+ 17 - 1
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java

@@ -464,9 +464,15 @@ public class SimpleModelUtils {
             addReasonRequire(node.getReasonRequire(), userTask);
             // 节点类型
             addNodeType(node.getType(), userTask);
+            // 添加跳过表达式
+            if (StrUtil.isNotEmpty(node.getSkipExpression())) {
+                userTask.setSkipExpression(node.getSkipExpression());
+            }
             return userTask;
         }
 
+
+
         private void addUserTaskListener(BpmSimpleModelNodeVO node, UserTask userTask) {
             List<FlowableListener> flowableListeners = new ArrayList<>(3);
             if (node.getTaskCreateListener() != null
@@ -967,7 +973,7 @@ public class SimpleModelUtils {
                 || nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE
                 || nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS
                 || nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) {
-            // 添加元素
+            // 添加此节点
             resultNodes.add(currentNode);
         }
 
@@ -1013,6 +1019,16 @@ public class SimpleModelUtils {
         simulateNextNode(currentNode.getChildNode(), variables, resultNodes);
     }
 
+    /**
+     * 根据跳过表达式,判断是否跳过此节点。
+     */
+    public static boolean isSkipNode(BpmSimpleModelNodeVO currentNode, Map<String, Object> variables) {
+        if (StrUtil.isEmpty(currentNode.getSkipExpression())) {
+            return false;
+        }
+        return BpmnModelUtils.evalConditionExpress(variables, currentNode.getSkipExpression());
+    }
+
     public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) {
         return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting));
     }

+ 22 - 4
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java

@@ -398,7 +398,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
                             ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()
                             : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别
                             BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()))
-                    .setStatus(FlowableUtils.getTaskStatus(task))
+                    .setStatus(getEndActivityNodeStatus(task))
                     .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
                     .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime()))
                     .setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task)));
@@ -462,6 +462,15 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
         return approvalNodes;
     }
 
+
+    /**
+     *  获取结束节点的状态
+     */
+    private Integer getEndActivityNodeStatus(HistoricTaskInstance task) {
+        Integer status = FlowableUtils.getTaskStatus(task);
+        return status == null ? BpmTaskStatusEnum.SKIP.getStatus() : status;  // 结束节点未获取到状态,为跳过状态
+    }
+
     /**
      * 获得【进行中】的活动节点们
      */
@@ -565,10 +574,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
         if (runActivityIds.contains(node.getId())) {
             return null;
         }
-
+        Integer status = BpmTaskStatusEnum.NOT_START.getStatus();
+        // 如果节点被跳过。设置状态为跳过
+        if (SimpleModelUtils.isSkipNode(node, processVariables)) {
+            status = BpmTaskStatusEnum.SKIP.getStatus();
+        }
         ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName())
                 .setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy())
-                .setStatus(BpmTaskStatusEnum.NOT_START.getStatus());
+                .setStatus(status);
 
         // 1. 开始节点/审批节点
         if (ObjectUtils.equalsAny(node.getType(),
@@ -608,8 +621,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
         if (runActivityIds.contains(node.getId())) {
             return null;
         }
+        Integer status = BpmTaskStatusEnum.NOT_START.getStatus();
+        // 如果节点被跳过,状态设置为跳过
+        if(BpmnModelUtils.isSkipNode(node, processVariables)){
+            status = BpmTaskStatusEnum.SKIP.getStatus();
+        }
         ActivityNode activityNode = new ActivityNode().setId(node.getId())
-                .setStatus(BpmTaskStatusEnum.NOT_START.getStatus());
+                .setStatus(status);
 
         // 1. 开始节点
         if (node instanceof StartEvent) {