diff --git a/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/PigxTenantConfiguration.java b/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/PigxTenantConfiguration.java
index 959ae79c8..1e1b15768 100644
--- a/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/PigxTenantConfiguration.java
+++ b/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/PigxTenantConfiguration.java
@@ -23,19 +23,29 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
/**
+ * 租户信息拦截配置类
+ *
* @author lengleng
- * @date 2020/4/29
- *
- * 租户信息拦截
+ * @date 2025/06/27
*/
@Configuration
public class PigxTenantConfiguration {
+ /**
+ * 创建并返回PigxFeignTenantInterceptor实例
+ *
+ * @return RequestInterceptor实例
+ */
@Bean
public RequestInterceptor pigxFeignTenantInterceptor() {
return new PigxFeignTenantInterceptor();
}
+ /**
+ * 创建并返回一个租户请求拦截器实例
+ *
+ * @return 配置好的租户请求拦截器
+ */
@Bean
public ClientHttpRequestInterceptor pigxTenantRequestInterceptor() {
return new TenantRequestInterceptor();
diff --git a/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantBroker.java b/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantBroker.java
index 443a6e5be..381519658 100644
--- a/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantBroker.java
+++ b/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantBroker.java
@@ -43,105 +43,148 @@ import java.util.function.Supplier;
@UtilityClass
public class TenantBroker {
- @FunctionalInterface
- public interface RunAs {
+ /**
+ * 以指定租户身份执行操作
+ *
+ * @param tenant 租户ID
+ * @param func 需要执行的操作
+ * @throws TenantBrokerExceptionWrapper 执行过程中发生异常时抛出
+ */
+ public void runAs(Long tenant, RunAs func) {
+ final Long pre = TenantContextHolder.getTenantId();
+ try {
+ log.trace("TenantBroker 切换租户{} -> {}", pre, tenant);
+ TenantContextHolder.setTenantId(tenant);
+ func.run(tenant);
+ } catch (Exception e) {
+ throw new TenantBrokerExceptionWrapper(e.getMessage(), e);
+ } finally {
+ log.trace("TenantBroker 还原租户{} <- {}", pre, tenant);
+ TenantContextHolder.setTenantId(pre);
+ }
+ }
- /**
- * 执行业务逻辑
- * @param tenantId
- * @throws Exception
- */
- void run(T tenantId) throws Exception;
+ /**
+ * 以指定租户身份执行操作
+ *
+ * @param tenant 租户ID
+ * @param func 需要执行的操作函数
+ * @param 操作返回的数据类型
+ * @return 操作函数的执行结果
+ * @throws TenantBrokerExceptionWrapper 执行过程中发生异常时抛出
+ */
+ public T applyAs(Long tenant, ApplyAs func) {
+ final Long pre = TenantContextHolder.getTenantId();
+ try {
+ log.trace("TenantBroker 切换租户{} -> {}", pre, tenant);
+ TenantContextHolder.setTenantId(tenant);
+ return func.apply(tenant);
+ } catch (Exception e) {
+ throw new TenantBrokerExceptionWrapper(e.getMessage(), e);
+ } finally {
+ log.trace("TenantBroker 还原租户{} <- {}", pre, tenant);
+ TenantContextHolder.setTenantId(pre);
+ }
+ }
- }
+ /**
+ * 以指定租户的身份执行操作
+ *
+ * @param supplier 租户ID提供者
+ * @param func 要执行的操作
+ */
+ public void runAs(Supplier supplier, RunAs func) {
+ runAs(supplier.get(), func);
+ }
- @FunctionalInterface
- public interface ApplyAs {
+ /**
+ * 执行给定的NoneAs操作,临时跳过租户上下文
+ *
+ * @param noneAs 要执行的操作
+ * @param 返回值的类型
+ * @return 操作执行结果
+ * @throws TenantBrokerExceptionWrapper 执行过程中\发生异常时抛出
+ */
+ public T noneAs(NoneAs noneAs) {
+ try {
+ TenantContextHolder.setTenantSkip();
+ return noneAs.run();
+ } catch (Exception e) {
+ throw new TenantBrokerExceptionWrapper(e.getMessage(), e);
+ } finally {
+ TenantContextHolder.unsetTenantSkip();
+ }
+ }
- /**
- * 执行业务逻辑,返回一个值
- * @param tenantId
- * @return
- * @throws Exception
- */
- R apply(T tenantId) throws Exception;
+ /**
+ * 以指定租户的身份执行操作
+ *
+ * @param supplier 租户ID提供者
+ * @param func 要执行的操作函数
+ * @param 返回数据的类型
+ * @return 操作函数的执行结果
+ */
+ public T applyAs(Supplier supplier, ApplyAs func) {
+ return applyAs(supplier.get(), func);
+ }
- }
+ @FunctionalInterface
+ public interface RunAs {
- /**
- * 以某个租户的身份运行
- * @param tenant 租户ID
- * @param func
- */
- public void runAs(Long tenant, RunAs func) {
- final Long pre = TenantContextHolder.getTenantId();
- try {
- log.trace("TenantBroker 切换租户{} -> {}", pre, tenant);
- TenantContextHolder.setTenantId(tenant);
- func.run(tenant);
- }
- catch (Exception e) {
- throw new TenantBrokerExceptionWrapper(e.getMessage(), e);
- }
- finally {
- log.trace("TenantBroker 还原租户{} <- {}", pre, tenant);
- TenantContextHolder.setTenantId(pre);
- }
- }
+ /**
+ * 执行业务逻辑
+ *
+ * @param tenantId 租户ID
+ * @throws Exception 执行过程中可能抛出的异常
+ */
+ void run(T tenantId) throws Exception;
- /**
- * 以某个租户的身份运行
- * @param tenant 租户ID
- * @param func
- * @param 返回数据类型
- * @return
- */
- public T applyAs(Long tenant, ApplyAs func) {
- final Long pre = TenantContextHolder.getTenantId();
- try {
- log.trace("TenantBroker 切换租户{} -> {}", pre, tenant);
- TenantContextHolder.setTenantId(tenant);
- return func.apply(tenant);
- }
- catch (Exception e) {
- throw new TenantBrokerExceptionWrapper(e.getMessage(), e);
- }
- finally {
- log.trace("TenantBroker 还原租户{} <- {}", pre, tenant);
- TenantContextHolder.setTenantId(pre);
- }
- }
+ }
- /**
- * 以某个租户的身份运行
- * @param supplier
- * @param func
- */
- public void runAs(Supplier supplier, RunAs func) {
- runAs(supplier.get(), func);
- }
- /**
- * 以某个租户的身份运行
- * @param supplier
- * @param func
- * @param 返回数据类型
- * @return
- */
- public T applyAs(Supplier supplier, ApplyAs func) {
- return applyAs(supplier.get(), func);
- }
+ @FunctionalInterface
+ public interface ApplyAs {
- public static class TenantBrokerExceptionWrapper extends RuntimeException {
+ /**
+ * 执行业务逻辑,返回一个值
+ *
+ * @param tenantId
+ * @return
+ * @throws Exception
+ */
+ R apply(T tenantId) throws Exception;
- public TenantBrokerExceptionWrapper(String message, Throwable cause) {
- super(message, cause);
- }
+ }
- public TenantBrokerExceptionWrapper(Throwable cause) {
- super(cause);
- }
+ /**
+ * 无参数函数式接口:用于定义无参数但有返回值的业务逻辑执行方法
+ *
+ * @author lengleng
+ * @date 2025/06/27
+ */
+ @FunctionalInterface
+ public interface NoneAs {
- }
+ /**
+ * 执行业务逻辑
+ *
+ * @return 业务执行结果
+ * @throws Exception 执行过程中发生异常时抛出
+ */
+ R run() throws Exception;
+
+ }
+
+ public static class TenantBrokerExceptionWrapper extends RuntimeException {
+
+ public TenantBrokerExceptionWrapper(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TenantBrokerExceptionWrapper(Throwable cause) {
+ super(cause);
+ }
+
+ }
}
diff --git a/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantContextHolder.java b/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantContextHolder.java
index 79b2527af..f24110f2f 100644
--- a/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantContextHolder.java
+++ b/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantContextHolder.java
@@ -48,6 +48,13 @@ public class TenantContextHolder {
THREAD_LOCAL_TENANT_SKIP_FLAG.set(Boolean.TRUE);
}
+ /**
+ * 清除当前线程的租户跳过标记
+ */
+ public void unsetTenantSkip() {
+ THREAD_LOCAL_TENANT_SKIP_FLAG.remove();
+ }
+
/**
* 获取TTL中的租户ID
* @return
diff --git a/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantRequestInterceptor.java b/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantRequestInterceptor.java
index 6832f082f..62a8de81b 100644
--- a/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantRequestInterceptor.java
+++ b/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantRequestInterceptor.java
@@ -9,13 +9,22 @@ import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;
/**
+ * RestTemplate 请求拦截器,用于传递租户ID
+ *
* @author lengleng
- * @date 2020/4/29
- *
- * 传递 RestTemplate 请求的租户ID
+ * @date 2025/06/27
*/
public class TenantRequestInterceptor implements ClientHttpRequestInterceptor {
+ /**
+ * 拦截HTTP请求,添加租户ID到请求头
+ *
+ * @param request HTTP请求对象
+ * @param body 请求体字节数组
+ * @param execution 请求执行器
+ * @return 客户端HTTP响应
+ * @throws IOException 当I/O操作失败时抛出
+ */
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxRedisOAuth2AuthorizationService.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxRedisOAuth2AuthorizationService.java
index b3b74c1cf..2d26c0205 100644
--- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxRedisOAuth2AuthorizationService.java
+++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxRedisOAuth2AuthorizationService.java
@@ -2,11 +2,11 @@ package com.pig4cloud.pigx.common.security.service;
import cn.hutool.core.collection.CollUtil;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
-import com.pig4cloud.pigx.common.core.util.KeyStrResolver;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.lang.Nullable;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
@@ -17,6 +17,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorizat
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.util.Assert;
+import java.security.Principal;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
@@ -37,8 +38,6 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
private final RedisTemplate redisTemplate;
- private final KeyStrResolver tenantKeyStrResolver;
-
private static boolean isState(OAuth2Authorization authorization) {
return Objects.nonNull(authorization.getAttribute("state"));
}
@@ -97,10 +96,14 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
.set(buildKey(OAuth2ParameterNames.ACCESS_TOKEN, accessToken.getTokenValue()), authorization, between,
TimeUnit.SECONDS);
- // 扩展记录 access-token 、username 的关系 1::token::username::admin::xxx
- String tokenUsername = String.format("%s::%s::%s::%s::%s", tenantKeyStrResolver.key(), AUTHORIZATION,
- SecurityConstants.DETAILS_USERNAME, authorization.getPrincipalName(), accessToken.getTokenValue());
- redisTemplate.opsForValue().set(tokenUsername, accessToken.getTokenValue(), between, TimeUnit.SECONDS);
+ UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = authorization.getAttribute(Principal.class.getName());
+
+ if (Objects.nonNull(usernamePasswordAuthenticationToken) && usernamePasswordAuthenticationToken.getPrincipal() instanceof PigxUser pigxUser) {
+ // 扩展记录 access-token 、username 的关系 token::username::admin::tenantId::xxx
+ String tokenUsername = String.format("%s::%s::%s::%s::%s::%s", AUTHORIZATION,
+ SecurityConstants.DETAILS_USERNAME, authorization.getPrincipalName(), authorization.getRegisteredClientId(), pigxUser.getTenantId(), accessToken.getTokenValue());
+ redisTemplate.opsForValue().set(tokenUsername, accessToken.getTokenValue(), between, TimeUnit.SECONDS);
+ }
}
}
@@ -131,8 +134,8 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
keys.add(buildKey(OAuth2ParameterNames.ACCESS_TOKEN, accessToken.getTokenValue()));
// 扩展记录 access-token 、username 的关系 1::token::username::admin::xxx
- String key = String.format("%s::%s::%s::%s::%s", tenantKeyStrResolver.key(), AUTHORIZATION,
- SecurityConstants.DETAILS_USERNAME, authorization.getPrincipalName(), accessToken.getTokenValue());
+ String key = String.format("%s::%s::%s::%s::*::%s", AUTHORIZATION,
+ SecurityConstants.DETAILS_USERNAME, authorization.getPrincipalName(), authorization.getRegisteredClientId(), accessToken.getTokenValue());
keys.add(key);
}
@@ -155,21 +158,20 @@ public class PigxRedisOAuth2AuthorizationService implements OAuth2AuthorizationS
}
private String buildKey(String type, String id) {
- return String.format("%s::%s::%s::%s", tenantKeyStrResolver.key(), AUTHORIZATION, type, id);
+ return String.format("%s::%s::%s", AUTHORIZATION, type, id);
}
/**
- * 扩展方法根据 username 查询是否存在存储的
+ * 根据用户名移除相关授权信息
*
- * @param authentication
- * @return
+ * @param authentication 认证信息,包含用户名
*/
public void removeByUsername(Authentication authentication) {
// 根据 username查询对应access-token
String authenticationName = authentication.getName();
// 扩展记录 access-token 、username 的关系 1::token::username::admin::xxx
- String tokenUsernameKey = String.format("%s::%s::%s::%s::*", tenantKeyStrResolver.key(), AUTHORIZATION,
+ String tokenUsernameKey = String.format("%s::%s::%s::*", AUTHORIZATION,
SecurityConstants.DETAILS_USERNAME, authenticationName);
Set keys = redisTemplate.keys(tokenUsernameKey);
if (CollUtil.isEmpty(keys)) {
diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxUserDetailsService.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxUserDetailsService.java
index 69f8eeeef..9f1e21951 100644
--- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxUserDetailsService.java
+++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxUserDetailsService.java
@@ -98,7 +98,7 @@ public interface PigxUserDetailsService extends UserDetailsService, Ordered {
SysUser user = info.getSysUser();
// 构造security用户
- return new PigxUser(user.getUserId(), user.getUsername(), user.getDeptId(), user.getPhone(), user.getAvatar(),
+ return new PigxUser(user.getUserId(), user.getUsername(), info.getDeptId(), user.getPhone(), user.getAvatar(),
user.getNickname(), user.getName(), user.getEmail(), user.getTenantId(),
SecurityConstants.BCRYPT + user.getPassword()
, true, true, UserTypeEnum.TOB.getStatus()
diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/dto/UserInfo.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/dto/UserInfo.java
index 42409e493..cb00fd84d 100644
--- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/dto/UserInfo.java
+++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/dto/UserInfo.java
@@ -33,22 +33,28 @@ import java.io.Serializable;
@Schema(description = "用户信息")
public class UserInfo implements Serializable {
- /**
- * 用户基本信息
- */
- @Schema(description = "用户基本信息")
- private SysUser sysUser;
+ /**
+ * 用户基本信息
+ */
+ @Schema(description = "用户基本信息")
+ private SysUser sysUser;
- /**
- * 权限标识集合
- */
- @Schema(description = "权限标识集合")
- private String[] permissions;
+ /**
+ * 权限标识集合
+ */
+ @Schema(description = "权限标识集合")
+ private String[] permissions;
- /**
- * 角色集合
- */
- @Schema(description = "角色标识集合")
- private Long[] roles;
+ /**
+ * 角色集合
+ */
+ @Schema(description = "角色标识集合")
+ private Long[] roles;
+
+ /**
+ * 部门ID
+ */
+ @Schema(description = "用户所属部门id")
+ private Long deptId;
}
diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysTenantUser.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysTenantUser.java
new file mode 100644
index 000000000..ef6559338
--- /dev/null
+++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysTenantUser.java
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.admin.api.entity;
+
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 租户用户信息实体类
+ *
+ * @author lengleng
+ * @date 2025/06/27
+ */
+@Data
+@Schema(description = "租户用户信息")
+@EqualsAndHashCode(callSuper = true)
+public class SysTenantUser extends Model {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 用户ID
+ */
+ @Schema(description = "用户id")
+ private Long userId;
+
+ /**
+ * 租户ID
+ */
+ @Schema(description = "租户ID")
+ private Long tenantId;
+
+}
diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java
index 4385c72f1..35df109eb 100644
--- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java
+++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java
@@ -146,11 +146,6 @@ public class SysUser extends Model implements Serializable {
@Schema(description = "头像地址")
private String avatar;
- /**
- * 部门ID
- */
- @Schema(description = "用户所属部门id")
- private Long deptId;
/**
* 租户ID
@@ -219,5 +214,4 @@ public class SysUser extends Model implements Serializable {
@PropertyName("邮箱")
@Schema(description = "邮箱")
private String email;
-
}
diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserDept.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserDept.java
new file mode 100644
index 000000000..225df6d73
--- /dev/null
+++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserDept.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pig4cloud.pigx.admin.api.entity;
+
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.pig4cloud.pigx.common.core.util.TenantTable;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 系统用户部门关联实体类
+ *
+ * @author lengleng
+ * @date 2025/06/27
+ */
+@Data
+@TenantTable
+@EqualsAndHashCode(callSuper = true)
+public class SysUserDept extends Model {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 用户ID
+ */
+ @Schema(description = "用户id")
+ private Long userId;
+
+ /**
+ * 岗位ID
+ */
+ @Schema(description = "岗位id")
+ private Long deptId;
+
+}
diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserPost.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserPost.java
index 0018a45ab..5f9614144 100644
--- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserPost.java
+++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserPost.java
@@ -17,21 +17,25 @@
package com.pig4cloud.pigx.admin.api.entity;
import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import java.io.Serial;
+
/**
- *
- * 用户岗位表
- *
+ * 用户岗位表实体类
*
- * @author fxz
+ * @author lengleng
+ * @date 2025/06/27
*/
@Data
+@TenantTable
@EqualsAndHashCode(callSuper = true)
public class SysUserPost extends Model {
+ @Serial
private static final long serialVersionUID = 1L;
/**
diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserRole.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserRole.java
index de5de054d..3a91c6dd6 100644
--- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserRole.java
+++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserRole.java
@@ -20,10 +20,13 @@
package com.pig4cloud.pigx.admin.api.entity;
import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import java.io.Serial;
+
/**
*
* 用户角色表
@@ -33,22 +36,31 @@ import lombok.EqualsAndHashCode;
* @since 2017-10-29
*/
@Data
+@TenantTable
@Schema(description = "用户角色")
@EqualsAndHashCode(callSuper = true)
public class SysUserRole extends Model {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * 用户ID
- */
- @Schema(description = "用户id")
- private Long userId;
+ /**
+ * 用户ID
+ */
+ @Schema(description = "用户id")
+ private Long userId;
- /**
- * 角色ID
- */
- @Schema(description = "角色id")
- private Long roleId;
+ /**
+ * 角色ID
+ */
+ @Schema(description = "角色id")
+ private Long roleId;
+
+
+ /**
+ * 租户ID
+ */
+ @Schema(description = "租户ID")
+ private Long tenantId;
}
diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserExcelVO.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserExcelVO.java
index 4c5180fb1..ccfa6fe77 100644
--- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserExcelVO.java
+++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserExcelVO.java
@@ -4,9 +4,9 @@ import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.pig4cloud.pigx.common.excel.annotation.ExcelLine;
+import jakarta.validation.constraints.NotBlank;
import lombok.Data;
-import jakarta.validation.constraints.NotBlank;
import java.io.Serializable;
import java.time.LocalDateTime;
@@ -75,7 +75,7 @@ public class UserExcelVO implements Serializable {
*/
@NotBlank(message = "部门名称不能为空")
@ExcelProperty("部门名称")
- private String deptName;
+ private String deptNameList;
/**
* 角色列表
diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserVO.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserVO.java
index e6f384e6d..91d887544 100644
--- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserVO.java
+++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserVO.java
@@ -20,6 +20,7 @@
package com.pig4cloud.pigx.admin.api.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.admin.api.entity.SysPost;
import com.pig4cloud.pigx.admin.api.entity.SysRole;
import com.pig4cloud.pigx.common.sensitive.annotation.Sensitive;
@@ -27,6 +28,7 @@ import com.pig4cloud.pigx.common.sensitive.core.SensitiveTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
+import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
@@ -39,163 +41,158 @@ import java.util.List;
@Schema(description = "前端用户展示对象")
public class UserVO implements Serializable {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * 主键ID
- */
- @Schema(description = "主键")
- private Long userId;
+ /**
+ * 主键ID
+ */
+ @Schema(description = "主键")
+ private Long userId;
- /**
- * 用户名
- */
- @Schema(description = "用户名")
- private String username;
+ /**
+ * 用户名
+ */
+ @Schema(description = "用户名")
+ private String username;
- /**
- * 密码
- */
- @JsonIgnore
- private String password;
+ /**
+ * 密码
+ */
+ @JsonIgnore
+ private String password;
- /**
- * 随机盐
- */
- @JsonIgnore
- private String salt;
+ /**
+ * 随机盐
+ */
+ @JsonIgnore
+ private String salt;
- /**
- * 微信openid
- */
- @Schema(description = "微信open id")
- private String wxOpenid;
+ /**
+ * 微信openid
+ */
+ @Schema(description = "微信open id")
+ private String wxOpenid;
- /**
- * QQ openid
- */
- @Schema(description = "qq open id")
- private String qqOpenid;
+ /**
+ * QQ openid
+ */
+ @Schema(description = "qq open id")
+ private String qqOpenid;
- /**
- * gitee openid
- */
- @Schema(description = "gitee open id")
- private String giteeOpenId;
+ /**
+ * gitee openid
+ */
+ @Schema(description = "gitee open id")
+ private String giteeOpenId;
- /**
- * 开源中国 openid
- */
- @Schema(description = "开源中国 open id")
- private String oscOpenId;
+ /**
+ * 开源中国 openid
+ */
+ @Schema(description = "开源中国 open id")
+ private String oscOpenId;
- /**
- * 企微微信 userid
- */
- @Schema(description = "企微微信 userid")
- private String wxCpUserid;
+ /**
+ * 企微微信 userid
+ */
+ @Schema(description = "企微微信 userid")
+ private String wxCpUserid;
- /**
- * 钉钉 userid
- */
- @Schema(description = "钉钉 userid")
- private String wxDingUserid;
+ /**
+ * 钉钉 userid
+ */
+ @Schema(description = "钉钉 userid")
+ private String wxDingUserid;
- /**
- * 创建时间
- */
- @Schema(description = "创建时间")
- private LocalDateTime createTime;
+ /**
+ * 创建时间
+ */
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
- /**
- * 修改时间
- */
- @Schema(description = "修改时间")
- private LocalDateTime updateTime;
+ /**
+ * 修改时间
+ */
+ @Schema(description = "修改时间")
+ private LocalDateTime updateTime;
- /**
- * 0-正常,1-删除
- */
- @Schema(description = "删除标记,1:已删除,0:正常")
- private String delFlag;
+ /**
+ * 0-正常,1-删除
+ */
+ @Schema(description = "删除标记,1:已删除,0:正常")
+ private String delFlag;
- /**
- * 锁定标记
- */
- @Schema(description = "锁定标记,0:正常,9:已锁定")
- private String lockFlag;
+ /**
+ * 锁定标记
+ */
+ @Schema(description = "锁定标记,0:正常,9:已锁定")
+ private String lockFlag;
- /**
- * 密码过期标记
- */
- @Schema(description = "密码过期标记")
- private String passwordExpireFlag;
+ /**
+ * 密码过期标记
+ */
+ @Schema(description = "密码过期标记")
+ private String passwordExpireFlag;
- /**
- * 密码修改时间
- */
- @Schema(description = "密码修改时间")
- private LocalDateTime passwordModifyTime;
+ /**
+ * 密码修改时间
+ */
+ @Schema(description = "密码修改时间")
+ private LocalDateTime passwordModifyTime;
- /**
- * 手机号
- */
- @Sensitive(type = SensitiveTypeEnum.MOBILE_PHONE)
- @Schema(description = "手机号")
- private String phone;
+ /**
+ * 手机号
+ */
+ @Sensitive(type = SensitiveTypeEnum.MOBILE_PHONE)
+ @Schema(description = "手机号")
+ private String phone;
- /**
- * 头像
- */
- @Schema(description = "头像")
- private String avatar;
+ /**
+ * 头像
+ */
+ @Schema(description = "头像")
+ private String avatar;
- /**
- * 部门ID
- */
- @Schema(description = "所属部门")
- private Long deptId;
- /**
- * 租户ID
- */
- @Schema(description = "所属租户")
- private Long tenantId;
+ /**
+ * 租户ID
+ */
+ @Schema(description = "所属租户")
+ private Long tenantId;
- /**
- * 部门名称
- */
- @Schema(description = "所属部门名称")
- private String deptName;
- /**
- * 角色列表
- */
- @Schema(description = "拥有的角色列表")
- private List roleList;
+ @Schema(description = "所属部门名称")
+ private List deptList;
- /**
- * 岗位列表
- */
- private List postList;
+ /**
+ * 角色列表
+ */
+ @Schema(description = "拥有的角色列表")
+ private List roleList;
- /**
- * 昵称
- */
- @Schema(description = "昵称")
- private String nickname;
+ /**
+ * 岗位列表
+ */
+ @Schema(description = "拥有的岗位列表")
+ private List postList;
- /**
- * 姓名
- */
- @Schema(description = "姓名")
- private String name;
+ /**
+ * 昵称
+ */
+ @Schema(description = "昵称")
+ private String nickname;
- /**
- * 邮箱
- */
- @Schema(description = "邮箱")
- private String email;
+ /**
+ * 姓名
+ */
+ @Schema(description = "姓名")
+ private String name;
+
+ /**
+ * 邮箱
+ */
+ @Schema(description = "邮箱")
+ private String email;
}
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysTenantController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysTenantController.java
index 98ccb3dfc..6a593e4f6 100755
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysTenantController.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysTenantController.java
@@ -59,118 +59,143 @@ import java.util.List;
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysTenantController {
- private final SysTenantService sysTenantService;
+ private final SysTenantService sysTenantService;
- private final SysMenuService sysMenuService;
+ private final SysMenuService sysMenuService;
- /**
- * 分页查询
- * @param page 分页对象
- * @param sysTenant 租户
- * @return
- */
- @GetMapping("/page")
- public R getSysTenantPage(@ParameterObject Page page, @ParameterObject SysTenant sysTenant) {
- return R.ok(sysTenantService.page(page, Wrappers.lambdaQuery()
- .like(StrUtil.isNotBlank(sysTenant.getName()), SysTenant::getName, sysTenant.getName())));
- }
+ /**
+ * 分页查询
+ *
+ * @param page 分页对象
+ * @param sysTenant 租户
+ * @return
+ */
+ @GetMapping("/page")
+ public R getSysTenantPage(@ParameterObject Page page, @ParameterObject SysTenant sysTenant) {
+ return R.ok(sysTenantService.page(page, Wrappers.lambdaQuery()
+ .like(StrUtil.isNotBlank(sysTenant.getName()), SysTenant::getName, sysTenant.getName())));
+ }
- /**
- * 通过ID 查询租户信息
- * @param id ID
- * @return R
- */
- @GetMapping("/details/{id}")
- public R getById(@PathVariable Long id) {
- return R.ok(sysTenantService.getById(id));
- }
+ /**
+ * 通过ID 查询租户信息
+ *
+ * @param id ID
+ * @return R
+ */
+ @GetMapping("/details/{id}")
+ public R getById(@PathVariable Long id) {
+ return R.ok(sysTenantService.getById(id));
+ }
- /**
- * 查询租户信息
- * @param query 查询条件
- * @return 租户信息
- */
- @GetMapping("/details")
- public R getDetails(@ParameterObject SysTenant query) {
- return R.ok(sysTenantService.getOne(Wrappers.query(query), false));
- }
+ /**
+ * 查询租户信息
+ *
+ * @param query 查询条件
+ * @return 租户信息
+ */
+ @GetMapping("/details")
+ public R getDetails(@ParameterObject SysTenant query) {
+ return R.ok(sysTenantService.getOne(Wrappers.query(query), false));
+ }
- /**
- * 新增租户
- * @param sysTenant 租户
- * @return R
- */
- @SysLog("新增租户")
- @PostMapping
- @HasPermission("sys_systenant_add")
- @CacheEvict(value = CacheConstants.TENANT_DETAILS, allEntries = true)
- public R save(@RequestBody SysTenant sysTenant) {
- return R.ok(sysTenantService.saveTenant(sysTenant));
- }
+ /**
+ * 新增租户
+ *
+ * @param sysTenant 租户
+ * @return R
+ */
+ @SysLog("新增租户")
+ @PostMapping
+ @HasPermission("sys_systenant_add")
+ @CacheEvict(value = CacheConstants.TENANT_DETAILS, allEntries = true)
+ public R save(@RequestBody SysTenant sysTenant) {
+ return R.ok(sysTenantService.saveTenant(sysTenant));
+ }
- /**
- * 修改租户
- * @param sysTenant 租户
- * @return R
- */
- @SysLog("修改租户")
- @PutMapping
- @HasPermission("sys_systenant_edit")
- public R updateById(@RequestBody SysTenant sysTenant) {
- return R.ok(sysTenantService.updateTenant(sysTenant));
- }
+ /**
+ * 修改租户
+ *
+ * @param sysTenant 租户
+ * @return R
+ */
+ @SysLog("修改租户")
+ @PutMapping
+ @HasPermission("sys_systenant_edit")
+ public R updateById(@RequestBody SysTenant sysTenant) {
+ return R.ok(sysTenantService.updateTenant(sysTenant));
+ }
- /**
- * 通过id删除租户
- *
- * 为了保证安全,这里只删除租户表的数据,不删除基础表中的租户初始化数据。
- * @param ids id 列表
- * @return R
- */
- @SysLog("删除租户")
- @DeleteMapping
- @HasPermission("sys_systenant_del")
- @CacheEvict(value = CacheConstants.TENANT_DETAILS, allEntries = true)
- public R removeById(@RequestBody Long[] ids) {
- return R.ok(sysTenantService.removeBatchByIds(CollUtil.toList(ids)));
- }
+ /**
+ * 通过id删除租户
+ *
+ * 为了保证安全,这里只删除租户表的数据,不删除基础表中的租户初始化数据。
+ *
+ * @param ids id 列表
+ * @return R
+ */
+ @SysLog("删除租户")
+ @DeleteMapping
+ @HasPermission("sys_systenant_del")
+ @CacheEvict(value = CacheConstants.TENANT_DETAILS, allEntries = true)
+ public R removeById(@RequestBody Long[] ids) {
+ return R.ok(sysTenantService.removeBatchByIds(CollUtil.toList(ids)));
+ }
- /**
- * 查询全部有效的租户
- * @return
- */
- @Inner(value = false)
- @GetMapping("/list")
- public R list() {
- List tenants = sysTenantService.getNormalTenant()
- .stream()
- .filter(tenant -> tenant.getStartTime().isBefore(LocalDateTime.now()))
- .filter(tenant -> tenant.getEndTime().isAfter(LocalDateTime.now()))
+ /**
+ * 查询全部有效的租户列表
+ *
+ * @return 包含有效租户列表的响应结果
+ */
+ @Inner(value = false)
+ @GetMapping("/list")
+ public R list() {
+ List tenants = sysTenantService.getNormalTenant()
+ .stream()
+ .filter(tenant -> tenant.getStartTime().isBefore(LocalDateTime.now()))
+ .filter(tenant -> tenant.getEndTime().isAfter(LocalDateTime.now()))
.toList();
- return R.ok(tenants);
- }
+ return R.ok(tenants);
+ }
- /**
- * 导出excel 表格
- * @return
- */
- @ResponseExcel
- @GetMapping("/export")
- @HasPermission("sys_systenant_export")
- public List export(SysTenant sysTenant, Long[] ids) {
- return sysTenantService
- .list(Wrappers.lambdaQuery(sysTenant).in(ArrayUtil.isNotEmpty(ids), SysTenant::getId, CollUtil.toList(ids)));
- }
+ /**
+ * 导出租户信息到Excel
+ *
+ * @param sysTenant 租户查询条件
+ * @param ids 租户ID数组
+ * @return 符合条件的租户列表
+ */
+ @ResponseExcel
+ @GetMapping("/export")
+ @HasPermission("sys_systenant_export")
+ public List export(SysTenant sysTenant, Long[] ids) {
+ return sysTenantService
+ .list(Wrappers.lambdaQuery(sysTenant).in(ArrayUtil.isNotEmpty(ids), SysTenant::getId, CollUtil.toList(ids)));
+ }
- @GetMapping(value = "/tree/menu")
- public R getTree() {
- Long defaultId = ParamResolver.getLong("TENANT_DEFAULT_ID", 1L);
- List> trees = new ArrayList<>();
- TenantBroker.runAs(defaultId, (id) -> {
- trees.addAll(sysMenuService.treeMenu(null, null, null));
- });
+ /**
+ * 获取租户菜单
+ *
+ * @return 包含菜单树结构的响应结果
+ */
+ @GetMapping(value = "/tree/menu")
+ public R getTree() {
+ Long defaultId = ParamResolver.getLong("TENANT_DEFAULT_ID", 1L);
+ List> trees = new ArrayList<>();
+ TenantBroker.runAs(defaultId, (id) -> {
+ trees.addAll(sysMenuService.treeMenu(null, null, null));
+ });
- return R.ok(trees);
- }
+ return R.ok(trees);
+ }
+
+ /**
+ * 获取用户租户信息
+ *
+ * @return 包含用户租户信息的响应结果
+ */
+ @GetMapping("/user-tenant")
+ public R getUserTenant() {
+ return R.ok(sysTenantService.getUserTenant());
+ }
}
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysUserController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysUserController.java
index 46c2d194a..47fc193e7 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysUserController.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysUserController.java
@@ -31,6 +31,7 @@ import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
+import com.pig4cloud.pigx.common.data.tenant.TenantBroker;
import com.pig4cloud.pigx.common.excel.annotation.RequestExcel;
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
@@ -50,8 +51,10 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
+ * 用户管理控制器:提供用户相关的REST接口
+ *
* @author lengleng
- * @date 2018/12/16
+ * @date 2025/07/04
*/
@RestController
@AllArgsConstructor
@@ -70,11 +73,12 @@ public class SysUserController {
@Inner
@GetMapping("/info/{username}")
public R info(@PathVariable String username) {
- SysUser user = userService.getOne(Wrappers.query().lambda().eq(SysUser::getUsername, username));
+ SysUser user = TenantBroker.noneAs(() -> userService.getOne(Wrappers.query().lambda().eq(SysUser::getUsername, username), false));
if (user == null) {
return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERINFO_EMPTY, username));
}
- return R.ok(userService.findUserInfo(user));
+
+ return TenantBroker.applyAs(user.getTenantId(), tenantId -> R.ok(userService.findUserInfo(user)));
}
/**
@@ -85,15 +89,18 @@ public class SysUserController {
@GetMapping(value = {"/info"})
public R info() {
String username = SecurityUtils.getUser().getUsername();
- SysUser user = userService.getOne(Wrappers.query().lambda().eq(SysUser::getUsername, username));
+ SysUser user = TenantBroker.noneAs(() -> userService.getOne(Wrappers.query().lambda().eq(SysUser::getUsername, username), false));
if (user == null) {
return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_QUERY_ERROR));
}
- // UserInfo 是复用对象,不能通过设置 @jsonIgnore 来忽略密码字段
- UserInfo userInfo = userService.findUserInfo(user);
- userInfo.getSysUser().setPassword(null);
- return R.ok(userInfo);
+
+ return TenantBroker.applyAs(user.getTenantId(), tenantId -> {
+ // UserInfo 是复用对象,不能通过设置 @jsonIgnore 来忽略密码字段
+ UserInfo userInfo = userService.findUserInfo(user);
+ userInfo.getSysUser().setPassword(null);
+ return R.ok(userInfo);
+ });
}
/**
@@ -191,12 +198,27 @@ public class SysUserController {
* @return R 返回结果对象,包含修改密码操作的结果信息
*/
@PutMapping("/personal/password")
- public R updatePassword(@RequestBody UserDTO userDto) {
+ public R updateUserPassword(@RequestBody UserDTO userDto) {
String username = SecurityUtils.getUser().getUsername();
userDto.setUsername(username);
return userService.changePassword(userDto);
}
+ /**
+ * 更新用户租户信息
+ *
+ * @param userDto 用户数据传输对象,包含需要更新的用户信息
+ * @return 操作结果
+ */
+ @PutMapping("/personal/tenant")
+ public R updateUserTenant(@RequestBody UserDTO userDto) {
+ String username = SecurityUtils.getUser().getUsername();
+ userDto.setUsername(username);
+ userDto.setUserId(SecurityUtils.getUser().getId());
+ return userService.updateUserTenant(userDto);
+ }
+
+
/**
* @param username 用户名称
* @return 上级部门用户列表
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysDeptMapper.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysDeptMapper.java
index e50fb1848..249b4a45e 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysDeptMapper.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysDeptMapper.java
@@ -19,19 +19,31 @@
package com.pig4cloud.pigx.admin.mapper;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
/**
- *
* 部门管理 Mapper 接口
- *
*
* @author lengleng
- * @since 2018-01-20
+ * @date 2025/06/27
*/
@Mapper
public interface SysDeptMapper extends PigxBaseMapper {
+ /**
+ * 根据用户ID和租户ID查询部门列表
+ *
+ * @param userId 用户ID
+ * @param tenantId 租户ID
+ * @return 部门列表
+ */
+ @InterceptorIgnore(tenantLine = "true")
+ List listDeptsByUserId(@Param("userId") Long userId, @Param("tenantId") Long tenantId);
+
}
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysPostMapper.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysPostMapper.java
index bd289ea09..08552c1c8 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysPostMapper.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysPostMapper.java
@@ -17,9 +17,11 @@
package com.pig4cloud.pigx.admin.mapper;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.pig4cloud.pigx.admin.api.entity.SysPost;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -32,11 +34,14 @@ import java.util.List;
@Mapper
public interface SysPostMapper extends PigxBaseMapper {
- /**
- * 通过用户ID,查询岗位信息
- * @param userId 用户id
- * @return 岗位信息
- */
- List listPostsByUserId(Long userId);
+ /**
+ * 通过用户ID和租户ID查询岗位信息
+ *
+ * @param userId 用户ID
+ * @param tenantId 租户ID
+ * @return 岗位信息列表
+ */
+ @InterceptorIgnore(tenantLine = "true")
+ List listPostsByUserId(@Param("userId") Long userId, @Param("tenantId") Long tenantId);
}
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysRoleMapper.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysRoleMapper.java
index 7752f8b6e..97467348f 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysRoleMapper.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysRoleMapper.java
@@ -19,9 +19,11 @@
package com.pig4cloud.pigx.admin.mapper;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.pig4cloud.pigx.admin.api.entity.SysRole;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -36,11 +38,14 @@ import java.util.List;
@Mapper
public interface SysRoleMapper extends PigxBaseMapper {
- /**
- * 通过用户ID,查询角色信息
- * @param userId
- * @return
- */
- List listRolesByUserId(Long userId);
+ /**
+ * 通过用户ID查询角色信息
+ *
+ * @param userId 用户ID
+ * @param tenantId 租户ID
+ * @return 角色信息列表
+ */
+ @InterceptorIgnore(tenantLine = "true")
+ List listRolesByUserId(@Param("userId") Long userId, @Param("tenantId") Long tenantId);
}
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysTenantUserMapper.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysTenantUserMapper.java
new file mode 100644
index 000000000..a72c1190c
--- /dev/null
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysTenantUserMapper.java
@@ -0,0 +1,36 @@
+/*
+ *
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ *
+ */
+
+package com.pig4cloud.pigx.admin.mapper;
+
+import com.pig4cloud.pigx.admin.api.entity.SysTenantUser;
+import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+
+/**
+ * 系统租户用户映射接口
+ *
+ * @author lengleng
+ * @date 2025/06/27
+ */
+@Mapper
+public interface SysTenantUserMapper extends PigxBaseMapper {
+
+}
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysUserDeptMapper.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysUserDeptMapper.java
new file mode 100644
index 000000000..ae60f3dab
--- /dev/null
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysUserDeptMapper.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.pig4cloud.pigx.admin.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pig4cloud.pigx.admin.api.entity.SysUserDept;
+import org.apache.ibatis.annotations.Mapper;
+
+
+/**
+ * 系统用户部门关联Mapper接口
+ *
+ * @author lengleng
+ * @date 2025/06/27
+ */
+@Mapper
+public interface SysUserDeptMapper extends BaseMapper {
+
+}
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysTenantService.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysTenantService.java
index f5aa7aae1..104ca8c85 100755
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysTenantService.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysTenantService.java
@@ -31,23 +31,32 @@ import java.util.List;
public interface SysTenantService extends IService {
/**
- * 获取正常的租户
- * @return
+ * 获取正常的租户列表
+ *
+ * @return 正常的租户列表
*/
List getNormalTenant();
/**
- * 保存租户
- * @param sysTenant
- * @return
+ * 保存租户信息
+ *
+ * @param sysTenant 租户信息对象
+ * @return 保存是否成功
*/
Boolean saveTenant(SysTenant sysTenant);
/**
- * 修改租户
- * @param sysTenant
- * @return
+ * 修改租户信息
+ *
+ * @param sysTenant 租户信息对象
+ * @return 修改是否成功
*/
Boolean updateTenant(SysTenant sysTenant);
+ /**
+ * 获取用户所属租户列表
+ *
+ * @return 用户所属租户列表
+ */
+ List getUserTenant();
}
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java
index 576c16819..4cbe743b1 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java
@@ -195,4 +195,12 @@ public interface SysUserService extends IService {
* @return
*/
R forgetUserPassword(RegisterUserDTO userDto, String code);
+
+ /**
+ * 更新用户租户信息
+ *
+ * @param userDto 用户数据传输对象
+ * @return 更新结果
+ */
+ R updateUserTenant(UserDTO userDto);
}
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysDeptServiceImpl.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysDeptServiceImpl.java
index 52945be30..aeca0ab8c 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysDeptServiceImpl.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysDeptServiceImpl.java
@@ -27,6 +27,7 @@ import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.pig4cloud.pigx.admin.api.constant.OrgTypeEnum;
import com.pig4cloud.pigx.admin.api.constant.PostCodeEnum;
import com.pig4cloud.pigx.admin.api.entity.*;
@@ -66,10 +67,13 @@ public class SysDeptServiceImpl extends ServiceImpl impl
private final SysRoleMapper roleMapper;
+ private final SysUserDeptMapper userDeptMapper;
+
private final SysUserPostMapper userPostMapper;
/**
* 删除部门
+ *
* @param id 部门 ID
* @return 成功、失败
*/
@@ -86,6 +90,7 @@ public class SysDeptServiceImpl extends ServiceImpl impl
/**
* 查询全部部门树
+ *
* @param deptName
* @param parentId
* @return 树 部门名称
@@ -94,33 +99,33 @@ public class SysDeptServiceImpl extends ServiceImpl impl
public List> selectTree(String deptName, Long parentId) {
// 查询全部部门
List deptAllList = deptMapper
- .selectList(Wrappers.lambdaQuery().like(StrUtil.isNotBlank(deptName), SysDept::getName, deptName));
+ .selectList(Wrappers.lambdaQuery().like(StrUtil.isNotBlank(deptName), SysDept::getName, deptName));
// 查询数据权限内部门
List deptOwnIdList = deptMapper
- .selectListByScope(
- Wrappers.lambdaQuery().like(StrUtil.isNotBlank(deptName), SysDept::getName, deptName),
- DataScope.of())
- .stream()
- .map(SysDept::getDeptId)
- .toList();
+ .selectListByScope(
+ Wrappers.lambdaQuery().like(StrUtil.isNotBlank(deptName), SysDept::getName, deptName),
+ DataScope.of())
+ .stream()
+ .map(SysDept::getDeptId)
+ .toList();
// 权限内部门
List> collect = deptAllList.stream()
- .filter(dept -> dept.getDeptId().intValue() != dept.getParentId())
- .sorted(Comparator.comparingInt(SysDept::getSortOrder))
- .map(dept -> {
- TreeNode treeNode = new TreeNode<>();
- treeNode.setId(dept.getDeptId());
- treeNode.setParentId(dept.getParentId());
- treeNode.setName(dept.getName());
- treeNode.setWeight(dept.getSortOrder());
- // 有权限不返回标识
- Map extra = new HashMap<>(8);
- extra.put("isLock", !deptOwnIdList.contains(dept.getDeptId()));
- extra.put("createTime", dept.getCreateTime());
- treeNode.setExtra(extra);
- return treeNode;
- })
+ .filter(dept -> dept.getDeptId().intValue() != dept.getParentId())
+ .sorted(Comparator.comparingInt(SysDept::getSortOrder))
+ .map(dept -> {
+ TreeNode treeNode = new TreeNode<>();
+ treeNode.setId(dept.getDeptId());
+ treeNode.setParentId(dept.getParentId());
+ treeNode.setName(dept.getName());
+ treeNode.setWeight(dept.getSortOrder());
+ // 有权限不返回标识
+ Map extra = new HashMap<>(8);
+ extra.put("isLock", !deptOwnIdList.contains(dept.getDeptId()));
+ extra.put("createTime", dept.getCreateTime());
+ treeNode.setExtra(extra);
+ return treeNode;
+ })
.toList();
// 模糊查询 不组装树结构 直接返回 表格方便编辑
@@ -138,6 +143,7 @@ public class SysDeptServiceImpl extends ServiceImpl impl
/**
* 导出部门
+ *
* @return
*/
@Override
@@ -147,10 +153,10 @@ public class SysDeptServiceImpl extends ServiceImpl impl
DeptExcelVO deptExcelVo = new DeptExcelVO();
deptExcelVo.setName(item.getName());
Optional first = this.list()
- .stream()
- .filter(it -> item.getParentId().equals(it.getDeptId()))
- .map(SysDept::getName)
- .findFirst();
+ .stream()
+ .filter(it -> item.getParentId().equals(it.getDeptId()))
+ .map(SysDept::getName)
+ .findFirst();
deptExcelVo.setParentName(first.orElse("根部门"));
deptExcelVo.setSortOrder(item.getSortOrder());
return deptExcelVo;
@@ -183,8 +189,7 @@ public class SysDeptServiceImpl extends ServiceImpl impl
sysDept.setParentId(one.getDeptId());
sysDept.setSortOrder(item.getSortOrder());
baseMapper.insert(sysDept);
- }
- else {
+ } else {
// 数据不合法情况
errorMessageList.add(new ErrorMessage(item.getLineNum(), errorMsg));
}
@@ -197,6 +202,7 @@ public class SysDeptServiceImpl extends ServiceImpl impl
/**
* 查询所有子节点 (包含当前节点)
+ *
* @param deptId 部门ID 目标部门ID
* @return ID
*/
@@ -216,37 +222,39 @@ public class SysDeptServiceImpl extends ServiceImpl impl
/**
* 获取部门负责人
- *
+ *
* 1. 根据dept 查询用户 2. 筛选用户列表中 post
+ *
* @param deptId deptId
* @return user id list
*/
@Override
public List listDeptLeader(Long deptId) {
- List sysUserList = userMapper
- .selectList(Wrappers.lambdaQuery().eq(SysUser::getDeptId, deptId));
- if (CollUtil.isEmpty(sysUserList)) {
+
+ List userDeptList = userDeptMapper.selectList(Wrappers.lambdaQuery().eq(SysUserDept::getDeptId, deptId));
+ if (CollUtil.isEmpty(userDeptList)) {
return null;
}
SysPost deptLeader = postMapper
- .selectOne(Wrappers.lambdaQuery().eq(SysPost::getPostCode, PostCodeEnum.TEAM_LEADER.getCode()));
+ .selectOne(Wrappers.lambdaQuery().eq(SysPost::getPostCode, PostCodeEnum.TEAM_LEADER.getCode()));
if (deptLeader == null) {
return null;
}
- List userIdList = sysUserList.stream().map(SysUser::getUserId).toList();
+ List userIdList = userDeptList.stream().map(SysUserDept::getUserId).toList();
return userPostMapper.selectList(Wrappers.lambdaQuery().in(SysUserPost::getUserId, userIdList))
- .stream()
- .filter(post -> Objects.equals(post.getPostId(), deptLeader.getPostId()))
- .map(SysUserPost::getUserId)
- .toList();
+ .stream()
+ .filter(post -> Objects.equals(post.getPostId(), deptLeader.getPostId()))
+ .map(SysUserPost::getUserId)
+ .toList();
}
/**
* 根据父部门ID和类型获取组织树
+ *
* @param parentDeptId 父部门ID
- * @param type 类型
+ * @param type 类型
* @return 组织树信息
*/
public Map listOrgTree(Long parentDeptId, String type) {
@@ -267,15 +275,15 @@ public class SysDeptServiceImpl extends ServiceImpl impl
});
return Dict.create()
- .set("roleList", orgs)
- .set("childDepartments", orgs)
- .set("employees", new ArrayList<>());
+ .set("roleList", orgs)
+ .set("childDepartments", orgs)
+ .set("employees", new ArrayList<>());
}
Dict dict = Dict.create()
- .set("titleDepartments", new ArrayList<>())
- .set("roleList", new ArrayList<>())
- .set("employees", new ArrayList<>());
+ .set("titleDepartments", new ArrayList<>())
+ .set("roleList", new ArrayList<>())
+ .set("employees", new ArrayList<>());
List deptList = this.list(
Wrappers.lambdaQuery().eq(Objects.nonNull(parentDeptId), SysDept::getParentId, parentDeptId));
@@ -296,8 +304,12 @@ public class SysDeptServiceImpl extends ServiceImpl impl
List userVoList = new ArrayList<>();
- List userList = userMapper
- .selectList(Wrappers.lambdaQuery().in(SysUser::getDeptId, CollUtil.toList(parentDeptId)));
+ MPJLambdaWrapper userQuery = new MPJLambdaWrapper<>();
+ userQuery.selectAll(SysUser.class)
+ .leftJoin(SysUserDept.class, SysUserDept::getUserId, SysUser::getUserId)
+ .eq(SysUserDept::getDeptId, parentDeptId);
+
+ List userList = userMapper.selectJoinList(userQuery);
userList.forEach(user -> {
OrgTreeVO orgTreeVo = new OrgTreeVO();
@@ -322,28 +334,30 @@ public class SysDeptServiceImpl extends ServiceImpl impl
/**
* 模糊搜索用户
+ *
* @param username 用户名/拼音/首字母
* @return 匹配到的用户
*/
public List getOrgTreeUser(String username) {
return userMapper.selectList(Wrappers.lambdaQuery().like(SysUser::getUsername, username))
- .stream()
- .map(user -> {
- OrgTreeVO orgTreeVo = new OrgTreeVO();
- orgTreeVo.setId(user.getUserId());
- orgTreeVo.setName(user.getUsername());
- orgTreeVo.setType(OrgTypeEnum.USER.getType());
- orgTreeVo.setSelected(false);
- orgTreeVo.setAvatar(user.getAvatar());
- return orgTreeVo;
- })
+ .stream()
+ .map(user -> {
+ OrgTreeVO orgTreeVo = new OrgTreeVO();
+ orgTreeVo.setId(user.getUserId());
+ orgTreeVo.setName(user.getUsername());
+ orgTreeVo.setType(OrgTypeEnum.USER.getType());
+ orgTreeVo.setSelected(false);
+ orgTreeVo.setAvatar(user.getAvatar());
+ return orgTreeVo;
+ })
.toList();
}
/**
* 递归查询所有子节点。
+ *
* @param allDeptList 所有部门列表
- * @param parentId 父部门ID
+ * @param parentId 父部门ID
* @param resDeptList 结果集合
*/
private void recursiveDept(List allDeptList, Long parentId, List resDeptList) {
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysRoleServiceImpl.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysRoleServiceImpl.java
index 1cba9dd36..a5e0b352a 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysRoleServiceImpl.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysRoleServiceImpl.java
@@ -35,6 +35,7 @@ import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
+import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
import com.pig4cloud.pigx.common.excel.vo.ErrorMessage;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
@@ -61,13 +62,14 @@ public class SysRoleServiceImpl extends ServiceImpl impl
private SysRoleMenuService roleMenuService;
/**
- * 通过用户ID,查询角色信息
- * @param userId
- * @return
+ * 通过用户ID查询角色信息
+ *
+ * @param userId 用户ID
+ * @return 角色信息列表
*/
@Override
public List findRolesByUserId(Long userId) {
- return baseMapper.listRolesByUserId(userId);
+ return baseMapper.listRolesByUserId(userId, TenantContextHolder.getTenantId());
}
/**
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysTenantServiceImpl.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysTenantServiceImpl.java
index 163822f45..503b2a094 100755
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysTenantServiceImpl.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysTenantServiceImpl.java
@@ -22,11 +22,13 @@ import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.pig4cloud.pigx.admin.api.constant.TenantStateEnum;
import com.pig4cloud.pigx.admin.api.entity.*;
import com.pig4cloud.pigx.admin.config.ClientDetailsInitRunner;
import com.pig4cloud.pigx.admin.mapper.SysRoleMenuMapper;
import com.pig4cloud.pigx.admin.mapper.SysTenantMapper;
+import com.pig4cloud.pigx.admin.mapper.SysTenantUserMapper;
import com.pig4cloud.pigx.admin.service.*;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
@@ -34,6 +36,7 @@ import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
import com.pig4cloud.pigx.common.data.datascope.DataScopeTypeEnum;
import com.pig4cloud.pigx.common.data.resolver.ParamResolver;
import com.pig4cloud.pigx.common.data.tenant.TenantBroker;
+import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.SneakyThrows;
@@ -84,6 +87,8 @@ public class SysTenantServiceImpl extends ServiceImpl getUserTenant() {
+ MPJLambdaWrapper wrapper = new MPJLambdaWrapper()
+ .selectAll(SysTenant.class)
+ .leftJoin(SysTenantUser.class, SysTenantUser::getTenantId, SysTenant::getId)
+ .eq(SysTenantUser::getUserId, SecurityUtils.getUser().getId());
+ return baseMapper.selectJoinList(wrapper);
+ }
+
/**
* 保存新的租户菜单,维护成新的菜单
*
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java
index 0ae8505ac..f9c6e0a77 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java
@@ -36,9 +36,7 @@ import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.*;
import com.pig4cloud.pigx.admin.api.vo.UserExcelVO;
import com.pig4cloud.pigx.admin.api.vo.UserVO;
-import com.pig4cloud.pigx.admin.mapper.SysUserMapper;
-import com.pig4cloud.pigx.admin.mapper.SysUserPostMapper;
-import com.pig4cloud.pigx.admin.mapper.SysUserRoleMapper;
+import com.pig4cloud.pigx.admin.mapper.*;
import com.pig4cloud.pigx.admin.service.*;
import com.pig4cloud.pigx.common.audit.annotation.Audit;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
@@ -49,6 +47,7 @@ import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.data.datascope.DataScope;
import com.pig4cloud.pigx.common.data.resolver.ParamResolver;
+import com.pig4cloud.pigx.common.data.tenant.TenantBroker;
import com.pig4cloud.pigx.common.excel.vo.ErrorMessage;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
@@ -92,7 +91,12 @@ public class SysUserServiceImpl extends ServiceImpl impl
private final SysUserPostMapper sysUserPostMapper;
+ private final SysUserDeptMapper sysUserDeptMapper;
+
+ private final SysTenantUserMapper sysTenantUserMapper;
+
private final CacheManager cacheManager;
+ private final SysDeptMapper sysDeptMapper;
private final StringRedisTemplate redisTemplate;
@@ -141,14 +145,30 @@ public class SysUserServiceImpl extends ServiceImpl impl
userRole.setRoleId(roleId);
return userRole;
}).forEach(sysUserRoleMapper::insert);
+
+ // 插入用户部门信息
+ if (Objects.nonNull(userDto.getDeptId())) {
+ SysUserDept sysUserDept = new SysUserDept();
+ sysUserDept.setUserId(sysUser.getUserId());
+ sysUserDept.setDeptId(userDto.getDeptId());
+ sysUserDeptMapper.insertOrUpdate(List.of(sysUserDept), (batchSqlSession, sysUserDept1) -> sysUserDeptMapper.exists(Wrappers.lambdaQuery()
+ .eq(SysUserDept::getDeptId, userDto.getDeptId())
+ .eq(SysUserDept::getUserId, sysUserDept1.getUserId())));
+ }
+
+ // 插入用户租户关系表
+ SysTenantUser sysTenantUser = new SysTenantUser();
+ sysTenantUser.setUserId(sysUser.getUserId());
+ sysTenantUser.setTenantId(SecurityUtils.getUser().getTenantId());
+ sysTenantUserMapper.insert(sysTenantUser);
return Boolean.TRUE;
}
/**
- * 通过查用户的全部信息
+ * 查询用户全部信息,包括角色和权限
*
- * @param sysUser 用户
- * @return
+ * @param sysUser 用户信息
+ * @return 包含用户角色和权限的用户信息对象
*/
@Override
public UserInfo findUserInfo(SysUser sysUser) {
@@ -184,6 +204,7 @@ public class SysUserServiceImpl extends ServiceImpl impl
*/
@Override
public IPage getUsersWithRolePage(Page page, UserDTO userDTO) {
+ userDTO.setTenantId(SecurityUtils.getUser().getTenantId());
return baseMapper.getUserVosPage(page, userDTO, DataScope.of());
}
@@ -214,7 +235,12 @@ public class SysUserServiceImpl extends ServiceImpl impl
cache.evict(sysUser.getUsername());
}
+ // 删除用户角色
sysUserRoleMapper.delete(Wrappers.lambdaQuery().in(SysUserRole::getUserId, CollUtil.toList(ids)));
+ sysUserDeptMapper.delete(Wrappers.lambdaQuery().in(SysUserDept::getUserId, CollUtil.toList(ids)));
+ sysUserPostMapper.delete(Wrappers.lambdaQuery().in(SysUserPost::getUserId, CollUtil.toList(ids)));
+ sysTenantUserMapper.delete(Wrappers.lambdaQuery().in(SysTenantUser::getUserId, CollUtil.toList(ids))
+ .eq(SysTenantUser::getTenantId, SecurityUtils.getUser().getTenantId()));
this.removeBatchByIds(CollUtil.toList(ids));
return Boolean.TRUE;
}
@@ -273,6 +299,15 @@ public class SysUserServiceImpl extends ServiceImpl impl
}).forEach(SysUserPost::insert);
}
+ // 更新用户部门表
+ if (Objects.nonNull(userDto.getDeptId())) {
+ sysUserDeptMapper.delete(Wrappers.lambdaQuery().eq(SysUserDept::getUserId, userDto.getUserId()));
+ SysUserDept sysUserDept = new SysUserDept();
+ sysUserDept.setUserId(sysUser.getUserId());
+ sysUserDept.setDeptId(userDto.getDeptId());
+ sysUserDept.insert();
+ }
+
return Boolean.TRUE;
}
@@ -286,13 +321,17 @@ public class SysUserServiceImpl extends ServiceImpl impl
public List listAncestorUsers(String username) {
SysUser sysUser = this.getOne(Wrappers.query().lambda().eq(SysUser::getUsername, username));
- SysDept sysDept = sysDeptService.getById(sysUser.getDeptId());
- if (sysDept == null) {
+ // 查询所属部门
+ List sysDeptList = sysDeptMapper.listDeptsByUserId(sysUser.getUserId(), sysUser.getTenantId());
+ if (CollUtil.isEmpty(sysDeptList)) {
return null;
}
- Long parentId = sysDept.getParentId();
- return this.list(Wrappers.query().lambda().eq(SysUser::getDeptId, parentId));
+ // 查询用户部门ID
+ List parentDeptList = sysDeptList.stream().map(SysDept::getParentId).toList();
+ List userIdList = sysUserDeptMapper.selectList(Wrappers.lambdaQuery().in(SysUserDept::getDeptId, parentDeptList))
+ .stream().map(SysUserDept::getUserId).toList();
+ return this.list(Wrappers.lambdaQuery().in(SysUser::getUserId, userIdList));
}
/**
@@ -305,21 +344,29 @@ public class SysUserServiceImpl extends ServiceImpl impl
@Override
public List listUser(UserDTO userDTO, Long[] ids) {
// 根据数据权限查询全部的用户信息
+ userDTO.setTenantId(SecurityUtils.getUser().getTenantId());
List voList = baseMapper.selectVoListByScope(userDTO, ids, DataScope.of());
// 转换成execl 对象输出
List userExcelVOList = voList.stream().map(userVO -> {
UserExcelVO excelVO = new UserExcelVO();
BeanUtils.copyProperties(userVO, excelVO);
+ // 转换角色名称
String roleNameList = userVO.getRoleList()
.stream()
.map(SysRole::getRoleName)
.collect(Collectors.joining(StrUtil.COMMA));
excelVO.setRoleNameList(roleNameList);
+ // 转化岗位名称
String postNameList = userVO.getPostList()
.stream()
.map(SysPost::getPostName)
.collect(Collectors.joining(StrUtil.COMMA));
excelVO.setPostNameList(postNameList);
+ // 转化部门名称
+ String deptNameList = userVO.getDeptList().stream()
+ .map(SysDept::getName)
+ .collect(Collectors.joining(StrUtil.COMMA));
+ excelVO.setDeptNameList(deptNameList);
return excelVO;
}).toList();
return userExcelVOList;
@@ -356,10 +403,10 @@ public class SysUserServiceImpl extends ServiceImpl impl
// 判断输入的部门名称列表是否合法
Optional deptOptional = deptList.stream()
- .filter(dept -> excel.getDeptName().equals(dept.getName()))
+ .filter(dept -> excel.getDeptNameList().equals(dept.getName()))
.findFirst();
if (!deptOptional.isPresent()) {
- errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_DEPT_DEPTNAME_INEXISTENCE, excel.getDeptName()));
+ errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_DEPT_DEPTNAME_INEXISTENCE, excel.getDeptNameList()));
}
// 判断输入的角色名称列表是否合法
@@ -423,6 +470,11 @@ public class SysUserServiceImpl extends ServiceImpl impl
userDTO.setRole(roleIdList);
// 插入用户
this.saveUser(userDTO);
+ // 插入用户租户关系表
+ SysTenantUser sysTenantUser = new SysTenantUser();
+ sysTenantUser.setUserId(userDTO.getUserId());
+ sysTenantUser.setTenantId(SecurityUtils.getUser().getTenantId());
+ sysTenantUserMapper.insert(sysTenantUser);
}
/**
@@ -499,6 +551,21 @@ public class SysUserServiceImpl extends ServiceImpl impl
return R.ok();
}
+
+ /**
+ * 更新用户租户信息
+ *
+ * @param userDto 用户数据传输对象
+ * @return 更新结果
+ */
+ @Override
+ @CacheEvict(value = CacheConstants.USER_DETAILS, key = "#userDto.username")
+ public R updateUserTenant(UserDTO userDto) {
+ return R.ok(TenantBroker.noneAs(() -> this.update(Wrappers.lambdaUpdate()
+ .set(SysUser::getTenantId, userDto.getTenantId())
+ .eq(SysUser::getUserId, userDto.getUserId()))));
+ }
+
@Override
public R unbinding(String type) {
PigxUser user = SecurityUtils.getUser();
@@ -588,7 +655,8 @@ public class SysUserServiceImpl extends ServiceImpl impl
return R.failed("验证码错误");
}
- String username = lambdaQuery().select(SysUser::getUsername).eq(SysUser::getPhone, userDto.getPhone()).one().getUsername();
+ String username = lambdaQuery().select(SysUser::getUsername).
+ eq(SysUser::getPhone, userDto.getPhone()).one().getUsername();
// 重置密码
String password = ENCODER.encode(userDto.getNewpassword1());
@@ -617,7 +685,9 @@ public class SysUserServiceImpl extends ServiceImpl impl
*/
@Override
public List listUserIdByDeptIds(List deptIdList) {
- return baseMapper.selectList(Wrappers.lambdaQuery().in(SysUser::getDeptId, deptIdList));
+ List userList = sysUserDeptMapper.selectList(Wrappers.lambdaQuery().in(SysUserDept::getDeptId, deptIdList))
+ .stream().map(SysUserDept::getUserId).toList();
+ return baseMapper.selectList(Wrappers.lambdaQuery().in(SysUser::getUserId, userList));
}
}
diff --git a/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysDeptMapper.xml b/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysDeptMapper.xml
index 81b39533f..0ea564cea 100644
--- a/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysDeptMapper.xml
+++ b/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysDeptMapper.xml
@@ -20,4 +20,15 @@
+
diff --git a/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysPostMapper.xml b/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysPostMapper.xml
index 8d523e8d5..f5f3b1603 100644
--- a/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysPostMapper.xml
+++ b/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysPostMapper.xml
@@ -48,6 +48,7 @@
WHERE p.post_id = up.post_id
AND p.del_flag = '0'
and up.user_id = #{userId}
+ and up.tenant_id = #{tenantId}
diff --git a/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysRoleMapper.xml b/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysRoleMapper.xml
index e7eaa6ea1..bffc9d670 100644
--- a/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysRoleMapper.xml
+++ b/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysRoleMapper.xml
@@ -49,5 +49,6 @@
WHERE sys_role.role_id = sys_user_role.role_id
AND sys_role.del_flag = '0'
and sys_user_role.user_id = #{userId}
+ and sys_user_role.tenant_id = #{tenantId}
diff --git a/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysUserMapper.xml b/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysUserMapper.xml
index 7deae29c1..843688beb 100644
--- a/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysUserMapper.xml
+++ b/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysUserMapper.xml
@@ -1,22 +1,4 @@
-
@@ -28,203 +10,131 @@
+
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+ select="com.pig4cloud.pigx.admin.mapper.SysRoleMapper.listRolesByUserId"
+ column="{userId=user_id, tenantId=tenant_id}">
+ select="com.pig4cloud.pigx.admin.mapper.SysPostMapper.listPostsByUserId"
+ column="{userId=user_id, tenantId=tenant_id}">
-
+
u.user_id,
u.username,
u.password,
u.salt,
u.phone,
u.avatar,
- u.wx_openid,
- u.qq_openid,
- u.gitee_login,
- u.osc_id,
- u.wx_cp_userid,
- u.wx_ding_userid,
- u.dept_id,
- u.del_flag,
- u.lock_flag,
- u.password_expire_flag,
- u.password_modify_time,
- u.tenant_id,
- u.create_by,
- u.create_time ucreate_time,
- u.update_time uupdate_time,
- r.role_id,
- r.role_name,
- r.role_code,
- r.role_desc,
- r.create_time rcreate_time,
- r.update_time rupdate_time
-
-
-
- u.user_id,
- u.username,
- u.password,
- u.salt,
- u.phone,
- u.avatar,
- u.wx_openid,
- u.qq_openid,
- u.gitee_login,
- u.osc_id,
- u.wx_cp_userid,
- u.wx_ding_userid,
- u.del_flag,
- u.lock_flag,
- u.password_expire_flag,
- u.password_modify_time,
- u.tenant_id,
- u.nickname,
u.name,
+ u.nickname,
u.email,
+ u.wx_openid,
+ u.qq_openid,
+ u.gitee_login,
+ u.osc_id,
+ u.wx_cp_userid,
+ u.wx_ding_userid,
+ u.del_flag,
+ u.lock_flag,
+ u.password_expire_flag,
+ u.password_modify_time,
+ u.tenant_id,
u.create_by,
- u.create_time ucreate_time,
- u.update_time uupdate_time,
- d.name dept_name,
- d.dept_id
+ u.create_time,
+ u.update_time