用户完善,缺查询用户列表

This commit is contained in:
lhx
2025-11-24 18:07:53 +08:00
parent db1c07d4ac
commit 0f4bd88dc8
14 changed files with 252 additions and 36 deletions

View File

@@ -5,6 +5,7 @@ import cn.dev33.satoken.annotation.handler.SaAnnotationHandlerInterface;
import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.exception.SaTokenException; import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import com.dc.dc_project.utils.PermissionUtils;
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.util.Arrays; import java.util.Arrays;
@@ -18,56 +19,50 @@ public class CheckPermission implements SaAnnotationHandlerInterface<DcCheckPerm
@Override @Override
public void checkMethod(DcCheckPermission dcCheckPermission, AnnotatedElement annotatedElement) { public void checkMethod(DcCheckPermission dcCheckPermission, AnnotatedElement annotatedElement) {
// 获取需要校验的权限数组
String[] requiredPermissions = dcCheckPermission.value(); String[] requiredPermissions = dcCheckPermission.value();
// 如果没有配置权限,直接通过
if (requiredPermissions == null || requiredPermissions.length == 0) { if (requiredPermissions == null || requiredPermissions.length == 0) {
return; return;
} }
// 获取当前用户拥有的权限列表
List<String> userPermissions = StpUtil.getPermissionList(); List<String> userPermissions = StpUtil.getPermissionList();
userPermissions = userPermissions.stream().map(permission -> {
int index = permission.indexOf('_');
return index != -1 ? permission.substring(0, index) : permission;
}).toList();
// 如果用户没有任何权限,直接抛出异常
if (userPermissions == null || userPermissions.isEmpty()) { if (userPermissions == null || userPermissions.isEmpty()) {
throw new SaTokenException("无权限访问:" + Arrays.toString(requiredPermissions)); throw new SaTokenException("无权限访问:" + Arrays.toString(requiredPermissions));
} }
// 检查是否满足任意一个权限(支持前缀匹配) Integer maxDataScopeLevel = null;
// 遍历需要的权限
for (String requiredPermission : requiredPermissions) { for (String requiredPermission : requiredPermissions) {
if (hasPermission(userPermissions, requiredPermission)) { // 遍历用户拥有的权限
// 只要满足一个权限即可通过
return;
}
}
// 所有权限都不满足,抛出异常
throw new SaTokenException("无权限访问:" + Arrays.toString(requiredPermissions));
}
private boolean hasPermission(List<String> userPermissions, String requiredPermission) {
for (String userPermission : userPermissions) { for (String userPermission : userPermissions) {
// 1. 精确匹配:用户权限完全等于需要的权限 // 提取用户权限的纯权限码和数据级别
if (userPermission.equals(requiredPermission)) { String userPermCode = PermissionUtils.removeLevel(userPermission);
return true; Integer userDataLevel = PermissionUtils.extractLevel(userPermission);
}
// 2. 前缀匹配:用户权限是需要权限的前缀 // 1. 精确匹配
// 例如:用户有 "system",需要 "system:user",则通过 if (userPermCode.equals(requiredPermission)) {
// 例如:用户有 "system:user",需要 "system:user:list",则通过 if (maxDataScopeLevel == null || userDataLevel > maxDataScopeLevel) {
if (requiredPermission.startsWith(userPermission + ":")) { maxDataScopeLevel = userDataLevel;
return true; }
}
// 2. 前缀匹配
else if (requiredPermission.startsWith(userPermCode + ":")) {
if (maxDataScopeLevel == null || userDataLevel > maxDataScopeLevel) {
maxDataScopeLevel = userDataLevel;
}
}
} }
} }
return false; if (maxDataScopeLevel == null) {
throw new SaTokenException("无权限访问:" + Arrays.toString(requiredPermissions));
} }
// 将数据权限级别存入 ThreadLocal
PermissionUtils.set(maxDataScopeLevel);
}
} }

View File

@@ -10,9 +10,9 @@ import lombok.Getter;
@Getter @Getter
public enum DataScopeType { public enum DataScopeType {
ALL("SELF_ONLY", "仅限用户自己所属组织", 3), CUSTOM("SELF_ONLY", "仅限用户自己所属组织", 1),
SELF("SELF_AND_DESCENDANTS", "用户自己所属组织及其所有子孙组织", 2), SELF("SELF_AND_DESCENDANTS", "用户自己所属组织及其所有子孙组织", 2),
CUSTOM("ALL_COMPANY ", "全公司所有组织", 1); ALL("ALL_COMPANY ", "全公司所有组织", 3);
private final String code; private final String code;
private final String desc; private final String desc;
@@ -59,4 +59,13 @@ public enum DataScopeType {
} }
return null; return null;
} }
public static DataScopeType getByLevel(Integer level) {
for (DataScopeType value : DataScopeType.values()) {
if (value.getLevel().equals(level)) {
return value;
}
}
return null;
}
} }

