feat(bpm):自选审批人 添加用户功能

- 在 BpmTaskAssignRuleTypeEnum 中新增 USER_SELECT 类型- 更新 BpmTaskAssignRuleDO 实体类,支持 USER_SELECT 类型的处理逻辑
- 在 BpmTaskAssignRuleServiceImpl 中实现用户自选审批人的验证和计算逻辑- 新增 calculateTaskCandidateUsersByUserSelect 方法,从流程变量中获取用户自选的审批人
-修复 BpmUserTaskActivityBehavior 中随机选择用户时的类型转换问题- 移除 BpmProcessInstanceExtDO 中 assignee 字段的 exist = false 配置
This commit is contained in:
2025-10-30 15:21:48 +08:00
parent 091ceb3619
commit 892012e41b
5 changed files with 21 additions and 2 deletions

View File

@@ -17,6 +17,7 @@ public enum BpmTaskAssignRuleTypeEnum {
DEPT_LEADER(21, "部门的负责人"), DEPT_LEADER(21, "部门的负责人"),
POST(22, "岗位"), POST(22, "岗位"),
USER(30, "用户"), USER(30, "用户"),
USER_SELECT(35, "用户自选"),
USER_GROUP(40, "用户组"), USER_GROUP(40, "用户组"),
SCRIPT(50, "自定义脚本"), // 例如说,发起人所在部门的领导、发起人所在部门的领导的领导 SCRIPT(50, "自定义脚本"), // 例如说,发起人所在部门的领导、发起人所在部门的领导的领导
; ;

View File

@@ -1,6 +1,7 @@
package com.jeelowcode.service.bpm.config.framework.flowable.core.behavior; package com.jeelowcode.service.bpm.config.framework.flowable.core.behavior;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import com.jeelowcode.service.bpm.service.IBpmTaskAssignRuleService; import com.jeelowcode.service.bpm.service.IBpmTaskAssignRuleService;
@@ -60,7 +61,7 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
// 解答:项目对 bpm 的任务是责任到人,所以每个任务有且仅有一个处理人。 // 解答:项目对 bpm 的任务是责任到人,所以每个任务有且仅有一个处理人。
// 如果希望一个任务可以同时被多个人处理,可以考虑使用 BpmParallelMultiInstanceBehavior 实现的会签 or 或签。 // 如果希望一个任务可以同时被多个人处理,可以考虑使用 BpmParallelMultiInstanceBehavior 实现的会签 or 或签。
int index = RandomUtil.randomInt(candidateUserIds.size()); int index = RandomUtil.randomInt(candidateUserIds.size());
return CollUtil.get(candidateUserIds, index); return Convert.toLong(CollUtil.get(candidateUserIds, index));
} }
} }

View File

@@ -92,7 +92,7 @@ public class BpmProcessInstanceExtDO extends BaseDO {
/** /**
* 提前设定好的审批人 * 提前设定好的审批人
*/ */
@TableField(typeHandler = JacksonTypeHandler.class, exist = false) // TODO 芋艿:临时 exist = false避免 db 报错; @TableField(typeHandler = JacksonTypeHandler.class) // TODO 芋艿:临时 exist = false避免 db 报错;
private Map<String, List<Long>> assignee; private Map<String, List<Long>> assignee;
} }

View File

@@ -76,6 +76,7 @@ public class BpmTaskAssignRuleDO extends BaseDO {
* 4. {@link BpmTaskAssignRuleTypeEnum#USER} 时:用户编号 * 4. {@link BpmTaskAssignRuleTypeEnum#USER} 时:用户编号
* 5. {@link BpmTaskAssignRuleTypeEnum#USER_GROUP} 时:用户组编号 * 5. {@link BpmTaskAssignRuleTypeEnum#USER_GROUP} 时:用户组编号
* 6. {@link BpmTaskAssignRuleTypeEnum#SCRIPT} 时:脚本编号,目前通过 {@link BpmTaskRuleScriptEnum#getId()} 标识 * 6. {@link BpmTaskAssignRuleTypeEnum#SCRIPT} 时:脚本编号,目前通过 {@link BpmTaskRuleScriptEnum#getId()} 标识
* 7. {@link BpmTaskAssignRuleTypeEnum#USER_SELECT} 时:空
*/ */
@TableField(typeHandler = JsonLongSetTypeHandler.class) @TableField(typeHandler = JsonLongSetTypeHandler.class)
private Set<Long> options; private Set<Long> options;

View File

@@ -3,6 +3,7 @@ package com.jeelowcode.service.bpm.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Sets;
import com.jeelowcode.tool.framework.common.enums.CommonStatusEnum; import com.jeelowcode.tool.framework.common.enums.CommonStatusEnum;
import com.jeelowcode.tool.framework.common.util.collection.CollectionUtils; import com.jeelowcode.tool.framework.common.util.collection.CollectionUtils;
import com.jeelowcode.tool.framework.common.util.object.ObjectUtils; import com.jeelowcode.tool.framework.common.util.object.ObjectUtils;
@@ -230,6 +231,8 @@ public class BpmTaskAssignRuleServiceImpl implements IBpmTaskAssignRuleService {
apiPostApi.validPostList(options); apiPostApi.validPostList(options);
} else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER.getType())) { } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER.getType())) {
apiAdminUserApi.validateUserList(options); apiAdminUserApi.validateUserList(options);
} else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_SELECT.getType())) {
log.info("[validTaskAssignRuleOptions][type({}) options({})]", type, options);
} else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_GROUP.getType())) { } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_GROUP.getType())) {
userGroupService.validUserGroups(options); userGroupService.validUserGroups(options);
} else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) { } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) {
@@ -287,6 +290,8 @@ public class BpmTaskAssignRuleServiceImpl implements IBpmTaskAssignRuleService {
assigneeUserIds = calculateTaskCandidateUsersByUserGroup(rule); assigneeUserIds = calculateTaskCandidateUsersByUserGroup(rule);
} else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) { } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {
assigneeUserIds = calculateTaskCandidateUsersByScript(execution, rule); assigneeUserIds = calculateTaskCandidateUsersByScript(execution, rule);
} else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_SELECT.getType(), rule.getType())) {
assigneeUserIds = calculateTaskCandidateUsersByUserSelect(execution, rule);
} }
// 移除被禁用的用户 // 移除被禁用的用户
@@ -346,6 +351,17 @@ public class BpmTaskAssignRuleServiceImpl implements IBpmTaskAssignRuleService {
return userIds; return userIds;
} }
private Set<Long> calculateTaskCandidateUsersByUserSelect(DelegateExecution execution, BpmTaskAssignRuleDO rule) {
// 应该从流程变量中,获取选择的用户
List<Long> assignee = processInstanceService.getAssigneeByProcessInstanceIdAndTaskDefinitionKey(
execution.getProcessInstanceId(), execution.getCurrentActivityId());
if (CollUtil.isNotEmpty(assignee)) {
return convertSet(assignee, Function.identity());
} else {
throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER);
}
}
@VisibleForTesting @VisibleForTesting
void removeDisableUsers(Set<Long> assigneeUserIds) { void removeDisableUsers(Set<Long> assigneeUserIds) {
if (CollUtil.isEmpty(assigneeUserIds)) { if (CollUtil.isEmpty(assigneeUserIds)) {