Commit 1684706e9aa70df8675b4b6bba212b7f5541d078
1 parent
76d89067
feat: [BPM 工作流] 增加跳过表达式判断。
Showing
5 changed files
with
71 additions
and
8 deletions
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 | 71 | @Schema(description = "是否填写审批意见", example = "false") |
| 72 | 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
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 | 800 | || currentElement instanceof EndEvent |
| 801 | 801 | || currentElement instanceof UserTask |
| 802 | 802 | || currentElement instanceof ServiceTask) { |
| 803 | - // 添加元素 | |
| 803 | + // 添加节点 | |
| 804 | 804 | FlowNode flowNode = (FlowNode) currentElement; |
| 805 | 805 | resultElements.add(flowNode); |
| 806 | + | |
| 806 | 807 | // 遍历子节点 |
| 807 | 808 | flowNode.getOutgoingFlows().forEach( |
| 808 | 809 | nextElement -> simulateNextFlowElements(nextElement.getTargetFlowElement(), variables, resultElements, visitElements)); |
| ... | ... | @@ -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 | 867 | * @param currentElement 当前节点 |
| ... | ... | @@ -997,7 +1023,7 @@ public class BpmnModelUtils { |
| 997 | 1023 | * @return 是否满足条件 |
| 998 | 1024 | */ |
| 999 | 1025 | public static boolean evalConditionExpress(Map<String, Object> variables, String expression) { |
| 1000 | - if (expression == null) { | |
| 1026 | + if (StrUtil.isEmpty(expression)) { | |
| 1001 | 1027 | return Boolean.FALSE; |
| 1002 | 1028 | } |
| 1003 | 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 | 464 | addReasonRequire(node.getReasonRequire(), userTask); |
| 465 | 465 | // 节点类型 |
| 466 | 466 | addNodeType(node.getType(), userTask); |
| 467 | + // 添加跳过表达式 | |
| 468 | + if (StrUtil.isNotEmpty(node.getSkipExpression())) { | |
| 469 | + userTask.setSkipExpression(node.getSkipExpression()); | |
| 470 | + } | |
| 467 | 471 | return userTask; |
| 468 | 472 | } |
| 469 | 473 | |
| 474 | + | |
| 475 | + | |
| 470 | 476 | private void addUserTaskListener(BpmSimpleModelNodeVO node, UserTask userTask) { |
| 471 | 477 | List<FlowableListener> flowableListeners = new ArrayList<>(3); |
| 472 | 478 | if (node.getTaskCreateListener() != null |
| ... | ... | @@ -967,7 +973,7 @@ public class SimpleModelUtils { |
| 967 | 973 | || nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE |
| 968 | 974 | || nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS |
| 969 | 975 | || nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) { |
| 970 | - // 添加元素 | |
| 976 | + // 添加此节点 | |
| 971 | 977 | resultNodes.add(currentNode); |
| 972 | 978 | } |
| 973 | 979 | |
| ... | ... | @@ -1013,6 +1019,16 @@ public class SimpleModelUtils { |
| 1013 | 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 | 1032 | public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { |
| 1017 | 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 | 398 | ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType() |
| 399 | 399 | : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别 |
| 400 | 400 | BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())) |
| 401 | - .setStatus(FlowableUtils.getTaskStatus(task)) | |
| 401 | + .setStatus(getEndActivityNodeStatus(task)) | |
| 402 | 402 | .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) |
| 403 | 403 | .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime())) |
| 404 | 404 | .setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task))); |
| ... | ... | @@ -462,6 +462,15 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 462 | 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 | 574 | if (runActivityIds.contains(node.getId())) { |
| 566 | 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 | 582 | ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName()) |
| 570 | 583 | .setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy()) |
| 571 | - .setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); | |
| 584 | + .setStatus(status); | |
| 572 | 585 | |
| 573 | 586 | // 1. 开始节点/审批节点 |
| 574 | 587 | if (ObjectUtils.equalsAny(node.getType(), |
| ... | ... | @@ -608,8 +621,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 608 | 621 | if (runActivityIds.contains(node.getId())) { |
| 609 | 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 | 629 | ActivityNode activityNode = new ActivityNode().setId(node.getId()) |
| 612 | - .setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); | |
| 630 | + .setStatus(status); | |
| 613 | 631 | |
| 614 | 632 | // 1. 开始节点 |
| 615 | 633 | if (node instanceof StartEvent) { | ... | ... |