Commit fedb9242b59b9846951d49e475b718c5a87a406e
1 parent
10d7cbb9
【代码评审】BPM:下一个审批人
Showing
6 changed files
with
62 additions
and
80 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
| ... | ... | @@ -58,7 +58,6 @@ public interface ErrorCodeConstants { |
| 58 | 58 | ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!"); |
| 59 | 59 | ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!"); |
| 60 | 60 | ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!"); |
| 61 | - ErrorCode TASK_START_USER_SELECT_NODE_NOT_EXISTS = new ErrorCode(1_009_004_007, "({})不是下一个执行的流程节点!"); | |
| 62 | 61 | |
| 63 | 62 | // ========== 动态表单模块 1-009-010-000 ========== |
| 64 | 63 | ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在"); | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java
| ... | ... | @@ -25,6 +25,6 @@ public class BpmTaskApproveReqVO { |
| 25 | 25 | private Map<String, Object> variables; |
| 26 | 26 | |
| 27 | 27 | @Schema(description = "下一个节点审批人", example = "{nodeId:[1, 2]}") |
| 28 | - private Map<String, List<Long>> nextAssignees; | |
| 28 | + private Map<String, List<Long>> nextAssignees; // 为什么是 Map,而不是 List 呢?因为下一个节点可能是多个,例如说并行网关的情况 | |
| 29 | 29 | |
| 30 | 30 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserSelectStrategy.java
| ... | ... | @@ -2,24 +2,21 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.d |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.lang.Assert; |
| 5 | -import cn.hutool.core.util.ObjectUtil; | |
| 6 | 5 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user.BpmTaskCandidateUserStrategy; |
| 7 | 6 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; |
| 8 | -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; | |
| 9 | 7 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; |
| 10 | 8 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| 11 | 9 | import com.google.common.collect.Sets; |
| 12 | 10 | import jakarta.annotation.Resource; |
| 13 | 11 | import org.flowable.bpmn.model.BpmnModel; |
| 14 | -import org.flowable.bpmn.model.ServiceTask; | |
| 15 | -import org.flowable.bpmn.model.Task; | |
| 16 | -import org.flowable.bpmn.model.UserTask; | |
| 17 | 12 | import org.flowable.engine.delegate.DelegateExecution; |
| 18 | 13 | import org.flowable.engine.runtime.ProcessInstance; |
| 19 | 14 | import org.springframework.context.annotation.Lazy; |
| 20 | 15 | import org.springframework.stereotype.Component; |
| 21 | 16 | |
| 22 | -import java.util.*; | |
| 17 | +import java.util.LinkedHashSet; | |
| 18 | +import java.util.List; | |
| 19 | +import java.util.Map; | |
| 23 | 20 | |
| 24 | 21 | /** |
| 25 | 22 | * 发起人自选 {@link BpmTaskCandidateUserStrategy} 实现类 |
| ... | ... | @@ -53,12 +50,9 @@ public class BpmTaskCandidateStartUserSelectStrategy extends AbstractBpmTaskCand |
| 53 | 50 | Map<String, List<Long>> startUserSelectAssignees = FlowableUtils.getStartUserSelectAssignees(processInstance); |
| 54 | 51 | Assert.notNull(startUserSelectAssignees, "流程实例({}) 的发起人自选审批人不能为空", |
| 55 | 52 | execution.getProcessInstanceId()); |
| 56 | - // 获得审批人,如果不存在,则直接返回空,fix: 用于节点预测时,如果该节点不存在发起人自选审批人,类型转换异常 | |
| 53 | + // 获得审批人 | |
| 57 | 54 | List<Long> assignees = startUserSelectAssignees.get(execution.getCurrentActivityId()); |
| 58 | - if (CollUtil.isEmpty(assignees)){ | |
| 59 | - return Sets.newLinkedHashSet(); | |
| 60 | - } | |
| 61 | - return new LinkedHashSet<>(assignees); | |
| 55 | + return CollUtil.isNotEmpty(assignees) ? new LinkedHashSet<>(assignees) : Sets.newLinkedHashSet(); | |
| 62 | 56 | } |
| 63 | 57 | |
| 64 | 58 | @Override |
| ... | ... | @@ -71,33 +65,9 @@ public class BpmTaskCandidateStartUserSelectStrategy extends AbstractBpmTaskCand |
| 71 | 65 | if (startUserSelectAssignees == null) { |
| 72 | 66 | return Sets.newLinkedHashSet(); |
| 73 | 67 | } |
| 74 | - // 获得审批人,如果不存在,则直接返回空,fix: 用于节点预测时,如果该节点不存在发起人自选审批人,类型转换异常 | |
| 68 | + // 获得审批人 | |
| 75 | 69 | List<Long> assignees = startUserSelectAssignees.get(activityId); |
| 76 | - if (CollUtil.isEmpty(assignees)){ | |
| 77 | - return Sets.newLinkedHashSet(); | |
| 78 | - } | |
| 79 | - return new LinkedHashSet<>(assignees); | |
| 80 | - } | |
| 81 | - | |
| 82 | - /** | |
| 83 | - * 获得发起人自选审批人或抄送人的 Task 列表 | |
| 84 | - * | |
| 85 | - * @param bpmnModel BPMN 模型 | |
| 86 | - * @return Task 列表 | |
| 87 | - */ | |
| 88 | - public static List<Task> getStartUserSelectTaskList(BpmnModel bpmnModel) { | |
| 89 | - if (bpmnModel == null) { | |
| 90 | - return Collections.emptyList(); | |
| 91 | - } | |
| 92 | - List<Task> tasks = new ArrayList<>(); | |
| 93 | - tasks.addAll(BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class)); | |
| 94 | - tasks.addAll(BpmnModelUtils.getBpmnModelElements(bpmnModel, ServiceTask.class)); | |
| 95 | - if (CollUtil.isEmpty(tasks)) { | |
| 96 | - return Collections.emptyList(); | |
| 97 | - } | |
| 98 | - tasks.removeIf(task -> ObjectUtil.notEqual(BpmnModelUtils.parseCandidateStrategy(task), | |
| 99 | - BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy())); | |
| 100 | - return tasks; | |
| 70 | + return CollUtil.isNotEmpty(assignees) ? new LinkedHashSet<>(assignees) : Sets.newLinkedHashSet(); | |
| 101 | 71 | } |
| 102 | 72 | |
| 103 | 73 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
| ... | ... | @@ -809,8 +809,7 @@ public class BpmnModelUtils { |
| 809 | 809 | if (currentElement instanceof ExclusiveGateway) { |
| 810 | 810 | // 查找满足条件的 SequenceFlow 路径 |
| 811 | 811 | Gateway gateway = (Gateway) currentElement; |
| 812 | - // TODO @小北:当一个网关节点下存在多个满足的并行节点时,只查询一个节点流程流转会存在问题,需要优化, | |
| 813 | - // TODO 具体见issue:https://github.com/YunaiV/ruoyi-vue-pro/issues/761 | |
| 812 | + // TODO @小北:当一个网关节点下存在多个满足的并行节点时,只查询一个节点流程流转会存在问题。需要优化,具体见issue:https://github.com/YunaiV/ruoyi-vue-pro/issues/761 | |
| 814 | 813 | SequenceFlow matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(), |
| 815 | 814 | flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId()) |
| 816 | 815 | && (evalConditionExpress(variables, flow.getConditionExpression()))); |
| ... | ... | @@ -866,27 +865,27 @@ public class BpmnModelUtils { |
| 866 | 865 | * @param bpmnModel BPMN模型 |
| 867 | 866 | * @param variables 流程变量 |
| 868 | 867 | */ |
| 868 | + @SuppressWarnings("PatternVariableCanBeUsed") | |
| 869 | 869 | public static List<FlowNode> getNextFlowNodes(FlowElement currentElement, BpmnModel bpmnModel, |
| 870 | 870 | Map<String, Object> variables){ |
| 871 | - // 下一个执行的流程节点集合 | |
| 872 | - List<FlowNode> nextFlowNodes = new ArrayList<>(); | |
| 873 | - // 当前执行节点的基本属性 | |
| 874 | - FlowNode currentNode = (FlowNode) currentElement; | |
| 875 | - // 获取当前节点的关联节点 | |
| 876 | - List<SequenceFlow> outgoingFlows = currentNode.getOutgoingFlows(); | |
| 877 | - if (CollUtil.isEmpty(outgoingFlows)){ | |
| 871 | + List<FlowNode> nextFlowNodes = new ArrayList<>(); // 下一个执行的流程节点集合 | |
| 872 | + FlowNode currentNode = (FlowNode) currentElement; // 当前执行节点的基本属性 | |
| 873 | + List<SequenceFlow> outgoingFlows = currentNode.getOutgoingFlows(); // 当前节点的关联节点 | |
| 874 | + if (CollUtil.isEmpty(outgoingFlows)) { | |
| 878 | 875 | log.warn("[getNextFlowNodes][当前节点({}) 的 outgoingFlows 为空]", currentNode.getId()); |
| 879 | 876 | return nextFlowNodes; |
| 880 | 877 | } |
| 878 | + | |
| 881 | 879 | // 遍历每个出口流 |
| 882 | 880 | for (SequenceFlow outgoingFlow : outgoingFlows) { |
| 883 | 881 | // 获取目标节点的基本属性 |
| 884 | 882 | FlowElement targetElement = bpmnModel.getFlowElement(outgoingFlow.getTargetRef()); |
| 885 | - if (targetElement == null){ | |
| 883 | + if (targetElement == null) { | |
| 886 | 884 | continue; |
| 887 | 885 | } |
| 888 | - if (targetElement instanceof Gateway gateway) { | |
| 889 | - // 处理不同类型的网关 | |
| 886 | + // 情况一:处理不同类型的网关 | |
| 887 | + if (targetElement instanceof Gateway) { | |
| 888 | + Gateway gateway = (Gateway) targetElement; | |
| 890 | 889 | if (gateway instanceof ExclusiveGateway) { |
| 891 | 890 | handleExclusiveGateway(gateway, bpmnModel, variables, nextFlowNodes); |
| 892 | 891 | } else if (gateway instanceof InclusiveGateway) { |
| ... | ... | @@ -895,7 +894,7 @@ public class BpmnModelUtils { |
| 895 | 894 | handleParallelGateway(gateway, bpmnModel, variables, nextFlowNodes); |
| 896 | 895 | } |
| 897 | 896 | } else { |
| 898 | - // 如果不是网关,直接添加到下一个节点列表 | |
| 897 | + // 情况二:如果不是网关,直接添加到下一个节点列表 | |
| 899 | 898 | nextFlowNodes.add((FlowNode) targetElement); |
| 900 | 899 | } |
| 901 | 900 | } |
| ... | ... | @@ -903,15 +902,17 @@ public class BpmnModelUtils { |
| 903 | 902 | } |
| 904 | 903 | |
| 905 | 904 | /** |
| 906 | - * 处理排他网关 | |
| 905 | + * 处理排它网关 | |
| 907 | 906 | * |
| 908 | 907 | * @param gateway 排他网关 |
| 909 | 908 | * @param bpmnModel BPMN模型 |
| 910 | 909 | * @param variables 流程变量 |
| 911 | 910 | * @param nextFlowNodes 下一个执行的流程节点集合 |
| 912 | 911 | */ |
| 913 | - private static void handleExclusiveGateway(Gateway gateway, BpmnModel bpmnModel, Map<String, Object> variables, List<FlowNode> nextFlowNodes) { | |
| 914 | - // TODO @小北: 这里和simulateNextFlowElements中有重复代码,是否重构??每个网关节点拆分出方法应该比较合理化,@芋道 | |
| 912 | + private static void handleExclusiveGateway(Gateway gateway, BpmnModel bpmnModel, | |
| 913 | + Map<String, Object> variables, List<FlowNode> nextFlowNodes) { | |
| 914 | + // TODO @小北: 这里和 simulateNextFlowElements 中有重复代码,是否重构??每个网关节点拆分出方法应该比较合理化,@芋艿 | |
| 915 | + // TODO @小北:ok,把 simulateNextFlowElements 里面处理网关的,复用这个方法,可以么? | |
| 915 | 916 | SequenceFlow matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(), |
| 916 | 917 | flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId()) |
| 917 | 918 | && (evalConditionExpress(variables, flow.getConditionExpression()))); |
| ... | ... | @@ -940,7 +941,8 @@ public class BpmnModelUtils { |
| 940 | 941 | * @param variables 流程变量 |
| 941 | 942 | * @param nextFlowNodes 下一个执行的流程节点集合 |
| 942 | 943 | */ |
| 943 | - private static void handleInclusiveGateway(Gateway gateway, BpmnModel bpmnModel, Map<String, Object> variables, List<FlowNode> nextFlowNodes) { | |
| 944 | + private static void handleInclusiveGateway(Gateway gateway, BpmnModel bpmnModel, | |
| 945 | + Map<String, Object> variables, List<FlowNode> nextFlowNodes) { | |
| 944 | 946 | Collection<SequenceFlow> matchSequenceFlows = CollUtil.filterNew(gateway.getOutgoingFlows(), |
| 945 | 947 | flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId()) |
| 946 | 948 | && evalConditionExpress(variables, flow.getConditionExpression())); |
| ... | ... | @@ -960,6 +962,7 @@ public class BpmnModelUtils { |
| 960 | 962 | } |
| 961 | 963 | }); |
| 962 | 964 | } |
| 965 | + | |
| 963 | 966 | /** |
| 964 | 967 | * 处理并行网关 |
| 965 | 968 | * |
| ... | ... | @@ -968,7 +971,8 @@ public class BpmnModelUtils { |
| 968 | 971 | * @param variables 流程变量 |
| 969 | 972 | * @param nextFlowNodes 下一个执行的流程节点集合 |
| 970 | 973 | */ |
| 971 | - private static void handleParallelGateway(Gateway gateway, BpmnModel bpmnModel, Map<String, Object> variables, List<FlowNode> nextFlowNodes) { | |
| 974 | + private static void handleParallelGateway(Gateway gateway, BpmnModel bpmnModel, | |
| 975 | + Map<String, Object> variables, List<FlowNode> nextFlowNodes) { | |
| 972 | 976 | // 并行网关,遍历所有出口路径,获取目标节点 |
| 973 | 977 | gateway.getOutgoingFlows().forEach(flow -> { |
| 974 | 978 | FlowElement targetElement = bpmnModel.getFlowElement(flow.getTargetRef()); | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| ... | ... | @@ -175,9 +175,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 175 | 175 | } |
| 176 | 176 | startUserId = Long.valueOf(historicProcessInstance.getStartUserId()); |
| 177 | 177 | processInstanceStatus = FlowableUtils.getProcessInstanceStatus(historicProcessInstance); |
| 178 | - // 如果流程变量不为空,则用前端传递的新变量值覆盖历史的流程变量 | |
| 178 | + // 合并 DB 和前端传递的流量变量,以前端的为主 | |
| 179 | 179 | Map<String, Object> historicVariables = historicProcessInstance.getProcessVariables(); |
| 180 | - if (null != processVariables) { | |
| 180 | + if (CollUtil.isNotEmpty(processVariables)) { | |
| 181 | 181 | historicVariables.putAll(processVariables); |
| 182 | 182 | } |
| 183 | 183 | processVariables = historicVariables; | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| ... | ... | @@ -11,13 +11,10 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| 11 | 11 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 12 | 12 | import cn.iocoder.yudao.framework.common.util.object.PageUtils; |
| 13 | 13 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; |
| 14 | -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailReqVO; | |
| 15 | -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO; | |
| 16 | 14 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; |
| 17 | 15 | import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; |
| 18 | 16 | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; |
| 19 | 17 | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; |
| 20 | -import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants; | |
| 21 | 18 | import cn.iocoder.yudao.module.bpm.enums.definition.*; |
| 22 | 19 | import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; |
| 23 | 20 | import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum; |
| ... | ... | @@ -63,7 +60,6 @@ import org.springframework.transaction.support.TransactionSynchronization; |
| 63 | 60 | import org.springframework.transaction.support.TransactionSynchronizationManager; |
| 64 | 61 | |
| 65 | 62 | import java.util.*; |
| 66 | -import java.util.stream.Collectors; | |
| 67 | 63 | import java.util.stream.Stream; |
| 68 | 64 | |
| 69 | 65 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| ... | ... | @@ -535,9 +531,15 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 535 | 531 | Map<String, Object> variables = FlowableUtils.filterTaskFormVariable(reqVO.getVariables()); |
| 536 | 532 | // 校验传递的参数中是否为下一个将要执行的任务节点 |
| 537 | 533 | validateNextAssignees(task.getTaskDefinitionKey(), reqVO.getVariables(), bpmnModel, reqVO.getNextAssignees(), instance); |
| 538 | - // 下个节点审批人如果不存在,则由前端传递 | |
| 534 | + // 如果有下一个审批人,则设置到流程变量中 | |
| 535 | + // TODO @小北:validateNextAssignees 升级成 validateAndSetNextAssignees,然后里面吧下面这一小段逻辑,抽进去如何? | |
| 539 | 536 | if (CollUtil.isNotEmpty(reqVO.getNextAssignees())) { |
| 540 | 537 | // 获取实例中的全部节点数据,避免后续节点的审批人被覆盖 |
| 538 | + // TODO @小北:这里有个需要讨论的点,微信哈; | |
| 539 | + // TODO 因为 PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES 定位是发起人,那么审批人选择的,放在 PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES。目前想到两个方案: | |
| 540 | + // TODO 方案一:增加一个 PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES,然后设置到这里面。然后,BpmTaskCandidateStartUserSelectStrategy 也从这里读 | |
| 541 | + // TODO 方案二:也是增加一个 PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES,根据节点审批人类型,放到 PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES、PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES | |
| 542 | + // TODO 方案三:融合成 PROCESS_INSTANCE_VARIABLE_USER_SELECT_ASSIGNEES,不再区分是发起人选择、还是审批人选择。 | |
| 541 | 543 | Map<String, List<Long>> hisProcessVariables = FlowableUtils.getStartUserSelectAssignees(instance.getProcessVariables()); |
| 542 | 544 | hisProcessVariables.putAll(reqVO.getNextAssignees()); |
| 543 | 545 | variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, hisProcessVariables); |
| ... | ... | @@ -554,45 +556,52 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 554 | 556 | |
| 555 | 557 | |
| 556 | 558 | /** |
| 557 | - * 校验传递的参数中是否为下一个将要执行的任务节点 | |
| 559 | + * 校验选择的下一个节点的审批人,是否合法 | |
| 558 | 560 | * |
| 559 | - * @param taskDefinitionKey 当前任务节点id | |
| 561 | + * 1. 是否有漏选:没有选择审批人 | |
| 562 | + * 2. 是否有多选:非下一个节点 | |
| 563 | + * | |
| 564 | + * @param taskDefinitionKey 当前任务节点标识 | |
| 560 | 565 | * @param variables 流程变量 |
| 561 | 566 | * @param bpmnModel 流程模型 |
| 562 | - * @param nextActivityNodes 下一个节点审批人集合(参数) | |
| 567 | + * @param nextAssignees 下一个节点审批人集合(参数) | |
| 568 | + * @param processInstance 流程实例 | |
| 563 | 569 | */ |
| 564 | 570 | private void validateNextAssignees(String taskDefinitionKey, Map<String, Object> variables, BpmnModel bpmnModel, |
| 565 | - Map<String, List<Long>> nextActivityNodes,ProcessInstance processInstance){ | |
| 566 | - // 1、获取当前任务节点的信息 | |
| 571 | + Map<String, List<Long>> nextAssignees, ProcessInstance processInstance) { | |
| 572 | + // 1. 获取当前任务节点的信息 | |
| 567 | 573 | FlowElement flowElement = bpmnModel.getFlowElement(taskDefinitionKey); |
| 568 | - // 2、获取下一个将要执行的节点集合 | |
| 574 | + // 2. 获取下一个将要执行的节点集合 | |
| 569 | 575 | List<FlowNode> nextFlowNodes = getNextFlowNodes(flowElement, bpmnModel, variables); |
| 570 | - // 3、循环下一个将要执行的节点集合 | |
| 576 | + | |
| 577 | + // 3. 循环下一个将要执行的节点集合 | |
| 571 | 578 | for (FlowNode nextFlowNode : nextFlowNodes) { |
| 572 | - // 3.1、获取下一个将要执行节点的属性(是否为自选审批人等) | |
| 579 | + // 3.1 获取下一个将要执行节点的属性(是否为自选审批人等) | |
| 580 | + // TODO @小北:public static Integer parseCandidateStrategy(FlowElement userTask) 使用这个工具方法哈。 | |
| 573 | 581 | Map<String, List<ExtensionElement>> extensionElements = nextFlowNode.getExtensionElements(); |
| 574 | 582 | List<ExtensionElement> elements = extensionElements.get(BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY); |
| 575 | - if (CollUtil.isEmpty(elements)){ | |
| 583 | + if (CollUtil.isEmpty(elements)) { | |
| 576 | 584 | continue; |
| 577 | 585 | } |
| 578 | - // 3.2、获取节点中的审批人策略 | |
| 586 | + // 3.2 获取节点中的审批人策略 | |
| 579 | 587 | Integer candidateStrategy = Integer.valueOf(elements.get(0).getElementText()); |
| 580 | - // 3.3、获取流程实例中的发起人自选审批人 | |
| 588 | + // 3.3 获取流程实例中的发起人自选审批人 | |
| 581 | 589 | Map<String, List<Long>> startUserSelectAssignees = FlowableUtils.getStartUserSelectAssignees(processInstance.getProcessVariables()); |
| 582 | 590 | List<Long> startUserSelectAssignee = startUserSelectAssignees.get(nextFlowNode.getId()); |
| 583 | - // 3.4、如果节点中的审批人策略为 发起人自选,并且该节点的审批人为空 | |
| 591 | + // 3.4 如果节点中的审批人策略为 发起人自选,并且该节点的审批人为空 | |
| 584 | 592 | if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy()) && CollUtil.isEmpty(startUserSelectAssignee)) { |
| 585 | 593 | // 先判断前端传递的参数节点节点是否为将要执行的节点 |
| 586 | - if (!nextActivityNodes.containsKey(nextFlowNode.getId())){ | |
| 594 | + // TODO @小北:!nextAssignees.containsKey(nextFlowNode.getId())、和 CollUtil.isEmpty(nextAssignees.get(nextFlowNode.getId()))) 是不是等价的? | |
| 595 | + if (!nextAssignees.containsKey(nextFlowNode.getId())) { | |
| 587 | 596 | throw exception(TASK_TARGET_NODE_NOT_EXISTS, nextFlowNode.getName()); |
| 588 | 597 | } |
| 589 | - // 如果节点存在,则获取节点中的审批人 | |
| 590 | - List<Long> nextAssignees = nextActivityNodes.get(nextFlowNode.getId()); | |
| 591 | 598 | // 如果前端传递的节点为空,则抛出异常 |
| 592 | - if (CollUtil.isEmpty(nextAssignees)) { | |
| 599 | + // TODO @小北:换一个错误码哈。 | |
| 600 | + if (CollUtil.isEmpty(nextAssignees.get(nextFlowNode.getId()))) { | |
| 593 | 601 | throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName()); |
| 594 | 602 | } |
| 595 | 603 | } |
| 604 | + // TODO @小北:加一个“审批人选择”的校验; | |
| 596 | 605 | } |
| 597 | 606 | } |
| 598 | 607 | ... | ... |