View File

@@ -3,6 +3,8 @@ package com.dc.dc_project.mapper;
import com.dc.dc_project.model.pojo.Org; import com.dc.dc_project.model.pojo.Org;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
/** /**
* @author ADMIN * @author ADMIN
* @description 针对表【sys_org(组织架构表(公司/项目部/试验室))】的数据库操作Mapper * @description 针对表【sys_org(组织架构表(公司/项目部/试验室))】的数据库操作Mapper
@@ -12,6 +14,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface OrgMapper extends BaseMapper<Org> { public interface OrgMapper extends BaseMapper<Org> {
Long getOrgIdByPersonnelId(Long id); Long getOrgIdByPersonnelId(Long id);
List<Long> getCListByOrgId(Long pOrgId);
} }

View File

@@ -1,8 +1,13 @@
package com.dc.dc_project.mapper; package com.dc.dc_project.mapper;
import com.dc.dc_project.model.dto.user.LoginDto; import com.dc.dc_project.model.dto.user.LoginDto;
import com.dc.dc_project.model.dto.user.UserReqDto;
import com.dc.dc_project.model.pojo.User; import com.dc.dc_project.model.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dc.dc_project.model.vo.UserVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/** /**
* @author ADMIN * @author ADMIN
@@ -12,6 +17,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/ */
public interface UserMapper extends BaseMapper<User> { public interface UserMapper extends BaseMapper<User> {
List<UserVo> getUserListBySelf(@Param("userReqDto") UserReqDto userReqDto,@Param("pOrgId") Long pOrgId);
} }

View File

@@ -51,6 +51,12 @@ public class Personnel {
@TableField(value = "email") @TableField(value = "email")
private String email; private String email;
/**
* 性别0=男,1=女)
*/
@TableField(value = "sex")
private Integer sex;
/** /**
* 主要负责(自由文本,如 混凝土试验、材料检测) * 主要负责(自由文本,如 混凝土试验、材料检测)
*/ */

View File

@@ -1,9 +1,11 @@
package com.dc.dc_project.model.vo; package com.dc.dc_project.model.vo;
import com.dc.dc_project.model.pojo.Role;
import com.dc.dc_project.model.pojo.User; import com.dc.dc_project.model.pojo.User;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Data @Data
@@ -19,6 +21,8 @@ public class UserVo {
*/ */
private String username; private String username;
private Long personnelId;
/** /**
* 真实姓名 * 真实姓名
*/ */
@@ -27,7 +31,7 @@ public class UserVo {
/** /**
* 性别0=未知1=男2=女) * 性别0=未知1=男2=女)
*/ */
private Integer gender; private Integer sex;
/** /**
* 联系电话 * 联系电话
@@ -48,6 +52,8 @@ public class UserVo {
*/ */
private String orgName; private String orgName;
private List<Role> roles;
/** /**
* 账户状态0=停用1=启用) * 账户状态0=停用1=启用)
*/ */

View File

@@ -5,6 +5,9 @@ import com.dc.dc_project.model.dto.OrgDto;
import com.dc.dc_project.model.pojo.Org; import com.dc.dc_project.model.pojo.Org;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import java.util.Collection;
import java.util.List;
/** /**
* @author ADMIN * @author ADMIN
* @description 针对表【sys_org(组织架构表(公司/项目部/试验室))】的数据库操作Service * @description 针对表【sys_org(组织架构表(公司/项目部/试验室))】的数据库操作Service
@@ -18,4 +21,11 @@ public interface OrgService extends IService<Org> {
* @return * @return
*/ */
ResponseResult newOrg(OrgDto orgDto); ResponseResult newOrg(OrgDto orgDto);
/**
* 获取组织及子组织列表
* @param pOrgId
* @return
*/
List<Long> getCListByOrgId(Long pOrgId);
} }

View File

@@ -10,4 +10,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/ */
public interface PersonnelService extends IService<Personnel> { public interface PersonnelService extends IService<Personnel> {
/**
* 根据用户id获取人员信息
* @param userId
* @return
*/
Personnel getOneByUserId(Long userId);
} }

View File

@@ -13,6 +13,7 @@ import com.dc.dc_project.mapper.OrgMapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
@@ -61,6 +62,11 @@ public class OrgServiceImpl extends ServiceImpl<OrgMapper, Org>
} }
return ResponseResult.success("添加成功"); return ResponseResult.success("添加成功");
} }
@Override
public List<Long> getCListByOrgId(Long pOrgId) {
List< Long> cList = baseMapper.getCListByOrgId(pOrgId);
}
} }

