1、完善DeptServiceImpl单元测试覆盖率90%;2、新增security mock能力;3、移除postservice相关代码;4、移除部分无用模块的单测代码;

This commit is contained in:
gaoqr
2025-09-10 16:54:02 +08:00
parent ecae82b507
commit 283759c90d
32 changed files with 586 additions and 1643 deletions
@@ -9,8 +9,6 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import java.util.Collection;
import java.util.List;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
@@ -27,18 +25,6 @@ public class DeptApiImpl implements DeptApi {
return success(BeanUtils.toBean(dept, DeptRespDTO.class));
}
@Override
public CommonResult<List<DeptRespDTO>> getDeptList(Collection<Long> ids) {
List<DeptDO> depts = deptService.getDeptList(ids);
return success(BeanUtils.toBean(depts, DeptRespDTO.class));
}
@Override
public CommonResult<Boolean> validateDeptList(Collection<Long> ids) {
deptService.validateDeptList(ids);
return success(true);
}
@Override
public CommonResult<Boolean> validateDept(Long deptId) {
deptService.validDept(deptId);
@@ -1,26 +0,0 @@
package com.cf.imes.module.system.api.dept;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.module.system.service.dept.PostService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import java.util.Collection;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class PostApiImpl implements PostApi {
@Resource
private PostService postService;
@Override
public CommonResult<Boolean> validPostList(Collection<Long> ids) {
postService.validatePostList(ids);
return success(true);
}
}
@@ -1,114 +0,0 @@
package com.cf.imes.module.system.controller.admin.dept;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.excel.core.util.ExcelUtils;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostPageReqVO;
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostRespVO;
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostSaveReqVO;
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostSimpleRespVO;
import com.cf.imes.module.system.dal.dataobject.dept.PostDO;
import com.cf.imes.module.system.service.dept.PostService;
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.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 岗位")
@RestController
@RequestMapping("/system/post")
@Validated
public class PostController {
@Resource
private PostService postService;
@PostMapping("/create")
@Operation(summary = "创建岗位")
@PreAuthorize("@ss.hasPermission('system:post:create')")
public CommonResult<Long> createPost(@Valid @RequestBody PostSaveReqVO createReqVO) {
Long postId = postService.createPost(createReqVO);
return success(postId);
}
@PutMapping("/update")
@Operation(summary = "修改岗位")
@PreAuthorize("@ss.hasPermission('system:post:update')")
public CommonResult<Boolean> updatePost(@Valid @RequestBody PostSaveReqVO updateReqVO) {
postService.updatePost(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除岗位")
@PreAuthorize("@ss.hasPermission('system:post:delete')")
public CommonResult<Boolean> deletePost(@RequestParam("id") Long id) {
postService.deletePost(id);
return success(true);
}
@GetMapping(value = "/get")
@Operation(summary = "获得岗位信息")
@Parameter(name = "id", description = "岗位编号", required = true, example = "1024")
// @PreAuthorize("@ss.hasPermission('system:post:query')")
public CommonResult<PostRespVO> getPost(@RequestParam("id") Long id) {
PostDO post = postService.getPost(id);
return success(BeanUtils.toBean(post, PostRespVO.class));
}
@GetMapping(value = {"/list-all-simple", "simple-list"})
@Operation(summary = "获取岗位全列表", description = "只包含被开启的岗位,主要用于前端的下拉选项")
public CommonResult<List<PostSimpleRespVO>> getSimplePostList(@RequestParam(value = "organId", required = false) Long organId) {
// 获得岗位列表,只要开启状态的
List<PostDO> list = postService.getPostList(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus()), organId);
// 排序后,返回给前端
list.sort(Comparator.comparing(PostDO::getSort));
return success(BeanUtils.toBean(list, PostSimpleRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得岗位分页列表")
@PreAuthorize("@ss.hasPermission('system:post:query')")
public CommonResult<PageResult<PostRespVO>> getPostPage(@Validated PostPageReqVO pageReqVO) {
PageResult<PostDO> pageResult = postService.getPostPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, PostRespVO.class));
}
@GetMapping("/export")
@Operation(summary = "岗位管理")
@PreAuthorize("@ss.hasPermission('system:post:export')")
@OperateLog(type = EXPORT)
public void export(HttpServletResponse response, @Validated PostPageReqVO reqVO) throws IOException {
reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<PostDO> list = postService.getPostPage(reqVO).getList();
AtomicLong sort = new AtomicLong();
list.forEach(f->{
sort.addAndGet(1);
f.setId(sort.get());
});
// 输出
ExcelUtils.write(response, "岗位数据.xls", "岗位列表", PostRespVO.class,
BeanUtils.toBean(list, PostRespVO.class));
}
}
@@ -5,7 +5,6 @@ import com.cf.imes.framework.common.validation.NumberValid;
import com.cf.imes.module.system.validation.common.CommonStatus;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
@@ -38,7 +37,7 @@ public class DeptSaveReqVO {
private Integer sort;
@Schema(description = "负责人", example = "2048")
@Length(max = 10, message = "负责人长度不能超过10个字符")
@Size(max = 30, message = "负责人长度不能超过30个字符")
private String leader;
@Schema(description = "联系电话", example = "15601691000")
@@ -8,7 +8,6 @@ import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpd
import com.cf.imes.module.system.dal.dataobject.dept.DeptDO;
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
import com.cf.imes.module.system.service.dept.DeptService;
import com.cf.imes.module.system.service.dept.PostService;
import com.cf.imes.module.system.service.user.AdminUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -42,8 +41,6 @@ public class OAuth2UserController {
private AdminUserService userService;
@Resource
private DeptService deptService;
@Resource
private PostService postService;
@GetMapping("/get")
@Operation(summary = "获得用户基本信息")
@@ -57,11 +54,6 @@ public class OAuth2UserController {
DeptDO dept = deptService.getDept(user.getDeptId());
resp.setDept(BeanUtils.toBean(dept, OAuth2UserInfoRespVO.Dept.class));
}
// // 获得岗位信息
// if (CollUtil.isNotEmpty(user.getPostIds())) {
// List<PostDO> posts = postService.getPostList(user.getPostIds());
// resp.setPosts(BeanUtils.toBean(posts, OAuth2UserInfoRespVO.Post.class));
// }
return success(resp);
}
@@ -6,6 +6,7 @@ import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.collection.CollectionUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.excel.core.util.ExcelUtils;
import com.cf.imes.framework.mybatis.core.query.MPJLambdaWrapperX;
@@ -121,8 +122,8 @@ public class UserController {
return success(new PageResult<>(pageResult.getTotal()));
}
// 拼接数据
Map<Long, DeptDO> deptMap = deptService.getDeptMap(
convertList(pageResult.getList(), AdminUserDO::getDeptId));
Map<Long, DeptDO> deptMap = CollectionUtils.convertMap(
deptService.getDeptList(convertList(pageResult.getList(), AdminUserDO::getDeptId)), DeptDO::getId);
return success(new PageResult<>(UserConvert.INSTANCE.convertList(pageResult.getList(), deptMap),
pageResult.getTotal()));
}
@@ -155,8 +156,7 @@ public class UserController {
@RequestParam(value = "deptId", required = false) Long deptId) {
List<AdminUserDO> list = userService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus(), organId, deptId);
// 拼接数据
Map<Long, DeptDO> deptMap = deptService.getDeptMap(
convertList(list, AdminUserDO::getDeptId));
Map<Long, DeptDO> deptMap = CollectionUtils.convertMap(deptService.getDeptList(convertList(list, AdminUserDO::getDeptId)), DeptDO::getId);
return success(UserConvert.INSTANCE.convertSimpleList(list, deptMap));
}
@@ -194,8 +194,7 @@ public class UserController {
Map<Long, List<UserPostDTO>> listMap = userPostDTOS.stream().collect(Collectors.groupingBy(UserPostDTO::getUserId));
// 输出 Excel
Map<Long, DeptDO> deptMap = deptService.getDeptMap(
convertList(list, AdminUserDO::getDeptId));
Map<Long, DeptDO> deptMap = CollectionUtils.convertMap(deptService.getDeptList(convertList(list, AdminUserDO::getDeptId)), DeptDO::getId);
List<UserExportRespVO> userRespVOS = UserConvert.INSTANCE.convertExportList(list, deptMap);
userRespVOS.forEach(e-> {
List<UserPostDTO> userPostDTOS1 = listMap.get(e.getId());
@@ -12,7 +12,6 @@ import com.cf.imes.module.system.dal.dataobject.permission.RoleDO;
import com.cf.imes.module.system.dal.dataobject.social.SocialUserDO;
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
import com.cf.imes.module.system.service.dept.DeptService;
import com.cf.imes.module.system.service.dept.PostService;
import com.cf.imes.module.system.service.permission.PermissionService;
import com.cf.imes.module.system.service.permission.RoleService;
import com.cf.imes.module.system.service.social.SocialUserService;
@@ -45,8 +44,6 @@ public class UserProfileController {
@Resource
private DeptService deptService;
@Resource
private PostService postService;
@Resource
private PermissionService permissionService;
@Resource
private RoleService roleService;
@@ -62,8 +59,6 @@ public class UserProfileController {
List<RoleDO> userRoles = roleService.getRoleListFromCache(permissionService.getUserRoleIdListByUserId(user.getId()));
// 获得部门信息
DeptDO dept = user.getDeptId() != null ? deptService.getDept(user.getDeptId()) : null;
// // 获得岗位信息
// List<PostDO> posts = CollUtil.isNotEmpty(user.getPostIds()) ? postService.getPostList(user.getPostIds()) : null;
// 获得社交用户信息
List<SocialUserDO> socialUsers = socialService.getSocialUserList(user.getId(), UserTypeEnum.ADMIN.getValue());
return success(UserConvert.INSTANCE.convert(user, userRoles, dept, null, socialUsers));
@@ -3,12 +3,8 @@ package com.cf.imes.module.system.dal.mysql.dept;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.organ.core.security.OrganSecurityWebFilter;
import com.cf.imes.framework.security.core.LoginUser;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import com.cf.imes.module.system.dal.dataobject.dept.DeptDO;
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
@@ -18,19 +14,12 @@ import java.util.Objects;
@Mapper
public interface DeptMapper extends BaseMapperX<DeptDO> {
default List<DeptDO> selectList(DeptListReqVO reqVO) {
default List<DeptDO> selectList(DeptListReqVO reqVO, Long organId) {
LambdaQueryWrapperX<DeptDO> lambdaQueryWrapperX = new LambdaQueryWrapperX<>();
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
assert loginUser != null;
Boolean isSupAdmin = loginUser.getIsSupAdmin();
if(isSupAdmin && !Objects.isNull(reqVO.getOrganId())) {
lambdaQueryWrapperX.eqIfPresent(DeptDO::getOrganId, reqVO.getOrganId());
}else{
lambdaQueryWrapperX.eqIfPresent(DeptDO::getOrganId, loginUser.getOrganId());
}
return selectList(lambdaQueryWrapperX
.likeIfPresent(DeptDO::getName, reqVO.getName())
.eqIfPresent(DeptDO::getStatus, reqVO.getStatus()));
.eqIfPresent(DeptDO::getStatus, reqVO.getStatus())
.eqIfPresent(DeptDO::getOrganId, organId));
}
default DeptDO selectByParentIdAndName(Long parentId, String name, Long organId) {
@@ -0,0 +1,20 @@
package com.cf.imes.module.system.framework.redis.config;
import com.cf.imes.module.system.util.redis.SystemRedisUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* system 模块的Redisa Configuration
*
* @author Gqr
* @since 2025/9/10 10:07
*/
@Configuration(proxyBeanMethods = false)
public class ChenfengSystemRedisConfiguration {
@Bean
public SystemRedisUtils systemRedisUtils(StringRedisTemplate stringRedisTemplate) {
return new SystemRedisUtils(stringRedisTemplate);
}
}
@@ -0,0 +1,4 @@
/**
* 占位
*/
package com.cf.imes.module.system.framework.redis;
@@ -1,13 +1,11 @@
package com.cf.imes.module.system.service.dept;
import com.cf.imes.framework.common.util.collection.CollectionUtils;
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.dept.DeptDO;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@@ -63,17 +61,6 @@ public interface DeptService {
*/
List<DeptDO> getDeptList(DeptListReqVO reqVO);
/**
* 获得指定编号的部门 Map
*
* @param ids 部门编号数组
* @return 部门 Map
*/
default Map<Long, DeptDO> getDeptMap(Collection<Long> ids) {
List<DeptDO> list = getDeptList(ids);
return CollectionUtils.convertMap(list, DeptDO::getId);
}
/**
* 获得指定部门的所有子部门
*
@@ -90,15 +77,6 @@ public interface DeptService {
*/
Set<Long> getChildDeptIdListFromCache(Long id);
/**
* 校验部门们是否有效。如下情况,视为无效:
* 1. 部门编号不存在
* 2. 部门被禁用
*
* @param ids 角色编号数组
*/
void validateDeptList(Collection<Long> ids);
/**
* 校验部门是否存在且有效(包括上级)
*
@@ -106,13 +84,6 @@ public interface DeptService {
*/
void validDept(Long deptId);
/**
* 用户登陆时部门校验
*
* @param deptId
*/
void validUserLoginDept(Long deptId);
/**
* 移除没有归属(上级)的部门
*
@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.security.core.LoginUser;
@@ -14,19 +13,16 @@ import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.dept.DeptDO;
import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.cf.imes.module.system.dal.mysql.dept.DeptMapper;
import com.cf.imes.module.system.dal.redis.RedisKeyConstants;
import com.cf.imes.module.system.enums.ErrorCodeConstants;
import com.cf.imes.module.system.service.user.AdminUserService;
import com.cf.imes.module.system.util.redis.SystemRedisUtils;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@@ -36,7 +32,6 @@ import java.util.stream.Collectors;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.framework.common.util.collection.CollectionUtils.convertSet;
import static com.cf.imes.module.system.dal.redis.RedisKeyConstants.OAUTH2_ACCESS_TOKEN;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.DEPT_USER_OPER_NOT_ALLOW;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PARENT_DEPT_USER_OPER_NOT_ALLOW;
@@ -58,15 +53,12 @@ public class DeptServiceImpl implements DeptService {
private AdminUserService userService;
@Resource
private StringRedisTemplate stringRedisTemplate;
private SystemRedisUtils systemRedisUtils;
@Override
@CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存
public Long createDept(DeptSaveReqVO createReqVO) {
if (createReqVO.getParentId() == null) {
createReqVO.setParentId(DeptDO.PARENT_ID_ROOT);
}
// 校验父部门的有效性
validateParentDept(null, createReqVO.getParentId());
// 校验部门名的唯一性
@@ -83,9 +75,6 @@ public class DeptServiceImpl implements DeptService {
allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存
public void updateDept(DeptSaveReqVO updateReqVO) {
Long deptId = updateReqVO.getId();
if (updateReqVO.getParentId() == null) {
updateReqVO.setParentId(DeptDO.PARENT_ID_ROOT);
}
// 校验自己存在
validateDeptExists(deptId);
// 校验父部门的有效性
@@ -100,7 +89,7 @@ public class DeptServiceImpl implements DeptService {
deptMapper.updateById(updateObj);
if (CommonStatusEnum.DISABLE.getStatus().equals(updateReqVO.getStatus())) {
// 移除部门下用户的token
scanAndCompareDeptAndDelToken(String.format(OAUTH2_ACCESS_TOKEN, "*"), deptId);
systemRedisUtils.scanAndCompareDeptAndDelToken(deptId);
}
}
@@ -125,43 +114,15 @@ public class DeptServiceImpl implements DeptService {
// 删除关联的用户
userService.deleteDeptUsers(id);
// 移除部门下用户的token
scanAndCompareDeptAndDelToken(String.format(OAUTH2_ACCESS_TOKEN, "*"), id);
}
/**
* 轮训redis token,移除对应部门下的用户的token
*
* @param keyPattern
* @param deptId
*/
private void scanAndCompareDeptAndDelToken(String keyPattern, Long deptId) {
// 根据keyPattern scan匹配的redis key
List<String> matchKeys = new ArrayList<>();
Cursor<String> cursor = stringRedisTemplate.scan(ScanOptions.scanOptions().match(keyPattern).count(200).build());
while (cursor.hasNext()) {
matchKeys.add(cursor.next());
}
cursor.close();
if (CollUtil.isNotEmpty(matchKeys)) {
for (String key : matchKeys) {
// 获取key下的用户信息
OAuth2AccessTokenDO oAuth2AccessTokenDO = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), OAuth2AccessTokenDO.class);
if (ObjectUtil.equal(deptId, oAuth2AccessTokenDO.getDeptId())) {
// 用户id匹配上了删除redis中的token缓存
stringRedisTemplate.delete(key);
return;
}
}
}
systemRedisUtils.scanAndCompareDeptAndDelToken(id);
}
/**
* 检查是否操作当前部门
*/
private void checkCurrentWhenOperate(Long deptId) {
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
Long currentDeptId = loginUser.getDeptId();
if (ObjectUtil.isNotNull(loginUser) && ObjectUtil.equal(deptId, currentDeptId)) {
Long currentDeptId = SecurityFrameworkUtils.getUserDeptId();
if (ObjectUtil.equal(deptId, currentDeptId)) {
throw exception(DEPT_USER_OPER_NOT_ALLOW);
}
// 递归查询所有下级,如果当前用户在范围内不允许操作
@@ -260,7 +221,17 @@ public class DeptServiceImpl implements DeptService {
@Override
public List<DeptDO> getDeptList(DeptListReqVO reqVO) {
List<DeptDO> list = deptMapper.selectList(reqVO);
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
assert loginUser != null;
Boolean isSupAdmin = loginUser.getIsSupAdmin();
Long organId;
// 只有超管的情况下可以查看请求来源的组织下部门
if (isSupAdmin && !Objects.isNull(reqVO.getOrganId())) {
organId = reqVO.getOrganId();
} else {
organId = loginUser.getOrganId();
}
List<DeptDO> list = deptMapper.selectList(reqVO, organId);
list.sort(Comparator.comparing(DeptDO::getSort));
return list;
}
@@ -291,25 +262,6 @@ public class DeptServiceImpl implements DeptService {
return convertSet(children, DeptDO::getId);
}
@Override
public void validateDeptList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return;
}
// 获得科室信息
Map<Long, DeptDO> deptMap = getDeptMap(ids);
// 校验
ids.forEach(id -> {
DeptDO dept = deptMap.get(id);
if (dept == null) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.DEPT_NOT_FOUND);
}
if (!CommonStatusEnum.ENABLE.getStatus().equals(dept.getStatus())) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.DEPT_NOT_ENABLE, dept.getName());
}
});
}
@Override
public void validDept(Long deptId) {
DeptDO deptDO = deptMapper.selectById(deptId);
@@ -324,21 +276,6 @@ public class DeptServiceImpl implements DeptService {
}
// 用户登陆时部门校验,部门不存在时也可以进行登录
@Override
public void validUserLoginDept(Long deptId) {
DeptDO deptDO = deptMapper.selectById(deptId);
if (deptDO == null) {
return;
}
if (!CommonStatusEnum.ENABLE.getStatus().equals(deptDO.getStatus())) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.DEPT_NOT_ALLOWED_LOGIN, deptDO.getName());
}
// 递归校验上级部门
validParentDept(deptDO);
}
/**
* 递归校验上级部门
*
@@ -414,7 +351,6 @@ public class DeptServiceImpl implements DeptService {
currentId = currentDept.getParentId();
}
topLevelCache.put(deptDO.getId(), false);
return false; // 默认返回false
}
@@ -1,86 +0,0 @@
package com.cf.imes.module.system.service.dept;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostPageReqVO;
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.dept.PostDO;
import org.springframework.lang.Nullable;
import java.util.Collection;
import java.util.List;
/**
* 岗位 Service 接口
*
* @author 晨丰科技
*/
public interface PostService {
/**
* 创建岗位
*
* @param createReqVO 岗位信息
* @return 岗位编号
*/
Long createPost(PostSaveReqVO createReqVO);
/**
* 更新岗位
*
* @param updateReqVO 岗位信息
*/
void updatePost(PostSaveReqVO updateReqVO);
/**
* 删除岗位信息
*
* @param id 岗位编号
*/
void deletePost(Long id);
/**
* 获得岗位列表
*
* @param ids 岗位编号数组
* @return 部门列表
*/
List<PostDO> getPostList(@Nullable Collection<Long> ids);
/**
* 获得符合条件的岗位列表
*
* @param ids 岗位编号数组。如果为空,不进行筛选
* @param statuses 状态数组。如果为空,不进行筛选
* @return 部门列表
*/
List<PostDO> getPostList(@Nullable Collection<Long> ids,
@Nullable Collection<Integer> statuses,
Long organId
);
/**
* 获得岗位分页列表
*
* @param reqVO 分页条件
* @return 部门分页列表
*/
PageResult<PostDO> getPostPage(PostPageReqVO reqVO);
/**
* 获得岗位信息
*
* @param id 岗位编号
* @return 岗位信息
*/
PostDO getPost(Long id);
/**
* 校验岗位们是否有效。如下情况,视为无效:
* 1. 岗位编号不存在
* 2. 岗位被禁用
*
* @param ids 岗位编号数组
*/
void validatePostList(Collection<Long> ids);
}
@@ -1,154 +0,0 @@
package com.cf.imes.module.system.service.dept;
import cn.hutool.core.collection.CollUtil;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostPageReqVO;
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.dept.PostDO;
import com.cf.imes.module.system.dal.mysql.dept.PostMapper;
import com.cf.imes.module.system.enums.ErrorCodeConstants;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.framework.common.util.collection.CollectionUtils.convertMap;
/**
* 岗位 Service 实现类
*
* @author 晨丰科技
*/
@Service
@Validated
public class PostServiceImpl implements PostService {
@Resource
private PostMapper postMapper;
@Override
public Long createPost(PostSaveReqVO createReqVO) {
// 校验正确性
validatePostForCreateOrUpdate(null, createReqVO.getName(), createReqVO.getCode());
// 插入岗位
PostDO post = BeanUtils.toBean(createReqVO, PostDO.class);
postMapper.insert(post);
return post.getId();
}
@Override
public void updatePost(PostSaveReqVO updateReqVO) {
// 校验正确性
validatePostForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getName(), updateReqVO.getCode());
// 更新岗位
PostDO updateObj = BeanUtils.toBean(updateReqVO, PostDO.class);
postMapper.updateById(updateObj);
}
@Override
public void deletePost(Long id) {
// 校验是否存在
validatePostExists(id);
// 删除部门
postMapper.deleteById(id);
}
private void validatePostForCreateOrUpdate(Long id, String name, String code) {
// 校验自己存在
validatePostExists(id);
// 校验岗位名的唯一性
validatePostNameUnique(id, name);
// 校验岗位编码的唯一性
validatePostCodeUnique(id, code);
}
private void validatePostNameUnique(Long id, String name) {
PostDO post = postMapper.selectByName(name);
if (post == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同 id 的岗位
if (id == null) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.POST_NAME_DUPLICATE);
}
if (!post.getId().equals(id)) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.POST_NAME_DUPLICATE);
}
}
private void validatePostCodeUnique(Long id, String code) {
PostDO post = postMapper.selectByCode(code);
if (post == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同 id 的岗位
if (id == null) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.POST_CODE_DUPLICATE);
}
if (!post.getId().equals(id)) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.POST_CODE_DUPLICATE);
}
}
private void validatePostExists(Long id) {
if (id == null) {
return;
}
if (postMapper.selectById(id) == null) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.POST_NOT_FOUND);
}
}
@Override
public List<PostDO> getPostList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return postMapper.selectBatchIds(ids);
}
@Override
public List<PostDO> getPostList(Collection<Long> ids, Collection<Integer> statuses, Long organId) {
return postMapper.selectList(ids, statuses, organId);
}
@Override
public PageResult<PostDO> getPostPage(PostPageReqVO reqVO) {
return postMapper.selectPage(reqVO);
}
@Override
public PostDO getPost(Long id) {
return postMapper.selectById(id);
}
@Override
public void validatePostList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return;
}
// 获得岗位信息
List<PostDO> posts = postMapper.selectBatchIds(ids);
Map<Long, PostDO> postMap = convertMap(posts, PostDO::getId);
// 校验
ids.forEach(id -> {
PostDO post = postMap.get(id);
if (post == null) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.POST_NOT_FOUND);
}
if (!CommonStatusEnum.ENABLE.getStatus().equals(post.getStatus())) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.POST_NOT_ENABLE, post.getName());
}
});
}
}
@@ -42,7 +42,6 @@ import com.cf.imes.module.system.enums.logger.LoginLogTypeEnum;
import com.cf.imes.module.system.enums.logger.LoginResultEnum;
import com.cf.imes.module.system.enums.sms.SmsSceneEnum;
import com.cf.imes.module.system.service.dept.DeptService;
import com.cf.imes.module.system.service.dept.PostService;
import com.cf.imes.module.system.service.logger.LoginLogService;
import com.cf.imes.module.system.service.organ.OrganService;
import com.cf.imes.module.system.service.permission.PermissionService;
@@ -90,8 +89,6 @@ public class AdminUserServiceImpl implements AdminUserService {
@Resource
private DeptService deptService;
@Resource
private PostService postService;
@Resource
private PermissionService permissionService;
@Resource
private PasswordEncoder passwordEncoder;
@@ -544,8 +541,6 @@ public class AdminUserServiceImpl implements AdminUserService {
// 校验部门处于开启状态
deptService.validDept(deptId);
}
// // 校验岗位处于开启状态
// postService.validatePostList(postIds);
return adminUserDO;
}
@@ -0,0 +1,53 @@
package com.cf.imes.module.system.util.redis;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import lombok.AllArgsConstructor;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.ArrayList;
import java.util.List;
import static com.cf.imes.module.system.dal.redis.RedisKeyConstants.OAUTH2_ACCESS_TOKEN;
/**
* system 模块 redis处理工具
*
* @author Gqr
* @since 2025/9/9 17:42
*/
@AllArgsConstructor
public class SystemRedisUtils {
private StringRedisTemplate stringRedisTemplate;
/**
* 轮训redis token,移除对应部门下的用户的token
*
* @param deptId
*/
public void scanAndCompareDeptAndDelToken(Long deptId) {
// 根据keyPattern scan匹配的redis key
List<String> matchKeys = new ArrayList<>();
Cursor<String> cursor = stringRedisTemplate.scan(ScanOptions.scanOptions().match(String.format(OAUTH2_ACCESS_TOKEN, "*")).count(200).build());
while (cursor.hasNext()) {
matchKeys.add(cursor.next());
}
cursor.close();
if (CollUtil.isNotEmpty(matchKeys)) {
for (String key : matchKeys) {
// 获取key下的用户信息
OAuth2AccessTokenDO oAuth2AccessTokenDO = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), OAuth2AccessTokenDO.class);
if (ObjectUtil.equal(deptId, oAuth2AccessTokenDO.getDeptId())) {
// 用户id匹配上了删除redis中的token缓存
stringRedisTemplate.delete(key);
return;
}
}
}
}
}