Commit 797fddfb3d495303378a4798d7934086cdedc9ae

Authored by YunaiV
1 parent cdbcd4d6

BPM:新增 flowable expression 表达式,替代现有 BpmTaskAssignScript,更加灵活

Showing 12 changed files with 59 additions and 90 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java
... ... @@ -18,7 +18,9 @@ public enum BpmTaskAssignRuleTypeEnum {
18 18 POST(22, "岗位"),
19 19 USER(30, "用户"),
20 20 USER_GROUP(40, "用户组"),
  21 + @Deprecated
21 22 SCRIPT(50, "自定义脚本"), // 例如说,发起人所在部门的领导、发起人所在部门的领导的领导
  23 + EXPRESS(60, "流程表达式"), // 表达式 ExpressionManager
22 24 ;
23 25  
24 26 /**
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java
... ... @@ -14,6 +14,7 @@ import java.util.Set;
14 14 *
15 15 * @author 芋道源码
16 16 */
  17 +@Deprecated
17 18 public interface BpmTaskAssignScript {
18 19  
19 20 /**
... ... @@ -30,5 +31,6 @@ public interface BpmTaskAssignScript {
30 31 * @return 枚举值
31 32 */
32 33 BpmTaskRuleScriptEnum getEnum();
  34 +
33 35 }
34 36  
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java
... ... @@ -24,6 +24,7 @@ import static java.util.Collections.emptySet;
24 24 *
25 25 * @author 芋道源码
26 26 */
  27 +@Deprecated
27 28 public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript {
28 29  
29 30 @Resource
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
... ... @@ -11,6 +11,7 @@ import java.util.Set;
11 11 *
12 12 * @author 芋道源码
13 13 */
  14 +@Deprecated
14 15 @Component
15 16 public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript {
16 17  
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
... ... @@ -11,6 +11,7 @@ import java.util.Set;
11 11 *
12 12 * @author 芋道源码
13 13 */
  14 +@Deprecated
14 15 @Component
15 16 public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript {
16 17  
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java
... ... @@ -18,6 +18,7 @@ import java.util.Set;
18 18 *
19 19 * @author 芋道源码
20 20 */
  21 +@Deprecated
21 22 @Component
22 23 public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript {
23 24  
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.handler;
2   -
3   -import cn.hutool.core.collection.CollUtil;
4   -import cn.hutool.core.util.ObjectUtil;
5   -import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants;
6   -import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
7   -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
8   -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
9   -import jakarta.annotation.Resource;
10   -import lombok.AllArgsConstructor;
11   -import org.flowable.bpmn.model.FlowElement;
12   -import org.flowable.bpmn.model.UserTask;
13   -import org.flowable.engine.delegate.DelegateExecution;
14   -import org.springframework.stereotype.Component;
15   -
16   -import java.util.ArrayList;
17   -import java.util.LinkedHashSet;
18   -import java.util.List;
19   -import java.util.Set;
20   -import java.util.stream.Collectors;
21   -
22   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
23   -
24   -// TODO @芋艿:bpmn 分配人融合时,需要搞下这块;
25   -/**
26   - * 多实例处理类
27   - */
28   -@AllArgsConstructor
29   -@Component("multiInstanceHandler")
30   -public class MultiInstanceHandler {
31   -
32   - @Resource
33   - private AdminUserApi userApi;
34   -
35   - @Resource
36   - private PermissionApi permissionApi;
37   -
38   - /**
39   - * 流程发起人那种情况不需要处理,
40   - * 由 flowable 完成
41   - *
42   - * @param execution flowable的执行对象
43   - * @return 用户ID
44   - */
45   - public Set<String> getUserIds(DelegateExecution execution) {
46   - Set<String> candidateUserIds = new LinkedHashSet<>();
47   - FlowElement flowElement = execution.getCurrentFlowElement();
48   - if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask userTask) {
49   - String dataType = userTask.getAttributeValue(BpmnModelConstants.NAMESPACE, BpmnModelConstants.PROCESS_CUSTOM_DATA_TYPE);
50   - if ("USERS".equals(dataType) && CollUtil.isNotEmpty(userTask.getCandidateUsers())) {
51   - // 添加候选用户id
52   - candidateUserIds.addAll(userTask.getCandidateUsers());
53   - } else if (CollUtil.isNotEmpty(userTask.getCandidateGroups())) {
54   - // 获取组的ID,角色ID集合或部门ID集合
55   - List<Long> groups = userTask.getCandidateGroups().stream()
56   - // 例如部门DEPT100,100才是部门id
57   - .map(item -> Long.parseLong(item.substring(4)))
58   - .collect(Collectors.toList());
59   - List<Long> userIds = new ArrayList<>();
60   - if ("ROLES".equals(dataType)) {
61   - // 通过角色id,获取所有用户id集合
62   - Set<Long> userRoleIdListByRoleIds = permissionApi.getUserRoleIdListByRoleIds(groups);
63   - userIds = new ArrayList<>(userRoleIdListByRoleIds);
64   - } else if ("DEPTS".equals(dataType)) {
65   - // 通过部门id,获取所有用户id集合
66   - List<AdminUserRespDTO> userListByDeptIds = userApi.getUserListByDeptIds(groups);
67   - userIds = convertList(userListByDeptIds, AdminUserRespDTO::getId);
68   - }
69   - // 添加候选用户id
70   - userIds.forEach(id -> candidateUserIds.add(String.valueOf(id)));
71   - }
72   - }
73   - return candidateUserIds;
74   - }
75   -
76   -}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
... ... @@ -171,9 +171,10 @@ public class BpmModelServiceImpl implements BpmModelService {
171 171 // 1.5 校验模型是否发生修改。如果未修改,则不允许创建
172 172 BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form)
173 173 .setBpmnBytes(bpmnBytes);
174   - if (processDefinitionService.isProcessDefinitionEquals(definitionCreateReqDTO)) { // 流程定义的信息相等
175   - throw exception(MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS);
176   - }
  174 + // TODO @芋艿:这里比较可能有点问题
  175 +// if (processDefinitionService.isProcessDefinitionEquals(definitionCreateReqDTO)) { // 流程定义的信息相等
  176 +// throw exception(MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS);
  177 +// }
177 178  
178 179 // 2.1 创建流程定义
179 180 String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO);
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
1 1 package cn.iocoder.yudao.module.bpm.service.definition;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
4 5 import cn.hutool.core.util.StrUtil;
5 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
... ... @@ -10,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils;
10 11 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
11 12 import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants;
12 13 import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
  14 +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
13 15 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
14 16 import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
15 17 import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
... ... @@ -26,6 +28,7 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
26 28 import com.google.common.annotations.VisibleForTesting;
27 29 import jakarta.annotation.Resource;
28 30 import lombok.extern.slf4j.Slf4j;
  31 +import org.dromara.hutool.core.convert.Convert;
29 32 import org.flowable.bpmn.model.BpmnModel;
30 33 import org.flowable.bpmn.model.FlowElement;
31 34 import org.flowable.bpmn.model.UserTask;
... ... @@ -57,6 +60,9 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
57 60 @Lazy // 解决循环依赖
58 61 private BpmProcessInstanceService processInstanceService;
59 62  
  63 +// @Resource
  64 +// private ExpressionManager expressionManager;
  65 +
60 66 @Resource
61 67 private RoleApi roleApi;
62 68 @Resource
... ... @@ -93,6 +99,10 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
93 99 if (type == null || StrUtil.isBlank(options)) {
94 100 throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, userTask.getName());
95 101 }
  102 + // TODO 芋艿:校验 options
  103 + if (ObjectUtil.equal(type, BpmTaskAssignRuleTypeEnum.EXPRESS.getType())) {
  104 + return;
  105 + }
96 106 validTaskAssignRuleOptions(type, StrUtils.splitToLong(options, ","));
97 107 });
98 108 }
... ... @@ -117,6 +127,14 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
117 127 }
118 128 }
119 129  
  130 + public Long test(DelegateExecution execution) {
  131 + return 1L;
  132 + }
  133 +
  134 + public Long test2(DelegateExecution execution, Long id) {
  135 + return id;
  136 + }
  137 +
