feat(user): 支持用户多部门关联及主部门切换功能

- 在SysUser实体类中新增deptId字段标识主部门
- 扩展UserDTO支持多部门ID列表传递
- 重构用户部门关联逻辑,支持设置主部门
- 新增获取用户部门列表和切换主部门接口
- 优化部门查询SQL确保主部门排序优先
- 调整用户详情查询逻辑适配多部门场景
This commit is contained in:
PIGCLOUD committed 2025-11-18 09:37:43 +08:00
1 parent 16dcbef197
commit 6117c47d7c
14 files changed
+1513 -1297

No files matched your search

+2 -1
View File
@@ -1328,6 +1328,7 @@ CREATE TABLE `sys_user` (
`osc_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '开源中国标识',
`wx_cp_userid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '企业微信唯一ID',
`wx_ding_userid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '钉钉唯一ID',
`dept_id` bigint(20) DEFAULT NULL COMMENT '主部门ID',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户ID',
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户表';
@@ -1336,7 +1337,7 @@ CREATE TABLE `sys_user` (
-- Records of sys_user
-- ----------------------------
BEGIN;
INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$c/Ae0pRjJtMZg3BnvVpO.eIK6WYWVbKTzqgdy3afR7w.vd.xi3Mgy', '', '17338122125', '/admin/sys-file/local/2a14ae08150e483c93e12ac8934173e2.png', '管理员666777', '管理员', 'sw@mail.pigxl.vip', ' ', 'admin', '2018-04-20 07:15:18', '2023-04-03 14:00:06', '0', '0', NULL, '0', NULL, 'oBxPy5E-v82xWGsfzZVzkD3wEX64', NULL, 'log4j', NULL, NULL,NULL,1);
INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$c/Ae0pRjJtMZg3BnvVpO.eIK6WYWVbKTzqgdy3afR7w.vd.xi3Mgy', '', '17338122125', '/admin/sys-file/local/2a14ae08150e483c93e12ac8934173e2.png', '管理员666777', '管理员', 'sw@mail.pigxl.vip', ' ', 'admin', '2018-04-20 07:15:18', '2023-04-03 14:00:06', '0', '0', NULL, '0', NULL, 'oBxPy5E-v82xWGsfzZVzkD3wEX64', NULL, 'log4j', NULL, NULL,NULL,1,1);
COMMIT;
-- ----------------------------
@@ -22,11 +22,13 @@ import cn.hutool.core.util.StrUtil;
import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.admin.api.entity.SysRole;
import com.pig4cloud.pigx.admin.api.feign.RemoteDataScopeService;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.constant.enums.UserTypeEnum;
import com.pig4cloud.pigx.common.core.util.RetOps;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import java.util.Arrays;
import java.util.Collections;
@@ -65,7 +67,12 @@ public class PigxDefaultDataScopeHandle implements DataScopeHandle {
}
// 获取用户角色ID列表
List<Long> roleIdList = user.getRoleIds();
List<String> roleIdList = user.getAuthorities()
.stream()
.map(GrantedAuthority::getAuthority)
.filter(authority -> authority.startsWith(SecurityConstants.ROLE))
.map(authority -> authority.split(StrUtil.UNDERLINE)[1])
.toList();
if (CollUtil.isEmpty(roleIdList)) {
return false;
}
@@ -128,24 +135,20 @@ public class PigxDefaultDataScopeHandle implements DataScopeHandle {
* 处理本级及下级数据权限
*/
private void handleOwnChildLevelScope(PigxUser user, List<Long> deptList) {
for (Long deptId : user.getDeptIds()) {
List<Long> descendantDeptIds = RetOps.of(dataScopeService.getDescendantList(deptId))
.getData()
.orElseGet(Collections::emptyList)
.stream()
.map(SysDept::getDeptId)
.toList();
deptList.addAll(descendantDeptIds);
}
List<Long> descendantDeptIds = RetOps.of(dataScopeService.getDescendantList(user.getDeptId()))
.getData()
.orElseGet(Collections::emptyList)
.stream()
.map(SysDept::getDeptId)
.toList();
deptList.addAll(descendantDeptIds);
}
/**
* 处理本级数据权限
*/
private void handleOwnLevelScope(PigxUser user, List<Long> deptList) {
deptList.addAll(user.getDeptIds());
deptList.add(user.getDeptId());
}
/**
@@ -52,88 +52,91 @@ import java.util.*;
@RequiredArgsConstructor
public class PigxTocDefaultUserDetailsServiceImpl implements PigxUserDetailsService {
private final CacheManager cacheManager;
private final CacheManager cacheManager;
private final Optional<RemoteAppUserService> remoteAppUserServiceOptional;
private final Optional<RemoteAppUserService> remoteAppUserServiceOptional;
/**
* 用户密码登录
* @param username 用户密码登录
* @return
*/
@Override
@SneakyThrows
public UserDetails loadUserByUsername(String username) {
Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS_MINI);
if (Objects.nonNull(cache) && Objects.nonNull(cache.get(username))) {
AppUserInfo appUserInfo = cache.get(username, AppUserInfo.class);
return getUserDetailsAppUser(R.ok(appUserInfo));
}
/**
* 用户密码登录
*
* @param username 用户密码登录
* @return
*/
@Override
@SneakyThrows
public UserDetails loadUserByUsername(String username) {
Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS_MINI);
if (Objects.nonNull(cache) && Objects.nonNull(cache.get(username))) {
AppUserInfo appUserInfo = cache.get(username, AppUserInfo.class);
return getUserDetailsAppUser(R.ok(appUserInfo));
}
R<AppUserInfo> result = remoteAppUserServiceOptional.get().info(username);
Optional<AppUserInfo> userInfoOptional = RetOps.of(result).getData();
userInfoOptional.ifPresent(userInfo -> Objects.requireNonNull(cache).put(username, userInfo));
return getUserDetailsAppUser(result);
}
R<AppUserInfo> result = remoteAppUserServiceOptional.get().info(username);
Optional<AppUserInfo> userInfoOptional = RetOps.of(result).getData();
userInfoOptional.ifPresent(userInfo -> Objects.requireNonNull(cache).put(username, userInfo));
return getUserDetailsAppUser(result);
}
@Override
public UserDetails loadUserByUser(PigxUser pigxUser) {
return pigxUser;
}
@Override
public UserDetails loadUserByUser(PigxUser pigxUser) {
return pigxUser;
}
UserDetails getUserDetailsAppUser(R<AppUserInfo> result) {
// @formatter:off
UserDetails getUserDetailsAppUser(R<AppUserInfo> result) {
// @formatter:off
return RetOps.of(result)
.assertSuccess(r -> new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, MsgUtils.getSecurityMessage(NOTFOUND_USER_ERROR_CODE),null)))
.getData()
.map(this::convertUserDetailsAppUser)
.orElseThrow(() -> new UsernameNotFoundException(MsgUtils.getSecurityMessage(NOTFOUND_USER_ERROR_CODE)));
// @formatter:on
}
}
/**
* UserInfo 转 UserDetails
* @param info
* @return 返回UserDetails对象
*/
UserDetails convertUserDetailsAppUser(AppUserInfo info) {
Set<String> dbAuthsSet = new HashSet<>();
if (ArrayUtil.isNotEmpty(info.getRoles())) {
// 获取角色
Arrays.stream(info.getRoles()).forEach(roleId -> dbAuthsSet.add(SecurityConstants.ROLE + roleId));
// 获取资源
dbAuthsSet.addAll(Arrays.asList(info.getPermissions()));
/**
* UserInfo 转 UserDetails
*
* @param info
* @return 返回UserDetails对象
*/
UserDetails convertUserDetailsAppUser(AppUserInfo info) {
Set<String> dbAuthsSet = new HashSet<>();
if (ArrayUtil.isNotEmpty(info.getRoles())) {
// 获取角色
Arrays.stream(info.getRoles()).forEach(roleId -> dbAuthsSet.add(SecurityConstants.ROLE + roleId));
// 获取资源
dbAuthsSet.addAll(Arrays.asList(info.getPermissions()));
}
Collection<? extends GrantedAuthority> authorities = AuthorityUtils
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
AppUser user = info.getAppUser();
// 构造security用户
}
Collection<? extends GrantedAuthority> authorities = AuthorityUtils
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
AppUser user = info.getAppUser();
// 构造security用户
return new PigxUser(user.getUserId(), user.getUsername(), null, null, null, user.getPhone(), user.getAvatar(),
user.getNickname(), user.getName(), user.getEmail(), user.getTenantId(),
SecurityConstants.BCRYPT + user.getPassword(), true, true, UserTypeEnum.TOC.getStatus(), true, null,
!CommonConstants.STATUS_LOCK.equals(user.getLockFlag()), authorities);
}
return new PigxUser(user.getUserId(), user.getUsername(), null, null, null, null, user.getPhone(), user.getAvatar(),
user.getNickname(), user.getName(), user.getEmail(), user.getTenantId(),
SecurityConstants.BCRYPT + user.getPassword(), true, true, UserTypeEnum.TOC.getStatus(), true, null,
!CommonConstants.STATUS_LOCK.equals(user.getLockFlag()), authorities);
}
@Override
public int getOrder() {
return 10;
}
@Override
public int getOrder() {
return 10;
}
/**
* 支持所有的 mobile 类型
* @param clientId 目标客户端
* @param grantType 授权类型
* @return true/false
*/
@Override
public boolean support(String clientId, String grantType) {
if (Objects.isNull(WebUtils.getRequest())) {
return false;
}
String header = WebUtils.getRequest().getHeader(SecurityConstants.HEADER_TOC);
return SecurityConstants.HEADER_TOC_YES.equals(header);
}
/**
* 支持所有的 mobile 类型
*
* @param clientId 目标客户端
* @param grantType 授权类型
* @return true/false
*/
@Override
public boolean support(String clientId, String grantType) {
if (Objects.isNull(WebUtils.getRequest())) {
return false;
}
String header = WebUtils.getRequest().getHeader(SecurityConstants.HEADER_TOC);
return SecurityConstants.HEADER_TOC_YES.equals(header);
}
}
@@ -49,82 +49,85 @@ import java.util.*;
@RequiredArgsConstructor
public class PigxTocMobileUserDetailsServiceImpl implements PigxUserDetailsService {
private final Optional<RemoteAppUserService> remoteAppUserServiceOptional;
private final Optional<RemoteAppUserService> remoteAppUserServiceOptional;
/**
* 用户密码登录
* @param phone 用户密码登录
* @return
*/
@Override
@SneakyThrows
public UserDetails loadUserByUsername(String phone) {
if (!remoteAppUserServiceOptional.isPresent()) {
throw new UnsupportedOperationException();
}
R<AppUserInfo> info = remoteAppUserServiceOptional.get().social(phone);
return this.getUserDetailsAppUser(info);
}
/**
* 用户密码登录
*
* @param phone 用户密码登录
* @return
*/
@Override
@SneakyThrows
public UserDetails loadUserByUsername(String phone) {
if (!remoteAppUserServiceOptional.isPresent()) {
throw new UnsupportedOperationException();
}
R<AppUserInfo> info = remoteAppUserServiceOptional.get().social(phone);
return this.getUserDetailsAppUser(info);
}
@Override
public UserDetails loadUserByUser(PigxUser pigxUser) {
return pigxUser;
}
@Override
public UserDetails loadUserByUser(PigxUser pigxUser) {
return pigxUser;
}
UserDetails getUserDetailsAppUser(R<AppUserInfo> result) {
// @formatter:off
UserDetails getUserDetailsAppUser(R<AppUserInfo> result) {
// @formatter:off
return RetOps.of(result)
.assertSuccess(r -> new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR,MsgUtils.getSecurityMessage(NOTFOUND_USER_ERROR_CODE),null)))
.getData()
.map(this::convertUserDetailsAppUser)
.orElseThrow(() -> new UsernameNotFoundException(MsgUtils.getSecurityMessage(NOTFOUND_USER_ERROR_CODE)));
// @formatter:on
}
}
/**
* UserInfo 转 UserDetails
* @param info
* @return 返回UserDetails对象
*/
UserDetails convertUserDetailsAppUser(AppUserInfo info) {
Set<String> dbAuthsSet = new HashSet<>();
if (ArrayUtil.isNotEmpty(info.getRoles())) {
// 获取角色
Arrays.stream(info.getRoles()).forEach(roleId -> dbAuthsSet.add(SecurityConstants.ROLE + roleId));
// 获取资源
dbAuthsSet.addAll(Arrays.asList(info.getPermissions()));
/**
* UserInfo 转 UserDetails
*
* @param info
* @return 返回UserDetails对象
*/
UserDetails convertUserDetailsAppUser(AppUserInfo info) {
Set<String> dbAuthsSet = new HashSet<>();
if (ArrayUtil.isNotEmpty(info.getRoles())) {
// 获取角色
Arrays.stream(info.getRoles()).forEach(roleId -> dbAuthsSet.add(SecurityConstants.ROLE + roleId));
// 获取资源
dbAuthsSet.addAll(Arrays.asList(info.getPermissions()));
}
Collection<? extends GrantedAuthority> authorities = AuthorityUtils
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
AppUser user = info.getAppUser();
// 构造security用户
}
Collection<? extends GrantedAuthority> authorities = AuthorityUtils
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
AppUser user = info.getAppUser();
// 构造security用户
return new PigxUser(user.getUserId(), user.getUsername(), null, null, null, user.getPhone(), user.getAvatar(),
user.getNickname(), user.getName(), user.getEmail(), user.getTenantId(),
SecurityConstants.BCRYPT + user.getPassword(), true, true, UserTypeEnum.TOC.getStatus(), true, null,
!CommonConstants.STATUS_LOCK.equals(user.getLockFlag()), authorities);
}
return new PigxUser(user.getUserId(), user.getUsername(), null, null, null, null, user.getPhone(), user.getAvatar(),
user.getNickname(), user.getName(), user.getEmail(), user.getTenantId(),
SecurityConstants.BCRYPT + user.getPassword(), true, true, UserTypeEnum.TOC.getStatus(), true, null,
!CommonConstants.STATUS_LOCK.equals(user.getLockFlag()), authorities);
}
@Override
public int getOrder() {
return 15;
}
@Override
public int getOrder() {
return 15;
}
/**
* 支持所有的 mobile 类型
* @param clientId 目标客户端
* @param grantType 授权类型
* @return true/false
*/
@Override
public boolean support(String clientId, String grantType) {
if (Objects.isNull(WebUtils.getRequest())) {
return false;
}
/**
* 支持所有的 mobile 类型
*
* @param clientId 目标客户端
* @param grantType 授权类型
* @return true/false
*/
@Override
public boolean support(String clientId, String grantType) {
if (Objects.isNull(WebUtils.getRequest())) {
return false;
}
String header = WebUtils.getRequest().getHeader(SecurityConstants.HEADER_TOC);
return SecurityConstants.HEADER_TOC_YES.equals(header) && SecurityConstants.GRANT_MOBILE.equals(grantType);
}
String header = WebUtils.getRequest().getHeader(SecurityConstants.HEADER_TOC);
return SecurityConstants.HEADER_TOC_YES.equals(header) && SecurityConstants.GRANT_MOBILE.equals(grantType);
}
}
@@ -39,131 +39,146 @@ import java.util.Map;
*/
public class PigxUser extends User implements OAuth2AuthenticatedPrincipal {
@Serial
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
@Serial
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
/**
* 扩展属性,方便存放oauth 上下文相关信息
*/
private final Map<String, Object> attributes = new HashMap<>();
/**
* 扩展属性,方便存放oauth 上下文相关信息
*/
private final Map<String, Object> attributes = new HashMap<>();
/**
* 用户ID
*/
@Getter
private Long id;
/**
* 用户ID
*/
@Getter
private Long id;
/** 角色ID列表 */
@Getter
private List<Long> roleIds;
/**
* 角色ID列表
*/
@Getter
private List<Long> roleIds;
/**
* 部门ID
*/
@Getter
private List<Long> deptIds;
/**
* 主部门ID
*/
@Getter
private Long deptId;
/**
* (全部)部门ID
*/
@Getter
private List<Long> deptIds;
/** 岗位ID列表 */
@Getter
private List<Long> postIds;
/**
* 岗位ID列表
*/
@Getter
private List<Long> postIds;
/**
* 手机号
*/
@Getter
private String phone;
/**
* 手机号
*/
@Getter
private String phone;
/**
* 头像
*/
@Getter
private String avatar;
/**
* 头像
*/
@Getter
private String avatar;
/**
* 租户ID
*/
@Getter
private Long tenantId;
/**
* 租户ID
*/
@Getter
private Long tenantId;
/**
* 拓展字段:昵称
*/
@Getter
private String nickname;
/**
* 拓展字段:昵称
*/
@Getter
private String nickname;
/**
* 拓展字段:姓名
*/
@Getter
private String name;
/**
* 拓展字段:姓名
*/
@Getter
private String name;
/**
* 拓展字段:邮箱
*/
@Getter
private String email;
/**
* 拓展字段:邮箱
*/
@Getter
private String email;
/** 用户类型 */
@Getter
private String userType;
/**
* 用户类型
*/
@Getter
private String userType;
/** 密码修改时间 */
@Getter
private LocalDateTime passwordModifyTime;
/**
* 密码修改时间
*/
@Getter
private LocalDateTime passwordModifyTime;
/**
* Construct the <code>User</code> with the details required by
* {@link DaoAuthenticationProvider}.
* @param id 用户ID
* @param deptIds 部门ID
* @param tenantId 租户ID
* @param nickname 昵称
* @param name 姓名
* @param email 邮箱 the username presented to the
* <code>DaoAuthenticationProvider</code>
* @param password the password that should be presented to the
* <code>DaoAuthenticationProvider</code>
* @param enabled set to <code>true</code> if the user is enabled
* @param accountNonExpired set to <code>true</code> if the account has not expired
* @param credentialsNonExpired set to <code>true</code> if the credentials have not
* expired
* @param accountNonLocked set to <code>true</code> if the account is not locked
* @param authorities the authorities that should be granted to the caller if they
* presented the correct username and password and the user is enabled. Not null.
* @throws IllegalArgumentException if a <code>null</code> value was passed either as
* a parameter or as an element in the <code>GrantedAuthority</code> collection
*/
@JsonCreator
public PigxUser(@JsonProperty("id") Long id, @JsonProperty("username") String username,
@JsonProperty("roleIds") List<Long> roleIds, @JsonProperty("deptIds") List<Long> deptIds,
@JsonProperty("postIds") List<Long> postIds, @JsonProperty("phone") String phone,
@JsonProperty("avatar") String avatar, @JsonProperty("nickname") String nickname,
@JsonProperty("name") String name, @JsonProperty("email") String email,
@JsonProperty("tenantId") Long tenantId, @JsonProperty("password") String password,
@JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired,
@JsonProperty("userType") String userType,
@JsonProperty("credentialsNonExpired") boolean credentialsNonExpired,
@JsonProperty("passwordModifyTime") LocalDateTime passwordModifyTime,
@JsonProperty("accountNonLocked") boolean accountNonLocked,
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
this.id = id;
this.roleIds = roleIds;
this.deptIds = deptIds;
this.postIds = postIds;
this.phone = phone;
this.avatar = avatar;
this.tenantId = tenantId;
this.nickname = nickname;
this.name = name;
this.email = email;
this.userType = userType;
this.passwordModifyTime = passwordModifyTime;
}
/**
* Construct the <code>User</code> with the details required by
* {@link DaoAuthenticationProvider}.
*
* @param id 用户ID
* @param deptIds 部门ID
* @param tenantId 租户ID
* @param nickname 昵称
* @param name 姓名
* @param email 邮箱 the username presented to the
* <code>DaoAuthenticationProvider</code>
* @param password the password that should be presented to the
* <code>DaoAuthenticationProvider</code>
* @param enabled set to <code>true</code> if the user is enabled
* @param accountNonExpired set to <code>true</code> if the account has not expired
* @param credentialsNonExpired set to <code>true</code> if the credentials have not
* expired
* @param accountNonLocked set to <code>true</code> if the account is not locked
* @param authorities the authorities that should be granted to the caller if they
* presented the correct username and password and the user is enabled. Not null.
* @throws IllegalArgumentException if a <code>null</code> value was passed either as
* a parameter or as an element in the <code>GrantedAuthority</code> collection
*/
@JsonCreator
public PigxUser(@JsonProperty("id") Long id, @JsonProperty("username") String username,
@JsonProperty("roleIds") List<Long> roleIds, @JsonProperty("deptId") Long deptId, @JsonProperty("deptIds") List<Long> deptIds,
@JsonProperty("postIds") List<Long> postIds, @JsonProperty("phone") String phone,
@JsonProperty("avatar") String avatar, @JsonProperty("nickname") String nickname,
@JsonProperty("name") String name, @JsonProperty("email") String email,
@JsonProperty("tenantId") Long tenantId, @JsonProperty("password") String password,
@JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired,
@JsonProperty("userType") String userType,
@JsonProperty("credentialsNonExpired") boolean credentialsNonExpired,
@JsonProperty("passwordModifyTime") LocalDateTime passwordModifyTime,
@JsonProperty("accountNonLocked") boolean accountNonLocked,
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
this.id = id;
this.roleIds = roleIds;
this.deptId = deptId;
this.deptIds = deptIds;
this.postIds = postIds;
this.phone = phone;
this.avatar = avatar;
this.tenantId = tenantId;
this.nickname = nickname;
this.name = name;
this.email = email;
this.userType = userType;
this.passwordModifyTime = passwordModifyTime;
}
@Override
public Map<String, Object> getAttributes() {
return this.attributes;
}
@Override
public Map<String, Object> getAttributes() {
return this.attributes;
}
}
@@ -42,75 +42,81 @@ import java.util.Set;
*/
public interface PigxUserDetailsService extends UserDetailsService, Ordered {
/**
* Notfound 用户错误代码
*/
String NOTFOUND_USER_ERROR_CODE = "UserDetailsService.notFound";
/**
* Notfound 用户错误代码
*/
String NOTFOUND_USER_ERROR_CODE = "UserDetailsService.notFound";
/**
* 是否支持此客户端校验
* @param clientId 请求客户端
* @param grantType 授权类型
* @return true/false
*/
default boolean support(String clientId, String grantType) {
return true;
}
/**
* 是否支持此客户端校验
*
* @param clientId 请求客户端
* @param grantType 授权类型
* @return true/false
*/
default boolean support(String clientId, String grantType) {
return true;
}
/**
* 排序值 默认取最大的
* @return 排序值
*/
default int getOrder() {
return 0;
}
/**
* 排序值 默认取最大的
*
* @return 排序值
*/
default int getOrder() {
return 0;
}
/**
* 获取用户详细信息
* @param userInfoOptional 用户信息:可选
* @return {@link UserDetails }
*/
default UserDetails getUserDetails(Optional<UserInfo> userInfoOptional) {
// @formatter:off
/**
* 获取用户详细信息
*
* @param userInfoOptional 用户信息:可选
* @return {@link UserDetails }
*/
default UserDetails getUserDetails(Optional<UserInfo> userInfoOptional) {
// @formatter:off
return userInfoOptional
.map(this::convertUserDetails)
.orElseThrow(() -> new UsernameNotFoundException(MsgUtils.getSecurityMessage(NOTFOUND_USER_ERROR_CODE)));
// @formatter:on
}
}
/**
* UserInfo 转 UserDetails
* @param info
* @return 返回UserDetails对象
*/
default UserDetails convertUserDetails(UserInfo info) {
Set<String> dbAuthsSet = new HashSet<>();
/**
* UserInfo 转 UserDetails
*
* @param info
* @return 返回UserDetails对象
*/
default UserDetails convertUserDetails(UserInfo info) {
Set<String> dbAuthsSet = new HashSet<>();
// 维护角色列表
info.getRoleList().forEach(role -> dbAuthsSet.add(SecurityConstants.ROLE + role.getRoleId()));
// 维护角色列表
info.getRoleList().forEach(role -> dbAuthsSet.add(SecurityConstants.ROLE + role.getRoleId()));
// 维护权限列表
dbAuthsSet.addAll(info.getPermissions());
Collection<GrantedAuthority> authorities = AuthorityUtils
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
// 维护权限列表
dbAuthsSet.addAll(info.getPermissions());
Collection<GrantedAuthority> authorities = AuthorityUtils
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
return new PigxUser(info.getUserId(), info.getUsername(),
info.getRoleList().stream().map(SysRole::getRoleId).toList(),
info.getDeptList().stream().map(SysDept::getDeptId).toList(),
info.getPostList().stream().map(SysPost::getPostId).toList(), info.getPhone(), info.getAvatar(),
info.getNickname(), info.getName(), info.getEmail(), info.getTenantId(),
SecurityConstants.BCRYPT + info.getPassword(), true, true, UserTypeEnum.TOB.getStatus(),
!CommonConstants.STATUS_LOCK.equals(info.getPasswordExpireFlag()) // 密码过期判断
, info.getPasswordModifyTime(), !CommonConstants.STATUS_LOCK.equals(info.getLockFlag()), authorities);
}
return new PigxUser(info.getUserId(), info.getUsername(),
info.getRoleList().stream().map(SysRole::getRoleId).toList(),
info.getDeptId(),
info.getDeptList().stream().map(SysDept::getDeptId).toList(),
info.getPostList().stream().map(SysPost::getPostId).toList(), info.getPhone(), info.getAvatar(),
info.getNickname(), info.getName(), info.getEmail(), info.getTenantId(),
SecurityConstants.BCRYPT + info.getPassword(), true, true, UserTypeEnum.TOB.getStatus(),
!CommonConstants.STATUS_LOCK.equals(info.getPasswordExpireFlag()) // 密码过期判断
, info.getPasswordModifyTime(), !CommonConstants.STATUS_LOCK.equals(info.getLockFlag()), authorities);
}
/**
* 通过用户实体查询
* @param pigxUser user
* @return
*/
default UserDetails loadUserByUser(PigxUser pigxUser) {
return this.loadUserByUsername(pigxUser.getUsername());
}
/**
* 通过用户实体查询
*
* @param pigxUser user
* @return
*/
default UserDetails loadUserByUser(PigxUser pigxUser) {
return this.loadUserByUsername(pigxUser.getUsername());
}
}
@@ -47,6 +47,12 @@ public class UserDTO extends SysUser {
@Schema(description = "部门id")
private Long deptId;
/**
* 部门id集合(支持多部门)
*/
@Schema(description = "部门id集合")
private List<Long> deptIds;
/**
* 岗位ID
*/
@@ -150,6 +150,12 @@ public class SysUser extends Model<SysUser> implements Serializable {
@Schema(description = "用户所属租户id")
private Long tenantId;
/**
* 主部门ID
*/
@Schema(description = "用户主部门id")
private Long deptId;
/**
* 微信openid
*/
@@ -160,6 +160,12 @@ public class UserVO implements Serializable {
@Schema(description = "所属租户")
private Long tenantId;
/**
* 主部门ID
*/
@Schema(description = "主部门id")
private Long deptId;
@Schema(description = "所属部门名称")
private List<SysDept> deptList = new ArrayList<>();
@@ -24,6 +24,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.vo.UserExcelVO;
import com.pig4cloud.pigx.admin.service.SysUserService;
@@ -61,238 +62,280 @@ import java.util.List;
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysUserController {
private final SysUserService userService;
private final SysUserService userService;
/**
* 获取指定用户全部信息
* @return 用户信息
*/
@Inner
@GetMapping("/info/{username}")
public R info(@PathVariable String username) {
UserDTO userDTO = new UserDTO();
userDTO.setUsername(username);
return userService.getUserInfo(userDTO);
}
/**
* 获取指定用户全部信息
*
* @return 用户信息
*/
@Inner
@GetMapping("/info/{username}")
public R info(@PathVariable String username) {
UserDTO userDTO = new UserDTO();
userDTO.setUsername(username);
return userService.getUserInfo(userDTO);
}
/**
* 获取当前用户全部信息
* @return 用户信息
*/
@GetMapping(value = { "/info" })
public R info() {
String username = SecurityUtils.getUser().getUsername();
UserDTO userDTO = new UserDTO();
userDTO.setUsername(username);
// 获取用户信息,不返回数据库密码字段
R<UserInfo> userInfoR = userService.getUserInfo(userDTO);
if (userInfoR.getData() != null) {
userInfoR.getData().setPassword(null);
}
return userInfoR;
}
/**
* 获取当前用户全部信息
*
* @return 用户信息
*/
@GetMapping(value = {"/info"})
public R info() {
String username = SecurityUtils.getUser().getUsername();
UserDTO userDTO = new UserDTO();
userDTO.setUsername(username);
// 获取用户信息,不返回数据库密码字段
R<UserInfo> userInfoR = userService.getUserInfo(userDTO);
if (userInfoR.getData() != null) {
userInfoR.getData().setPassword(null);
}
return userInfoR;
}
/**
* 通过ID查询用户信息
* @param id ID
* @return 用户信息
*/
@GetMapping("/details/{id}")
public R user(@PathVariable Long id) {
return R.ok(userService.selectUserVoById(id));
}
/**
* 通过ID查询用户信息
*
* @param id ID
* @return 用户信息
*/
@GetMapping("/details/{id}")
public R user(@PathVariable Long id) {
return R.ok(userService.selectUserVoById(id));
}
/**
* 查询用户信息
* @param query 查询条件
* @return 不为空返回用户名
*/
@Inner(value = false)
@GetMapping("/details")
public R getDetails(@ParameterObject SysUser query) {
// 根据用户名、手机号 查询不区分租户
SysUser sysUser = TenantBroker.noneAs(() -> userService.getOne(Wrappers.query(query), false));
return R.ok(sysUser == null ? null : CommonConstants.SUCCESS);
}
/**
* 查询用户信息
*
* @param query 查询条件
* @return 不为空返回用户名
*/
@Inner(value = false)
@GetMapping("/details")
public R getDetails(@ParameterObject SysUser query) {
// 根据用户名、手机号 查询不区分租户
SysUser sysUser = TenantBroker.noneAs(() -> userService.getOne(Wrappers.query(query), false));
return R.ok(sysUser == null ? null : CommonConstants.SUCCESS);
}
/**
* 删除用户信息
* @param ids ID
* @return R
*/
@SysLog("删除用户信息")
@DeleteMapping
@HasPermission("sys_user_del")
@Operation(summary = "删除用户", description = "根据ID删除用户")
public R userDel(@RequestBody Long[] ids) {
return R.ok(userService.deleteUserByIds(ids));
}
/**
* 删除用户信息
*
* @param ids ID
* @return R
*/
@SysLog("删除用户信息")
@DeleteMapping
@HasPermission("sys_user_del")
@Operation(summary = "删除用户", description = "根据ID删除用户")
public R userDel(@RequestBody Long[] ids) {
return R.ok(userService.deleteUserByIds(ids));
}
/**
* 添加用户
* @param userDto 用户信息
* @return success/false
*/
@SysLog("添加用户")
@PostMapping
@HasPermission("sys_user_add")
public R user(@RequestBody UserDTO userDto) {
return R.ok(userService.saveUser(userDto));
}
/**
* 添加用户
*
* @param userDto 用户信息
* @return success/false
*/
@SysLog("添加用户")
@PostMapping
@HasPermission("sys_user_add")
public R user(@RequestBody UserDTO userDto) {
return R.ok(userService.saveUser(userDto));
}
/**
* 分页查询用户
* @param page 参数集
* @param userDTO 查询参数列表
* @return 用户集合
*/
@GetMapping("/page")
@HasPermission("sys_user_view")
public R getUserPage(@ParameterObject Page page, @ParameterObject UserDTO userDTO) {
return R.ok(userService.getUsersWithRolePage(page, userDTO));
}
/**
* 分页查询用户
*
* @param page 参数集
* @param userDTO 查询参数列表
* @return 用户集合
*/
@GetMapping("/page")
@HasPermission("sys_user_view")
public R getUserPage(@ParameterObject Page page, @ParameterObject UserDTO userDTO) {
return R.ok(userService.getUsersWithRolePage(page, userDTO));
}
/**
* 管理员更新用户信息
* @param userDto 用户信息
* @return R
*/
@SysLog("更新用户信息")
@PutMapping
@HasPermission("sys_user_edit")
public R updateUser(@Valid @RequestBody UserDTO userDto) {
return R.ok(userService.updateUser(userDto));
}
/**
* 管理员更新用户信息
*
* @param userDto 用户信息
* @return R
*/
@SysLog("更新用户信息")
@PutMapping
@HasPermission("sys_user_edit")
public R updateUser(@Valid @RequestBody UserDTO userDto) {
return R.ok(userService.updateUser(userDto));
}
/**
* 修改个人信息 (当前用户)
* @param userDto userDto
* @return success/false
*/
@SysLog("修改个人信息")
@PutMapping("/personal/edit")
public R updateUserInfo(@Valid @RequestBody UserDTO userDto) {
return userService.updateUserInfo(userDto);
}
/**
* 修改个人信息 (当前用户)
*
* @param userDto userDto
* @return success/false
*/
@SysLog("修改个人信息")
@PutMapping("/personal/edit")
public R updateUserInfo(@Valid @RequestBody UserDTO userDto) {
return userService.updateUserInfo(userDto);
}
/**
* 修改个人密码 (当前用户)
* @param userDto 用户DTO对象,包含需要修改密码的用户信息
* @return R 返回结果对象,包含修改密码操作的结果信息
*/
@PutMapping("/personal/password")
public R updateUserPassword(@RequestBody UserDTO userDto) {
String username = SecurityUtils.getUser().getUsername();
userDto.setUsername(username);
return userService.changePassword(userDto);
}
/**
* 修改个人密码 (当前用户)
*
* @param userDto 用户DTO对象,包含需要修改密码的用户信息
* @return R 返回结果对象,包含修改密码操作的结果信息
*/
@PutMapping("/personal/password")
public R updateUserPassword(@RequestBody UserDTO userDto) {
String username = SecurityUtils.getUser().getUsername();
userDto.setUsername(username);
return userService.changePassword(userDto);
}
/**
* @param username 用户名称
* @return 上级部门用户列表
*/
@GetMapping("/ancestor/{username}")
public R listAncestorUsers(@PathVariable String username) {
return R.ok(userService.listAncestorUsers(username));
}
/**
* @param username 用户名称
* @return 上级部门用户列表
*/
@GetMapping("/ancestor/{username}")
public R listAncestorUsers(@PathVariable String username) {
return R.ok(userService.listAncestorUsers(username));
}
/**
* 导出excel 表格
* @param userDTO 查询条件
* @return
*/
@ResponseExcel
@GetMapping("/export")
@HasPermission("sys_user_export")
public List export(UserDTO userDTO, Long[] ids) {
return userService.listUser(userDTO, ids);
}
/**
* 导出excel 表格
*
* @param userDTO 查询条件
* @return
*/
@ResponseExcel
@GetMapping("/export")
@HasPermission("sys_user_export")
public List export(UserDTO userDTO, Long[] ids) {
return userService.listUser(userDTO, ids);
}
/**
* 导入用户
* @param excelVOList 用户列表
* @param bindingResult 错误信息列表
* @return R
*/
@PostMapping("/import")
@HasPermission("sys_user_export")
public R importUser(@RequestExcel List<UserExcelVO> excelVOList, BindingResult bindingResult) {
return userService.importUser(excelVOList, bindingResult);
}
/**
* 导入用户
*
* @param excelVOList 用户列表
* @param bindingResult 错误信息列表
* @return R
*/
@PostMapping("/import")
@HasPermission("sys_user_export")
public R importUser(@RequestExcel List<UserExcelVO> excelVOList, BindingResult bindingResult) {
return userService.importUser(excelVOList, bindingResult);
}
/**
* 锁定指定用户
* @param username 用户名
* @return R
*/
@Inner
@PutMapping("/lock/{username}")
public R lockUser(@PathVariable String username) {
return userService.lockUser(username);
}
/**
* 锁定指定用户
*
* @param username 用户名
* @return R
*/
@Inner
@PutMapping("/lock/{username}")
public R lockUser(@PathVariable String username) {
return userService.lockUser(username);
}
/**
* 解绑定接口
* @param type 需要解绑定的类型
* @return R 返回结果对象,包含解绑定操作的结果信息
*/
@PostMapping("/unbinding")
public R unbinding(String type) {
return userService.unbinding(type);
}
/**
* 解绑定接口
*
* @param type 需要解绑定的类型
* @return R 返回结果对象,包含解绑定操作的结果信息
*/
@PostMapping("/unbinding")
public R unbinding(String type) {
return userService.unbinding(type);
}
/**
* 校验密码接口
* @param password 需要校验的密码
* @return R 返回结果对象,包含校验密码操作的结果信息
*/
@PostMapping("/check")
public R check(String password) {
return userService.checkPassword(SecurityUtils.getUser().getUsername(), password);
}
/**
* 校验密码接口
*
* @param password 需要校验的密码
* @return R 返回结果对象,包含校验密码操作的结果信息
*/
@PostMapping("/check")
public R check(String password) {
return userService.checkPassword(SecurityUtils.getUser().getUsername(), password);
}
/**
* 根据角色ID列表获取用户ID列表接口
* @param roleIdList 角色ID列表
* @return R 返回结果对象,包含根据角色ID列表获取到的用户ID列表信息
*/
@Inner
@GetMapping("/getUserIdListByRoleIdList")
public R<List<Long>> getUserIdListByRoleIdList(Long[] roleIdList) {
return R.ok(userService.listUserIdByRoleIds(CollUtil.toList(roleIdList)));
}
/**
* 根据角色ID列表获取用户ID列表接口
*
* @param roleIdList 角色ID列表
* @return R 返回结果对象,包含根据角色ID列表获取到的用户ID列表信息
*/
@Inner
@GetMapping("/getUserIdListByRoleIdList")
public R<List<Long>> getUserIdListByRoleIdList(Long[] roleIdList) {
return R.ok(userService.listUserIdByRoleIds(CollUtil.toList(roleIdList)));
}
/**
* 根据部门ID列表获取用户ID列表接口
* @param deptIdList 部门ID列表
* @return R 返回结果对象,包含根据部门ID列表获取到的用户ID列表信息
*/
@Inner
@GetMapping("/getUserIdListByDeptIdList")
public R<List<SysUser>> getUserIdListByDeptIdList(Long[] deptIdList) {
return R.ok(userService.listUserIdByDeptIds(CollUtil.toList(deptIdList)));
}
/**
* 根据部门ID列表获取用户ID列表接口
*
* @param deptIdList 部门ID列表
* @return R 返回结果对象,包含根据部门ID列表获取到的用户ID列表信息
*/
@Inner
@GetMapping("/getUserIdListByDeptIdList")
public R<List<SysUser>> getUserIdListByDeptIdList(Long[] deptIdList) {
return R.ok(userService.listUserIdByDeptIds(CollUtil.toList(deptIdList)));
}
/**
* 根据用户名获取用户列表
* @param username 用户名
* @return 用户列表
*/
@GetMapping("/getUserListByUserName")
public R<List<SysUser>> getUserListByUserName(String username) {
return R.ok(TenantBroker
.noneAs(() -> userService.list(Wrappers.<SysUser>lambdaQuery().like(SysUser::getUsername, username))));
}
/**
* 根据用户名获取用户列表
*
* @param username 用户名
* @return 用户列表
*/
@GetMapping("/getUserListByUserName")
public R<List<SysUser>> getUserListByUserName(String username) {
return R.ok(TenantBroker
.noneAs(() -> userService.list(Wrappers.<SysUser>lambdaQuery().like(SysUser::getUsername, username))));
}
/**
* 根据IDS获取用户列表
* @param userIds ID列表
* @return 用户列表
*/
@GetMapping("/list")
public R<List<SysUser>> getUserListByIds(@RequestParam("userIds") List<Long> userIds) {
return R.ok(TenantBroker
.noneAs(() -> userService.list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUserId, userIds))));
}
/**
* 根据IDS获取用户列表
*
* @param userIds ID列表
* @return 用户列表
*/
@GetMapping("/list")
public R<List<SysUser>> getUserListByIds(@RequestParam("userIds") List<Long> userIds) {
return R.ok(TenantBroker
.noneAs(() -> userService.list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUserId, userIds))));
}
/**
* 获取当前用户的部门列表
*
* @return 部门列表
*/
@GetMapping("/personal/dept")
@Operation(summary = "获取当前用户的部门列表", description = "返回当前登录用户所属的所有部门")
public R<List<SysDept>> getUserDeptList() {
return R.ok(userService.getUserDeptList());
}
/**
* 切换当前用户的部门
*
* @param userDTO 部门ID
* @return 操作结果
*/
@PutMapping("/personal/dept/update")
@Operation(summary = "切换当前部门", description = "切换当前用户的工作部门")
public R<Boolean> updateUserDept(@RequestBody UserDTO userDTO) {
return userService.updateUserDept(userDTO.getDeptId());
}
}
@@ -25,6 +25,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.admin.api.dto.RegisterUserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.vo.UserExcelVO;
import com.pig4cloud.pigx.admin.api.vo.UserVO;
@@ -39,142 +40,176 @@ import java.util.List;
*/
public interface SysUserService extends IService<SysUser> {
/**
* 查询用户信息
* @param userDTO 用户数据传输对象
* @return 用户信息对象
*/
R<UserInfo> getUserInfo(UserDTO userDTO);
/**
* 查询用户信息
*
* @param userDTO 用户数据传输对象
* @return 用户信息对象
*/
R<UserInfo> getUserInfo(UserDTO userDTO);
/**
* 分页查询用户信息(含有角色信息)
* @param page 分页对象
* @param userDTO 参数列表
* @return
*/
IPage getUsersWithRolePage(Page page, UserDTO userDTO);
/**
* 分页查询用户信息(含有角色信息)
*
* @param page 分页对象
* @param userDTO 参数列表
* @return
*/
IPage getUsersWithRolePage(Page page, UserDTO userDTO);
/**
* 删除用户
* @param ids 用户
* @return boolean
*/
Boolean deleteUserByIds(Long[] ids);
/**
* 删除用户
*
* @param ids 用户
* @return boolean
*/
Boolean deleteUserByIds(Long[] ids);
/**
* 更新当前用户基本信息
* @param userDto 用户信息
* @return Boolean
*/
R<Boolean> updateUserInfo(UserDTO userDto);
/**
* 更新当前用户基本信息
*
* @param userDto 用户信息
* @return Boolean
*/
R<Boolean> updateUserInfo(UserDTO userDto);
/**
* 更新指定用户信息
* @param userDto 用户信息DTO对象
* @return 更新操作是否成功
*/
Boolean updateUser(UserDTO userDto);
/**
* 更新指定用户信息
*
* @param userDto 用户信息DTO对象
* @return 更新操作是否成功
*/
Boolean updateUser(UserDTO userDto);
/**
* 通过ID查询用户信息
* @param id 用户ID
* @return 用户信息
*/
UserVO selectUserVoById(Long id);
/**
* 通过ID查询用户信息
*
* @param id 用户ID
* @return 用户信息
*/
UserVO selectUserVoById(Long id);
/**
* 查询上级部门的用户信息
* @param username 用户名
* @return R
*/
List<SysUser> listAncestorUsers(String username);
/**
* 查询上级部门的用户信息
*
* @param username 用户名
* @return R
*/
List<SysUser> listAncestorUsers(String username);
/**
* 保存用户信息
* @param userDto DTO 对象
* @return success/fail
*/
Boolean saveUser(UserDTO userDto);
/**
* 保存用户信息
*
* @param userDto DTO 对象
* @return success/fail
*/
Boolean saveUser(UserDTO userDto);
/**
* 查询全部的用户
* @param userDTO 查询条件
* @param ids 目标列表
* @return list
*/
List<UserExcelVO> listUser(UserDTO userDTO, Long[] ids);
/**
* 查询全部的用户
*
* @param userDTO 查询条件
* @param ids 目标列表
* @return list
*/
List<UserExcelVO> listUser(UserDTO userDTO, Long[] ids);
/**
* excel 导入用户
* @param excelVOList excel 列表数据
* @param bindingResult 错误数据
* @return ok fail
*/
R importUser(List<UserExcelVO> excelVOList, BindingResult bindingResult);
/**
* excel 导入用户
*
* @param excelVOList excel 列表数据
* @param bindingResult 错误数据
* @return ok fail
*/
R importUser(List<UserExcelVO> excelVOList, BindingResult bindingResult);
/**
* 注册用户
* @param userDto 用户信息
* @return success/false
*/
R<Boolean> registerUser(RegisterUserDTO userDto);
/**
* 注册用户
*
* @param userDto 用户信息
* @return success/false
*/
R<Boolean> registerUser(RegisterUserDTO userDto);
/**
* 锁定用户
* @param username 用户名
* @return R
*/
R<Boolean> lockUser(String username);
/**
* 锁定用户
*
* @param username 用户名
* @return R
*/
R<Boolean> lockUser(String username);
/**
* 修改用户密码
* @param userDto 包含用户信息的DTO对象
* @return 操作结果
*/
R changePassword(UserDTO userDto);
/**
* 修改用户密码
*
* @param userDto 包含用户信息的DTO对象
* @return 操作结果
*/
R changePassword(UserDTO userDto);
/**
* 解绑社交登录
* @param type 社交登录类型
* @return R
*/
R unbinding(String type);
/**
* 解绑社交登录
*
* @param type 社交登录类型
* @return R
*/
R unbinding(String type);
/**
* 校验密码
* @param username 用户名
* @param password 密码
* @return R
*/
R checkPassword(String username, String password);
/**
* 校验密码
*
* @param username 用户名
* @param password 密码
* @return R
*/
R checkPassword(String username, String password);
/**
* 根据角色ID列表获取用户ID列表接口
* @param roleIdList 角色ID列表
* @return List<Long> 返回结果对象,包含根据角色ID列表获取到的用户ID列表信息
*/
List<Long> listUserIdByRoleIds(List<Long> roleIdList);
/**
* 根据角色ID列表获取用户ID列表接口
*
* @param roleIdList 角色ID列表
* @return List<Long> 返回结果对象,包含根据角色ID列表获取到的用户ID列表信息
*/
List<Long> listUserIdByRoleIds(List<Long> roleIdList);
/**
* 根据部门ID列表获取用户ID列表接口
* @param deptIdList 部门ID列表
* @return List<Long> 返回结果对象,包含根据部门ID列表获取到的用户ID列表信息
*/
List<SysUser> listUserIdByDeptIds(List<Long> deptIdList);
/**
* 根据部门ID列表获取用户ID列表接口
*
* @param deptIdList 部门ID列表
* @return List<Long> 返回结果对象,包含根据部门ID列表获取到的用户ID列表信息
*/
List<SysUser> listUserIdByDeptIds(List<Long> deptIdList);
/**
* 重置用户密码
* @param userDto 用户信息DTO
* @return 操作结果,包含是否成功的布尔值
*/
R<Boolean> resetUserPassword(RegisterUserDTO userDto);
/**
* 重置用户密码
*
* @param userDto 用户信息DTO
* @return 操作结果,包含是否成功的布尔值
*/
R<Boolean> resetUserPassword(RegisterUserDTO userDto);
/**
* 找回用户密码
* @param userDto 用户信息DTO
* @param code 验证码
* @return 操作结果,包含是否成功的布尔值
*/
R<Boolean> forgetUserPassword(RegisterUserDTO userDto, String code);
/**
* 找回用户密码
*
* @param userDto 用户信息DTO
* @param code 验证码
* @return 操作结果,包含是否成功的布尔值
*/
R<Boolean> forgetUserPassword(RegisterUserDTO userDto, String code);
/**
* 获取当前用户的部门列表
*
* @return 部门列表
*/
List<SysDept> getUserDeptList();
/**
* 切换用户当前部门
*
* @param deptId 部门ID
* @return 操作结果
*/
R<Boolean> updateUserDept(Long deptId);
}
@@ -30,5 +30,6 @@
AND sys_dept.del_flag = '0'
and sys_user_dept.user_id = #{userId}
and sys_user_dept.tenant_id = #{tenantId}
ORDER BY sys_user_dept.is_primary DESC
</select>
</mapper>
@@ -26,6 +26,7 @@
<result column="password_modify_time" property="passwordModifyTime"/>
<result column="del_flag" property="delFlag"/>
<result column="tenant_id" property="tenantId"/>
<result column="dept_id" property="deptId"/>
<collection property="deptList" ofType="com.pig4cloud.pigx.admin.api.entity.SysDept"
select="com.pig4cloud.pigx.admin.mapper.SysDeptMapper.listDeptsByUserId"
column="{userId=user_id, tenantId=tenant_id}">
@@ -61,6 +62,7 @@
u.password_expire_flag,
u.password_modify_time,
u.tenant_id,
u.dept_id,
u.create_by,
u.create_time,
u.update_time
@@ -109,16 +111,18 @@
<select id="getUserVosPage" resultMap="baseResultMap">
SELECT
<include refid="userColumns"/>,
ud.dept_id
<include refid="userColumns"/>
FROM
sys_user u
LEFT JOIN sys_user_dept ud ON u.user_id = ud.user_id
AND ud.tenant_id = #{query.tenantId}
<!-- 如果传递了部门ID,需要关联 sys_user_dept 查询该部门的所有用户 -->
<if test="query.deptId != null and query.deptId != ''">
INNER JOIN sys_user_dept ud ON u.user_id = ud.user_id
AND ud.dept_id = #{query.deptId}
AND ud.tenant_id = #{query.tenantId}
</if>
WHERE
u.del_flag = '0'
AND u.tenant_id = #{query.tenantId}
AND (ud.tenant_id = #{query.tenantId} OR ud.tenant_id IS NULL)
<!-- 用户名模糊查询 -->
<if test="query.username != null and query.username != ''">
@@ -126,11 +130,6 @@
AND u.username LIKE #{usernameLike}
</if>
<!-- 部门精确查询 -->
<if test="query.deptId != null and query.deptId != ''">
AND ud.dept_id = #{query.deptId}
</if>
<!-- 手机号模糊查询 -->
<if test="query.phone != null and query.phone != ''">
<bind name="phoneLike" value="'%' + query.phone + '%'"/>
@@ -142,23 +141,23 @@
<select id="getUserVoListByScope" resultMap="baseResultMap">
SELECT
<include refid="userColumns"/>,
ud.dept_id
<include refid="userColumns"/>
FROM
sys_user u
LEFT JOIN sys_user_dept ud ON u.user_id = ud.user_id
<!-- 如果传递了部门ID,需要关联 sys_user_dept 查询该部门的所有用户 -->
<if test="query.deptId != null and query.deptId != ''">
INNER JOIN sys_user_dept ud ON u.user_id = ud.user_id
AND ud.dept_id = #{query.deptId}
AND ud.tenant_id = #{query.tenantId}
</if>
WHERE
u.del_flag = '0'
AND (ud.tenant_id = #{query.tenantId} OR ud.tenant_id IS NULL)
AND u.tenant_id = #{query.tenantId}
<!-- 用户名模糊查询 -->
<if test="query.username != null and query.username != ''">
<bind name="usernameLike" value="'%' + query.username + '%'"/>
AND u.username LIKE #{usernameLike}
</if>
<!-- 部门精确查询 -->
<if test="query.deptId != null and query.deptId != ''">
AND ud.dept_id = #{query.deptId}
</if>
<!-- 手机号模糊查询 -->
<if test="query.phone != null and query.phone != ''">
<bind name="phoneLike" value="'%' + query.phone + '%'"/>