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,7 +18,9 @@ public enum BpmTaskAssignRuleTypeEnum {
18 POST(22, "岗位"), 18 POST(22, "岗位"),
19 USER(30, "用户"), 19 USER(30, "用户"),
20 USER_GROUP(40, "用户组"), 20 USER_GROUP(40, "用户组"),
  21 + @Deprecated
21 SCRIPT(50, "自定义脚本"), // 例如说,发起人所在部门的领导、发起人所在部门的领导的领导 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,6 +14,7 @@ import java.util.Set;
14 * 14 *
15 * @author 芋道源码 15 * @author 芋道源码
16 */ 16 */
  17 +@Deprecated
17 public interface BpmTaskAssignScript { 18 public interface BpmTaskAssignScript {
18 19
19 /** 20 /**
@@ -30,5 +31,6 @@ public interface BpmTaskAssignScript { @@ -30,5 +31,6 @@ public interface BpmTaskAssignScript {
30 * @return 枚举值 31 * @return 枚举值
31 */ 32 */
32 BpmTaskRuleScriptEnum getEnum(); 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,6 +24,7 @@ import static java.util.Collections.emptySet;
24 * 24 *
25 * @author 芋道源码 25 * @author 芋道源码
26 */ 26 */
  27 +@Deprecated
27 public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript { 28 public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript {
28 29
29 @Resource 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,6 +11,7 @@ import java.util.Set;
11 * 11 *
12 * @author 芋道源码 12 * @author 芋道源码
13 */ 13 */
  14 +@Deprecated
14 @Component 15 @Component
15 public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript { 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,6 +11,7 @@ import java.util.Set;
11 * 11 *
12 * @author 芋道源码 12 * @author 芋道源码
13 */ 13 */
  14 +@Deprecated
14 @Component 15 @Component
15 public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript { 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,6 +18,7 @@ import java.util.Set;
18 * 18 *
19 * @author 芋道源码 19 * @author 芋道源码
20 */ 20 */
  21 +@Deprecated
21 @Component 22 @Component
22 public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript { 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,9 +171,10 @@ public class BpmModelServiceImpl implements BpmModelService {
171 // 1.5 校验模型是否发生修改。如果未修改,则不允许创建 171 // 1.5 校验模型是否发生修改。如果未修改,则不允许创建
172 BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form) 172 BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form)
173 .setBpmnBytes(bpmnBytes); 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 // 2.1 创建流程定义 179 // 2.1 创建流程定义
179 String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO); 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 package cn.iocoder.yudao.module.bpm.service.definition; 1 package cn.iocoder.yudao.module.bpm.service.definition;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
4 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
@@ -10,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils; @@ -10,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils;
10 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; 11 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
11 import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants; 12 import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants;
12 import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; 13 import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
  14 +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
13 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; 15 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
14 import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants; 16 import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
15 import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; 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,6 +28,7 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
26 import com.google.common.annotations.VisibleForTesting; 28 import com.google.common.annotations.VisibleForTesting;
27 import jakarta.annotation.Resource; 29 import jakarta.annotation.Resource;
28 import lombok.extern.slf4j.Slf4j; 30 import lombok.extern.slf4j.Slf4j;
  31 +import org.dromara.hutool.core.convert.Convert;
29 import org.flowable.bpmn.model.BpmnModel; 32 import org.flowable.bpmn.model.BpmnModel;
30 import org.flowable.bpmn.model.FlowElement; 33 import org.flowable.bpmn.model.FlowElement;
31 import org.flowable.bpmn.model.UserTask; 34 import org.flowable.bpmn.model.UserTask;
@@ -57,6 +60,9 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -57,6 +60,9 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
57 @Lazy // 解决循环依赖 60 @Lazy // 解决循环依赖
58 private BpmProcessInstanceService processInstanceService; 61 private BpmProcessInstanceService processInstanceService;
59 62
  63 +// @Resource
  64 +// private ExpressionManager expressionManager;
  65 +
60 @Resource 66 @Resource
61 private RoleApi roleApi; 67 private RoleApi roleApi;
62 @Resource 68 @Resource
@@ -93,6 +99,10 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -93,6 +99,10 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
93 if (type == null || StrUtil.isBlank(options)) { 99 if (type == null || StrUtil.isBlank(options)) {
94 throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, userTask.getName()); 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 validTaskAssignRuleOptions(type, StrUtils.splitToLong(options, ",")); 106 validTaskAssignRuleOptions(type, StrUtils.splitToLong(options, ","));
97 }); 107 });
98 } 108 }
@@ -117,6 +127,14 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -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 @Override 138 @Override
121 @DataPermission(enable = false) // 忽略数据权限,不然分配会存在问题 139 @DataPermission(enable = false) // 忽略数据权限,不然分配会存在问题
122 public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) { 140 public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) {
@@ -137,7 +155,11 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -137,7 +155,11 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
137 // TODO 芋艿:assignType/assignOptions/, 枚举 155 // TODO 芋艿:assignType/assignOptions/, 枚举
138 FlowElement flowElement = execution.getCurrentFlowElement(); 156 FlowElement flowElement = execution.getCurrentFlowElement();
139 Integer type = NumberUtils.parseInt(flowElement.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignType")); 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 Set<Long> assigneeUserIds = null; 165 Set<Long> assigneeUserIds = null;
@@ -155,6 +177,9 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -155,6 +177,9 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
155 assigneeUserIds = calculateTaskCandidateUsersByUserGroup(options); 177 assigneeUserIds = calculateTaskCandidateUsersByUserGroup(options);
156 } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), type)) { 178 } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), type)) {
157 assigneeUserIds = calculateTaskCandidateUsersByScript(execution, options); 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,9 +14,4 @@ public interface BpmnModelConstants {
14 */ 14 */
15 String NAMESPACE = "http://flowable.org/bpmn"; 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 package cn.iocoder.yudao.framework.flowable.core.util; 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 import org.flowable.common.engine.impl.identity.Authentication; 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 * Flowable 相关的工具方法 11 * Flowable 相关的工具方法
@@ -29,4 +34,15 @@ public class FlowableUtils { @@ -29,4 +34,15 @@ public class FlowableUtils {
29 return activityId + "_assignee"; 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,11 +46,11 @@
46 <!-- <version>${revision}</version>--> 46 <!-- <version>${revision}</version>-->
47 <!-- </dependency>--> 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 <!-- <dependency>--> 55 <!-- <dependency>-->
56 <!-- <groupId>cn.iocoder.boot</groupId>--> 56 <!-- <groupId>cn.iocoder.boot</groupId>-->