update: 增加通过部门和岗位ID查询用户ID的方法,优化用户查询逻辑

This commit is contained in:
AprilWind 2026-10-30 20:19:39 +08:00
parent 6d0bcceb6d
commit ff297aa68f
6 changed files with 141 additions and 201 deletions

View File

@ -93,6 +93,14 @@ public interface UserService {
*/
List<UserDTO> selectUsersByDeptIds(Collection<Long> deptIds);
/**
* 通过部门ID查询用户ID
*
* @param deptIds 部门ids
* @return 用户ids
*/
List<Long> selectUserIdsByDeptIds(Collection<Long> deptIds);
/**
* 通过岗位ID查询用户
*
@ -101,6 +109,14 @@ public interface UserService {
*/
List<UserDTO> selectUsersByPostIds(Collection<Long> postIds);
/**
* 通过岗位ID查询用户ID
*
* @param postIds 岗位ids
* @return 用户ids
*/
List<Long> selectUserIdsByPostIds(Collection<Long> postIds);
/**
* 根据用户 ID 列表查询用户昵称映射关系
*

View File

@ -690,8 +690,12 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
if (CollUtil.isEmpty(roleIds)) {
return List.of();
}
List<SysUserRole> userRoles = userRoleMapper.lambda().in(SysUserRole::getRoleId, roleIds).list();
return StreamUtils.toList(userRoles, SysUserRole::getUserId);
List<SysUserRole> userRoles = userRoleMapper.lambda()
.select(SysUserRole::getUserId)
.in(SysUserRole::getRoleId, roleIds)
.list();
Set<Long> userIds = StreamUtils.toSet(userRoles, SysUserRole::getUserId);
return new ArrayList<>(userIds);
}
/**
@ -702,17 +706,8 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
*/
@Override
public List<UserDTO> selectUsersByRoleIds(Collection<Long> roleIds) {
if (CollUtil.isEmpty(roleIds)) {
return List.of();
}
// 通过角色ID获取用户角色信息
List<SysUserRole> userRoles = userRoleMapper.lambda().in(SysUserRole::getRoleId, roleIds).list();
// 获取用户ID列表
Set<Long> userIds = StreamUtils.toSet(userRoles, SysUserRole::getUserId);
return this.selectListByIds(new ArrayList<>(userIds));
List<Long> userIds = this.selectUserIdsByRoleIds(roleIds);
return this.selectListByIds(userIds);
}
/**
@ -726,14 +721,33 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
if (CollUtil.isEmpty(deptIds)) {
return List.of();
}
List<SysUserVo> list = userMapper.lambda()
List<SysUser> list = userMapper.lambda()
.select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhoneNumber)
.eq(SysUser::getStatus, SystemConstants.NORMAL)
.in(SysUser::getDeptId, deptIds)
.voList();
.list();
return BeanUtil.copyToList(list, UserDTO.class);
}
/**
* 通过部门ID查询用户ID
*
* @param deptIds 部门ids
* @return 用户ids
*/
@Override
public List<Long> selectUserIdsByDeptIds(Collection<Long> deptIds) {
if (CollUtil.isEmpty(deptIds)) {
return List.of();
}
List<SysUser> list = userMapper.lambda()
.select(SysUser::getUserId)
.eq(SysUser::getStatus, SystemConstants.NORMAL)
.in(SysUser::getDeptId, deptIds)
.list();
return StreamUtils.toList(list, SysUser::getUserId);
}
/**
* 通过岗位ID查询用户
*
@ -742,17 +756,27 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
*/
@Override
public List<UserDTO> selectUsersByPostIds(Collection<Long> postIds) {
List<Long> userIds = this.selectUserIdsByPostIds(postIds);
return this.selectListByIds(userIds);
}
/**
* 通过岗位ID查询用户ID
*
* @param postIds 岗位ids
* @return 用户ids
*/
@Override
public List<Long> selectUserIdsByPostIds(Collection<Long> postIds) {
if (CollUtil.isEmpty(postIds)) {
return List.of();
}
// 通过岗位ID获取用户岗位信息
List<SysUserPost> userPosts = userPostMapper.lambda().in(SysUserPost::getPostId, postIds).list();
// 获取用户ID列表
List<SysUserPost> userPosts = userPostMapper.lambda()
.select(SysUserPost::getUserId)
.in(SysUserPost::getPostId, postIds)
.list();
Set<Long> userIds = StreamUtils.toSet(userPosts, SysUserPost::getUserId);
return this.selectListByIds(new ArrayList<>(userIds));
return new ArrayList<>(userIds);
}
/**

View File

@ -1,69 +0,0 @@
package org.dromara.workflow.handler;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.api.domain.UserDTO;
import org.dromara.warm.flow.core.spi.PermissionHandler;
import org.dromara.workflow.common.ConditionalOnEnable;
import org.dromara.workflow.service.IFlwTaskAssigneeService;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
/**
* 办理人权限处理器
*
* @author AprilWind
*/
@ConditionalOnEnable
@RequiredArgsConstructor
@Component
@Slf4j
public class WorkflowPermissionHandler implements PermissionHandler {
private final IFlwTaskAssigneeService flwTaskAssigneeService;
/**
* 办理人权限标识,比如用户,角色,部门等,用于校验是否有权限办理任务
* 后续在流程上下文中获取。
* 返回当前用户权限集合
*
* @return 当前用户权限集合
*/
@Override
public List<String> permissions() {
return Collections.singletonList(LoginHelper.getUserIdStr());
}
/**
* 获取当前办理人
*
* @return 当前办理人
*/
@Override
public String getHandler() {
return LoginHelper.getUserIdStr();
}
/**
* 将预设办理人转换为实际用户 ID 列表。
*
* @param permissions 预设权限标识列表
* @return 用户 ID 列表
*/
@Override
public List<String> convertPermissions(List<String> permissions) {
if (CollUtil.isEmpty(permissions)) {
return permissions;
}
String storageIds = CollUtil.join(permissions, StringUtils.SEPARATOR);
List<UserDTO> users = flwTaskAssigneeService.fetchUsersByStorageIds(storageIds);
return StreamUtils.toList(users, userDTO -> Convert.toStr(userDTO.getUserId()));
}
}

View File

@ -1,24 +0,0 @@
package org.dromara.workflow.service;
import org.dromara.system.api.domain.UserDTO;
import java.util.List;
/**
* 流程设计器-获取办理人
*
* @author AprilWind
*/
public interface IFlwTaskAssigneeService {
/**
* 批量解析多个存储标识符(storageIds),按类型分类并合并查询用户列表
* 输入格式支持多个以逗号分隔的标识(如 "user:123,role:456,789")
* 会自动去重返回结果,非法格式的标识将被忽略
*
* @param storageIds 多个存储标识符字符串(逗号分隔)
* @return 合并后的用户列表,去重后返回,非法格式的标识将被跳过
*/
List<UserDTO> fetchUsersByStorageIds(String storageIds);
}

View File

@ -10,11 +10,12 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.api.*;
import org.dromara.system.api.domain.DeptDTO;
import org.dromara.system.api.domain.TaskAssigneeDTO;
import org.dromara.system.api.domain.UserDTO;
import org.dromara.system.api.model.TaskAssigneeBody;
import org.dromara.warm.flow.core.spi.PermissionHandler;
import org.dromara.warm.flow.ui.dto.HandlerFunDto;
import org.dromara.warm.flow.ui.dto.HandlerQuery;
import org.dromara.warm.flow.ui.dto.TreeFunDto;
@ -24,7 +25,6 @@ import org.dromara.warm.flow.ui.vo.HandlerSelectVo;
import org.dromara.workflow.common.ConditionalOnEnable;
import org.dromara.workflow.common.enums.TaskAssigneeEnum;
import org.dromara.workflow.service.IFlwSpelService;
import org.dromara.workflow.service.IFlwTaskAssigneeService;
import org.springframework.stereotype.Service;
import java.util.*;
@ -39,7 +39,7 @@ import java.util.stream.Collectors;
@Slf4j
@RequiredArgsConstructor
@Service
public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, HandlerSelectService {
public class FlwTaskAssigneeServiceImpl implements PermissionHandler, HandlerSelectService {
private static final String DEFAULT_GROUP_NAME = "默认分组";
@ -50,6 +50,69 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand
private final PostService postService;
private final IFlwSpelService spelService;
/**
* 办理人权限标识,比如用户,角色,部门等,用于校验是否有权限办理任务
* 后续在流程上下文中获取。
* 返回当前用户权限集合
*
* @return 当前用户权限集合
*/
@Override
public List<String> permissions() {
return Collections.singletonList(LoginHelper.getUserIdStr());
}
/**
* 获取当前办理人
*
* @return 当前办理人
*/
@Override
public String getHandler() {
return LoginHelper.getUserIdStr();
}
/**
* 将预设办理人转换为实际用户 ID 列表。
*
* @param permissions 预设权限标识列表
* @return 用户 ID 列表
*/
@Override
public List<String> convertPermissions(List<String> permissions) {
if (CollUtil.isEmpty(permissions)) {
return permissions;
}
Map<TaskAssigneeEnum, List<String>> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class);
for (String storageId : permissions) {
Pair<TaskAssigneeEnum, String> parsed = this.parseStorageId(storageId);
if (parsed != null) {
typeIdMap.computeIfAbsent(parsed.getKey(), k -> new ArrayList<>()).add(parsed.getValue());
}
}
return typeIdMap.entrySet()
.stream()
.map(entry -> {
TaskAssigneeEnum type = entry.getKey();
List<Long> longIds = StreamUtils.toList(entry.getValue(), Convert::toLong);
return switch (type) {
case USER -> longIds;
case ROLE -> userService.selectUserIdsByRoleIds(longIds);
case DEPT -> userService.selectUserIdsByDeptIds(longIds);
case POST -> userService.selectUserIdsByPostIds(longIds);
default -> Collections.<Long>emptyList();
};
})
.filter(CollUtil::isNotEmpty)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.distinct()
.map(Convert::toStr)
.toList();
}
/**
* 获取办理人权限设置列表tabs页签
*
@ -192,45 +255,6 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand
.setCreateTime(assignee -> DateUtils.formatLocalDateTime(assignee.getCreateTime()));
}
/**
* 批量解析多个存储标识符(storageIds),按类型分类并合并查询用户列表
* 输入格式支持多个以逗号分隔的标识(如 "user:123,role:456,789")
* 会自动去重返回结果,非法格式的标识将被忽略
*
* @param storageIds 多个存储标识符字符串(逗号分隔)
* @return 合并后的用户列表,去重后返回,非法格式的标识将被跳过
*/
@Override
public List<UserDTO> fetchUsersByStorageIds(String storageIds) {
if (StringUtils.isEmpty(storageIds)) {
return List.of();
}
Map<TaskAssigneeEnum, List<String>> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class);
for (String storageId : StringUtils.str2List(storageIds, StringUtils.SEPARATOR, true, true)) {
Pair<TaskAssigneeEnum, String> parsed = this.parseStorageId(storageId);
if (parsed != null) {
typeIdMap.computeIfAbsent(parsed.getKey(), k -> new ArrayList<>()).add(parsed.getValue());
}
}
return this.getUsersByTypes(typeIdMap).stream()
.distinct()
.toList();
}
/**
* 按任务分配类型批量查询用户。
*
* @param typeIdMap 任务分配类型与 id 列表映射
* @return 用户列表
*/
private List<UserDTO> getUsersByTypes(Map<TaskAssigneeEnum, List<String>> typeIdMap) {
return typeIdMap.entrySet().stream()
.map(entry -> this.getUsersByType(entry.getKey(), entry.getValue()))
.filter(CollUtil::isNotEmpty)
.flatMap(Collection::stream)
.toList();
}
/**
* 按任务分配类型批量查询名称映射。
*
@ -243,30 +267,6 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand
return nameMap;
}
/**
* 根据指定的任务分配类型(TaskAssigneeEnum)和 ID 列表,获取对应的用户信息列表
*
* @param type 任务分配类型,表示用户、角色、部门或其他(TaskAssigneeEnum 枚举值)
* @param ids 与指定分配类型关联的 ID 列表(例如用户ID、角色ID、部门ID等)
* @return 返回包含用户信息的列表。如果类型为用户(USER),则通过用户ID列表查询;
* 如果类型为角色(ROLE),则通过角色ID列表查询;
* 如果类型为部门(DEPT),则通过部门ID列表查询;
* 如果类型为岗位(POST)或无法识别的类型,则返回空列表
*/
private List<UserDTO> getUsersByType(TaskAssigneeEnum type, List<String> ids) {
if (type == TaskAssigneeEnum.SPEL) {
return new ArrayList<>();
}
List<Long> longIds = StreamUtils.toList(ids, Convert::toLong);
return switch (type) {
case USER -> userService.selectListByIds(longIds);
case ROLE -> userService.selectUsersByRoleIds(longIds);
case DEPT -> userService.selectUsersByDeptIds(longIds);
case POST -> userService.selectUsersByPostIds(longIds);
default -> new ArrayList<>();
};
}
/**
* 根据任务分配类型和对应 ID 列表,批量查询名称映射关系
*

View File

@ -63,7 +63,6 @@ import org.dromara.workflow.mapper.FlwHisTaskMapper;
import org.dromara.workflow.mapper.FlwTaskMapper;
import org.dromara.workflow.service.IFlwCommonService;
import org.dromara.workflow.service.IFlwNodeExtService;
import org.dromara.workflow.service.IFlwTaskAssigneeService;
import org.dromara.workflow.service.IFlwTaskService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -105,7 +104,6 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
private final FlwHisTaskMapper flwHisTaskMapper;
private final FlwCategoryMapper flwCategoryMapper;
private final FlowNodeMapper flowNodeMapper;
private final IFlwTaskAssigneeService flwTaskAssigneeService;
private final IFlwCommonService flwCommonService;
private final IFlwNodeExtService flwNodeExtService;
@ -567,25 +565,20 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
if (CollUtil.isEmpty(nextNodeList)) {
return new ArrayList<>();
}
List<FlowNode> nextFlowNodes = BeanUtil.copyToList(nextNodeList, FlowNode.class);
// 只获取中间节点
nextFlowNodes = StreamUtils.filter(nextFlowNodes, node -> NodeType.BETWEEN.getKey().equals(node.getNodeType()));
if (CollUtil.isNotEmpty(nextNodeList)) {
nextNodeList = StreamUtils.filter(nextNodeList, node -> NodeType.BETWEEN.getKey().equals(node.getNodeType()));
if (CollUtil.isEmpty(nextNodeList)) {
return new ArrayList<>();
}
List<FlowNode> nextFlowNodes = BeanUtil.copyToList(nextNodeList, FlowNode.class);
//构建以下节点数据
List<Task> buildNextTaskList = StreamUtils.toList(nextNodeList, node -> taskService.addTask(node, instance
, definition, new WorkflowContext(), SkipType.PASS.getKey()));
//办理人变量替换
ExpressionUtil.evalVariable(buildNextTaskList, mergeVariable, null, false);
for (FlowNode flowNode : nextFlowNodes) {
StreamUtils.findFirst(buildNextTaskList, t -> t.getNodeCode().equals(flowNode.getNodeCode()))
.ifPresent(first -> {
List<UserDTO> users;
if (CollUtil.isNotEmpty(first.getPermissionList())
&& CollUtil.isNotEmpty(users = flwTaskAssigneeService.fetchUsersByStorageIds(StringUtils.joinComma(first.getPermissionList())))) {
flowNode.setPermissionFlag(StreamUtils.join(users, e -> Convert.toStr(e.getUserId())));
}
});
}
Map<String, List<String>> map = StreamUtils.toMap(buildNextTaskList, Task::getNodeCode, Task::getPermissionList);
for (FlowNode node : nextFlowNodes) {
node.setPermissionFlag(StringUtils.joinComma(map.get(node.getNodeCode())));
}
return nextFlowNodes;
}