120 138 @Override
121 139 @DataPermission(enable = false) // 忽略数据权限,不然分配会存在问题
122 140 public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) {
... ... @@ -137,7 +155,11 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
137 155 // TODO 芋艿:assignType/assignOptions/, 枚举
138 156 FlowElement flowElement = execution.getCurrentFlowElement();
139 157 Integer type = NumberUtils.parseInt(flowElement.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignType"));
140   - Set<Long> options = StrUtils.splitToLongSet(flowElement.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignOptions"), ",");
  158 + String optionStr = flowElement.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignOptions");
  159 + Set<Long> options = null;
  160 + if (ObjectUtil.notEqual(BpmTaskAssignRuleTypeEnum.EXPRESS.getType(), type)) {
  161 + options = StrUtils.splitToLongSet(optionStr, ",");
  162 + }
141 163  
142 164 // 计算审批人
143 165 Set<Long> assigneeUserIds = null;
... ... @@ -155,6 +177,9 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
155 177 assigneeUserIds = calculateTaskCandidateUsersByUserGroup(options);
156 178 } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), type)) {
157 179 assigneeUserIds = calculateTaskCandidateUsersByScript(execution, options);
  180 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.EXPRESS.getType(), type)) {
  181 + Object result = FlowableUtils.getExpressionValue(execution, optionStr);
  182 + assigneeUserIds = Convert.toSet(Long.class, result);
158 183 }
159 184  
160 185 // 移除被禁用的用户
... ...
yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java
... ... @@ -14,9 +14,4 @@ public interface BpmnModelConstants {
14 14 */
15 15 String NAMESPACE = "http://flowable.org/bpmn";
16 16  
17   - /**
18   - * 自定义属性 dataType
19   - */
20   - String PROCESS_CUSTOM_DATA_TYPE = "dataType";
21   -
22 17 }
... ...
yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java
1 1 package cn.iocoder.yudao.framework.flowable.core.util;
2 2  
  3 +import org.flowable.common.engine.api.delegate.Expression;
  4 +import org.flowable.common.engine.api.variable.VariableContainer;
  5 +import org.flowable.common.engine.impl.el.ExpressionManager;
