From 8a9d64bbaf7948e099ae52c7d7d8ae18397beb31 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Wed, 26 Feb 2025 15:18:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AD=90=E6=B5=81=E7=A8=8B-=E5=A4=9A?= =?UTF-8?q?=E5=AE=9E=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ildProcessMultiInstanceSourceTypeEnum.java | 36 +++++++++++ .../vo/model/simple/BpmSimpleModelNodeVO.java | 31 ++++++++++ .../BpmParallelMultiInstanceBehavior.java | 61 +++++++++++++------ .../BpmSequentialMultiInstanceBehavior.java | 59 ++++++++++++------ .../core/enums/BpmnModelConstants.java | 5 ++ .../flowable/core/util/BpmnModelUtils.java | 11 ++++ .../flowable/core/util/SimpleModelUtils.java | 27 ++++++-- .../listener/BpmCallActivityListener.java | 20 +++--- 8 files changed, 198 insertions(+), 52 deletions(-) create mode 100644 yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessMultiInstanceSourceTypeEnum.java diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessMultiInstanceSourceTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessMultiInstanceSourceTypeEnum.java new file mode 100644 index 0000000000..f3cac8ba92 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessMultiInstanceSourceTypeEnum.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 BpmChildProcessMultiInstanceSourceTypeEnum implements ArrayValuable { + + FIXED_QUANTITY(1, "固定数量"), + DIGITAL_FORM(2, "数字表单"), + MULTI_FORM(3, "多项表单"); + + private final Integer type; + private final String name; + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmChildProcessMultiInstanceSourceTypeEnum::getType).toArray(Integer[]::new); + + public static BpmChildProcessMultiInstanceSourceTypeEnum 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 76a44fe3e1..c0d2a06672 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 @@ -452,6 +452,9 @@ public class BpmSimpleModelNodeVO { @Schema(description = "超时设置", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") private TimeoutSetting timeoutSetting; + @Schema(description = "多实例设置", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") + private MultiInstanceSetting multiInstanceSetting; + @Schema(description = "子流程发起人配置") @Data @Valid @@ -490,5 +493,33 @@ public class BpmSimpleModelNodeVO { } + @Schema(description = "多实例设置") + @Data + @Valid + public static class MultiInstanceSetting { + + @Schema(description = "是否开启多实例", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @NotNull(message = "是否开启多实例不能为空") + private Boolean enable; + + @Schema(description = "是否串行", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @NotNull(message = "是否串行不能为空") + private Boolean sequential; + + @Schema(description = "完成比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "完成比例不能为空") + private Integer completeRatio; + + @Schema(description = "多实例来源类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "多实例来源类型不能为空") + @InEnum(BpmChildProcessMultiInstanceSourceTypeEnum.class) + private Integer sourceType; + + @Schema(description = "多实例来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "多实例来源不能为空") + private String source; + + } + } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java index d239dbe3ff..84c89fc97b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java @@ -1,15 +1,21 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessMultiInstanceSourceTypeEnum; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; import lombok.Setter; import org.flowable.bpmn.model.Activity; +import org.flowable.bpmn.model.CallActivity; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.bpmn.model.UserTask; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; +import java.util.List; import java.util.Set; /** @@ -42,27 +48,42 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav */ @Override protected int resolveNrOfInstances(DelegateExecution execution) { - // 第一步,设置 collectionVariable 和 CollectionVariable - // 从 execution.getVariable() 读取所有任务处理人的 key - super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的 - super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId()); - // 从 execution.getVariable() 读取当前所有任务处理的人的 key - super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId()); + if (execution.getCurrentFlowElement() instanceof UserTask) { + // 第一步,设置 collectionVariable 和 CollectionVariable + // 从 execution.getVariable() 读取所有任务处理人的 key + super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的 + super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId()); + // 从 execution.getVariable() 读取当前所有任务处理的人的 key + super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId()); - // 第二步,获取任务的所有处理人 - @SuppressWarnings("unchecked") - Set assigneeUserIds = (Set) execution.getVariable(super.collectionVariable, Set.class); - if (assigneeUserIds == null) { - assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution); - if (CollUtil.isEmpty(assigneeUserIds)) { - // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过! - // 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务 - // 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时 - assigneeUserIds = SetUtils.asSet((Long) null); + // 第二步,获取任务的所有处理人 + @SuppressWarnings("unchecked") + Set assigneeUserIds = (Set) execution.getVariable(super.collectionVariable, Set.class); + if (assigneeUserIds == null) { + assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution); + if (CollUtil.isEmpty(assigneeUserIds)) { + // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过! + // 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务 + // 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时 + assigneeUserIds = SetUtils.asSet((Long) null); + } + execution.setVariableLocal(super.collectionVariable, assigneeUserIds); } - execution.setVariableLocal(super.collectionVariable, assigneeUserIds); + return assigneeUserIds.size(); } - return assigneeUserIds.size(); + + if (execution.getCurrentFlowElement() instanceof CallActivity) { + FlowElement flowElement = execution.getCurrentFlowElement(); + Integer sourceType = BpmnModelUtils.parseMultiInstanceSourceType(flowElement); + if (sourceType.equals(BpmChildProcessMultiInstanceSourceTypeEnum.DIGITAL_FORM.getType())) { + return execution.getVariable(super.collectionExpression.getExpressionText(), Integer.class); + } + if (sourceType.equals(BpmChildProcessMultiInstanceSourceTypeEnum.MULTI_FORM.getType())) { + return execution.getVariable(super.collectionExpression.getExpressionText(), List.class).size(); + } + } + + return super.resolveNrOfInstances(execution); } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java index b3a3a24f80..a3ba19c70e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java @@ -2,14 +2,20 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessMultiInstanceSourceTypeEnum; import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; import lombok.Setter; import org.flowable.bpmn.model.Activity; +import org.flowable.bpmn.model.CallActivity; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.bpmn.model.UserTask; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; +import java.util.List; import java.util.Set; /** @@ -35,28 +41,43 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB */ @Override protected int resolveNrOfInstances(DelegateExecution execution) { - // 第一步,设置 collectionVariable 和 CollectionVariable - // 从 execution.getVariable() 读取所有任务处理人的 key - super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的 - super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId()); - // 从 execution.getVariable() 读取当前所有任务处理的人的 key - super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId()); + if (execution.getCurrentFlowElement() instanceof UserTask) { + // 第一步,设置 collectionVariable 和 CollectionVariable + // 从 execution.getVariable() 读取所有任务处理人的 key + super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的 + super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId()); + // 从 execution.getVariable() 读取当前所有任务处理的人的 key + super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId()); - // 第二步,获取任务的所有处理人 - // 不使用 execution.getVariable 原因:目前依次审批任务回退后 collectionVariable 变量没有清理, 如果重新进入该任务不会重新分配审批人 - @SuppressWarnings("unchecked") - Set assigneeUserIds = (Set) execution.getVariableLocal(super.collectionVariable, Set.class); - if (assigneeUserIds == null) { - assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution); - if (CollUtil.isEmpty(assigneeUserIds)) { - // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过! - // 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务 - // 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时 - assigneeUserIds = SetUtils.asSet((Long) null); + // 第二步,获取任务的所有处理人 + // 不使用 execution.getVariable 原因:目前依次审批任务回退后 collectionVariable 变量没有清理, 如果重新进入该任务不会重新分配审批人 + @SuppressWarnings("unchecked") + Set assigneeUserIds = (Set) execution.getVariableLocal(super.collectionVariable, Set.class); + if (assigneeUserIds == null) { + assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution); + if (CollUtil.isEmpty(assigneeUserIds)) { + // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过! + // 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务 + // 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时 + assigneeUserIds = SetUtils.asSet((Long) null); + } + execution.setVariableLocal(super.collectionVariable, assigneeUserIds); } - execution.setVariableLocal(super.collectionVariable, assigneeUserIds); + return assigneeUserIds.size(); } - return assigneeUserIds.size(); + + if (execution.getCurrentFlowElement() instanceof CallActivity) { + FlowElement flowElement = execution.getCurrentFlowElement(); + Integer sourceType = BpmnModelUtils.parseMultiInstanceSourceType(flowElement); + if (sourceType.equals(BpmChildProcessMultiInstanceSourceTypeEnum.DIGITAL_FORM.getType())) { + return execution.getVariable(super.collectionExpression.getExpressionText(), Integer.class); + } + if (sourceType.equals(BpmChildProcessMultiInstanceSourceTypeEnum.MULTI_FORM.getType())) { + return execution.getVariable(super.collectionExpression.getExpressionText(), List.class).size(); + } + } + + return super.resolveNrOfInstances(execution); } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java index cb857b7390..e416428c4e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java @@ -68,6 +68,11 @@ public interface BpmnModelConstants { */ String USER_TASK_APPROVE_METHOD = "approveMethod"; + /** + * BPMN Child Process 的扩展属性,用于标记多实例来源类型 + */ + String CHILD_PROCESS_MULTI_INSTANCE_SOURCE_TYPE = "childProcessMultiInstanceSourceType"; + /** * BPMN ExtensionElement 流程表单字段权限元素, 用于标记字段权限 */ diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index 27d923bdeb..83b9b44662 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java @@ -158,6 +158,17 @@ public class BpmnModelUtils { return NumberUtils.parseInt(parseExtensionElement(userTask, BpmnModelConstants.USER_TASK_APPROVE_TYPE)); } + /** + * 解析子流程多实例来源类型 + * + * @see BpmChildProcessMultiInstanceSourceTypeEnum + * @param element 任务节点 + * @return 多实例来源类型 + */ + public static Integer parseMultiInstanceSourceType(FlowElement element) { + return NumberUtils.parseInt(parseExtensionElement(element, BpmnModelConstants.CHILD_PROCESS_MULTI_INSTANCE_SOURCE_TYPE)); + } + /** * 添加任务拒绝处理元素 * 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 b48e3eb87d..9a32f4cf1f 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 @@ -853,18 +853,35 @@ public class SimpleModelUtils { callActivity.setExecutionListeners(executionListeners); // 7. 超时设置 - if (childProcessSetting.getTimeoutSetting() != null) { + if (childProcessSetting.getTimeoutSetting() != null && Boolean.TRUE.equals(childProcessSetting.getTimeoutSetting().getEnable())) { BoundaryEvent boundaryEvent = null; - if (node.getDelaySetting().getDelayType().equals(BpmDelayTimerTypeEnum.FIXED_DATE_TIME.getType())) { + if (childProcessSetting.getTimeoutSetting().getType().equals(BpmDelayTimerTypeEnum.FIXED_DATE_TIME.getType())) { boundaryEvent = buildTimeoutBoundaryEvent(callActivity, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT.getType(), - node.getDelaySetting().getDelayTime(), null, null); - } else if (node.getDelaySetting().getDelayType().equals(BpmDelayTimerTypeEnum.FIXED_TIME_DURATION.getType())) { + childProcessSetting.getTimeoutSetting().getTimeExpression(), null, null); + } else if (childProcessSetting.getTimeoutSetting().getType().equals(BpmDelayTimerTypeEnum.FIXED_TIME_DURATION.getType())) { boundaryEvent = buildTimeoutBoundaryEvent(callActivity, BpmBoundaryEventTypeEnum.CHILD_PROCESS_TIMEOUT.getType(), - null, null, node.getDelaySetting().getDelayTime()); + null, null, childProcessSetting.getTimeoutSetting().getTimeExpression()); } flowElements.add(boundaryEvent); } + // 8. 多实例 + if (childProcessSetting.getMultiInstanceSetting() != null && Boolean.TRUE.equals(childProcessSetting.getMultiInstanceSetting().getEnable())) { + MultiInstanceLoopCharacteristics multiInstanceCharacteristics = new MultiInstanceLoopCharacteristics(); + multiInstanceCharacteristics.setSequential(childProcessSetting.getMultiInstanceSetting().getSequential()); + if (childProcessSetting.getMultiInstanceSetting().getSourceType().equals(BpmChildProcessMultiInstanceSourceTypeEnum.FIXED_QUANTITY.getType())) { + multiInstanceCharacteristics.setLoopCardinality(childProcessSetting.getMultiInstanceSetting().getSource()); + } + if (childProcessSetting.getMultiInstanceSetting().getSourceType().equals(BpmChildProcessMultiInstanceSourceTypeEnum.DIGITAL_FORM.getType()) || + childProcessSetting.getMultiInstanceSetting().getSourceType().equals(BpmChildProcessMultiInstanceSourceTypeEnum.MULTI_FORM.getType())) { + multiInstanceCharacteristics.setInputDataItem(childProcessSetting.getMultiInstanceSetting().getSource()); + } + multiInstanceCharacteristics.setCompletionCondition(String.format("${ nrOfCompletedInstances/nrOfInstances >= %s}", + String.format("%.2f", childProcessSetting.getMultiInstanceSetting().getCompleteRatio() / 100D))); + callActivity.setLoopCharacteristics(multiInstanceCharacteristics); + addExtensionElement(callActivity, CHILD_PROCESS_MULTI_INSTANCE_SOURCE_TYPE, childProcessSetting.getMultiInstanceSetting().getSourceType()); + } + // 添加节点类型 addNodeType(node.getType(), callActivity); flowElements.add(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 index b454d33335..40313a9663 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,7 @@ package cn.iocoder.yudao.module.bpm.service.task.listener; import cn.hutool.core.lang.Assert; +import cn.hutool.core.map.MapUtil; 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; @@ -9,13 +10,14 @@ import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessStartUserEmpt 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 cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 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.flowable.engine.runtime.ProcessInstance; import org.springframework.stereotype.Component; import java.util.List; @@ -37,30 +39,32 @@ public class BpmCallActivityListener implements ExecutionListener { @Resource private BpmProcessDefinitionService processDefinitionService; + @Resource + private BpmProcessInstanceService processInstanceService; + @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); + ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getRootProcessInstanceId()); // 1. 当发起人来源为主流程发起人时,并兜底 startUserSetting 为空时 if (startUserSetting == null || startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER.getType())) { - ExecutionEntity parent = (ExecutionEntity) execution.getParent(); - FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); + FlowableUtils.setAuthenticatedUserId(Long.parseLong(processInstance.getStartUserId())); return; } // 2. 当发起人来源为表单时 if (startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.FROM_FORM.getType())) { - ExecutionEntity parent = (ExecutionEntity) execution.getParent(); - String formFieldValue = parent.getVariable(startUserSetting.getFormField(), String.class); + String formFieldValue = MapUtil.getStr(processInstance.getProcessVariables(), startUserSetting.getFormField()); // 2.1 当表单值为空时 if (StrUtil.isEmpty(formFieldValue)) { // 2.1.1 来自主流程发起人 if (startUserSetting.getEmptyType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())) { - FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); + FlowableUtils.setAuthenticatedUserId(Long.parseLong(processInstance.getStartUserId())); return; } // 2.1.2 来自子流程管理员 @@ -72,7 +76,7 @@ public class BpmCallActivityListener implements ExecutionListener { } // 2.1.3 来自主流程管理员 if (startUserSetting.getEmptyType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())) { - BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(parent.getProcessDefinitionId()); + BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(processInstance.getProcessDefinitionId()); List managerUserIds = processDefinition.getManagerUserIds(); FlowableUtils.setAuthenticatedUserId(managerUserIds.get(0)); return; @@ -84,7 +88,7 @@ public class BpmCallActivityListener implements ExecutionListener { } catch (Exception e) { log.error("[notify][监听器:{},子流程监听器设置流程的发起人字符串转 Long 失败,字符串:{}]", DELEGATE_EXPRESSION, formFieldValue); - FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); + FlowableUtils.setAuthenticatedUserId(Long.parseLong(processInstance.getStartUserId())); } } }