From 9698fee36447d3d14a7812c06c6e25f8e4844fb8 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Fri, 21 Feb 2025 09:52:43 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E5=AD=90=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BpmSimpleModelNodeTypeEnum.java | 3 + .../module/bpm/enums/task/BpmReasonEnum.java | 1 + .../vo/model/simple/BpmSimpleModelNodeVO.java | 32 +++++++++ .../core/enums/BpmnVariableConstants.java | 7 ++ .../flowable/core/util/SimpleModelUtils.java | 65 ++++++++++++++++++- .../bpm/service/task/BpmTaskServiceImpl.java | 37 +++++++---- 6 files changed, 132 insertions(+), 13 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java index c9da0718df..44cba2bd15 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java @@ -30,6 +30,9 @@ public enum BpmSimpleModelNodeTypeEnum implements ArrayValuable { DELAY_TIMER_NODE(14, "延迟器", "receiveTask"), TRIGGER_NODE(15, "触发器", "serviceTask"), + CHILD_PROCESS(20, "子流程", "callActivity"), + ASYNC_CHILD_PROCESS(21, "异步子流程", "callActivity"), + // 50 ~ 条件分支 CONDITION_NODE(50, "条件", "sequenceFlow"), // 用于构建流转条件的表达式 CONDITION_BRANCH_NODE(51, "条件分支", "exclusiveGateway"), diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java index d41c0c3133..bb6b244b02 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java @@ -26,6 +26,7 @@ public enum BpmReasonEnum { TIMEOUT_REJECT("审批超时,系统自动不通过"), ASSIGN_START_USER_APPROVE("审批人与提交人为同一人时,自动通过"), ASSIGN_START_USER_APPROVE_WHEN_SKIP("审批人与提交人为同一人时,自动通过"), + ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE("发起人节点首次自动通过"), ASSIGN_START_USER_APPROVE_WHEN_DEPT_LEADER_NOT_FOUND("审批人与提交人为同一人时,找不到部门负责人,自动通过"), ASSIGN_START_USER_TRANSFER_DEPT_LEADER("审批人与提交人为同一人时,转交给部门负责人审批"), ASSIGN_EMPTY_APPROVE("审批人为空,自动通过"), diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java index 50c45a96a2..23371b19d7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java @@ -10,6 +10,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.flowable.bpmn.model.IOParameter; import org.hibernate.validator.constraints.URL; import java.util.List; @@ -122,6 +123,8 @@ public class BpmSimpleModelNodeVO { */ private TriggerSetting triggerSetting; + private ChildProcessSetting childProcessSetting; + @Schema(description = "任务监听器") @Valid @Data @@ -397,4 +400,33 @@ public class BpmSimpleModelNodeVO { private Map updateFormFields; } } + + @Schema(description = "子流程节点配置") + @Data + @Valid + public static class ChildProcessSetting { + + @Schema(description = "被调用流程", example = "xxx") + @NotEmpty(message = "被调用流程不能为空") + private String calledElement; + + @Schema(description = "被调用流程名称", example = "xxx") + @NotEmpty(message = "被调用流程名称不能为空") + private String calledElementName; + + @Schema(description = "是否异步", example = "false") + @NotNull(message = "是否异步不能为空") + private Boolean async; + + @Schema(description = "输入参数(主->子)", example = "[]") + private List inVariable; + + @Schema(description = "输出参数(子->主)", example = "[]") + private List outVariable; + + @Schema(description = "是否自动跳过子流程发起节点", example = "false") + @NotNull(message = "是否自动跳过子流程发起节点不能为空") + private Boolean skipStartUserNode; + + } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java index 8172cf59a5..119a441857 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java @@ -51,6 +51,13 @@ public class BpmnVariableConstants { */ public static final String PROCESS_INSTANCE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED"; + /** + * 流程实例的变量 - 用于判断流程是否需要跳过发起人节点 + * + * @see ProcessInstance#getProcessVariables() + */ + public static final String PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE = "PROCESS_SKIP_START_USER_NODE"; + /** * 流程实例的变量 - 流程开始时间 * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index e32d93ceb0..d41fc44242 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -22,6 +22,8 @@ import org.springframework.util.MultiValueMap; import java.util.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE; +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; import static cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener.DELEGATE_EXPRESSION; import static java.util.Arrays.asList; @@ -42,7 +44,8 @@ public class SimpleModelUtils { List converts = asList(new StartNodeConvert(), new EndNodeConvert(), new StartUserNodeConvert(), new ApproveNodeConvert(), new CopyNodeConvert(), new TransactorNodeConvert(), new DelayTimerNodeConvert(), new TriggerNodeConvert(), - new ConditionBranchNodeConvert(), new ParallelBranchNodeConvert(), new InclusiveBranchNodeConvert(), new RouteBranchNodeConvert()); + new ConditionBranchNodeConvert(), new ParallelBranchNodeConvert(), new InclusiveBranchNodeConvert(), new RouteBranchNodeConvert(), + new ChildProcessConvert(), new AsyncChildProcessConvert()); converts.forEach(convert -> NODE_CONVERTS.put(convert.getType(), convert)); } @@ -773,6 +776,66 @@ public class SimpleModelUtils { } + private static class ChildProcessConvert implements NodeConvert { + + @Override + public CallActivity convert(BpmSimpleModelNodeVO node) { + BpmSimpleModelNodeVO.ChildProcessSetting childProcessSetting = node.getChildProcessSetting(); + List inVariable = childProcessSetting.getInVariable() == null ? + new ArrayList<>() : new ArrayList<>(childProcessSetting.getInVariable()); + CallActivity callActivity = new CallActivity(); + callActivity.setId(node.getId()); + callActivity.setName(node.getName()); + callActivity.setCalledElementType("key"); + // 1. 是否异步 + callActivity.setAsynchronous(node.getChildProcessSetting().getAsync()); + // 2. 调用的子流程 + callActivity.setCalledElement(childProcessSetting.getCalledElement()); + callActivity.setProcessInstanceName(childProcessSetting.getCalledElementName()); + // 3. 是否自动跳过子流程发起节点 + if (Boolean.TRUE.equals(childProcessSetting.getSkipStartUserNode())) { + IOParameter ioParameter = new IOParameter(); + ioParameter.setSourceExpression("true"); + ioParameter.setTarget(PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); + inVariable.add(ioParameter); + } else { + IOParameter ioParameter = new IOParameter(); + ioParameter.setSourceExpression("false"); + ioParameter.setTarget(PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); + inVariable.add(ioParameter); + } + // 4. 主→子变量传递 + // 默认需要传递的一些变量 + // 4.1 流程状态 + IOParameter ioParameter = new IOParameter(); + ioParameter.setSource(PROCESS_INSTANCE_VARIABLE_STATUS); + ioParameter.setTarget(PROCESS_INSTANCE_VARIABLE_STATUS); + inVariable.add(ioParameter); + callActivity.setInParameters(inVariable); + // 5. 子→主变量传递 + if (childProcessSetting.getOutVariable() != null && !childProcessSetting.getOutVariable().isEmpty()) { + callActivity.setOutParameters(childProcessSetting.getOutVariable()); + } + return callActivity; + } + + @Override + public BpmSimpleModelNodeTypeEnum getType() { + return BpmSimpleModelNodeTypeEnum.CHILD_PROCESS; + } + + } + + private static class AsyncChildProcessConvert extends ChildProcessConvert { + + @Override + public BpmSimpleModelNodeTypeEnum getType() { + return BpmSimpleModelNodeTypeEnum.ASYNC_CHILD_PROCESS; + } + + } + + private static String buildGatewayJoinId(String id) { return id + "_join"; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index f57f088ef5..e104141965 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.*; import cn.hutool.extra.spring.SpringUtil; @@ -63,6 +64,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG; +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; /** @@ -1212,19 +1214,30 @@ public class BpmTaskServiceImpl implements BpmTaskService { } } - // 审批人与提交人为同一人时,根据 BpmUserTaskAssignStartUserHandlerTypeEnum 策略进行处理 - if (StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) { - // 判断是否为退回或者驳回:如果是退回或者驳回不走这个策略 - // TODO 芋艿:【优化】未来有没更好的判断方式?!另外,还要考虑清理机制。就是说,下次处理了之后,就移除这个标识 - Boolean returnTaskFlag = runtimeService.getVariable(processInstance.getProcessInstanceId(), - String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class); + // 发起人节点 + BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId()); + if (bpmnModel == null) { + log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId()); + return; + } + FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); + // 判断是否为退回或者驳回:如果是退回或者驳回不走这个策略 + // TODO 芋艿:【优化】未来有没更好的判断方式?!另外,还要考虑清理机制。就是说,下次处理了之后,就移除这个标识 + Boolean returnTaskFlag = runtimeService.getVariable(processInstance.getProcessInstanceId(), + String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class); + Boolean skipStartUserNodeFlag = Convert.toBool(runtimeService.getVariable(processInstance.getProcessInstanceId(), + PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class)); + if (userTaskElement.getId().equals(START_USER_NODE_ID) && + (skipStartUserNodeFlag == null || Boolean.TRUE.equals(skipStartUserNodeFlag)) && + !Boolean.TRUE.equals(returnTaskFlag)) { + getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) + .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason())); + return; + } + // 当不为发起人节点时,审批人与提交人为同一人时,根据 BpmUserTaskAssignStartUserHandlerTypeEnum 策略进行处理 + if (!userTaskElement.getId().equals(START_USER_NODE_ID) && + StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) { if (ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) { - BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId()); - if (bpmnModel == null) { - log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId()); - return; - } - FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); Integer assignStartUserHandlerType = BpmnModelUtils.parseAssignStartUserHandlerType(userTaskElement); // 情况一:自动跳过 From 0e48458ef7e85bb6bc8ba5e663885b32164a59f8 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Fri, 21 Feb 2025 14:04:00 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E5=AD=90=E6=B5=81=E7=A8=8B-?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=AB=98=E4=BA=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/core/util/SimpleModelUtils.java | 4 ++++ .../task/BpmProcessInstanceServiceImpl.java | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index d41fc44242..18798bb3fb 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -816,6 +816,8 @@ public class SimpleModelUtils { if (childProcessSetting.getOutVariable() != null && !childProcessSetting.getOutVariable().isEmpty()) { callActivity.setOutParameters(childProcessSetting.getOutVariable()); } + // 添加节点类型 + addNodeType(node.getType(), callActivity); return callActivity; } @@ -865,6 +867,8 @@ public class SimpleModelUtils { || nodeType == BpmSimpleModelNodeTypeEnum.APPROVE_NODE || nodeType == BpmSimpleModelNodeTypeEnum.TRANSACTOR_NODE || nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE + || nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS + || nodeType == BpmSimpleModelNodeTypeEnum.ASYNC_CHILD_PROCESS || nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) { // 添加元素 resultNodes.add(currentNode); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 632ed47073..c0c1525517 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -320,6 +320,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 遍历 tasks 列表,只处理已结束的 UserTask // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities // 的话,它无法成为一个节点 + // TODO @芋艿:子流程只有activity,这里获取不到已结束的子流程 List endTasks = filterList(tasks, task -> task.getEndTime() != null); List approvalNodes = convertList(endTasks, task -> { FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); @@ -390,7 +391,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService List tasks) { // 构建运行中的任务,基于 activityId 分组 List runActivities = filterList(activities, activity -> activity.getEndTime() == null - && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER))); + && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER, ELEMENT_CALL_ACTIVITY))); Map> runningTaskMap = convertMultiMap(runActivities, HistoricActivityInstance::getActivityId); @@ -404,7 +405,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService HistoricActivityInstance firstActivity = CollUtil.getFirst(taskActivities); // 取第一个任务,会签/或签的任务,开始时间相同 ActivityNode activityNode = new ActivityNode().setId(firstActivity.getActivityId()) .setName(firstActivity.getActivityName()) - .setNodeType(ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别 + .setNodeType(ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”和"子流程"的识别 BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())) .setStatus(BpmTaskStatusEnum.RUNNING.getStatus()) .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) @@ -413,6 +414,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 处理每个任务的 tasks 属性 for (HistoricActivityInstance activity : taskActivities) { HistoricTaskInstance task = taskMap.get(activity.getTaskId()); + if (task == null) { + continue; + } activityNode.getTasks().add(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task)); // 加签子任务,需要过滤掉已经完成的加签子任务 List childrenTasks = filterList( @@ -503,6 +507,12 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService activityNode.setCandidateUserIds(candidateUserIds); return activityNode; } + + // 4. 子流程节点 + if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(node.getType()) || + BpmSimpleModelNodeTypeEnum.ASYNC_CHILD_PROCESS.getType().equals(node.getType())) { + return activityNode; + } return null; } From 11858ca0dd3b7063ea7743bb551c1ca73fda5089 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Fri, 21 Feb 2025 15:40:23 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=E5=AD=90=E6=B5=81=E7=A8=8B-?= =?UTF-8?q?=E5=AD=90=E6=B5=81=E7=A8=8B=E5=8F=91=E8=B5=B7=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...BpmChildProcessStartUserEmptyTypeEnum.java | 36 ++++++++ .../BpmChildProcessStartUserTypeEnum.java | 35 ++++++++ .../vo/model/simple/BpmSimpleModelNodeVO.java | 22 +++++ .../flowable/core/util/FlowableUtils.java | 3 +- .../flowable/core/util/SimpleModelUtils.java | 14 +++ .../listener/BpmCallActivityListener.java | 88 +++++++++++++++++++ 6 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserEmptyTypeEnum.java create mode 100644 yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserTypeEnum.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserEmptyTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserEmptyTypeEnum.java new file mode 100644 index 0000000000..55e6e02e87 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserEmptyTypeEnum.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.bpm.enums.definition; + +import cn.hutool.core.util.ArrayUtil; +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * BPM 当子流程发起人为空时类型枚举 + * + * @author Lesan + */ +@Getter +@AllArgsConstructor +public enum BpmChildProcessStartUserEmptyTypeEnum implements ArrayValuable { + + MAIN_PROCESS_START_USER(1, "同主流程发起人"), + CHILD_PROCESS_ADMIN(2, "子流程管理员"), + MAIN_PROCESS_ADMIN(3, "主流程管理员"); + + private final Integer type; + private final String name; + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmChildProcessStartUserEmptyTypeEnum::getType).toArray(Integer[]::new); + + public static BpmChildProcessStartUserEmptyTypeEnum typeOf(Integer type) { + return ArrayUtil.firstMatch(item -> item.getType().equals(type), values()); + } + + @Override + public Integer[] array() { + return ARRAYS; + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserTypeEnum.java new file mode 100644 index 0000000000..10d04ea4f4 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserTypeEnum.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.bpm.enums.definition; + +import cn.hutool.core.util.ArrayUtil; +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * BPM 子流程发起人类型枚举 + * + * @author Lesan + */ +@Getter +@AllArgsConstructor +public enum BpmChildProcessStartUserTypeEnum implements ArrayValuable { + + MAIN_PROCESS_START_USER(1, "同主流程发起人"), + FROM_FORM(2, "表单"); + + private final Integer type; + private final String name; + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmChildProcessStartUserTypeEnum::getType).toArray(Integer[]::new); + + public static BpmChildProcessStartUserTypeEnum typeOf(Integer type) { + return ArrayUtil.firstMatch(item -> item.getType().equals(type), values()); + } + + @Override + public Integer[] array() { + return ARRAYS; + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java index 23371b19d7..fc1cc2bb4a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java @@ -428,5 +428,27 @@ public class BpmSimpleModelNodeVO { @NotNull(message = "是否自动跳过子流程发起节点不能为空") private Boolean skipStartUserNode; + @Schema(description = "子流程发起人配置", example = "{}") + private StartUserSetting startUserSetting; + + @Schema(description = "子流程发起人配置") + @Data + @Valid + public static class StartUserSetting { + + @Schema(description = "子流程发起人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "子流程发起人类型") + @InEnum(BpmChildProcessStartUserTypeEnum.class) + private Integer type; + + @Schema(description = "表单", example = "xxx") + private String formField; + + @Schema(description = "当子流程发起人为空时类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @InEnum(BpmChildProcessStartUserEmptyTypeEnum.class) + private Integer emptyHandleType; + + } + } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java index a458567d81..998320eb58 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.util; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -240,7 +241,7 @@ public class FlowableUtils { return formFieldsMap.entrySet().stream() .limit(3) .map(entry -> new KeyValue<>(entry.getValue().getTitle(), - processVariables.getOrDefault(entry.getValue().getField(), "").toString())) + StrUtil.toStringOrEmpty(processVariables.getOrDefault(entry.getValue().getField(), "")))) .collect(Collectors.toList()); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 18798bb3fb..fbc38cbeab 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -5,6 +5,7 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.*; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups; import cn.iocoder.yudao.module.bpm.enums.definition.*; @@ -16,6 +17,7 @@ import org.flowable.bpmn.BpmnAutoLayout; import org.flowable.bpmn.constants.BpmnXMLConstants; import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.*; +import org.flowable.engine.delegate.ExecutionListener; import org.flowable.engine.delegate.TaskListener; import org.springframework.util.MultiValueMap; @@ -816,6 +818,18 @@ public class SimpleModelUtils { if (childProcessSetting.getOutVariable() != null && !childProcessSetting.getOutVariable().isEmpty()) { callActivity.setOutParameters(childProcessSetting.getOutVariable()); } + // 6. 子流程发起人配置 + List executionListeners = new ArrayList<>(); + FlowableListener flowableListener = new FlowableListener(); + flowableListener.setEvent(ExecutionListener.EVENTNAME_START); + flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); + flowableListener.setImplementation("${bpmCallActivityListener}"); + FieldExtension fieldExtension = new FieldExtension(); + fieldExtension.setFieldName("listenerConfig"); + fieldExtension.setStringValue(JsonUtils.toJsonString(childProcessSetting.getStartUserSetting())); + flowableListener.getFieldExtensions().add(fieldExtension); + executionListeners.add(flowableListener); + callActivity.setExecutionListeners(executionListeners); // 添加节点类型 addNodeType(node.getType(), callActivity); return callActivity; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java new file mode 100644 index 0000000000..fe34c6964f --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.bpm.service.task.listener; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessStartUserEmptyTypeEnum; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessStartUserTypeEnum; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; +import jakarta.annotation.Resource; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.ExecutionListener; +import org.flowable.engine.impl.el.FixedValue; +import org.flowable.engine.impl.persistence.entity.ExecutionEntity; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * BPM 子流程监听器 + * + * @author Lesan + */ +@Component +@Slf4j +public class BpmCallActivityListener implements ExecutionListener { + + public static final String DELEGATE_EXPRESSION = "${bpmCallActivityListener}"; + + @Setter + private FixedValue listenerConfig; + + @Resource + private BpmProcessDefinitionService processDefinitionService; + + @Override + public void notify(DelegateExecution execution) { + String expressionText = listenerConfig.getExpressionText(); + Assert.notNull(expressionText, "监听器扩展字段({})不能为空", expressionText); + BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting startUserSetting = JsonUtils.parseObject(expressionText, BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting.class); + // 1. 当发起人来源为表单时 + if (startUserSetting != null && + startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.FROM_FORM.getType())) { + ExecutionEntity parent = (ExecutionEntity) execution.getParent(); + String formField = parent.getVariable(startUserSetting.getFormField(), String.class); + // 1.1 当表单值为空时 + if (StrUtil.isEmpty(formField)) { + // 1.1.1 来自主流程发起人 + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())){ + FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); + return; + } + // 1.1.2 来自子流程管理员 + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.CHILD_PROCESS_ADMIN.getType())){ + BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(execution.getProcessDefinitionId()); + List managerUserIds = processDefinition.getManagerUserIds(); + FlowableUtils.setAuthenticatedUserId(Convert.toLong(managerUserIds.get(0))); + return; + } + // 1.1.3 来自主流程管理员 + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())){ + BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(parent.getProcessDefinitionId()); + List managerUserIds = processDefinition.getManagerUserIds(); + FlowableUtils.setAuthenticatedUserId(Convert.toLong(managerUserIds.get(0))); + return; + } + } + // 1.2 使用表单值,并兜底字符串转Long失败时使用主流程发起人 + try { + FlowableUtils.setAuthenticatedUserId(Long.parseLong(formField)); + } catch (Exception e) { + FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); + } + } + // 2. 当发起人来源为主流程发起人时,并兜底startUserSetting为空时 + if (startUserSetting == null || + startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER.getType())) { + ExecutionEntity parent = (ExecutionEntity) execution.getParent(); + FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); + } + } + +} \ No newline at end of file From 7a6d1bdd791cc84f4746d6a096b6d0c7dc28bb2b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 22 Feb 2025 16:20:04 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91BPM=EF=BC=9A=E5=88=A0=E9=99=A4=E8=A1=A8?= =?UTF-8?q?=E5=8D=95=E6=95=B0=E6=8D=AE=E8=A7=A6=E5=8F=91=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/bpm/service/task/BpmProcessInstanceService.java | 4 ++-- .../bpm/service/task/BpmProcessInstanceServiceImpl.java | 4 ++-- .../bpm/service/task/trigger/BpmFormDeleteTrigger.java | 6 +++--- .../bpm/service/task/trigger/BpmFormUpdateTrigger.java | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java index 83d453ed4e..c4684d3402 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java @@ -160,10 +160,10 @@ public interface BpmProcessInstanceService { /** * 删除 ProcessInstance 的变量 * - * @param processInstanceId 流程编号 + * @param id 流程编号 * @param variableNames 流程变量名 */ - void removeProcessInstanceVariables(String processInstanceId, Collection variableNames); + void removeProcessInstanceVariables(String id, Collection variableNames); // ========== Event 事件相关方法 ========== diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 271561eeaf..28993d40d7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -790,8 +790,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService } @Override - public void removeProcessInstanceVariables(String processInstanceId, Collection variableNames) { - runtimeService.removeVariables(processInstanceId, variableNames); + public void removeProcessInstanceVariables(String id, Collection variableNames) { + runtimeService.removeVariables(id, variableNames); } // ========== Event 事件相关方法 ========== diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormDeleteTrigger.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormDeleteTrigger.java index 488c48b082..ab29c502d5 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormDeleteTrigger.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormDeleteTrigger.java @@ -43,10 +43,10 @@ public class BpmFormDeleteTrigger implements BpmTrigger { return; } - // 2.获取流程变量 + // 2. 获取流程变量 Map processVariables = processInstanceService.getProcessInstance(processInstanceId).getProcessVariables(); - // 3.获取需要删除的表单字段 + // 3.1 获取需要删除的表单字段 Set deleteFields = new HashSet<>(); settings.forEach(setting -> { if (CollUtil.isEmpty(setting.getDeleteFields())) { @@ -64,7 +64,7 @@ public class BpmFormDeleteTrigger implements BpmTrigger { } }); - // 4. 删除流程变量 + // 3.2 删除流程变量 if (CollUtil.isNotEmpty(deleteFields)) { processInstanceService.removeProcessInstanceVariables(processInstanceId, deleteFields); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormUpdateTrigger.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormUpdateTrigger.java index 0382397d08..9ec2608b93 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormUpdateTrigger.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormUpdateTrigger.java @@ -41,10 +41,10 @@ public class BpmFormUpdateTrigger implements BpmTrigger { return; } - // 2.获取流程变量 + // 2. 获取流程变量 Map processVariables = processInstanceService.getProcessInstance(processInstanceId).getProcessVariables(); - // 3.更新流程变量 + // 3. 更新流程变量 for (FormTriggerSetting setting : settings) { if (CollUtil.isEmpty(setting.getUpdateFormFields())) { continue; From 254b55778f839de4639c4831ca0110f89bbbaf36 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 22 Feb 2025 17:17:27 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91BPM=EF=BC=9A=E5=AD=90=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BpmSimpleModelNodeTypeEnum.java | 2 +- .../module/bpm/enums/task/BpmReasonEnum.java | 2 +- .../vo/model/simple/BpmSimpleModelNodeVO.java | 19 +++++-- .../flowable/core/util/FlowableUtils.java | 6 ++- .../flowable/core/util/SimpleModelUtils.java | 36 ++++++++----- .../task/BpmProcessInstanceServiceImpl.java | 5 +- .../bpm/service/task/BpmTaskServiceImpl.java | 13 ++--- .../listener/BpmCallActivityListener.java | 53 ++++++++++--------- 8 files changed, 81 insertions(+), 55 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java index 44cba2bd15..b21bc65313 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java @@ -30,7 +30,7 @@ public enum BpmSimpleModelNodeTypeEnum implements ArrayValuable { DELAY_TIMER_NODE(14, "延迟器", "receiveTask"), TRIGGER_NODE(15, "触发器", "serviceTask"), - CHILD_PROCESS(20, "子流程", "callActivity"), + CHILD_PROCESS(20, "子流程", "callActivity"), // TODO @lesan:CHILD_PROCESS、ASYNC_CHILD_PROCESS 可以合并为一个么? ASYNC_CHILD_PROCESS(21, "异步子流程", "callActivity"), // 50 ~ 条件分支 diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java index bb6b244b02..b0ade75299 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java @@ -26,7 +26,7 @@ public enum BpmReasonEnum { TIMEOUT_REJECT("审批超时,系统自动不通过"), ASSIGN_START_USER_APPROVE("审批人与提交人为同一人时,自动通过"), ASSIGN_START_USER_APPROVE_WHEN_SKIP("审批人与提交人为同一人时,自动通过"), - ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE("发起人节点首次自动通过"), + ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE("发起人节点首次自动通过"), // 目前仅“子流程”使用 ASSIGN_START_USER_APPROVE_WHEN_DEPT_LEADER_NOT_FOUND("审批人与提交人为同一人时,找不到部门负责人,自动通过"), ASSIGN_START_USER_TRANSFER_DEPT_LEADER("审批人与提交人为同一人时,转交给部门负责人审批"), ASSIGN_EMPTY_APPROVE("审批人为空,自动通过"), diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java index b238779a48..9ba95d87e3 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java @@ -124,6 +124,9 @@ public class BpmSimpleModelNodeVO { */ private TriggerSetting triggerSetting; + /** + * 子流程设置 + */ private ChildProcessSetting childProcessSetting; @Schema(description = "任务监听器") @@ -410,21 +413,24 @@ public class BpmSimpleModelNodeVO { @Valid public static class ChildProcessSetting { - @Schema(description = "被调用流程", example = "xxx") + // TODO @lesan:calledElement => calledProcessDefinitionKey ? 这样更容易理解?不过如果一个流程多次发起,key 变了,好像会有问题? + @Schema(description = "被调用流程", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxx") @NotEmpty(message = "被调用流程不能为空") private String calledElement; - @Schema(description = "被调用流程名称", example = "xxx") + @Schema(description = "被调用流程名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxx") @NotEmpty(message = "被调用流程名称不能为空") private String calledElementName; - @Schema(description = "是否异步", example = "false") + @Schema(description = "是否异步", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") @NotNull(message = "是否异步不能为空") private Boolean async; - @Schema(description = "输入参数(主->子)", example = "[]") + // TODO @lesan:inVariables + @Schema(description = "输入参数(主->子)", requiredMode = Schema.RequiredMode.REQUIRED, example = "[]") private List inVariable; + // TODO @lesan:outVariables @Schema(description = "输出参数(子->主)", example = "[]") private List outVariable; @@ -432,7 +438,8 @@ public class BpmSimpleModelNodeVO { @NotNull(message = "是否自动跳过子流程发起节点不能为空") private Boolean skipStartUserNode; - @Schema(description = "子流程发起人配置", example = "{}") + @Schema(description = "子流程发起人配置", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") + // TODO @lesan:这个应该也必须填写? private StartUserSetting startUserSetting; @Schema(description = "子流程发起人配置") @@ -448,7 +455,9 @@ public class BpmSimpleModelNodeVO { @Schema(description = "表单", example = "xxx") private String formField; + // TODO @lesan:emptyHandleType => emptyType,和 type 对上? @Schema(description = "当子流程发起人为空时类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "当子流程发起人为空时类型不能为空") @InEnum(BpmChildProcessStartUserEmptyTypeEnum.class) private Integer emptyHandleType; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java index 998320eb58..7ab71a0470 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java @@ -25,7 +25,10 @@ import org.flowable.engine.impl.util.CommandContextUtil; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.TaskInfo; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.concurrent.Callable; import java.util.stream.Collectors; @@ -241,6 +244,7 @@ public class FlowableUtils { return formFieldsMap.entrySet().stream() .limit(3) .map(entry -> new KeyValue<>(entry.getValue().getTitle(), + // TODO @lesan: MapUtil.getStr 可以更简单? StrUtil.toStringOrEmpty(processVariables.getOrDefault(entry.getValue().getField(), "")))) .collect(Collectors.toList()); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index fbc38cbeab..a92ab7044e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -11,8 +11,11 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.B import cn.iocoder.yudao.module.bpm.enums.definition.*; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmCopyTaskDelegate; import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmTriggerTaskDelegate; +import cn.iocoder.yudao.module.bpm.service.task.listener.BpmCallActivityListener; +import cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener; import org.flowable.bpmn.BpmnAutoLayout; import org.flowable.bpmn.constants.BpmnXMLConstants; import org.flowable.bpmn.model.Process; @@ -24,10 +27,7 @@ import org.springframework.util.MultiValueMap; import java.util.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE; -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; -import static cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener.DELEGATE_EXPRESSION; import static java.util.Arrays.asList; /** @@ -462,7 +462,7 @@ public class SimpleModelUtils { FlowableListener flowableListener = new FlowableListener(); flowableListener.setEvent(TaskListener.EVENTNAME_CREATE); flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); - flowableListener.setImplementation(DELEGATE_EXPRESSION); + flowableListener.setImplementation(BpmUserTaskListener.DELEGATE_EXPRESSION); addListenerConfig(flowableListener, node.getTaskCreateListener()); flowableListeners.add(flowableListener); } @@ -471,7 +471,7 @@ public class SimpleModelUtils { FlowableListener flowableListener = new FlowableListener(); flowableListener.setEvent(TaskListener.EVENTNAME_ASSIGNMENT); flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); - flowableListener.setImplementation(DELEGATE_EXPRESSION); + flowableListener.setImplementation(BpmUserTaskListener.DELEGATE_EXPRESSION); addListenerConfig(flowableListener, node.getTaskAssignListener()); flowableListeners.add(flowableListener); } @@ -480,7 +480,7 @@ public class SimpleModelUtils { FlowableListener flowableListener = new FlowableListener(); flowableListener.setEvent(TaskListener.EVENTNAME_COMPLETE); flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); - flowableListener.setImplementation(DELEGATE_EXPRESSION); + flowableListener.setImplementation(BpmUserTaskListener.DELEGATE_EXPRESSION); addListenerConfig(flowableListener, node.getTaskCompleteListener()); flowableListeners.add(flowableListener); } @@ -788,48 +788,56 @@ public class SimpleModelUtils { CallActivity callActivity = new CallActivity(); callActivity.setId(node.getId()); callActivity.setName(node.getName()); - callActivity.setCalledElementType("key"); + callActivity.setCalledElementType("key"); // TODO @lesan:这里为啥是 key 哈? // 1. 是否异步 callActivity.setAsynchronous(node.getChildProcessSetting().getAsync()); + // 2. 调用的子流程 callActivity.setCalledElement(childProcessSetting.getCalledElement()); callActivity.setProcessInstanceName(childProcessSetting.getCalledElementName()); + // 3. 是否自动跳过子流程发起节点 + // TODO @lesan:貌似只有 SourceExpression 的区别,直接通过 valueOf childProcessSetting.getSkipStartUserNode()??? if (Boolean.TRUE.equals(childProcessSetting.getSkipStartUserNode())) { IOParameter ioParameter = new IOParameter(); ioParameter.setSourceExpression("true"); - ioParameter.setTarget(PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); + ioParameter.setTarget(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); inVariable.add(ioParameter); } else { IOParameter ioParameter = new IOParameter(); ioParameter.setSourceExpression("false"); - ioParameter.setTarget(PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); + ioParameter.setTarget(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); inVariable.add(ioParameter); } + // 4. 主→子变量传递 - // 默认需要传递的一些变量 - // 4.1 流程状态 + // 4.1 【默认需要传递的一些变量】流程状态 + // TODO @lesan:4.1 这个要不,单独一个序号,类似 3. 这个。然后下面,就是把 主→子变量传递、子→主变量传递;这样逻辑连贯点哈 IOParameter ioParameter = new IOParameter(); - ioParameter.setSource(PROCESS_INSTANCE_VARIABLE_STATUS); - ioParameter.setTarget(PROCESS_INSTANCE_VARIABLE_STATUS); + ioParameter.setSource(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); + ioParameter.setTarget(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); inVariable.add(ioParameter); callActivity.setInParameters(inVariable); + // 5. 子→主变量传递 + // TODO @lesan:通过 isNotEmpty 这种哈 if (childProcessSetting.getOutVariable() != null && !childProcessSetting.getOutVariable().isEmpty()) { callActivity.setOutParameters(childProcessSetting.getOutVariable()); } + // 6. 子流程发起人配置 List executionListeners = new ArrayList<>(); FlowableListener flowableListener = new FlowableListener(); flowableListener.setEvent(ExecutionListener.EVENTNAME_START); flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); - flowableListener.setImplementation("${bpmCallActivityListener}"); + flowableListener.setImplementation(BpmCallActivityListener.DELEGATE_EXPRESSION); FieldExtension fieldExtension = new FieldExtension(); fieldExtension.setFieldName("listenerConfig"); fieldExtension.setStringValue(JsonUtils.toJsonString(childProcessSetting.getStartUserSetting())); flowableListener.getFieldExtensions().add(fieldExtension); executionListeners.add(flowableListener); callActivity.setExecutionListeners(executionListeners); + // 添加节点类型 addNodeType(node.getType(), callActivity); return callActivity; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 758d63a79e..558180dd3f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -320,7 +320,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 遍历 tasks 列表,只处理已结束的 UserTask // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities // 的话,它无法成为一个节点 - // TODO @芋艿:子流程只有activity,这里获取不到已结束的子流程 + // TODO @芋艿:子流程只有activity,这里获取不到已结束的子流程;TODO @lesan:这个会有啥影响?微信聊? List endTasks = filterList(tasks, task -> task.getEndTime() != null); List approvalNodes = convertList(endTasks, task -> { FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); @@ -389,7 +389,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService Map processVariables, List activities, List tasks) { - // 构建运行中的任务,基于 activityId 分组 + // 构建运行中的任务、子流程,基于 activityId 分组 List runActivities = filterList(activities, activity -> activity.getEndTime() == null && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER, ELEMENT_CALL_ACTIVITY))); Map> runningTaskMap = convertMultiMap(runActivities, @@ -414,6 +414,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 处理每个任务的 tasks 属性 for (HistoricActivityInstance activity : taskActivities) { HistoricTaskInstance task = taskMap.get(activity.getTaskId()); + // TODO @lesan:这里为啥 continue 哈? if (task == null) { continue; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index e104141965..902ce8529d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -1214,7 +1214,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { } } - // 发起人节点 + // 获取发起人节点 BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId()); if (bpmnModel == null) { log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId()); @@ -1227,16 +1227,17 @@ public class BpmTaskServiceImpl implements BpmTaskService { String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class); Boolean skipStartUserNodeFlag = Convert.toBool(runtimeService.getVariable(processInstance.getProcessInstanceId(), PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class)); - if (userTaskElement.getId().equals(START_USER_NODE_ID) && - (skipStartUserNodeFlag == null || Boolean.TRUE.equals(skipStartUserNodeFlag)) && - !Boolean.TRUE.equals(returnTaskFlag)) { + if (userTaskElement.getId().equals(START_USER_NODE_ID) + && (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核 + || Boolean.TRUE.equals(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核 + && !Boolean.TRUE.equals(returnTaskFlag)) { // TODO @lesan:ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE) 改成这个有问题么?尽量不用 ! 取反 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason())); return; } // 当不为发起人节点时,审批人与提交人为同一人时,根据 BpmUserTaskAssignStartUserHandlerTypeEnum 策略进行处理 - if (!userTaskElement.getId().equals(START_USER_NODE_ID) && - StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) { + if (ObjectUtil.notEqual(userTaskElement.getId(), START_USER_NODE_ID) + && StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) { if (ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) { Integer assignStartUserHandlerType = BpmnModelUtils.parseAssignStartUserHandlerType(userTaskElement); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java index fe34c6964f..2be4fcc8de 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.bpm.service.task.listener; -import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -22,7 +21,7 @@ import org.springframework.stereotype.Component; import java.util.List; /** - * BPM 子流程监听器 + * BPM 子流程监听器:设置流程的发起人 * * @author Lesan */ @@ -42,47 +41,51 @@ public class BpmCallActivityListener implements ExecutionListener { public void notify(DelegateExecution execution) { String expressionText = listenerConfig.getExpressionText(); Assert.notNull(expressionText, "监听器扩展字段({})不能为空", expressionText); - BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting startUserSetting = JsonUtils.parseObject(expressionText, BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting.class); - // 1. 当发起人来源为表单时 - if (startUserSetting != null && - startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.FROM_FORM.getType())) { + BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting startUserSetting = JsonUtils.parseObject( + expressionText, BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting.class); + + // 1. 当发起人来源为主流程发起人时,并兜底 startUserSetting 为空时 + if (startUserSetting == null + || startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER.getType())) { ExecutionEntity parent = (ExecutionEntity) execution.getParent(); - String formField = parent.getVariable(startUserSetting.getFormField(), String.class); - // 1.1 当表单值为空时 - if (StrUtil.isEmpty(formField)) { - // 1.1.1 来自主流程发起人 - if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())){ + FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); + return; + } + + // 2. 当发起人来源为表单时 + if (startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.FROM_FORM.getType())) { + ExecutionEntity parent = (ExecutionEntity) execution.getParent(); + String formFieldValue = parent.getVariable(startUserSetting.getFormField(), String.class); + // 2.1 当表单值为空时 + if (StrUtil.isEmpty(formFieldValue)) { + // 2.1.1 来自主流程发起人 + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())) { FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); return; } - // 1.1.2 来自子流程管理员 - if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.CHILD_PROCESS_ADMIN.getType())){ + // 2.1.2 来自子流程管理员 + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.CHILD_PROCESS_ADMIN.getType())) { BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(execution.getProcessDefinitionId()); List managerUserIds = processDefinition.getManagerUserIds(); - FlowableUtils.setAuthenticatedUserId(Convert.toLong(managerUserIds.get(0))); + FlowableUtils.setAuthenticatedUserId(managerUserIds.get(0)); return; } - // 1.1.3 来自主流程管理员 - if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())){ + // 2.1.3 来自主流程管理员 + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())) { BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(parent.getProcessDefinitionId()); List managerUserIds = processDefinition.getManagerUserIds(); - FlowableUtils.setAuthenticatedUserId(Convert.toLong(managerUserIds.get(0))); + FlowableUtils.setAuthenticatedUserId(managerUserIds.get(0)); return; } } - // 1.2 使用表单值,并兜底字符串转Long失败时使用主流程发起人 + // 2.2 使用表单值,并兜底字符串转 Long 失败时使用主流程发起人 try { - FlowableUtils.setAuthenticatedUserId(Long.parseLong(formField)); + FlowableUtils.setAuthenticatedUserId(Long.parseLong(formFieldValue)); } catch (Exception e) { + // todo @lesan:打个日志,方便排查 FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); } } - // 2. 当发起人来源为主流程发起人时,并兜底startUserSetting为空时 - if (startUserSetting == null || - startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER.getType())) { - ExecutionEntity parent = (ExecutionEntity) execution.getParent(); - FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); - } } } \ No newline at end of file