View File

@@ -1,5 +1,6 @@
package com.dc.dc_project.service.impl; package com.dc.dc_project.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dc.dc_project.model.pojo.Personnel; import com.dc.dc_project.model.pojo.Personnel;
import com.dc.dc_project.service.PersonnelService; import com.dc.dc_project.service.PersonnelService;
@@ -17,6 +18,13 @@ import lombok.extern.slf4j.Slf4j;
public class PersonnelServiceImpl extends ServiceImpl<PersonnelMapper, Personnel> public class PersonnelServiceImpl extends ServiceImpl<PersonnelMapper, Personnel>
implements PersonnelService{ implements PersonnelService{
@Override
public Personnel getOneByUserId(Long userId) {
LambdaQueryWrapper<Personnel> queryWrapper = new LambdaQueryWrapper<Personnel>()
.eq(Personnel::getUserId, userId)
.eq(Personnel::getIsDeleted, 0);
return this.getOne(queryWrapper);
}
} }

View File

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dc.dc_project.common.ResponseResult; import com.dc.dc_project.common.ResponseResult;
import com.dc.dc_project.common.ResultCode; import com.dc.dc_project.common.ResultCode;
import com.dc.dc_project.enums.DataScopeType;
import com.dc.dc_project.mapper.*; import com.dc.dc_project.mapper.*;
import com.dc.dc_project.model.dto.user.LoginDto; import com.dc.dc_project.model.dto.user.LoginDto;
import com.dc.dc_project.model.dto.user.UserReqDto; import com.dc.dc_project.model.dto.user.UserReqDto;
@@ -12,14 +13,18 @@ import com.dc.dc_project.model.pojo.*;
import com.dc.dc_project.model.vo.PersonnelVo; import com.dc.dc_project.model.vo.PersonnelVo;
import com.dc.dc_project.model.vo.PositionVo; import com.dc.dc_project.model.vo.PositionVo;
import com.dc.dc_project.model.vo.UserInfoVo; import com.dc.dc_project.model.vo.UserInfoVo;
import com.dc.dc_project.model.vo.UserVo;
import com.dc.dc_project.service.OrgService;
import com.dc.dc_project.service.PermissionService; import com.dc.dc_project.service.PermissionService;
import com.dc.dc_project.service.PersonnelService; import com.dc.dc_project.service.PersonnelService;
import com.dc.dc_project.service.UserService; import com.dc.dc_project.service.UserService;
import com.dc.dc_project.utils.PermissionUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -42,6 +47,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
private final RoleMapper roleMapper; private final RoleMapper roleMapper;
private final PositionMapper positionMapper; private final PositionMapper positionMapper;
private final PermissionService permissionService; private final PermissionService permissionService;
private final OrgService orgService;
@Override @Override
public ResponseResult login(LoginDto loginDto) { public ResponseResult login(LoginDto loginDto) {
@@ -101,8 +107,36 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
@Override @Override
public ResponseResult UserList(UserReqDto userReqDto, Long userId) { public ResponseResult UserList(UserReqDto userReqDto, Long userId) {
int level = PermissionUtils.getOrDefault(DataScopeType.CUSTOM.getLevel());
DataScopeType dataScopeType = DataScopeType.getByLevel(level);
Personnel personnel = personnelService.getOneByUserId(userId);
Long pOrgId = orgMapper.getOrgIdByPersonnelId(personnel.getId());
List<Long> orgIds = new ArrayList<>();
List<UserVo> userVos = new ArrayList<>();
if (dataScopeType != null) {
switch (dataScopeType){
case DataScopeType.SELF:
orgIds.addAll(orgService.getCListByOrgId(pOrgId));
break;
case DataScopeType.ALL :
userVos = baseMapper.getUserListByAll(userReqDto);
break;
default:
if(userReqDto.getOrgId() != null && !userReqDto.getOrgId().equals(pOrgId)){
return ResponseResult.error(ResultCode.NO_PERMISSION);
}
userVos = baseMapper.getUserListByCustom(userReqDto, pOrgId);
}
}
else {
return ResponseResult.error(ResultCode.FAILURE);
}
userVos = baseMapper.getUserListByAll(userReqDto, orgIds);
return null; return null;

View File

@@ -0,0 +1,86 @@
package com.dc.dc_project.utils;
public class PermissionUtils {
private static final ThreadLocal<Integer> DATA_SCOPE_LEVEL = new ThreadLocal<>();
/**
* 设置当前请求的数据权限级别
*/
public static void set(Integer level) {
DATA_SCOPE_LEVEL.set(level);
}
/**
* 获取当前请求的数据权限级别
*/
public static Integer get() {
return DATA_SCOPE_LEVEL.get();
}
/**
* 获取当前请求的数据权限级别(如果没有则返回默认值 0 - 只能查看自己的数据)
*/
public static Integer getOrDefault(Integer defaultLevel) {
Integer level = DATA_SCOPE_LEVEL.get();
return level != null ? level : defaultLevel;
}
/**
* 清除当前请求的数据权限级别
*/
public static void clear() {
DATA_SCOPE_LEVEL.remove();
}
/**
* 从权限字符串中提取数据权限级别
*
* @param permission 权限字符串,如 "system:user:edit_3"
* @return 数据权限级别,如果没有后缀则返回 Integer.MAX_VALUE最高级别
*/
public static Integer extractLevel(String permission) {
if (permission == null || permission.isEmpty()) {
return Integer.MAX_VALUE;
}
int lastUnderscoreIndex = permission.lastIndexOf('_');
if (lastUnderscoreIndex > 0 && lastUnderscoreIndex < permission.length() - 1) {
String levelStr = permission.substring(lastUnderscoreIndex + 1);
try {
return Integer.parseInt(levelStr);
} catch (NumberFormatException e) {
return Integer.MAX_VALUE;
}
}
return Integer.MAX_VALUE;
}
/**
* 从权限字符串中移除数据权限级别后缀
*
* @param permission 权限字符串,如 "system:user:edit_3"
* @return 纯权限码,如 "system:user:edit"
*/
public static String removeLevel(String permission) {
if (permission == null || permission.isEmpty()) {
return permission;
}
int lastUnderscoreIndex = permission.lastIndexOf('_');
if (lastUnderscoreIndex > 0 && lastUnderscoreIndex < permission.length() - 1) {
String levelStr = permission.substring(lastUnderscoreIndex + 1);
try {
Integer.parseInt(levelStr);
return permission.substring(0, lastUnderscoreIndex);
} catch (NumberFormatException e) {
return permission;
}
}
return permission;
}
}

View File

@@ -12,4 +12,7 @@
<select id="getOrgIdByPersonnelId" resultType="java.lang.Long"> <select id="getOrgIdByPersonnelId" resultType="java.lang.Long">
select so.id from sys_org so where id == (select org_id from sys_personnel_org where personnel_id=#{personnelId}) select so.id from sys_org so where id == (select org_id from sys_personnel_org where personnel_id=#{personnelId})
</select> </select>
<select id="getCListByOrgId" resultType="java.lang.Long">
select id from sys_org where parent_id=#{orgId}
</select>
</mapper> </mapper>

View File

@@ -26,4 +26,41 @@
email,org_id,status,last_login_time,remark, email,org_id,status,last_login_time,remark,
created_at,updated_at,is_deleted created_at,updated_at,is_deleted
</sql> </sql>
<select id="getUserListBySelf" resultType="com.dc.dc_project.model.vo.UserVo">
SELECT
u.id,
u.username,
p.name as real_name,
p.sex,
u.phone,
p.email,
o.id as org_id,
u.status,
u.last_login_time,
u.remark,
p.id AS personnel_id,
o.name AS org_name
FROM sys_user u
LEFT JOIN sys_personnel_org spo ON u.id = spo.user_id
LEFT JOIN sys_org o ON spo.org_id = o.id
LEFT JOIN sys_personnel p ON u.id = p.user_id
<where>
<if test="userReqDto.name != null">
AND (p.name LIKE CONCAT('%',#{userReqDto.name},'%') OR u.username LIKE CONCAT('%',#{userReqDto.name},'%'))
</if>
<if test="userReqDto.phone != null">
AND u.phone LIKE CONCAT('%',#{userReqDto.phone},'%')
</if>
<if test="userReqDto.email != null">
AND p.email LIKE CONCAT('%',#{userReqDto.email},'%')
</if>
<if test="userReqDto.status != null">
AND u.status = #{userReqDto.status}
</if>
<if test="pOrgId != null">
AND o.id = #{pOrgId}
</if>
and u.is_deleted = 0
</where>
</select>
</mapper> </mapper>