Commit 11858ca0dd3b7063ea7743bb551c1ca73fda5089

Authored by Lesan
1 parent 0e48458e

feat: 子流程-子流程发起人

yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserEmptyTypeEnum.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 BpmChildProcessStartUserEmptyTypeEnum implements ArrayValuable<Integer> {
  18 +
  19 + MAIN_PROCESS_START_USER(1, "同主流程发起人"),
  20 + CHILD_PROCESS_ADMIN(2, "子流程管理员"),
  21 + MAIN_PROCESS_ADMIN(3, "主流程管理员");
  22 +
  23 + private final Integer type;
  24 + private final String name;
  25 +
  26 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmChildProcessStartUserEmptyTypeEnum::getType).toArray(Integer[]::new);
  27 +
  28 + public static BpmChildProcessStartUserEmptyTypeEnum 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-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserTypeEnum.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 BpmChildProcessStartUserTypeEnum implements ArrayValuable<Integer> {
  18 +
  19 + MAIN_PROCESS_START_USER(1, "同主流程发起人"),
  20 + FROM_FORM(2, "表单");
  21 +
  22 + private final Integer type;
  23 + private final String name;
  24 +
  25 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmChildProcessStartUserTypeEnum::getType).toArray(Integer[]::new);
  26 +
  27 + public static BpmChildProcessStartUserTypeEnum typeOf(Integer type) {
  28 + return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
  29 + }
  30 +
  31 + @Override
  32 + public Integer[] array() {
  33 + return ARRAYS;
  34 + }
  35 +}
... ...
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 {
428 428 @NotNull(message = "是否自动跳过子流程发起节点不能为空")
429 429 private Boolean skipStartUserNode;
430 430  
  431 + @Schema(description = "子流程发起人配置", example = "{}")
  432 + private StartUserSetting startUserSetting;
  433 +
  434 + @Schema(description = "子流程发起人配置")
  435 + @Data
  436 + @Valid
  437 + public static class StartUserSetting {
  438 +
  439 + @Schema(description = "子流程发起人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  440 + @NotNull(message = "子流程发起人类型")
  441 + @InEnum(BpmChildProcessStartUserTypeEnum.class)
  442 + private Integer type;
  443 +
  444 + @Schema(description = "表单", example = "xxx")
  445 + private String formField;
  446 +
  447 + @Schema(description = "当子流程发起人为空时类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  448 + @InEnum(BpmChildProcessStartUserEmptyTypeEnum.class)
  449 + private Integer emptyHandleType;
  450 +
  451 + }
  452 +
431 453 }
432 454 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java
1 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
2 2  
3 3 import cn.hutool.core.util.ObjectUtil;
  4 +import cn.hutool.core.util.StrUtil;
4 5 import cn.hutool.extra.spring.SpringUtil;
5 6 import cn.iocoder.yudao.framework.common.core.KeyValue;
6 7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
... ... @@ -240,7 +241,7 @@ public class FlowableUtils {
240 241 return formFieldsMap.entrySet().stream()
241 242 .limit(3)
242 243 .map(entry -> new KeyValue<>(entry.getValue().getTitle(),
243   - processVariables.getOrDefault(entry.getValue().getField(), "").toString()))
  244 + StrUtil.toStringOrEmpty(processVariables.getOrDefault(entry.getValue().getField(), ""))))
244 245 .collect(Collectors.toList());
245 246 }
246 247  
... ...
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;
5 5 import cn.hutool.core.map.MapUtil;
6 6 import cn.hutool.core.util.*;
7 7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  8 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
8 9 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
9 10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups;
10 11 import cn.iocoder.yudao.module.bpm.enums.definition.*;
... ... @@ -16,6 +17,7 @@ import org.flowable.bpmn.BpmnAutoLayout;
16 17 import org.flowable.bpmn.constants.BpmnXMLConstants;
17 18 import org.flowable.bpmn.model.Process;
18 19 import org.flowable.bpmn.model.*;
  20 +import org.flowable.engine.delegate.ExecutionListener;
