mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-19 03:30:06 +08:00
仿钉钉流程设计- 新增连续多级部门负责人审批策略
This commit is contained in:
parent
ae7dbd3c53
commit
620a0d8c2c
@ -0,0 +1,75 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门的负责人 {@link BpmTaskCandidateStrategy} 抽象类
|
||||||
|
*
|
||||||
|
* @author jason
|
||||||
|
*/
|
||||||
|
public abstract class BpmTaskCandidateAbstractDeptLeaderStrategy implements BpmTaskCandidateStrategy {
|
||||||
|
|
||||||
|
protected DeptApi deptApi;
|
||||||
|
|
||||||
|
public BpmTaskCandidateAbstractDeptLeaderStrategy(DeptApi deptApi) {
|
||||||
|
this.deptApi = deptApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上级部门的负责人
|
||||||
|
*
|
||||||
|
* @param assignDept 指定部门
|
||||||
|
* @param level 第几级
|
||||||
|
* @return 部门负责人 Id
|
||||||
|
*/
|
||||||
|
protected Long getAssignLevelDeptLeaderId(DeptRespDTO assignDept, Integer level) {
|
||||||
|
Assert.isTrue(level > 0, "level 必须大于 0");
|
||||||
|
if (assignDept == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DeptRespDTO dept = assignDept;
|
||||||
|
for (int i = 1; i < level; i++) {
|
||||||
|
DeptRespDTO parentDept = deptApi.getDept(dept.getParentId());
|
||||||
|
if (parentDept == null) { // 找不到父级部门,到了最高级。返回最高级的部门负责人
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dept = parentDept;
|
||||||
|
}
|
||||||
|
return dept.getLeaderUserId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取连续上级部门的负责人, 包含指定部门的负责人
|
||||||
|
*
|
||||||
|
* @param assignDept 指定部门
|
||||||
|
* @param level 第几级
|
||||||
|
* @return 连续部门负责人 Id
|
||||||
|
*/
|
||||||
|
protected Set<Long> getMultiLevelDeptLeaderIds(DeptRespDTO assignDept, Integer level){
|
||||||
|
Assert.isTrue(level > 0, "level 必须大于 0");
|
||||||
|
if (assignDept == null) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
Set<Long> deptLeaderIds = new LinkedHashSet<>(); // 保证有序
|
||||||
|
DeptRespDTO dept = assignDept;
|
||||||
|
for (int i = 0; i < level; i++) {
|
||||||
|
if (dept.getLeaderUserId() != null) {
|
||||||
|
deptLeaderIds.add(dept.getLeaderUserId());
|
||||||
|
}
|
||||||
|
DeptRespDTO parentDept = deptApi.getDept(dept.getParentId());
|
||||||
|
if (parentDept == null) { // 找不到父级部门. 已经到了最高层级了
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dept = parentDept;
|
||||||
|
}
|
||||||
|
return deptLeaderIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||||
|
import org.flowable.engine.delegate.DelegateExecution;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连续多级部门的负责人 {@link BpmTaskCandidateStrategy} 实现类
|
||||||
|
*
|
||||||
|
* @author jason
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BpmTaskCandidateMultiLevelDeptLeaderStrategy extends BpmTaskCandidateAbstractDeptLeaderStrategy {
|
||||||
|
|
||||||
|
public BpmTaskCandidateMultiLevelDeptLeaderStrategy(DeptApi deptApi) {
|
||||||
|
super(deptApi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BpmTaskCandidateStrategyEnum getStrategy() {
|
||||||
|
return BpmTaskCandidateStrategyEnum.MULTI_LEVEL_DEPT_LEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validateParam(String param) {
|
||||||
|
// 参数格式: ,分割。 前面一个指定指定部门Id, 后面一个是部门的层级
|
||||||
|
List<Long> params = StrUtils.splitToLong(param, ",");
|
||||||
|
Assert.isTrue(params.size() == 2, "参数格式不匹配");
|
||||||
|
deptApi.validateDeptList(CollUtil.toList(params.get(0)));
|
||||||
|
Assert.isTrue(params.get(1) > 0, "部门层级必须大于 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Long> calculateUsers(DelegateExecution execution, String param) {
|
||||||
|
// 参数格式: ,分割。 前面一个指定指定部门Id, 后面一个是审批的层级
|
||||||
|
List<Long> params = StrUtils.splitToLong(param, ",");
|
||||||
|
// TODO @芋艿 是否要支持多个部门。 是不是这种场景,一个部门就可以了
|
||||||
|
Long deptId = params.get(0);
|
||||||
|
Long level = params.get(1);
|
||||||
|
DeptRespDTO dept = deptApi.getDept(deptId);
|
||||||
|
return getMultiLevelDeptLeaderIds(dept, level.intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
|
||||||
|
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.flowable.engine.delegate.DelegateExecution;
|
||||||
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
||||||
|
import static java.util.Collections.emptySet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起人的部门负责人, 可以是上级部门负责人 {@link BpmTaskCandidateStrategy} 实现类
|
||||||
|
*
|
||||||
|
* @author jason
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BpmTaskCandidateStartUserDeptLeaderStrategy extends BpmTaskCandidateAbstractDeptLeaderStrategy {
|
||||||
|
@Resource
|
||||||
|
@Lazy
|
||||||
|
private BpmProcessInstanceService processInstanceService;
|
||||||
|
@Resource
|
||||||
|
private AdminUserApi adminUserApi;
|
||||||
|
@Override
|
||||||
|
public BpmTaskCandidateStrategyEnum getStrategy() {
|
||||||
|
return BpmTaskCandidateStrategyEnum.START_USER_DEPT_LEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BpmTaskCandidateStartUserDeptLeaderStrategy(DeptApi deptApi) {
|
||||||
|
super(deptApi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validateParam(String param) {
|
||||||
|
// 参数是部门的层级
|
||||||
|
Assert.isTrue(Integer.parseInt(param) > 0, "部门的层级必须大于 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Long> calculateUsers(DelegateExecution execution, String param) {
|
||||||
|
// 获得流程发起人
|
||||||
|
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||||
|
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
||||||
|
|
||||||
|
DeptRespDTO dept = getStartUserDept(startUserId);
|
||||||
|
Long deptLeaderId = getAssignLevelDeptLeaderId(dept, Integer.valueOf(param)); // 参数是部门的层级
|
||||||
|
return deptLeaderId != null ? asSet(deptLeaderId) : emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取发起人的部门
|
||||||
|
*
|
||||||
|
* @param startUserId 发起人 Id
|
||||||
|
*/
|
||||||
|
protected DeptRespDTO getStartUserDept(Long startUserId) {
|
||||||
|
AdminUserRespDTO startUser = adminUserApi.getUser(startUserId);
|
||||||
|
if (startUser.getDeptId() == null) { // 找不到部门
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deptApi.getDept(startUser.getDeptId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
|
||||||
|
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.flowable.engine.delegate.DelegateExecution;
|
||||||
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起人连续多级部门的负责人 {@link BpmTaskCandidateStrategy} 实现类
|
||||||
|
*
|
||||||
|
* @author jason
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BpmTaskCandidateStartUserMultiLevelDeptLeaderStrategy extends BpmTaskCandidateAbstractDeptLeaderStrategy {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Lazy
|
||||||
|
private BpmProcessInstanceService processInstanceService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AdminUserApi adminUserApi;
|
||||||
|
|
||||||
|
public BpmTaskCandidateStartUserMultiLevelDeptLeaderStrategy(AdminUserApi adminUserApi, DeptApi deptApi) {
|
||||||
|
super(deptApi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BpmTaskCandidateStrategyEnum getStrategy() {
|
||||||
|
return BpmTaskCandidateStrategyEnum.START_USER_MULTI_LEVEL_DEPT_LEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validateParam(String param) {
|
||||||
|
// 参数是部门的层级
|
||||||
|
Assert.isTrue(Integer.parseInt(param) > 0, "部门的层级必须大于 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Long> calculateUsers(DelegateExecution execution, String param) {
|
||||||
|
// 获得流程发起人
|
||||||
|
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||||
|
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
||||||
|
|
||||||
|
DeptRespDTO dept = getStartUserDept(startUserId);
|
||||||
|
return getMultiLevelDeptLeaderIds(dept, Integer.valueOf(param)); // 参数是部门的层级
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取发起人的部门
|
||||||
|
*
|
||||||
|
* @param startUserId 发起人 Id
|
||||||
|
*/
|
||||||
|
protected DeptRespDTO getStartUserDept(Long startUserId) {
|
||||||
|
AdminUserRespDTO startUser = adminUserApi.getUser(startUserId);
|
||||||
|
if (startUser.getDeptId() == null) { // 找不到部门
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deptApi.getDept(startUser.getDeptId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -21,10 +21,13 @@ public enum BpmTaskCandidateStrategyEnum implements IntArrayValuable {
|
|||||||
ROLE(10, "角色"),
|
ROLE(10, "角色"),
|
||||||
DEPT_MEMBER(20, "部门的成员"), // 包括负责人
|
DEPT_MEMBER(20, "部门的成员"), // 包括负责人
|
||||||
DEPT_LEADER(21, "部门的负责人"),
|
DEPT_LEADER(21, "部门的负责人"),
|
||||||
|
MULTI_LEVEL_DEPT_LEADER(23, "连续多级部门的负责人"),
|
||||||
POST(22, "岗位"),
|
POST(22, "岗位"),
|
||||||
USER(30, "用户"),
|
USER(30, "用户"),
|
||||||
START_USER_SELECT(35, "发起人自选"), // 申请人自己,可在提交申请时选择此节点的审批人
|
START_USER_SELECT(35, "发起人自选"), // 申请人自己,可在提交申请时选择此节点的审批人
|
||||||
START_USER(36, "发起人自己"), // 申请人自己, 一般紧挨开始节点,常用于发起人信息审核场景
|
START_USER(36, "发起人自己"), // 申请人自己, 一般紧挨开始节点,常用于发起人信息审核场景
|
||||||
|
START_USER_DEPT_LEADER(37, "发起人部门负责人"), // 可以是发起人上级部门负责人
|
||||||
|
START_USER_MULTI_LEVEL_DEPT_LEADER(38, "发起人连续多级部门的负责人"),
|
||||||
USER_GROUP(40, "用户组"),
|
USER_GROUP(40, "用户组"),
|
||||||
EXPRESSION(60, "流程表达式"), // 表达式 ExpressionManager
|
EXPRESSION(60, "流程表达式"), // 表达式 ExpressionManager
|
||||||
;
|
;
|
||||||
|
Loading…
Reference in New Issue
Block a user