fix(产品需求): 解决测试后存在的一些问题。

This commit is contained in:
dk
2026-05-09 13:44:38 +08:00
parent 7575784c01
commit 604bf61981
10 changed files with 365 additions and 182 deletions

View File

@@ -4,11 +4,16 @@ import com.njcn.rdms.framework.apilog.core.annotation.ApiAccessLog;
import com.njcn.rdms.framework.common.pojo.CommonResult;
import com.njcn.rdms.framework.common.util.object.BeanUtils;
import com.njcn.rdms.framework.excel.core.util.ExcelUtils;
import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserSimpleRespVO;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationQueryReqVO;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationRespVO;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationSaveReqVO;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationTreeRespVO;
import com.njcn.rdms.module.system.convert.user.UserConvert;
import com.njcn.rdms.module.system.dal.dataobject.dept.DeptDO;
import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO;
import com.njcn.rdms.module.system.dal.dataobject.user.UserManagementRelationDO;
import com.njcn.rdms.module.system.service.dept.DeptService;
import com.njcn.rdms.module.system.service.user.UserManagementRelationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -22,9 +27,11 @@ import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static com.njcn.rdms.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.njcn.rdms.framework.common.pojo.CommonResult.success;
import static com.njcn.rdms.framework.common.util.collection.CollectionUtils.convertList;
/**
* 用户管理链路 Controller
@@ -43,6 +50,9 @@ import static com.njcn.rdms.framework.common.pojo.CommonResult.success;
@Validated
public class UserManagementRelationController {
@Resource
private DeptService deptService;
@Resource
private UserManagementRelationService userManagementRelationService;
@@ -147,6 +157,19 @@ public class UserManagementRelationController {
return success(list);
}
/**
* 获取未绑定直属上级的候选下级用户列表
* @return 候选下级用户列表
*/
@GetMapping("/candidate-users")
@Operation(summary = "获取未绑定直属上级的候选下级用户列表")
@PreAuthorize("@ss.hasPermission('system:user-management-relation:query')")
public CommonResult<List<UserSimpleRespVO>> getCandidateSubordinateUsers() {
List<AdminUserDO> users = userManagementRelationService.getCandidateSubordinateUsers();
Map<Long, DeptDO> deptMap = deptService.getDeptMap(convertList(users, AdminUserDO::getDeptId));
return success(UserConvert.INSTANCE.convertSimpleList(users, deptMap));
}
/**
* 获取用户管理链路树形结构
*

View File

@@ -5,6 +5,7 @@ import com.njcn.rdms.framework.common.util.collection.CollectionUtils;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationQueryReqVO;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationSaveReqVO;
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationTreeRespVO;
import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO;
import com.njcn.rdms.module.system.dal.dataobject.user.UserManagementRelationDO;
import java.util.Collection;
@@ -99,6 +100,13 @@ public interface UserManagementRelationService {
*/
List<UserManagementRelationTreeRespVO> getRelationTree(UserManagementRelationQueryReqVO reqVO);
/**
* 获取还未绑定直属上级的候选下级用户列表
*
* @return 候选下级用户列表
*/
List<AdminUserDO> getCandidateSubordinateUsers();
/**
* 获得用户管理链路 Map
*

View File

@@ -3,6 +3,7 @@ package com.njcn.rdms.module.system.service.user;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.annotations.VisibleForTesting;
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
import com.njcn.rdms.framework.common.exception.ServiceException;
import com.njcn.rdms.framework.common.util.object.BeanUtils;
import com.njcn.rdms.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -243,7 +244,7 @@ public class UserManagementRelationServiceImpl implements UserManagementRelation
Long targetUserId = determineTargetUserId(reqVO, context);
if (targetUserId == null) {
return buildFullTree(context);
return Collections.emptyList();
}
return buildTargetBranchTree(targetUserId, context);
@@ -272,6 +273,32 @@ public class UserManagementRelationServiceImpl implements UserManagementRelation
return userManagementRelationMapper.selectListBySubordinateUserId(subordinateUserId);
}
/**
* 获取候选的下属用户列表
* @return 候选的下属用户列表
*/
@Override
public List<AdminUserDO> getCandidateSubordinateUsers() {
List<AdminUserDO> users = adminUserService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus());
if (CollUtil.isEmpty(users)) {
return Collections.emptyList();
}
List<UserManagementRelationDO> relations =
userManagementRelationMapper.selectList(new UserManagementRelationQueryReqVO());
Set<Long> boundSubordinateUserIds = relations.stream()
.map(UserManagementRelationDO::getSubordinateUserId)
.collect(Collectors.toSet());
return users.stream()
.filter(adminUserService::isUserAvailable)
.filter(user -> !boundSubordinateUserIds.contains(user.getId()))
.sorted(Comparator.comparing(AdminUserDO::getDeptId, Comparator.nullsLast(Long::compareTo))
.thenComparing(AdminUserDO::getNickname, Comparator.nullsLast(String::compareTo))
.thenComparing(AdminUserDO::getId))
.collect(Collectors.toList());
}
/**
* 获取用户管理链路树形结构
* 业务逻辑:
@@ -402,112 +429,50 @@ public class UserManagementRelationServiceImpl implements UserManagementRelation
}
/**
* 构建目标用户相关的分支树形结构
* 只包含目标用户的上级链和下级树,不包含同级节点
* 构建目标用户相关的分支树形结构(搜索模式)
* 只包含目标用户的上级链和目标用户本身,不显示下级
* <p>
* 构建逻辑:
* 1. 从目标用户向上追溯到根节点,记录上级链
* 2. 从根节点开始,只沿着包含目标用户的分支向下构建
* 3. 构建目标用户的所有下级
* 3. 目标用户节点不构建下级
*
* @param targetUserId 目标用户ID
* @param context 树形结构上下文
* @return 目标用户相关的分支树形结构列表
*/
private List<UserManagementRelationTreeRespVO> buildTargetBranchTree(Long targetUserId, TreeBuildContext context) {
LinkedList<Long> pathToRoot = findPathToRoot(targetUserId, context);
if (pathToRoot.isEmpty()) {
AdminUserDO targetUser = context.getUserMap().get(targetUserId);
if (targetUser == null) {
return Collections.emptyList();
}
Long rootUserId = pathToRoot.getFirst();
UserManagementRelationTreeRespVO rootNode = buildRootNode(rootUserId, context);
if (rootNode == null) {
UserManagementRelationDO targetRelation = context.getSubordinateToRelationMap().get(targetUserId);
Long targetRelationId = targetRelation != null ? targetRelation.getId() : null;
if (targetRelation == null || Objects.equals(targetRelation.getManagerUserId(), targetUserId)) {
// 根节点搜索时只返回本人,不继续展示更高层级
UserManagementRelationTreeRespVO targetNode =
buildTreeNodeForSearch(targetRelationId, targetUserId, targetUserId, context);
return targetNode == null ? Collections.emptyList() : Collections.singletonList(targetNode);
}
Long managerUserId = targetRelation.getManagerUserId();
UserManagementRelationDO managerRelation = context.getSubordinateToRelationMap().get(managerUserId);
Long managerRelationId = managerRelation != null ? managerRelation.getId() : null;
UserManagementRelationTreeRespVO managerNode =
buildTreeNodeForSearch(managerRelationId, managerUserId, managerUserId, context);
if (managerNode == null) {
return Collections.emptyList();
}
if (pathToRoot.size() > 1) {
buildBranchPath(rootNode, pathToRoot, context);
UserManagementRelationTreeRespVO targetNode =
buildTreeNodeForSearch(targetRelationId, targetUserId, managerUserId, context);
if (targetNode == null) {
return Collections.emptyList();
}
return Collections.singletonList(rootNode);
}
/**
* 从目标用户向上追溯到根节点,记录路径
*
* @param targetUserId 目标用户ID
* @param context 树形结构上下文
* @return 从根节点到目标用户的路径(包含根节点和目标用户)
*/
private LinkedList<Long> findPathToRoot(Long targetUserId, TreeBuildContext context) {
LinkedList<Long> path = new LinkedList<>();
Set<Long> visited = new HashSet<>();
Long currentUserId = targetUserId;
while (currentUserId != null && !visited.contains(currentUserId)) {
visited.add(currentUserId);
path.addFirst(currentUserId);
if (!context.getHasManagerUserIds().contains(currentUserId)) {
break;
}
UserManagementRelationDO relation = context.getSubordinateToRelationMap().get(currentUserId);
if (relation == null) {
break;
}
Long managerUserId = relation.getManagerUserId();
if (managerUserId.equals(currentUserId)) {
break;
}
currentUserId = managerUserId;
}
return path;
}
/**
* 沿着指定路径构建分支
* 从根节点的下一层开始,只构建路径中包含的用户节点
*
* @param parentNode 父节点
* @param pathToRoot 从根节点到目标用户的路径
* @param context 树形结构上下文
*/
private void buildBranchPath(UserManagementRelationTreeRespVO parentNode, LinkedList<Long> pathToRoot, TreeBuildContext context) {
if (pathToRoot.size() <= 1) {
return;
}
Long parentUserId = parentNode.getUserId();
List<Long> subordinateIds = context.getManagerToSubordinatesMap().get(parentUserId);
if (CollUtil.isEmpty(subordinateIds)) {
return;
}
Long nextUserIdInPath = pathToRoot.get(1);
for (Long subordinateId : subordinateIds) {
if (subordinateId.equals(parentUserId)) {
continue;
}
UserManagementRelationDO childRelation = context.getSubordinateToRelationMap().get(subordinateId);
Long childRelationId = childRelation != null ? childRelation.getId() : null;
if (subordinateId.equals(nextUserIdInPath)) {
UserManagementRelationTreeRespVO childNode = buildTreeNode(childRelationId, subordinateId, parentUserId, context);
if (childNode != null) {
parentNode.setChildren(Collections.singletonList(childNode));
if (pathToRoot.size() > 2) {
LinkedList<Long> remainingPath = new LinkedList<>(pathToRoot.subList(1, pathToRoot.size()));
buildBranchPath(childNode, remainingPath, context);
}
}
break;
}
}
managerNode.setChildren(Collections.singletonList(targetNode));
return Collections.singletonList(managerNode);
}
/**
@@ -611,6 +576,40 @@ public class UserManagementRelationServiceImpl implements UserManagementRelation
return node;
}
/**
* 构建树形节点(搜索模式)
* 与buildTreeNode的区别不构建下级节点只返回当前节点信息
*
* @param relationId 关系记录主键ID
* @param userId 当前用户ID
* @param managerUserId 上级用户ID
* @param context 树形结构上下文
* @return 树形节点(无下级)
*/
private UserManagementRelationTreeRespVO buildTreeNodeForSearch(Long relationId, Long userId, Long managerUserId,
TreeBuildContext context) {
AdminUserDO user = context.getUserMap().get(userId);
if (user == null) {
return null;
}
UserManagementRelationTreeRespVO node = new UserManagementRelationTreeRespVO();
node.setId(relationId);
node.setUserId(userId);
node.setUserNickname(user.getNickname());
node.setManagerUserId(managerUserId);
if (managerUserId != null) {
AdminUserDO managerUser = context.getUserMap().get(managerUserId);
if (managerUser != null) {
node.setManagerNickname(managerUser.getNickname());
}
}
node.setChildren(Collections.emptyList());
return node;
}
/**
* 统一时间有效性过滤条件:
* <p>