19 21 import org.flowable.engine.delegate.TaskListener;
20 22 import org.springframework.util.MultiValueMap;
21 23  
... ... @@ -816,6 +818,18 @@ public class SimpleModelUtils {
816 818 if (childProcessSetting.getOutVariable() != null && !childProcessSetting.getOutVariable().isEmpty()) {
817 819 callActivity.setOutParameters(childProcessSetting.getOutVariable());
818 820 }
  821 + // 6. 子流程发起人配置
  822 + List<FlowableListener> executionListeners = new ArrayList<>();
  823 + FlowableListener flowableListener = new FlowableListener();
  824 + flowableListener.setEvent(ExecutionListener.EVENTNAME_START);
  825 + flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
  826 + flowableListener.setImplementation("${bpmCallActivityListener}");
  827 + FieldExtension fieldExtension = new FieldExtension();
  828 + fieldExtension.setFieldName("listenerConfig");
  829 + fieldExtension.setStringValue(JsonUtils.toJsonString(childProcessSetting.getStartUserSetting()));
  830 + flowableListener.getFieldExtensions().add(fieldExtension);
  831 + executionListeners.add(flowableListener);
  832 + callActivity.setExecutionListeners(executionListeners);
819 833 // 添加节点类型
820 834 addNodeType(node.getType(), callActivity);
821 835 return callActivity;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task.listener;
  2 +
  3 +import cn.hutool.core.convert.Convert;
  4 +import cn.hutool.core.lang.Assert;
  5 +import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
  8 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
  9 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessStartUserEmptyTypeEnum;
  10 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmChildProcessStartUserTypeEnum;
  11 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
  12 +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
  13 +import jakarta.annotation.Resource;
  14 +import lombok.Setter;
  15 +import lombok.extern.slf4j.Slf4j;
  16 +import org.flowable.engine.delegate.DelegateExecution;
  17 +import org.flowable.engine.delegate.ExecutionListener;
  18 +import org.flowable.engine.impl.el.FixedValue;
  19 +import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
  20 +import org.springframework.stereotype.Component;
  21 +
  22 +import java.util.List;
  23 +
  24 +/**
  25 + * BPM 子流程监听器
  26 + *
  27 + * @author Lesan
  28 + */
  29 +@Component
  30 +@Slf4j
  31 +public class BpmCallActivityListener implements ExecutionListener {
  32 +
  33 + public static final String DELEGATE_EXPRESSION = "${bpmCallActivityListener}";
  34 +
  35 + @Setter
  36 + private FixedValue listenerConfig;
  37 +
  38 + @Resource
  39 + private BpmProcessDefinitionService processDefinitionService;
  40 +
  41 + @Override
  42 + public void notify(DelegateExecution execution) {
  43 + String expressionText = listenerConfig.getExpressionText();
  44 + Assert.notNull(expressionText, "监听器扩展字段({})不能为空", expressionText);
  45 + BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting startUserSetting = JsonUtils.parseObject(expressionText, BpmSimpleModelNodeVO.ChildProcessSetting.StartUserSetting.class);
  46 + // 1. 当发起人来源为表单时
  47 + if (startUserSetting != null &&
  48 + startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.FROM_FORM.getType())) {
  49 + ExecutionEntity parent = (ExecutionEntity) execution.getParent();
  50 + String formField = parent.getVariable(startUserSetting.getFormField(), String.class);
  51 + // 1.1 当表单值为空时
  52 + if (StrUtil.isEmpty(formField)) {
  53 + // 1.1.1 来自主流程发起人
  54 + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())){
  55 + FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId()));
  56 + return;
  57 + }
  58 + // 1.1.2 来自子流程管理员
  59 + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.CHILD_PROCESS_ADMIN.getType())){
  60 + BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(execution.getProcessDefinitionId());
  61 + List<Long> managerUserIds = processDefinition.getManagerUserIds();
  62 + FlowableUtils.setAuthenticatedUserId(Convert.toLong(managerUserIds.get(0)));
  63 + return;
  64 + }
  65 + // 1.1.3 来自主流程管理员
  66 + if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())){
  67 + BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(parent.getProcessDefinitionId());
  68 + List<Long> managerUserIds = processDefinition.getManagerUserIds();
  69 + FlowableUtils.setAuthenticatedUserId(Convert.toLong(managerUserIds.get(0)));
  70 + return;
  71 + }
  72 + }
  73 + // 1.2 使用表单值,并兜底字符串转Long失败时使用主流程发起人
  74 + try {
  75 + FlowableUtils.setAuthenticatedUserId(Long.parseLong(formField));
  76 + } catch (Exception e) {
  77 + FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId()));
  78 + }
  79 + }
  80 + // 2. 当发起人来源为主流程发起人时,并兜底startUserSetting为空时
  81 + if (startUserSetting == null ||
  82 + startUserSetting.getType().equals(BpmChildProcessStartUserTypeEnum.MAIN_PROCESS_START_USER.getType())) {
  83 + ExecutionEntity parent = (ExecutionEntity) execution.getParent();
  84 + FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId()));
  85 + }
  86 + }
  87 +
  88 +}
0 89 \ No newline at end of file
... ...