feat(user-management-relation): 完成带人关系后端接口(即直接管理)
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
package com.njcn.rdms.module.system.api.user;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||
import com.njcn.rdms.framework.common.util.collection.CollectionUtils;
|
||||
import com.njcn.rdms.module.system.api.user.dto.UserManagementRelationRespDTO;
|
||||
import com.njcn.rdms.module.system.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@FeignClient(name = ApiConstants.NAME)
|
||||
@Tag(name = "RPC 服务 - 用户带人关系")
|
||||
public interface UserManagementRelationApi {
|
||||
|
||||
String PREFIX = ApiConstants.PREFIX + "/user-management-relation";
|
||||
|
||||
@GetMapping(PREFIX + "/list-by-manager")
|
||||
@Operation(summary = "根据管理者用户ID获得带人关系列表")
|
||||
@Parameter(name = "managerUserId", description = "管理者用户ID", example = "1", required = true)
|
||||
CommonResult<List<UserManagementRelationRespDTO>> getRelationListByManagerUserId(@RequestParam("managerUserId") Long managerUserId);
|
||||
|
||||
@GetMapping(PREFIX + "/list-by-subordinate")
|
||||
@Operation(summary = "根据被管理者用户ID获得带人关系列表")
|
||||
@Parameter(name = "subordinateUserId", description = "被管理者用户ID", example = "2", required = true)
|
||||
CommonResult<List<UserManagementRelationRespDTO>> getRelationListBySubordinateUserId(@RequestParam("subordinateUserId") Long subordinateUserId);
|
||||
|
||||
@GetMapping(PREFIX + "/list")
|
||||
@Operation(summary = "获得带人关系列表")
|
||||
@Parameter(name = "ids", description = "关系编号数组", example = "1,2", required = true)
|
||||
CommonResult<List<UserManagementRelationRespDTO>> getRelationList(@RequestParam("ids") Collection<Long> ids);
|
||||
|
||||
default Map<Long, UserManagementRelationRespDTO> getRelationMap(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return MapUtil.empty();
|
||||
}
|
||||
List<UserManagementRelationRespDTO> list = getRelationList(ids).getData();
|
||||
return CollectionUtils.convertMap(list, UserManagementRelationRespDTO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.njcn.rdms.module.system.api.user.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户带人关系 Response DTO
|
||||
*
|
||||
* @author dklive
|
||||
*/
|
||||
@Schema(description = "RPC 服务 - 用户带人关系 Response DTO")
|
||||
@Data
|
||||
public class UserManagementRelationRespDTO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "管理者用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long managerUserId;
|
||||
|
||||
@Schema(description = "被管理用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Long subordinateUserId;
|
||||
|
||||
@Schema(description = "生效开始时间")
|
||||
private LocalDateTime effectiveFrom;
|
||||
|
||||
@Schema(description = "生效结束时间")
|
||||
private LocalDateTime effectiveUntil;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -54,6 +54,10 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode USER_REGISTER_DISABLED = new ErrorCode(1_002_003_011, "注册功能已关闭");
|
||||
ErrorCode USER_IS_RESIGNED = new ErrorCode(1_002_003_012, "名字为【{}】的用户已离职");
|
||||
|
||||
// ========== 用户带人关系模块 1-002-003-100 ==========
|
||||
ErrorCode USER_MANAGEMENT_RELATION_NOT_FOUND = new ErrorCode(1_002_003_100, "用户带人关系不存在");
|
||||
ErrorCode USER_MANAGEMENT_RELATION_MANAGER_EXISTS = new ErrorCode(1_002_003_101, "该用户已有直属上级,不能重复添加");
|
||||
|
||||
// ========== 部门模块 1-002-004-000 ==========
|
||||
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
|
||||
ErrorCode DEPT_PARENT_NOT_EXITS = new ErrorCode(1_002_004_001,"父级部门不存在");
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.njcn.rdms.module.system.api.user;
|
||||
|
||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||
import com.njcn.rdms.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.rdms.module.system.api.user.dto.UserManagementRelationRespDTO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.user.UserManagementRelationDO;
|
||||
import com.njcn.rdms.module.system.service.user.UserManagementRelationService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.njcn.rdms.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RestController
|
||||
@Validated
|
||||
@Hidden
|
||||
public class UserManagementRelationApiImpl implements UserManagementRelationApi {
|
||||
|
||||
@Resource
|
||||
private UserManagementRelationService userManagementRelationService;
|
||||
|
||||
@Override
|
||||
public CommonResult<List<UserManagementRelationRespDTO>> getRelationListByManagerUserId(Long managerUserId) {
|
||||
List<UserManagementRelationDO> list = userManagementRelationService.getRelationListByManagerUserId(managerUserId);
|
||||
return success(BeanUtils.toBean(list, UserManagementRelationRespDTO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<UserManagementRelationRespDTO>> getRelationListBySubordinateUserId(Long subordinateUserId) {
|
||||
List<UserManagementRelationDO> list = userManagementRelationService.getRelationListBySubordinateUserId(subordinateUserId);
|
||||
return success(BeanUtils.toBean(list, UserManagementRelationRespDTO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<UserManagementRelationRespDTO>> getRelationList(Collection<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return success(Collections.emptyList());
|
||||
}
|
||||
List<UserManagementRelationDO> list = userManagementRelationService.getRelationList(ids);
|
||||
return success(BeanUtils.toBean(list, UserManagementRelationRespDTO.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package com.njcn.rdms.module.system.controller.admin.user;
|
||||
|
||||
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.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.dal.dataobject.user.UserManagementRelationDO;
|
||||
import com.njcn.rdms.module.system.service.user.UserManagementRelationService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static com.njcn.rdms.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static com.njcn.rdms.framework.common.pojo.CommonResult.success;
|
||||
|
||||
/**
|
||||
* 用户带人关系 Controller
|
||||
*
|
||||
* 提供用户带人关系的管理接口,包括:
|
||||
* - 创建、更新、删除用户带人关系
|
||||
* - 查询用户带人关系列表和详情
|
||||
* - 获取用户带人关系树形结构
|
||||
* - 导出用户带人关系数据
|
||||
*
|
||||
* @author dklive
|
||||
*/
|
||||
@Tag(name = "管理后台 - 用户带人关系")
|
||||
@RestController
|
||||
@RequestMapping("/system/user-management-relation")
|
||||
@Validated
|
||||
public class UserManagementRelationController {
|
||||
|
||||
@Resource
|
||||
private UserManagementRelationService userManagementRelationService;
|
||||
|
||||
/**
|
||||
* 创建用户带人关系
|
||||
*
|
||||
* 权限要求:system:user-management-relation:create
|
||||
*
|
||||
* @param createReqVO 创建请求VO
|
||||
* @return 关系记录主键ID
|
||||
*/
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建用户带人关系")
|
||||
@PreAuthorize("@ss.hasPermission('system:user-management-relation:create')")
|
||||
public CommonResult<Long> createUserManagementRelation(@Valid @RequestBody UserManagementRelationSaveReqVO createReqVO) {
|
||||
Long id = userManagementRelationService.createRelation(createReqVO);
|
||||
return success(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户带人关系
|
||||
*
|
||||
* 权限要求:system:user-management-relation:update
|
||||
*
|
||||
* @param updateReqVO 更新请求VO
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "修改用户带人关系")
|
||||
@PreAuthorize("@ss.hasPermission('system:user-management-relation:update')")
|
||||
public CommonResult<Boolean> updateUserManagementRelation(@Valid @RequestBody UserManagementRelationSaveReqVO updateReqVO) {
|
||||
userManagementRelationService.updateRelation(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户带人关系
|
||||
*
|
||||
* 根据主键ID删除单条用户带人关系记录
|
||||
* 权限要求:system:user-management-relation:delete
|
||||
*
|
||||
* @param id 关系记录主键ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除用户带人关系")
|
||||
@PreAuthorize("@ss.hasPermission('system:user-management-relation:delete')")
|
||||
public CommonResult<Boolean> deleteUserManagementRelation(@RequestParam("id") Long id) {
|
||||
userManagementRelationService.deleteRelation(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除用户带人关系
|
||||
*
|
||||
* 根据主键ID列表批量删除用户带人关系记录
|
||||
* 权限要求:system:user-management-relation:delete
|
||||
*
|
||||
* @param ids 关系记录主键ID列表
|
||||
* @return 操作结果
|
||||
*/
|
||||
@DeleteMapping("/delete-list")
|
||||
@Operation(summary = "批量删除用户带人关系")
|
||||
@PreAuthorize("@ss.hasPermission('system:user-management-relation:delete')")
|
||||
public CommonResult<Boolean> deleteUserManagementRelationList(@RequestParam("ids") List<Long> ids) {
|
||||
userManagementRelationService.deleteRelationList(ids);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得用户带人关系信息
|
||||
*
|
||||
* 根据主键ID查询单条用户带人关系记录
|
||||
* 权限要求:system:user-management-relation:query
|
||||
*
|
||||
* @param id 关系记录主键ID
|
||||
* @return 用户带人关系详情
|
||||
*/
|
||||
@GetMapping(value = "/get")
|
||||
@Operation(summary = "获得用户带人关系信息")
|
||||
@Parameter(name = "id", description = "关系编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:user-management-relation:query')")
|
||||
public CommonResult<UserManagementRelationRespVO> getUserManagementRelation(@RequestParam("id") Long id) {
|
||||
UserManagementRelationDO relation = userManagementRelationService.getRelation(id);
|
||||
return success(BeanUtils.toBean(relation, UserManagementRelationRespVO.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户带人关系列表
|
||||
*
|
||||
* 根据查询条件查询用户带人关系记录列表
|
||||
* 权限要求:system:user-management-relation:query
|
||||
*
|
||||
* @param reqVO 查询条件VO
|
||||
* @return 用户带人关系列表
|
||||
*/
|
||||
@GetMapping("/query")
|
||||
@Operation(summary = "获取用户带人关系列表")
|
||||
@PreAuthorize("@ss.hasPermission('system:user-management-relation:query')")
|
||||
public CommonResult<List<UserManagementRelationTreeRespVO>> getUserManagementRelationQuery(@Validated UserManagementRelationQueryReqVO reqVO) {
|
||||
List<UserManagementRelationTreeRespVO> list = userManagementRelationService.getRelationQuery(reqVO);
|
||||
return success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户带人关系树形结构
|
||||
*
|
||||
* 构建用户上下级关系的树形结构,用于前端树形控件展示
|
||||
* 树形结构特点:
|
||||
* - 根节点:最高领导,没有上级
|
||||
* - 中间节点:有上级也有下级
|
||||
* - 叶子节点:基层员工,没有下级
|
||||
*
|
||||
* 权限要求:system:user-management-relation:query
|
||||
*
|
||||
* @return 用户带人关系树形列表
|
||||
*/
|
||||
@GetMapping("/tree")
|
||||
@Operation(summary = "获取用户带人关系树形结构", description = "用于前端树形控件展示,包含用户的上下级层级关系")
|
||||
@PreAuthorize("@ss.hasPermission('system:user-management-relation:query')")
|
||||
public CommonResult<List<UserManagementRelationTreeRespVO>> getUserManagementRelationTree() {
|
||||
return success(userManagementRelationService.getRelationTree());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 导出用户带人关系 Excel
|
||||
*
|
||||
* 根据查询条件导出用户带人关系数据到Excel文件
|
||||
* 权限要求:system:user-management-relation:export
|
||||
*
|
||||
* @param response HTTP响应对象
|
||||
* @param reqVO 查询条件VO
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出用户带人关系 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('system:user-management-relation:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void export(HttpServletResponse response, @Validated UserManagementRelationQueryReqVO reqVO) throws IOException {
|
||||
List<UserManagementRelationTreeRespVO> list = userManagementRelationService.getRelationQuery(reqVO);
|
||||
ExcelUtils.write(response, "用户带人关系数据.xls", "用户带人关系列表", UserManagementRelationRespVO.class,
|
||||
BeanUtils.toBean(list, UserManagementRelationRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 用户带人关系列表 Request VO")
|
||||
@Data
|
||||
public class UserManagementRelationQueryReqVO {
|
||||
|
||||
@Schema(description = "管理者用户ID", example = "1")
|
||||
private Long managerUserId;
|
||||
|
||||
@Schema(description = "被管理用户ID", example = "2")
|
||||
private Long subordinateUserId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 用户带人关系信息 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class UserManagementRelationRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@ExcelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "管理者用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("管理者用户ID")
|
||||
private Long managerUserId;
|
||||
|
||||
@Schema(description = "被管理用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty("被管理用户ID")
|
||||
private Long subordinateUserId;
|
||||
|
||||
@Schema(description = "生效开始时间")
|
||||
@ExcelProperty("生效开始时间")
|
||||
private LocalDateTime effectiveFrom;
|
||||
|
||||
@Schema(description = "生效结束时间")
|
||||
@ExcelProperty("生效结束时间")
|
||||
private LocalDateTime effectiveUntil;
|
||||
|
||||
@Schema(description = "备注", example = "直属上级关系")
|
||||
@ExcelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 用户带人关系创建/修改 Request VO")
|
||||
@Data
|
||||
public class UserManagementRelationSaveReqVO {
|
||||
|
||||
@Schema(description = "主键ID", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "管理者用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "管理者用户ID不能为空")
|
||||
private Long managerUserId;
|
||||
|
||||
@Schema(description = "被管理用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "被管理用户ID不能为空")
|
||||
private Long subordinateUserId;
|
||||
|
||||
@Schema(description = "生效开始时间")
|
||||
private LocalDateTime effectiveFrom;
|
||||
|
||||
@Schema(description = "生效结束时间")
|
||||
private LocalDateTime effectiveUntil;
|
||||
|
||||
@Schema(description = "备注", example = "直属上级关系")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户带人关系树形 Response VO
|
||||
*
|
||||
* 用于前端树形控件展示用户的上下级层级关系
|
||||
* 包含关系记录的主键ID,便于前端执行删除和更新操作
|
||||
*
|
||||
* @author hongawen
|
||||
*/
|
||||
@Schema(description = "管理后台 - 用户带人关系树形 Response VO")
|
||||
@Data
|
||||
public class UserManagementRelationTreeRespVO {
|
||||
|
||||
/**
|
||||
* 关系记录主键ID
|
||||
* 用于前端执行删除和更新操作
|
||||
*/
|
||||
@Schema(description = "关系记录主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
|
||||
private String userNickname;
|
||||
|
||||
/**
|
||||
* 上级用户ID
|
||||
* 最高领导此字段为null
|
||||
*/
|
||||
@Schema(description = "上级用户ID", example = "1")
|
||||
private Long managerUserId;
|
||||
|
||||
/**
|
||||
* 上级用户昵称
|
||||
* 最高领导此字段为null
|
||||
*/
|
||||
@Schema(description = "上级用户昵称", example = "李四")
|
||||
private String managerNickname;
|
||||
|
||||
/**
|
||||
* 下级用户列表
|
||||
* 基层员工此字段为空列表
|
||||
*/
|
||||
@Schema(description = "下级用户列表")
|
||||
private List<UserManagementRelationTreeRespVO> children;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.njcn.rdms.module.system.dal.dataobject.user;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户带人关系表 DO
|
||||
*
|
||||
* 用于存储用户之间的直属上下级管理关系
|
||||
* 每条记录代表一个管理者与被管理者之间的关系
|
||||
*
|
||||
* 表名:system_user_management_relation
|
||||
*
|
||||
* 业务场景:
|
||||
* - 组织架构中的直属上下级关系管理
|
||||
* - 支持关系的生效时间范围设置
|
||||
* - 一个用户可以有多个上级,但只有一个直属上级
|
||||
* - 一个用户可以有多个下属
|
||||
*
|
||||
* @author dklive
|
||||
*/
|
||||
@TableName("system_user_management_relation")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserManagementRelationDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 管理者用户ID
|
||||
*
|
||||
* 表示上级用户的ID,即管理者的用户ID
|
||||
* 对应 system_users 表的 id 字段
|
||||
*/
|
||||
private Long managerUserId;
|
||||
|
||||
/**
|
||||
* 被管理用户ID
|
||||
*
|
||||
* 表示下级用户的ID,即被管理者的用户ID
|
||||
* 对应 system_users 表的 id 字段
|
||||
*/
|
||||
private Long subordinateUserId;
|
||||
|
||||
/**
|
||||
* 生效开始时间
|
||||
*
|
||||
* 关系开始生效的时间
|
||||
* 为空表示立即长期生效
|
||||
*/
|
||||
private LocalDateTime effectiveFrom;
|
||||
|
||||
/**
|
||||
* 生效结束时间
|
||||
*
|
||||
* 关系失效的时间
|
||||
* 为空表示长期有效
|
||||
*/
|
||||
private LocalDateTime effectiveUntil;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*
|
||||
* 用于记录关系的额外说明信息
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.njcn.rdms.module.system.dal.mysql.user;
|
||||
|
||||
import com.njcn.rdms.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.njcn.rdms.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.njcn.rdms.module.system.controller.admin.user.vo.userManagementRelation.UserManagementRelationQueryReqVO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.user.UserManagementRelationDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户带人关系 Mapper 接口
|
||||
*
|
||||
* 提供用户带人关系表的数据访问操作
|
||||
* 继承 BaseMapperX 获得基础的 CRUD 功能
|
||||
*
|
||||
* @author hongawen
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserManagementRelationMapper extends BaseMapperX<UserManagementRelationDO> {
|
||||
|
||||
/**
|
||||
* 根据查询条件查询用户带人关系列表
|
||||
*
|
||||
* 支持的查询条件:
|
||||
* - managerUserId:管理者用户ID,精确匹配
|
||||
* - subordinateUserId:被管理用户ID,精确匹配
|
||||
*
|
||||
* 排序规则:按主键ID降序排列
|
||||
*
|
||||
* @param reqVO 查询条件VO
|
||||
* @return 用户带人关系DO列表
|
||||
*/
|
||||
default List<UserManagementRelationDO> selectList(UserManagementRelationQueryReqVO reqVO) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
return selectList(new LambdaQueryWrapperX<UserManagementRelationDO>()
|
||||
.eqIfPresent(UserManagementRelationDO::getManagerUserId, reqVO.getManagerUserId())
|
||||
.eqIfPresent(UserManagementRelationDO::getSubordinateUserId, reqVO.getSubordinateUserId())
|
||||
.orderByDesc(UserManagementRelationDO::getId)
|
||||
// (from IS NULL OR from <= now)
|
||||
.and(w -> w.isNull(UserManagementRelationDO::getEffectiveFrom)
|
||||
.or().le(UserManagementRelationDO::getEffectiveFrom, now))
|
||||
// (until IS NULL OR until >= now)
|
||||
.and(w -> w.isNull(UserManagementRelationDO::getEffectiveUntil)
|
||||
.or().ge(UserManagementRelationDO::getEffectiveUntil, now))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据管理者用户ID查询其下属关系列表
|
||||
*
|
||||
* 查询指定用户作为管理者时的所有带人关系记录
|
||||
* 用于获取某个用户的所有直接下属
|
||||
*
|
||||
* @param managerUserId 管理者用户ID
|
||||
* @return 用户带人关系DO列表
|
||||
*/
|
||||
default List<UserManagementRelationDO> selectListByManagerUserId(Long managerUserId) {
|
||||
return selectList(UserManagementRelationDO::getManagerUserId, managerUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据被管理者用户ID查询其上级关系列表
|
||||
*
|
||||
* 查询指定用户作为被管理者时的所有带人关系记录
|
||||
* 用于获取某个用户的所有直接上级
|
||||
*
|
||||
* @param subordinateUserId 被管理者用户ID
|
||||
* @return 用户带人关系DO列表
|
||||
*/
|
||||
default List<UserManagementRelationDO> selectListBySubordinateUserId(Long subordinateUserId) {
|
||||
return selectList(UserManagementRelationDO::getSubordinateUserId, subordinateUserId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.njcn.rdms.module.system.service.user;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
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.UserManagementRelationDO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 用户带人关系 Service 接口
|
||||
*
|
||||
* @author dklive
|
||||
*/
|
||||
public interface UserManagementRelationService {
|
||||
|
||||
/**
|
||||
* 创建用户带人关系
|
||||
*
|
||||
* @param createReqVO 关系信息
|
||||
* @return 关系编号
|
||||
*/
|
||||
Long createRelation(UserManagementRelationSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新用户带人关系
|
||||
*
|
||||
* @param updateReqVO 关系信息
|
||||
*/
|
||||
void updateRelation(UserManagementRelationSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除用户带人关系
|
||||
*
|
||||
* @param id 关系编号
|
||||
*/
|
||||
void deleteRelation(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除用户带人关系
|
||||
*
|
||||
* @param ids 关系编号数组
|
||||
*/
|
||||
void deleteRelationList(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得用户带人关系
|
||||
*
|
||||
* @param id 关系编号
|
||||
* @return 用户带人关系
|
||||
*/
|
||||
UserManagementRelationDO getRelation(Long id);
|
||||
|
||||
/**
|
||||
* 获得用户带人关系列表
|
||||
*
|
||||
* @param ids 关系编号数组
|
||||
* @return 用户带人关系列表
|
||||
*/
|
||||
List<UserManagementRelationDO> getRelationList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得用户带人关系列表
|
||||
*
|
||||
* @param reqVO 查询条件
|
||||
* @return 用户带人关系列表
|
||||
*/
|
||||
List<UserManagementRelationTreeRespVO> getRelationQuery(UserManagementRelationQueryReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 根据管理者用户ID获得带人关系列表
|
||||
*
|
||||
* @param managerUserId 管理者用户ID
|
||||
* @return 带人关系列表
|
||||
*/
|
||||
List<UserManagementRelationDO> getRelationListByManagerUserId(Long managerUserId);
|
||||
|
||||
/**
|
||||
* 根据被管理者用户ID获得带人关系列表
|
||||
*
|
||||
* @param subordinateUserId 被管理者用户ID
|
||||
* @return 带人关系列表
|
||||
*/
|
||||
List<UserManagementRelationDO> getRelationListBySubordinateUserId(Long subordinateUserId);
|
||||
|
||||
/**
|
||||
* 获得用户带人关系树形结构
|
||||
*
|
||||
* 构建用户上下级关系的树形结构,用于前端树形控件展示
|
||||
* - 最高领导:没有上级,作为树的根节点
|
||||
* - 基层员工:没有下级,children为空列表
|
||||
*
|
||||
* @return 用户带人关系树形列表
|
||||
*/
|
||||
List<UserManagementRelationTreeRespVO> getRelationTree();
|
||||
|
||||
/**
|
||||
* 获得用户带人关系 Map
|
||||
*
|
||||
* @param ids 关系编号数组
|
||||
* @return 用户带人关系 Map
|
||||
*/
|
||||
default Map<Long, UserManagementRelationDO> getRelationMap(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
return CollectionUtils.convertMap(getRelationList(ids), UserManagementRelationDO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,597 @@
|
||||
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.exception.ServiceException;
|
||||
import com.njcn.rdms.framework.common.util.object.BeanUtils;
|
||||
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 com.njcn.rdms.module.system.dal.mysql.user.AdminUserMapper;
|
||||
import com.njcn.rdms.module.system.dal.mysql.user.UserManagementRelationMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.Data;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_MANAGEMENT_RELATION_MANAGER_EXISTS;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_MANAGEMENT_RELATION_NOT_FOUND;
|
||||
|
||||
/**
|
||||
* 用户带人关系 Service 实现类
|
||||
* 提供用户带人关系的增删改查功能,以及树形结构构建功能
|
||||
* 树形结构用于前端展示用户的上下级层级关系
|
||||
* 业务规则:
|
||||
* 1. 一个用户只能有一个直属上级
|
||||
* 2. 一个用户可以有多个下属
|
||||
* 3. 可以将自己设置为被管理者(自己管理自己)
|
||||
*
|
||||
* @author dklive
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class UserManagementRelationServiceImpl implements UserManagementRelationService {
|
||||
|
||||
@Resource
|
||||
private UserManagementRelationMapper userManagementRelationMapper;
|
||||
|
||||
@Resource
|
||||
private AdminUserMapper adminUserMapper;
|
||||
|
||||
/**
|
||||
* 树形结构构建上下文
|
||||
* 包含构建树形结构所需的所有基础数据
|
||||
*/
|
||||
@Data
|
||||
private static class TreeBuildContext {
|
||||
private Map<Long, AdminUserDO> userMap;
|
||||
private Map<Long, List<Long>> managerToSubordinatesMap;
|
||||
private Map<Long, UserManagementRelationDO> subordinateToRelationMap;
|
||||
private Set<Long> hasManagerUserIds;
|
||||
private Set<Long> allUserIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建用户带人关系
|
||||
* 业务逻辑:
|
||||
* 1. 校验被管理者是否已有直属上级(一个用户只能有一个直属上级)
|
||||
* 2. 插入关系记录
|
||||
*
|
||||
* @param createReqVO 创建请求VO
|
||||
* @return 关系记录主键ID
|
||||
*/
|
||||
@Override
|
||||
public Long createRelation(UserManagementRelationSaveReqVO createReqVO) {
|
||||
validateRelationForCreateOrUpdate(null, createReqVO.getSubordinateUserId());
|
||||
UserManagementRelationDO relation = BeanUtils.toBean(createReqVO, UserManagementRelationDO.class);
|
||||
userManagementRelationMapper.insert(relation);
|
||||
return relation.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户带人关系
|
||||
* 业务逻辑:
|
||||
* 1. 校验关系记录是否存在
|
||||
* 2. 校验被管理者是否已有其他直属上级(一个用户只能有一个直属上级)
|
||||
* 3. 更新关系记录
|
||||
*
|
||||
* @param updateReqVO 更新请求VO
|
||||
*/
|
||||
@Override
|
||||
public void updateRelation(UserManagementRelationSaveReqVO updateReqVO) {
|
||||
validateRelationForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getSubordinateUserId());
|
||||
UserManagementRelationDO updateObj = BeanUtils.toBean(updateReqVO, UserManagementRelationDO.class);
|
||||
userManagementRelationMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户带人关系
|
||||
* 业务逻辑:
|
||||
* 1. 校验关系记录是否存在
|
||||
* 2. 根据主键ID删除关系记录
|
||||
*
|
||||
* @param id 关系记录主键ID
|
||||
*/
|
||||
@Override
|
||||
public void deleteRelation(Long id) {
|
||||
validateRelationExists(id);
|
||||
userManagementRelationMapper.deleteById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除用户带人关系
|
||||
* 业务逻辑:
|
||||
* 根据主键ID列表批量删除关系记录
|
||||
*
|
||||
* @param ids 关系记录主键ID列表
|
||||
*/
|
||||
@Override
|
||||
public void deleteRelationList(List<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return;
|
||||
}
|
||||
userManagementRelationMapper.deleteByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验关系记录的合法性
|
||||
* 校验规则:
|
||||
* 1. 更新时,校验关系记录是否存在
|
||||
* 2. 被管理者用户只能有一个直属上级(创建时校验,更新时校验是否更换了被管理者)
|
||||
*
|
||||
* @param id 关系记录主键ID(创建时为null)
|
||||
* @param subordinateUserId 被管理者用户ID
|
||||
*/
|
||||
private void validateRelationForCreateOrUpdate(Long id, Long subordinateUserId) {
|
||||
validateRelationExists(id);
|
||||
validateSubordinateHasNoOtherManager(id, subordinateUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验被管理者是否已有其他直属上级
|
||||
* 业务规则:一个用户只能有一个直属上级
|
||||
* 校验逻辑:
|
||||
* 1. 查询该被管理者用户的所有关系记录
|
||||
* 2. 如果存在其他关系记录(排除当前记录),则抛出异常
|
||||
*
|
||||
* @param excludeId 排除的关系记录主键ID(创建时为null,更新时为当前记录ID)
|
||||
* @param subordinateUserId 被管理者用户ID
|
||||
* @throws ServiceException 被管理者已有其他直属上级时抛出异常
|
||||
*/
|
||||
private void validateSubordinateHasNoOtherManager(Long excludeId, Long subordinateUserId) {
|
||||
if (subordinateUserId == null) {
|
||||
return;
|
||||
}
|
||||
List<UserManagementRelationDO> existingRelations =
|
||||
userManagementRelationMapper.selectListBySubordinateUserId(subordinateUserId);
|
||||
if (CollUtil.isEmpty(existingRelations)) {
|
||||
return;
|
||||
}
|
||||
if (excludeId == null) {
|
||||
throw exception(USER_MANAGEMENT_RELATION_MANAGER_EXISTS);
|
||||
}
|
||||
boolean hasOtherManager = existingRelations.stream()
|
||||
.anyMatch(relation -> !relation.getId().equals(excludeId));
|
||||
if (hasOtherManager) {
|
||||
throw exception(USER_MANAGEMENT_RELATION_MANAGER_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验关系记录是否存在
|
||||
*
|
||||
* @param id 关系记录主键ID
|
||||
* @throws ServiceException 关系记录不存在时抛出异常
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void validateRelationExists(Long id) {
|
||||
if (id == null) {
|
||||
return;
|
||||
}
|
||||
if (userManagementRelationMapper.selectById(id) == null) {
|
||||
throw exception(USER_MANAGEMENT_RELATION_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据主键ID获取用户带人关系
|
||||
*
|
||||
* @param id 关系记录主键ID
|
||||
* @return 用户带人关系DO
|
||||
*/
|
||||
@Override
|
||||
public UserManagementRelationDO getRelation(Long id) {
|
||||
return userManagementRelationMapper.selectOne(
|
||||
buildValidQuery().eq(UserManagementRelationDO::getId, id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据主键ID列表获取用户带人关系列表
|
||||
*
|
||||
* @param ids 关系记录主键ID列表
|
||||
* @return 用户带人关系DO列表
|
||||
*/
|
||||
@Override
|
||||
public List<UserManagementRelationDO> getRelationList(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return userManagementRelationMapper.selectList(
|
||||
buildValidQuery().in(UserManagementRelationDO::getId, ids)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据查询条件获取用户带人关系树形结构
|
||||
* 业务逻辑:
|
||||
* 1. 构建树形结构上下文(包含所有基础数据)
|
||||
* 2. 根据查询条件确定目标用户ID(subordinateUserId优先于managerUserId)
|
||||
* 3. 如果有目标用户,只构建包含该用户的分支(上级链 + 下级树)
|
||||
* 4. 如果没有目标用户,返回完整的树形结构
|
||||
* <p>
|
||||
* 查询参数优先级:
|
||||
* - 当subordinateUserId和managerUserId同时存在时,优先使用subordinateUserId
|
||||
* - 正常业务场景下,两个参数只会传递其中一个
|
||||
* <p>
|
||||
* 边界情况处理:
|
||||
* - 两个参数都为null:返回完整的树形结构(等同于getRelationTree)
|
||||
* - subordinateUserId不为null:构建包含该用户的上级链和下级树,不包含同级节点
|
||||
* - managerUserId不为null:构建以该用户为根节点的完整下级树
|
||||
*
|
||||
* @param reqVO 查询条件VO,包含subordinateUserId或managerUserId
|
||||
* @return 用户带人关系树形结构列表
|
||||
*/
|
||||
@Override
|
||||
public List<UserManagementRelationTreeRespVO> getRelationQuery(UserManagementRelationQueryReqVO reqVO) {
|
||||
TreeBuildContext context = buildTreeContext();
|
||||
if (context == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Long targetUserId = determineTargetUserId(reqVO, context);
|
||||
if (targetUserId == null) {
|
||||
return buildFullTree(context);
|
||||
}
|
||||
|
||||
return buildTargetBranchTree(targetUserId, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据管理者用户ID获取其下属关系列表
|
||||
*
|
||||
* @param managerUserId 管理者用户ID
|
||||
* @return 用户带人关系DO列表
|
||||
*/
|
||||
@Override
|
||||
public List<UserManagementRelationDO> getRelationListByManagerUserId(Long managerUserId) {
|
||||
return userManagementRelationMapper.selectListByManagerUserId(managerUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据被管理者用户ID获取其上级关系列表
|
||||
* 注意:由于一个用户只能有一个直属上级,此方法最多返回一条记录
|
||||
*
|
||||
* @param subordinateUserId 被管理者用户ID
|
||||
* @return 用户带人关系DO列表
|
||||
*/
|
||||
@Override
|
||||
public List<UserManagementRelationDO> getRelationListBySubordinateUserId(Long subordinateUserId) {
|
||||
return userManagementRelationMapper.selectListBySubordinateUserId(subordinateUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户带人关系树形结构
|
||||
* 业务逻辑:
|
||||
* 1. 构建树形结构上下文(包含所有基础数据)
|
||||
* 2. 找出所有根节点(没有上级的用户,即最高领导;也包括自己管理自己的用户)
|
||||
* 3. 从根节点开始递归构建完整的树形结构
|
||||
* <p>
|
||||
* 边界情况处理:
|
||||
* - 根节点(还没有设置直属上级的用户):managerUserId设置为自己的userId,managerNickname为自己的昵称
|
||||
* - 自己管理自己的用户:managerUserId等于userId,managerNickname为自己的昵称
|
||||
* - 基层员工:没有下级,children为空列表
|
||||
* - 空数据:返回空列表
|
||||
*
|
||||
* @return 用户带人关系树形结构列表
|
||||
*/
|
||||
@Override
|
||||
public List<UserManagementRelationTreeRespVO> getRelationTree() {
|
||||
TreeBuildContext context = buildTreeContext();
|
||||
if (context == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return buildFullTree(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建树形结构上下文
|
||||
* 查询并组装构建树形结构所需的所有基础数据
|
||||
*
|
||||
* @return 树形结构上下文,如果没有数据则返回null
|
||||
*/
|
||||
private TreeBuildContext buildTreeContext() {
|
||||
List<UserManagementRelationDO> allRelations = userManagementRelationMapper.selectList(new UserManagementRelationQueryReqVO());
|
||||
if (CollUtil.isEmpty(allRelations)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<Long> allUserIds = new HashSet<>();
|
||||
for (UserManagementRelationDO relation : allRelations) {
|
||||
allUserIds.add(relation.getManagerUserId());
|
||||
allUserIds.add(relation.getSubordinateUserId());
|
||||
}
|
||||
|
||||
List<AdminUserDO> users = adminUserMapper.selectByIds(allUserIds);
|
||||
Map<Long, AdminUserDO> userMap = users.stream()
|
||||
.collect(Collectors.toMap(AdminUserDO::getId, user -> user));
|
||||
|
||||
Map<Long, List<Long>> managerToSubordinatesMap = allRelations.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
UserManagementRelationDO::getManagerUserId,
|
||||
Collectors.mapping(UserManagementRelationDO::getSubordinateUserId, Collectors.toList())
|
||||
));
|
||||
|
||||
Map<Long, UserManagementRelationDO> subordinateToRelationMap = allRelations.stream()
|
||||
.collect(Collectors.toMap(
|
||||
UserManagementRelationDO::getSubordinateUserId,
|
||||
relation -> relation,
|
||||
(existing, replacement) -> existing
|
||||
));
|
||||
|
||||
Set<Long> hasManagerUserIds = allRelations.stream()
|
||||
.filter(relation -> !relation.getManagerUserId().equals(relation.getSubordinateUserId()))
|
||||
.map(UserManagementRelationDO::getSubordinateUserId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
TreeBuildContext context = new TreeBuildContext();
|
||||
context.setUserMap(userMap);
|
||||
context.setManagerToSubordinatesMap(managerToSubordinatesMap);
|
||||
context.setSubordinateToRelationMap(subordinateToRelationMap);
|
||||
context.setHasManagerUserIds(hasManagerUserIds);
|
||||
context.setAllUserIds(allUserIds);
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建完整的树形结构
|
||||
* 从所有根节点开始构建完整的树形结构
|
||||
*
|
||||
* @param context 树形结构上下文
|
||||
* @return 完整的树形结构列表
|
||||
*/
|
||||
private List<UserManagementRelationTreeRespVO> buildFullTree(TreeBuildContext context) {
|
||||
List<Long> rootUserIds = context.getAllUserIds().stream()
|
||||
.filter(userId -> !context.getHasManagerUserIds().contains(userId))
|
||||
.toList();
|
||||
|
||||
List<UserManagementRelationTreeRespVO> treeList = new ArrayList<>();
|
||||
for (Long rootUserId : rootUserIds) {
|
||||
UserManagementRelationTreeRespVO rootNode = buildRootNode(rootUserId, context);
|
||||
if (rootNode != null) {
|
||||
treeList.add(rootNode);
|
||||
}
|
||||
}
|
||||
return treeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建目标用户相关的分支树形结构
|
||||
* 只包含目标用户的上级链和下级树,不包含同级节点
|
||||
* <p>
|
||||
* 构建逻辑:
|
||||
* 1. 从目标用户向上追溯到根节点,记录上级链
|
||||
* 2. 从根节点开始,只沿着包含目标用户的分支向下构建
|
||||
* 3. 构建目标用户的所有下级
|
||||
*
|
||||
* @param targetUserId 目标用户ID
|
||||
* @param context 树形结构上下文
|
||||
* @return 目标用户相关的分支树形结构列表
|
||||
*/
|
||||
private List<UserManagementRelationTreeRespVO> buildTargetBranchTree(Long targetUserId, TreeBuildContext context) {
|
||||
LinkedList<Long> pathToRoot = findPathToRoot(targetUserId, context);
|
||||
if (pathToRoot.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Long rootUserId = pathToRoot.getFirst();
|
||||
UserManagementRelationTreeRespVO rootNode = buildRootNode(rootUserId, context);
|
||||
if (rootNode == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (pathToRoot.size() > 1) {
|
||||
buildBranchPath(rootNode, pathToRoot, context);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建根节点
|
||||
*
|
||||
* @param rootUserId 根节点用户ID
|
||||
* @param context 树形结构上下文
|
||||
* @return 根节点
|
||||
*/
|
||||
private UserManagementRelationTreeRespVO buildRootNode(Long rootUserId, TreeBuildContext context) {
|
||||
UserManagementRelationDO rootRelation = context.getSubordinateToRelationMap().get(rootUserId);
|
||||
Long rootRelationId = rootRelation != null ? rootRelation.getId() : null;
|
||||
Long rootManagerUserId;
|
||||
if (rootRelation == null) {
|
||||
rootManagerUserId = rootUserId;
|
||||
} else if (rootRelation.getManagerUserId().equals(rootRelation.getSubordinateUserId())) {
|
||||
rootManagerUserId = rootUserId;
|
||||
} else {
|
||||
rootManagerUserId = rootRelation.getManagerUserId();
|
||||
}
|
||||
return buildTreeNode(rootRelationId, rootUserId, rootManagerUserId, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定目标用户ID
|
||||
* 根据查询参数优先级确定目标用户:
|
||||
* 1. 如果subordinateUserId不为null,返回subordinateUserId
|
||||
* 2. 如果managerUserId不为null,返回managerUserId
|
||||
* 3. 否则返回null(表示查询所有)
|
||||
*
|
||||
* @param reqVO 查询条件VO
|
||||
* @param context 树形结构上下文
|
||||
* @return 目标用户ID,如果没有指定则返回null
|
||||
*/
|
||||
private Long determineTargetUserId(UserManagementRelationQueryReqVO reqVO, TreeBuildContext context) {
|
||||
if (reqVO == null) {
|
||||
return null;
|
||||
}
|
||||
if (reqVO.getSubordinateUserId() != null && context.getAllUserIds().contains(reqVO.getSubordinateUserId())) {
|
||||
return reqVO.getSubordinateUserId();
|
||||
}
|
||||
if (reqVO.getManagerUserId() != null && context.getAllUserIds().contains(reqVO.getManagerUserId())) {
|
||||
return reqVO.getManagerUserId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建树形节点
|
||||
* 构建逻辑:
|
||||
* 1. 根据用户ID获取用户信息
|
||||
* 2. 设置节点的基本信息(关系记录ID、用户ID、用户昵称)
|
||||
* 3. 设置上级信息(上级用户ID、上级用户昵称)
|
||||
* 4. 递归构建所有下级节点列表
|
||||
*
|
||||
* @param relationId 关系记录主键ID(根节点且非自己管理自己时为null)
|
||||
* @param userId 当前用户ID
|
||||
* @param managerUserId 上级用户ID(根节点时为自己的userId)
|
||||
* @param context 树形结构上下文
|
||||
* @return 树形节点
|
||||
*/
|
||||
private UserManagementRelationTreeRespVO buildTreeNode(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());
|
||||
}
|
||||
}
|
||||
|
||||
List<Long> subordinateIds = context.getManagerToSubordinatesMap().get(userId);
|
||||
if (CollUtil.isNotEmpty(subordinateIds)) {
|
||||
List<UserManagementRelationTreeRespVO> children = new ArrayList<>();
|
||||
for (Long subordinateId : subordinateIds) {
|
||||
if (subordinateId.equals(userId)) {
|
||||
continue;
|
||||
}
|
||||
UserManagementRelationDO childRelation = context.getSubordinateToRelationMap().get(subordinateId);
|
||||
Long childRelationId = childRelation != null ? childRelation.getId() : null;
|
||||
UserManagementRelationTreeRespVO childNode = buildTreeNode(childRelationId, subordinateId, userId, context);
|
||||
if (childNode != null) {
|
||||
children.add(childNode);
|
||||
}
|
||||
}
|
||||
node.setChildren(children);
|
||||
} else {
|
||||
node.setChildren(Collections.emptyList());
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一时间有效性过滤条件:
|
||||
* <p>
|
||||
* 1.如果这两个字段都是null,那就直接查出来
|
||||
* 2.如果effective_util是null、effective_from不是null,那就只需要当前时间>=effective_from就行
|
||||
* 3.如果effective_from是null、effective_util不是null,那就只需要当前时间<=effective_util就行
|
||||
* <p>
|
||||
* 如果上面三个条件都不满足,那就判断为此条关系已经失效,不查出来
|
||||
*/
|
||||
private LambdaQueryWrapper<UserManagementRelationDO> buildValidQuery() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
return new LambdaQueryWrapper<UserManagementRelationDO>()
|
||||
// (from IS NULL OR from <= now)
|
||||
.and(w -> w.isNull(UserManagementRelationDO::getEffectiveFrom)
|
||||
.or().le(UserManagementRelationDO::getEffectiveFrom, now))
|
||||
// (until IS NULL OR until >= now)
|
||||
.and(w -> w.isNull(UserManagementRelationDO::getEffectiveUntil)
|
||||
.or().ge(UserManagementRelationDO::getEffectiveUntil, now));
|
||||
// BaseMapperX 通常已自动处理 deleted 字段,无需额外加
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user