3 6 import org.flowable.common.engine.impl.identity.Authentication;
  7 +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
  8 +import org.flowable.engine.impl.util.CommandContextUtil;
4 9  
5 10 /**
6 11 * Flowable 相关的工具方法
... ... @@ -29,4 +34,15 @@ public class FlowableUtils {
29 34 return activityId + "_assignee";
30 35 }
31 36  
  37 + // ========== Expression 相关的工具方法 ==========
  38 +
  39 + public static Object getExpressionValue(VariableContainer variableContainer, String expressionString) {
  40 + ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
  41 + assert processEngineConfiguration != null;
  42 + ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager();
  43 + assert expressionManager != null;
  44 + Expression expression = expressionManager.createExpression(expressionString);
  45 + return expression.getValue(variableContainer);
  46 + }
  47 +
32 48 }
... ...
yudao-server/pom.xml
... ... @@ -46,11 +46,11 @@
46 46 <!-- <version>${revision}</version>-->
47 47 <!-- </dependency>-->
48 48 <!-- 工作流。默认注释,保证编译速度 -->
49   -<!-- <dependency>-->
50   -<!-- <groupId>cn.iocoder.boot</groupId>-->
51   -<!-- <artifactId>yudao-module-bpm-biz</artifactId>-->
52   -<!-- <version>${revision}</version>-->
53   -<!-- </dependency>-->
  49 + <dependency>
  50 + <groupId>cn.iocoder.boot</groupId>
  51 + <artifactId>yudao-module-bpm-biz</artifactId>
  52 + <version>${revision}</version>
  53 + </dependency>
54 54 <!-- 支付服务。默认注释,保证编译速度 -->
55 55 <!-- <dependency>-->
56 56 <!-- <groupId>cn.iocoder.boot</groupId>-->
... ...