Commit 35f0d689f1e4126a78f99b832074aaae0402f8b1
Committed by
Gitee
!1262 feat: 子流程-多实例
Merge pull request !1262 from Lesan/feature/bpm-子流程
Showing
9 changed files
with
242 additions
and
90 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessMultiInstanceSourceTypeEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.enums.definition; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.ArrayUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.core.ArrayValuable; | ||
| 5 | +import lombok.AllArgsConstructor; | ||
| 6 | +import lombok.Getter; | ||
| 7 | + | ||
| 8 | +import java.util.Arrays; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * BPM 子流程多实例来源类型枚举 | ||
| 12 | + * | ||
| 13 | + * @author Lesan | ||
| 14 | + */ | ||
| 15 | +@Getter | ||
| 16 | +@AllArgsConstructor | ||
| 17 | +public enum BpmChildProcessMultiInstanceSourceTypeEnum implements ArrayValuable<Integer> { | ||
| 18 | + | ||
| 19 | + FIXED_QUANTITY(1, "固定数量"), | ||
| 20 | + DIGITAL_FORM(2, "数字表单"), | ||
| 21 | + MULTI_FORM(3, "多项表单"); | ||
| 22 | + | ||
| 23 | + private final Integer type; | ||
| 24 | + private final String name; | ||
| 25 | + | ||
| 26 | + public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmChildProcessMultiInstanceSourceTypeEnum::getType).toArray(Integer[]::new); | ||
| 27 | + | ||
| 28 | + public static BpmChildProcessMultiInstanceSourceTypeEnum typeOf(Integer type) { | ||
| 29 | + return ArrayUtil.firstMatch(item -> item.getType().equals(type), values()); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + @Override | ||
| 33 | + public Integer[] array() { | ||
| 34 | + return ARRAYS; | ||
| 35 | + } | ||
| 36 | +} |
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 { | @@ -452,6 +452,9 @@ public class BpmSimpleModelNodeVO { | ||
| 452 | @Schema(description = "超时设置", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") | 452 | @Schema(description = "超时设置", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") |
| 453 | private TimeoutSetting timeoutSetting; | 453 | private TimeoutSetting timeoutSetting; |
| 454 | 454 | ||
| 455 | + @Schema(description = "多实例设置", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") | ||
| 456 | + private MultiInstanceSetting multiInstanceSetting; | ||
| 457 | + | ||
| 455 | @Schema(description = "子流程发起人配置") | 458 | @Schema(description = "子流程发起人配置") |
| 456 | @Data | 459 | @Data |
| 457 | @Valid | 460 | @Valid |
| @@ -490,5 +493,33 @@ public class BpmSimpleModelNodeVO { | @@ -490,5 +493,33 @@ public class BpmSimpleModelNodeVO { | ||
| 490 | 493 | ||
| 491 | } | 494 | } |
| 492 | 495 | ||
| 496 | + @Schema(description = "多实例设置") | ||
| 497 | + @Data | ||
| 498 | + @Valid | ||
| 499 | + public static class MultiInstanceSetting { | ||
| 500 | + | ||
| 501 | + @Schema(description = "是否开启多实例", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") | ||
| 502 | + @NotNull(message = "是否开启多实例不能为空") | ||
| 503 | + private Boolean enable; | ||
| 504 | + | ||
| 505 | + @Schema(description = "是否串行", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") | ||
| 506 | + @NotNull(message = "是否串行不能为空") | ||
| 507 | + private Boolean sequential; | ||
| 508 | + | ||
| 509 | + @Schema(description = "完成比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | ||
| 510 | + @NotNull(message = "完成比例不能为空") | ||
| 511 | + private Integer completeRatio; | ||
| 512 | + | ||
| 513 | + @Schema(description = "多实例来源类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 514 | + @NotNull(message = "多实例来源类型不能为空") | ||
| 515 | + @InEnum(BpmChildProcessMultiInstanceSourceTypeEnum.class) | ||
| 516 | + private Integer sourceType; | ||
| 517 | + | ||
| 518 | + @Schema(description = "多实例来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 519 | + @NotNull(message = "多实例来源不能为空") | ||
| 520 | + private String source; | ||
| 521 | + | ||
| 522 | + } | ||
| 523 | + | ||
| 493 | } | 524 | } |
| 494 | } | 525 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java
| 1 | package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; | 1 | package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | ||
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessMultiInstanceSourceTypeEnum; | ||
| 4 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; | 6 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; |
| 7 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; | ||
| 5 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; | 8 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; |
| 6 | -import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | ||
| 7 | import lombok.Setter; | 9 | import lombok.Setter; |
| 8 | import org.flowable.bpmn.model.Activity; | 10 | import org.flowable.bpmn.model.Activity; |
| 11 | +import org.flowable.bpmn.model.CallActivity; | ||
| 12 | +import org.flowable.bpmn.model.FlowElement; | ||
| 13 | +import org.flowable.bpmn.model.UserTask; | ||
| 9 | import org.flowable.engine.delegate.DelegateExecution; | 14 | import org.flowable.engine.delegate.DelegateExecution; |
| 10 | import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; | 15 | import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; |
| 11 | import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; | 16 | import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; |
| 12 | 17 | ||
| 18 | +import java.util.List; | ||
| 13 | import java.util.Set; | 19 | import java.util.Set; |
| 14 | 20 | ||
| 15 | /** | 21 | /** |
| @@ -42,27 +48,42 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav | @@ -42,27 +48,42 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav | ||
| 42 | */ | 48 | */ |
| 43 | @Override | 49 | @Override |
| 44 | protected int resolveNrOfInstances(DelegateExecution execution) { | 50 | protected int resolveNrOfInstances(DelegateExecution execution) { |
| 45 | - // 第一步,设置 collectionVariable 和 CollectionVariable | ||
| 46 | - // 从 execution.getVariable() 读取所有任务处理人的 key | ||
| 47 | - super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的 | ||
| 48 | - super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId()); | ||
| 49 | - // 从 execution.getVariable() 读取当前所有任务处理的人的 key | ||
| 50 | - super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId()); | 51 | + if (execution.getCurrentFlowElement() instanceof UserTask) { |
| 52 | + // 第一步,设置 collectionVariable 和 CollectionVariable | ||
| 53 | + // 从 execution.getVariable() 读取所有任务处理人的 key | ||
| 54 | + super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的 | ||
| 55 | + super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId()); | ||
| 56 | + // 从 execution.getVariable() 读取当前所有任务处理的人的 key | ||
| 57 | + super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId()); | ||
| 51 | 58 | ||
| 52 | - // 第二步,获取任务的所有处理人 | ||
| 53 | - @SuppressWarnings("unchecked") | ||
| 54 | - Set<Long> assigneeUserIds = (Set<Long>) execution.getVariable(super.collectionVariable, Set.class); | ||
| 55 | - if (assigneeUserIds == null) { | ||
| 56 | - assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution); | ||
| 57 | - if (CollUtil.isEmpty(assigneeUserIds)) { | ||
| 58 | - // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过! | ||
| 59 | - // 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务 | ||
| 60 | - // 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时 | ||
| 61 | - assigneeUserIds = SetUtils.asSet((Long) null); | 59 | + // 第二步,获取任务的所有处理人 |
| 60 | + @SuppressWarnings("unchecked") | ||
| 61 | + Set<Long> assigneeUserIds = (Set<Long>) execution.getVariable(super.collectionVariable, Set.class); | ||
| 62 | + if (assigneeUserIds == null) { | ||
| 63 | + assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution); | ||
| 64 | + if (CollUtil.isEmpty(assigneeUserIds)) { | ||
| 65 | + // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过! | ||
| 66 | + // 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务 | ||
| 67 | + // 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时 | ||
| 68 | + assigneeUserIds = SetUtils.asSet((Long) null); | ||
| 69 | + } | ||
| 70 | + execution.setVariableLocal(super.collectionVariable, assigneeUserIds); | ||
| 62 | } | 71 | } |
| 63 | - execution.setVariableLocal(super.collectionVariable, assigneeUserIds); | 72 | + return assigneeUserIds.size(); |
| 64 | } | 73 | } |
| 65 | - return assigneeUserIds.size(); | 74 | + |
| 75 | + if (execution.getCurrentFlowElement() instanceof CallActivity) { | ||
| 76 | + FlowElement flowElement = execution.getCurrentFlowElement(); | ||
| 77 | + Integer sourceType = BpmnModelUtils.parseMultiInstanceSourceType(flowElement); | ||
| 78 | + if (sourceType.equals(BpmChildProcessMultiInstanceSourceTypeEnum.DIGITAL_FORM.getType())) { | ||
| 79 | + return execution.getVariable(super.collectionExpression.getExpressionText(), Integer.class); | ||
| 80 | + } | ||
| 81 | + if (sourceType.equals(BpmChildProcessMultiInstanceSourceTypeEnum.MULTI_FORM.getType())) { | ||
| 82 | + return execution.getVariable(super.collectionExpression.getExpressionText(), List.class).size(); | ||
| 83 | + } | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + return super.resolveNrOfInstances(execution); | ||
| 66 | } | 87 | } |
| 67 | 88 | ||
| 68 | } | 89 | } |
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; | @@ -2,14 +2,20 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | 4 | import cn.iocoder.yudao.framework.common.util.collection.SetUtils; |
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessMultiInstanceSourceTypeEnum; | ||
| 5 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; | 6 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; |
| 7 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; | ||
| 6 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; | 8 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; |
| 7 | import lombok.Setter; | 9 | import lombok.Setter; |
| 8 | import org.flowable.bpmn.model.Activity; | 10 | import org.flowable.bpmn.model.Activity; |
| 11 | +import org.flowable.bpmn.model.CallActivity; | ||
| 12 | +import org.flowable.bpmn.model.FlowElement; | ||
| 13 | +import org.flowable.bpmn.model.UserTask; | ||
| 9 | import org.flowable.engine.delegate.DelegateExecution; | 14 | import org.flowable.engine.delegate.DelegateExecution; |
| 10 | import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; | 15 | import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; |
| 11 | import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; | 16 | import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; |
| 12 | 17 | ||
| 18 | +import java.util.List; | ||
| 13 | import java.util.Set; | 19 | import java.util.Set; |
| 14 | 20 | ||
| 15 | /** | 21 | /** |
| @@ -35,28 +41,43 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB | @@ -35,28 +41,43 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB | ||
| 35 | */ | 41 | */ |
| 36 | @Override | 42 | @Override |
| 37 | protected int resolveNrOfInstances(DelegateExecution execution) { | 43 | protected int resolveNrOfInstances(DelegateExecution execution) { |
| 38 | - // 第一步,设置 collectionVariable 和 CollectionVariable | ||
| 39 | - // 从 execution.getVariable() 读取所有任务处理人的 key | ||
| 40 | - super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的 | ||
| 41 | - super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId()); | ||
| 42 | - // 从 execution.getVariable() 读取当前所有任务处理的人的 key | ||
| 43 | - super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId()); | ||
| 44 | - | ||
| 45 | - // 第二步,获取任务的所有处理人 | ||
| 46 | - // 不使用 execution.getVariable 原因:目前依次审批任务回退后 collectionVariable 变量没有清理, 如果重新进入该任务不会重新分配审批人 | ||
| 47 | - @SuppressWarnings("unchecked") | ||
| 48 | - Set<Long> assigneeUserIds = (Set<Long>) execution.getVariableLocal(super.collectionVariable, Set.class); | ||
| 49 | - if (assigneeUserIds == null) { | ||
| 50 | - assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution); | ||
| 51 | - if (CollUtil.isEmpty(assigneeUserIds)) { | ||
| 52 | - // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过! | ||
| 53 | - // 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务 | ||
| 54 | - // 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时 | ||
| 55 | - assigneeUserIds = SetUtils.asSet((Long) null); | 44 | + if (execution.getCurrentFlowElement() instanceof UserTask) { |
| 45 | + // 第一步,设置 collectionVariable 和 CollectionVariable | ||
| 46 | + // 从 execution.getVariable() 读取所有任务处理人的 key | ||
| 47 | + super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的 | ||
| 48 | + super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId()); | ||
| 49 | + // 从 execution.getVariable() 读取当前所有任务处理的人的 key | ||
| 50 | + super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId()); | ||
| 51 | + | ||
| 52 | + // 第二步,获取任务的所有处理人 | ||
| 53 | + // 不使用 execution.getVariable 原因:目前依次审批任务回退后 collectionVariable 变量没有清理, 如果重新进入该任务不会重新分配审批人 | ||
| 54 | + @SuppressWarnings("unchecked") | ||
| 55 | + Set<Long> assigneeUserIds = (Set<Long>) execution.getVariableLocal(super.collectionVariable, Set.class); | ||
| 56 | + if (assigneeUserIds == null) { | ||
| 57 | + assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution); | ||
| 58 | + if (CollUtil.isEmpty(assigneeUserIds)) { | ||
| 59 | + // 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过! | ||
| 60 | + // 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务 | ||
| 61 | + // 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时 | ||
| 62 | + assigneeUserIds = SetUtils.asSet((Long) null); | ||
| 63 | + } | ||
| 64 | + execution.setVariableLocal(super.collectionVariable, assigneeUserIds); | ||
| 65 | + } | ||
| 66 | + return assigneeUserIds.size(); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + if (execution.getCurrentFlowElement() instanceof CallActivity) { | ||
| 70 | + FlowElement flowElement = execution.getCurrentFlowElement(); | ||
| 71 | + Integer sourceType = BpmnModelUtils.parseMultiInstanceSourceType(flowElement); | ||
| 72 | + if (sourceType.equals(BpmChildProcessMultiInstanceSourceTypeEnum.DIGITAL_FORM.getType())) { | ||
| 73 | + return execution.getVariable(super.collectionExpression.getExpressionText(), Integer.class); | ||
| 74 | + } | ||
| 75 | + if (sourceType.equals(BpmChildProcessMultiInstanceSourceTypeEnum.MULTI_FORM.getType())) { | ||
| 76 | + return execution.getVariable(super.collectionExpression.getExpressionText(), List.class).size(); | ||
| 56 | } | 77 | } |
| 57 | - execution.setVariableLocal(super.collectionVariable, assigneeUserIds); | ||
| 58 | } | 78 | } |
| 59 | - return assigneeUserIds.size(); | 79 | + |
| 80 | + return super.resolveNrOfInstances(execution); | ||
| 60 | } | 81 | } |
| 61 | 82 | ||
| 62 | } | 83 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java
| @@ -69,6 +69,11 @@ public interface BpmnModelConstants { | @@ -69,6 +69,11 @@ public interface BpmnModelConstants { | ||
| 69 | String USER_TASK_APPROVE_METHOD = "approveMethod"; | 69 | String USER_TASK_APPROVE_METHOD = "approveMethod"; |
| 70 | 70 | ||
| 71 | /** | 71 | /** |
| 72 | + * BPMN Child Process 的扩展属性,用于标记多实例来源类型 | ||
| 73 | + */ | ||
| 74 | + String CHILD_PROCESS_MULTI_INSTANCE_SOURCE_TYPE = "childProcessMultiInstanceSourceType"; | ||
| 75 | + | ||
| 76 | + /** | ||
| 72 | * BPMN ExtensionElement 流程表单字段权限元素, 用于标记字段权限 | 77 | * BPMN ExtensionElement 流程表单字段权限元素, 用于标记字段权限 |
| 73 | */ | 78 | */ |
| 74 | String FORM_FIELD_PERMISSION_ELEMENT = "fieldsPermission"; | 79 | String FORM_FIELD_PERMISSION_ELEMENT = "fieldsPermission"; |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
| @@ -159,6 +159,17 @@ public class BpmnModelUtils { | @@ -159,6 +159,17 @@ public class BpmnModelUtils { | ||
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | /** | 161 | /** |
| 162 | + * 解析子流程多实例来源类型 | ||
| 163 | + * | ||
| 164 | + * @see BpmChildProcessMultiInstanceSourceTypeEnum | ||
| 165 | + * @param element 任务节点 | ||
| 166 | + * @return 多实例来源类型 | ||
| 167 | + */ | ||
| 168 | + public static Integer parseMultiInstanceSourceType(FlowElement element) { | ||
| 169 | + return NumberUtils.parseInt(parseExtensionElement(element, BpmnModelConstants.CHILD_PROCESS_MULTI_INSTANCE_SOURCE_TYPE)); | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + /** | ||
| 162 | * 添加任务拒绝处理元素 | 173 | * 添加任务拒绝处理元素 |
| 163 | * | 174 | * |
| 164 | * @param rejectHandler 任务拒绝处理 | 175 | * @param rejectHandler 任务拒绝处理 |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.B | @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.B | ||
| 10 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups; | 10 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups; |
| 11 | import cn.iocoder.yudao.module.bpm.enums.definition.*; | 11 | import cn.iocoder.yudao.module.bpm.enums.definition.*; |
| 12 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; | 12 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; |
| 13 | -import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; | ||
| 14 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; | 13 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; |
| 15 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmCopyTaskDelegate; | 14 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmCopyTaskDelegate; |
| 16 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmTriggerTaskDelegate; | 15 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmTriggerTaskDelegate; |
| @@ -84,7 +83,7 @@ public class SimpleModelUtils { | @@ -84,7 +83,7 @@ public class SimpleModelUtils { | ||
| 84 | traverseNodeToBuildFlowNode(startNode, process); | 83 | traverseNodeToBuildFlowNode(startNode, process); |
| 85 | 84 | ||
| 86 | // 3. 构建并添加节点之间的连线 Sequence Flow | 85 | // 3. 构建并添加节点之间的连线 Sequence Flow |
| 87 | - EndEvent endEvent = BpmnModelUtils.getEndEvent(bpmnModel); | 86 | + EndEvent endEvent = getEndEvent(bpmnModel); |
| 88 | traverseNodeToBuildSequenceFlow(process, startNode, endEvent.getId()); | 87 | traverseNodeToBuildSequenceFlow(process, startNode, endEvent.getId()); |
| 89 | 88 | ||
| 90 | // 4. 自动布局 | 89 | // 4. 自动布局 |
| @@ -364,7 +363,7 @@ public class SimpleModelUtils { | @@ -364,7 +363,7 @@ public class SimpleModelUtils { | ||
| 364 | userTask.setName(node.getName()); | 363 | userTask.setName(node.getName()); |
| 365 | 364 | ||
| 366 | // 人工审批 | 365 | // 人工审批 |
| 367 | - addExtensionElement(userTask, BpmnModelConstants.USER_TASK_APPROVE_TYPE, BpmUserTaskApproveTypeEnum.USER.getType()); | 366 | + addExtensionElement(userTask, USER_TASK_APPROVE_TYPE, BpmUserTaskApproveTypeEnum.USER.getType()); |
| 368 | // 候选人策略为发起人自己 | 367 | // 候选人策略为发起人自己 |
| 369 | addCandidateElements(BpmTaskCandidateStrategyEnum.START_USER.getStrategy(), null, userTask); | 368 | addCandidateElements(BpmTaskCandidateStrategyEnum.START_USER.getStrategy(), null, userTask); |
| 370 | // 添加表单字段权限属性元素 | 369 | // 添加表单字段权限属性元素 |
| @@ -415,25 +414,17 @@ public class SimpleModelUtils { | @@ -415,25 +414,17 @@ public class SimpleModelUtils { | ||
| 415 | */ | 414 | */ |
| 416 | private BoundaryEvent buildUserTaskTimeoutBoundaryEvent(UserTask userTask, | 415 | private BoundaryEvent buildUserTaskTimeoutBoundaryEvent(UserTask userTask, |
| 417 | BpmSimpleModelNodeVO.TimeoutHandler timeoutHandler) { | 416 | BpmSimpleModelNodeVO.TimeoutHandler timeoutHandler) { |
| 418 | - // 1.1 定时器边界事件 | ||
| 419 | - // TODO @lesan:一些 BoundaryEvent timeout 的,可以做一些基础的设置么? | ||
| 420 | - BoundaryEvent boundaryEvent = new BoundaryEvent(); | ||
| 421 | - boundaryEvent.setId("Event-" + IdUtil.fastUUID()); | ||
| 422 | - boundaryEvent.setCancelActivity(false); // 设置关联的任务为不会被中断 | ||
| 423 | - boundaryEvent.setAttachedToRef(userTask); | ||
| 424 | - // 1.2 定义超时时间、最大提醒次数 | ||
| 425 | - TimerEventDefinition eventDefinition = new TimerEventDefinition(); | ||
| 426 | - eventDefinition.setTimeDuration(timeoutHandler.getTimeDuration()); | 417 | + // 1. 创建 Timeout Boundary Event |
| 418 | + String timeCycle = null; | ||
| 427 | if (Objects.equals(BpmUserTaskTimeoutHandlerTypeEnum.REMINDER.getType(), timeoutHandler.getType()) && | 419 | if (Objects.equals(BpmUserTaskTimeoutHandlerTypeEnum.REMINDER.getType(), timeoutHandler.getType()) && |
| 428 | timeoutHandler.getMaxRemindCount() != null && timeoutHandler.getMaxRemindCount() > 1) { | 420 | timeoutHandler.getMaxRemindCount() != null && timeoutHandler.getMaxRemindCount() > 1) { |
| 429 | - eventDefinition.setTimeCycle(String.format("R%d/%s", | ||
| 430 | - timeoutHandler.getMaxRemindCount(), timeoutHandler.getTimeDuration())); | 421 | + timeCycle = String.format("R%d/%s", |
| 422 | + timeoutHandler.getMaxRemindCount(), timeoutHandler.getTimeDuration()); | ||
| 431 | } | 423 | } |
| 432 | - boundaryEvent.addEventDefinition(eventDefinition); | 424 | + BoundaryEvent boundaryEvent = buildTimeoutBoundaryEvent(userTask, BpmBoundaryEventTypeEnum.USER_TASK_TIMEOUT.getType(), |
| 425 | + timeoutHandler.getTimeDuration(), timeCycle, null); | ||
| 433 | 426 | ||
| 434 | - // 2.1 添加定时器边界事件类型 | ||
| 435 | - addExtensionElement(boundaryEvent, BOUNDARY_EVENT_TYPE, BpmBoundaryEventTypeEnum.USER_TASK_TIMEOUT.getType()); | ||
| 436 | - // 2.2 添加超时执行动作元素 | 427 | + // 2 添加超时执行动作元素 |
| 437 | addExtensionElement(boundaryEvent, USER_TASK_TIMEOUT_HANDLER_TYPE, timeoutHandler.getType()); | 428 | addExtensionElement(boundaryEvent, USER_TASK_TIMEOUT_HANDLER_TYPE, timeoutHandler.getType()); |
| 438 | return boundaryEvent; | 429 | return boundaryEvent; |
| 439 | } | 430 | } |
| @@ -516,7 +507,7 @@ public class SimpleModelUtils { | @@ -516,7 +507,7 @@ public class SimpleModelUtils { | ||
| 516 | BpmUserTaskApproveMethodEnum approveMethodEnum = BpmUserTaskApproveMethodEnum.valueOf(approveMethod); | 507 | BpmUserTaskApproveMethodEnum approveMethodEnum = BpmUserTaskApproveMethodEnum.valueOf(approveMethod); |
| 517 | Assert.notNull(approveMethodEnum, "审批方式({})不能为空", approveMethodEnum); | 508 | Assert.notNull(approveMethodEnum, "审批方式({})不能为空", approveMethodEnum); |
| 518 | // 添加审批方式的扩展属性 | 509 | // 添加审批方式的扩展属性 |
| 519 | - addExtensionElement(userTask, BpmnModelConstants.USER_TASK_APPROVE_METHOD, approveMethod); | 510 | + addExtensionElement(userTask, USER_TASK_APPROVE_METHOD, approveMethod); |
| 520 | if (approveMethodEnum == BpmUserTaskApproveMethodEnum.RANDOM) { | 511 | if (approveMethodEnum == BpmUserTaskApproveMethodEnum.RANDOM) { |
| 521 | // 随机审批,不需要设置多实例属性 | 512 | // 随机审批,不需要设置多实例属性 |
| 522 | return; | 513 | return; |
| @@ -723,21 +714,14 @@ public class SimpleModelUtils { | @@ -723,21 +714,14 @@ public class SimpleModelUtils { | ||
| 723 | 714 | ||
| 724 | // 2. 添加接收任务的 Timer Boundary Event | 715 | // 2. 添加接收任务的 Timer Boundary Event |
| 725 | if (node.getDelaySetting() != null) { | 716 | if (node.getDelaySetting() != null) { |
| 726 | - // 2.1 定时器边界事件 | ||
| 727 | - // TODO @lesan:一些 BoundaryEvent timeout 的,可以做一些基础的设置么? | ||
| 728 | - BoundaryEvent boundaryEvent = new BoundaryEvent(); | ||
| 729 | - boundaryEvent.setId("Event-" + IdUtil.fastUUID()); | ||
| 730 | - boundaryEvent.setCancelActivity(false); | ||
| 731 | - boundaryEvent.setAttachedToRef(receiveTask); | ||
| 732 | - // 2.2 定义超时时间 | ||
| 733 | - TimerEventDefinition eventDefinition = new TimerEventDefinition(); | 717 | + BoundaryEvent boundaryEvent = null; |
| 734 | if (node.getDelaySetting().getDelayType().equals(BpmDelayTimerTypeEnum.FIXED_DATE_TIME.getType())) { | 718 | if (node.getDelaySetting().getDelayType().equals(BpmDelayTimerTypeEnum.FIXED_DATE_TIME.getType())) { |
| 735 | - eventDefinition.setTimeDuration(node.getDelaySetting().getDelayTime()); | 719 | + boundaryEvent = buildTimeoutBoundaryEvent(receiveTask, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT.getType(), |
| 720 | + node.getDelaySetting().getDelayTime(), null, null); | ||
| 736 | } else if (node.getDelaySetting().getDelayType().equals(BpmDelayTimerTypeEnum.FIXED_TIME_DURATION.getType())) { | 721 | } else if (node.getDelaySetting().getDelayType().equals(BpmDelayTimerTypeEnum.FIXED_TIME_DURATION.getType())) { |
| 737 | - eventDefinition.setTimeDate(node.getDelaySetting().getDelayTime()); | 722 | + boundaryEvent = buildTimeoutBoundaryEvent(receiveTask, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT.getType(), |
| 723 | + null, null, node.getDelaySetting().getDelayTime()); | ||
| 738 | } | 724 | } |
| 739 | - boundaryEvent.addEventDefinition(eventDefinition); | ||
| 740 | - addExtensionElement(boundaryEvent, BOUNDARY_EVENT_TYPE, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT.getType()); | ||
| 741 | flowElements.add(boundaryEvent); | 725 | flowElements.add(boundaryEvent); |
| 742 | } | 726 | } |
| 743 | return flowElements; | 727 | return flowElements; |
| @@ -869,23 +853,35 @@ public class SimpleModelUtils { | @@ -869,23 +853,35 @@ public class SimpleModelUtils { | ||
| 869 | callActivity.setExecutionListeners(executionListeners); | 853 | callActivity.setExecutionListeners(executionListeners); |
| 870 | 854 | ||
| 871 | // 7. 超时设置 | 855 | // 7. 超时设置 |
| 872 | - if (childProcessSetting.getTimeoutSetting() != null) { | ||
| 873 | - // TODO @lesan:一些 BoundaryEvent timeout 的,可以做一些基础的设置么? | ||
| 874 | - BoundaryEvent boundaryEvent = new BoundaryEvent(); | ||
| 875 | - boundaryEvent.setId("Event-" + IdUtil.fastUUID()); | ||
| 876 | - boundaryEvent.setCancelActivity(false); | ||
| 877 | - boundaryEvent.setAttachedToRef(callActivity); | ||
| 878 | - TimerEventDefinition eventDefinition = new TimerEventDefinition(); | 856 | + if (childProcessSetting.getTimeoutSetting() != null && Boolean.TRUE.equals(childProcessSetting.getTimeoutSetting().getEnable())) { |
| 857 | + BoundaryEvent boundaryEvent = null; | ||
| 879 | if (childProcessSetting.getTimeoutSetting().getType().equals(BpmDelayTimerTypeEnum.FIXED_DATE_TIME.getType())) { | 858 | if (childProcessSetting.getTimeoutSetting().getType().equals(BpmDelayTimerTypeEnum.FIXED_DATE_TIME.getType())) { |
| 880 | - eventDefinition.setTimeDuration(childProcessSetting.getTimeoutSetting().getTimeExpression()); | 859 | + boundaryEvent = buildTimeoutBoundaryEvent(callActivity, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT.getType(), |
| 860 | + childProcessSetting.getTimeoutSetting().getTimeExpression(), null, null); | ||
| 881 | } else if (childProcessSetting.getTimeoutSetting().getType().equals(BpmDelayTimerTypeEnum.FIXED_TIME_DURATION.getType())) { | 861 | } else if (childProcessSetting.getTimeoutSetting().getType().equals(BpmDelayTimerTypeEnum.FIXED_TIME_DURATION.getType())) { |
| 882 | - eventDefinition.setTimeDate(childProcessSetting.getTimeoutSetting().getTimeExpression()); | 862 | + boundaryEvent = buildTimeoutBoundaryEvent(callActivity, BpmBoundaryEventTypeEnum.CHILD_PROCESS_TIMEOUT.getType(), |
| 863 | + null, null, childProcessSetting.getTimeoutSetting().getTimeExpression()); | ||
| 883 | } | 864 | } |
| 884 | - boundaryEvent.addEventDefinition(eventDefinition); | ||
| 885 | - addExtensionElement(boundaryEvent, BOUNDARY_EVENT_TYPE, BpmBoundaryEventTypeEnum.CHILD_PROCESS_TIMEOUT.getType()); | ||
| 886 | flowElements.add(boundaryEvent); | 865 | flowElements.add(boundaryEvent); |
| 887 | } | 866 | } |
| 888 | 867 | ||
| 868 | + // 8. 多实例 | ||
| 869 | + if (childProcessSetting.getMultiInstanceSetting() != null && Boolean.TRUE.equals(childProcessSetting.getMultiInstanceSetting().getEnable())) { | ||
| 870 | + MultiInstanceLoopCharacteristics multiInstanceCharacteristics = new MultiInstanceLoopCharacteristics(); | ||
| 871 | + multiInstanceCharacteristics.setSequential(childProcessSetting.getMultiInstanceSetting().getSequential()); | ||
| 872 | + if (childProcessSetting.getMultiInstanceSetting().getSourceType().equals(BpmChildProcessMultiInstanceSourceTypeEnum.FIXED_QUANTITY.getType())) { | ||
| 873 | + multiInstanceCharacteristics.setLoopCardinality(childProcessSetting.getMultiInstanceSetting().getSource()); | ||
| 874 | + } | ||
| 875 | + if (childProcessSetting.getMultiInstanceSetting().getSourceType().equals(BpmChildProcessMultiInstanceSourceTypeEnum.DIGITAL_FORM.getType()) || | ||
| 876 | + childProcessSetting.getMultiInstanceSetting().getSourceType().equals(BpmChildProcessMultiInstanceSourceTypeEnum.MULTI_FORM.getType())) { | ||
| 877 | + multiInstanceCharacteristics.setInputDataItem(childProcessSetting.getMultiInstanceSetting().getSource()); | ||
| 878 | + } | ||
| 879 | + multiInstanceCharacteristics.setCompletionCondition(String.format("${ nrOfCompletedInstances/nrOfInstances >= %s}", | ||
| 880 | + String.format("%.2f", childProcessSetting.getMultiInstanceSetting().getCompleteRatio() / 100D))); | ||
| 881 | + callActivity.setLoopCharacteristics(multiInstanceCharacteristics); | ||
| 882 | + addExtensionElement(callActivity, CHILD_PROCESS_MULTI_INSTANCE_SOURCE_TYPE, childProcessSetting.getMultiInstanceSetting().getSourceType()); | ||
| 883 | + } | ||
| 884 | + | ||
| 889 | // 添加节点类型 | 885 | // 添加节点类型 |
| 890 | addNodeType(node.getType(), callActivity); | 886 | addNodeType(node.getType(), callActivity); |
| 891 | flowElements.add(callActivity); | 887 | flowElements.add(callActivity); |
| @@ -903,6 +899,33 @@ public class SimpleModelUtils { | @@ -903,6 +899,33 @@ public class SimpleModelUtils { | ||
| 903 | return id + "_join"; | 899 | return id + "_join"; |
| 904 | } | 900 | } |
| 905 | 901 | ||
| 902 | + private static BoundaryEvent buildTimeoutBoundaryEvent(Activity attachedToRef, Integer type, | ||
| 903 | + String timeDuration, | ||
| 904 | + String timeCycle, | ||
| 905 | + String timeDate) { | ||
| 906 | + // 1.1 定时器边界事件 | ||
| 907 | + BoundaryEvent boundaryEvent = new BoundaryEvent(); | ||
| 908 | + boundaryEvent.setId("Event-" + IdUtil.fastUUID()); | ||
| 909 | + boundaryEvent.setCancelActivity(false); // 设置关联的任务为不会被中断 | ||
| 910 | + boundaryEvent.setAttachedToRef(attachedToRef); | ||
| 911 | + // 1.2 定义超时时间表达式 | ||
| 912 | + TimerEventDefinition eventDefinition = new TimerEventDefinition(); | ||
| 913 | + if (ObjUtil.isNotNull(timeDuration)) { | ||
| 914 | + eventDefinition.setTimeDuration(timeDuration); | ||
| 915 | + } | ||
| 916 | + if (ObjUtil.isNotNull(timeDuration)) { | ||
| 917 | + eventDefinition.setTimeCycle(timeCycle); | ||
| 918 | + } | ||
| 919 | + if (ObjUtil.isNotNull(timeDate)) { | ||
| 920 | + eventDefinition.setTimeDate(timeDate); | ||
| 921 | + } | ||
| 922 | + boundaryEvent.addEventDefinition(eventDefinition); | ||
| 923 | + | ||
| 924 | + // 2.1 添加定时器边界事件类型 | ||
| 925 | + addExtensionElement(boundaryEvent, BOUNDARY_EVENT_TYPE, type); | ||
| 926 | + return boundaryEvent; | ||
| 927 | + } | ||
| 928 | + | ||
| 906 | // ========== SIMPLE 流程预测相关的方法 ========== | 929 | // ========== SIMPLE 流程预测相关的方法 ========== |
| 907 | 930 | ||
| 908 | public static List<BpmSimpleModelNodeVO> simulateProcess(BpmSimpleModelNodeVO rootNode, Map<String, Object> variables) { | 931 | public static List<BpmSimpleModelNodeVO> simulateProcess(BpmSimpleModelNodeVO rootNode, Map<String, Object> variables) { |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| @@ -414,7 +414,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -414,7 +414,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 414 | // 处理每个任务的 tasks 属性 | 414 | // 处理每个任务的 tasks 属性 |
| 415 | for (HistoricActivityInstance activity : taskActivities) { | 415 | for (HistoricActivityInstance activity : taskActivities) { |
| 416 | HistoricTaskInstance task = taskMap.get(activity.getTaskId()); | 416 | HistoricTaskInstance task = taskMap.get(activity.getTaskId()); |
| 417 | - // TODO @lesan:这里为啥 continue 哈? @芋艿:子流程的 activity 中 task 是null 下面的方法会报错;TODO @lesan:写个注释??? | 417 | + // ChildProcess 子流程节点仅存在于 activity 中,并且没有自身的 task ,需要跳过执行 |
| 418 | if (task == null) { | 418 | if (task == null) { |
| 419 | continue; | 419 | continue; |
| 420 | } | 420 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java
| 1 | package cn.iocoder.yudao.module.bpm.service.task.listener; | 1 | package cn.iocoder.yudao.module.bpm.service.task.listener; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.lang.Assert; | 3 | import cn.hutool.core.lang.Assert; |
| 4 | +import cn.hutool.core.map.MapUtil; | ||
| 4 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 6 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 6 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; | 7 | 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 | @@ -9,13 +10,14 @@ import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessStartUserEmpt | ||
| 9 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessStartUserTypeEnum; | 10 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessStartUserTypeEnum; |
| 10 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; | 11 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; |
| 11 | import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; | 12 | import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; |
| 13 | +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | ||
| 12 | import jakarta.annotation.Resource; | 14 | import jakarta.annotation.Resource; |
| 13 | import lombok.Setter; | 15 | import lombok.Setter; |
| 14 | import lombok.extern.slf4j.Slf4j; | 16 | import lombok.extern.slf4j.Slf4j; |
| 15 | import org.flowable.engine.delegate.DelegateExecution; | 17 | import org.flowable.engine.delegate.DelegateExecution; |
| 16 | import org.flowable.engine.delegate.ExecutionListener; | 18 | import org.flowable.engine.delegate.ExecutionListener; |
| 17 | import org.flowable.engine.impl.el.FixedValue; | 19 | import org.flowable.engine.impl.el.FixedValue; |
| 18 | -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; | 20 | +import org.flowable.engine.runtime.ProcessInstance; |
| 19 | import org.springframework.stereotype.Component; | 21 | import org.springframework.stereotype.Component; |
| 20 | 22 | ||
| 21 | import java.util.List; | 23 | import java.util.List; |
| @@ -37,30 +39,32 @@ public class BpmCallActivityListener implements ExecutionListener { | @@ -37,30 +39,32 @@ public class BpmCallActivityListener implements ExecutionListener { | ||
| 37 | @Resource | 39 | @Resource |
| 38 | private BpmProcessDefinitionService processDefinitionService; | 40 | private BpmProcessDefinitionService processDefinitionService; |
| 39 | 41 | ||
| 42 | + @Resource | ||
| 43 | + private BpmProcessInstanceService processInstanceService; | ||
| 44 | + | ||
| 40 | @Override | 45 | @Override |
| 41 | public void notify(DelegateExecution execution) { | 46 | public void notify(DelegateExecution execution) { |
| 42 | String expressionText = listenerConfig.getExpressionText(); | 47 | String expressionText = listenerConfig.getExpressionText(); |
| 43 | Assert.notNull(expressionText, "监听器扩展字段({})不能为空", expressionText); | 48 | Assert.notNull(expressionText, "监听器扩展字段({})不能为空", expressionText); |
| 44 | BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting startUserSetting = JsonUtils.parseObject( | 49 | BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting startUserSetting = JsonUtils.parseObject( |
| 45 | expressionText, BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting.class); | 50 | expressionText, BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting.class); |
| 51 | + ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getRootProcessInstanceId()); | ||
| 46 | 52 | ||
| 47 | // 1. 当发起人来源为主流程发起人时,并兜底 startUserSetting 为空时 | 53 | // 1. 当发起人来源为主流程发起人时,并兜底 startUserSetting 为空时 |
| 48 | if (startUserSetting == null | 54 | if (startUserSetting == null |
| 49 | || startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER.getType())) { | 55 | || startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER.getType())) { |
| 50 | - ExecutionEntity parent = (ExecutionEntity) execution.getParent(); | ||
| 51 | - FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); | 56 | + FlowableUtils.setAuthenticatedUserId(Long.parseLong(processInstance.getStartUserId())); |
| 52 | return; | 57 | return; |
| 53 | } | 58 | } |
| 54 | 59 | ||
| 55 | // 2. 当发起人来源为表单时 | 60 | // 2. 当发起人来源为表单时 |
| 56 | if (startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.FROM_FORM.getType())) { | 61 | if (startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.FROM_FORM.getType())) { |
| 57 | - ExecutionEntity parent = (ExecutionEntity) execution.getParent(); | ||
| 58 | - String formFieldValue = parent.getVariable(startUserSetting.getFormField(), String.class); | 62 | + String formFieldValue = MapUtil.getStr(processInstance.getProcessVariables(), startUserSetting.getFormField()); |
| 59 | // 2.1 当表单值为空时 | 63 | // 2.1 当表单值为空时 |
| 60 | if (StrUtil.isEmpty(formFieldValue)) { | 64 | if (StrUtil.isEmpty(formFieldValue)) { |
| 61 | // 2.1.1 来自主流程发起人 | 65 | // 2.1.1 来自主流程发起人 |
| 62 | if (startUserSetting.getEmptyType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())) { | 66 | if (startUserSetting.getEmptyType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())) { |
| 63 | - FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); | 67 | + FlowableUtils.setAuthenticatedUserId(Long.parseLong(processInstance.getStartUserId())); |
| 64 | return; | 68 | return; |
| 65 | } | 69 | } |
| 66 | // 2.1.2 来自子流程管理员 | 70 | // 2.1.2 来自子流程管理员 |
| @@ -72,7 +76,7 @@ public class BpmCallActivityListener implements ExecutionListener { | @@ -72,7 +76,7 @@ public class BpmCallActivityListener implements ExecutionListener { | ||
| 72 | } | 76 | } |
| 73 | // 2.1.3 来自主流程管理员 | 77 | // 2.1.3 来自主流程管理员 |
| 74 | if (startUserSetting.getEmptyType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())) { | 78 | if (startUserSetting.getEmptyType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())) { |
| 75 | - BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(parent.getProcessDefinitionId()); | 79 | + BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(processInstance.getProcessDefinitionId()); |
| 76 | List<Long> managerUserIds = processDefinition.getManagerUserIds(); | 80 | List<Long> managerUserIds = processDefinition.getManagerUserIds(); |
| 77 | FlowableUtils.setAuthenticatedUserId(managerUserIds.get(0)); | 81 | FlowableUtils.setAuthenticatedUserId(managerUserIds.get(0)); |
| 78 | return; | 82 | return; |
| @@ -84,7 +88,7 @@ public class BpmCallActivityListener implements ExecutionListener { | @@ -84,7 +88,7 @@ public class BpmCallActivityListener implements ExecutionListener { | ||
| 84 | } catch (Exception e) { | 88 | } catch (Exception e) { |
| 85 | log.error("[notify][监听器:{},子流程监听器设置流程的发起人字符串转 Long 失败,字符串:{}]", | 89 | log.error("[notify][监听器:{},子流程监听器设置流程的发起人字符串转 Long 失败,字符串:{}]", |
| 86 | DELEGATE_EXPRESSION, formFieldValue); | 90 | DELEGATE_EXPRESSION, formFieldValue); |
| 87 | - FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); | 91 | + FlowableUtils.setAuthenticatedUserId(Long.parseLong(processInstance.getStartUserId())); |
| 88 | } | 92 | } |
| 89 | } | 93 | } |
| 90 | } | 94 | } |