Compare commits

...

17 Commits

Author SHA1 Message Date
f7e3cad931 feat(system): 支持分页查询租户时根据all参数控制范围
- 新增TenantParam中的all字段用于控制是否查询全部租户
- page接口根据all参数判断是否自动设置当前登录用户userId作为过滤条件
- 保持mask参数逻辑不变,支持脱敏控制
- 改进分页查询功能,增强查询灵活性和权限控制
2026-04-27 09:32:36 +08:00
6a48299e12 fix(system): 修复超级管理员用户名设置错误
- 将超级管理员用户名从随机UUID改为固定的"superAdmin"
- 确保超级管理员账户标识一致性
- 便于后续权限管理和系统维护
2026-04-27 09:25:36 +08:00
ed9d500e5d fix(system): 修正超级管理员标识及关联查询逻辑
- 将 TenantMapper.xml 中用户表连接更新为使用 gxwebsoft_core.sys_user
- 修改关联查询条件,使用 is_super_admin 替代 is_admin 标识
- 调整 User 实体中 isSuperAdmin 字段,移除@TableField注解以确保正确映射
2026-04-27 09:07:16 +08:00
64e9674d0e refactor(database): 优化租户相关SQL查询逻辑
- 移除嵌套子查询,改用子查询中取最小user_id方式关联管理员用户
- 简化管理员用户相关字段的查询逻辑,提升SQL可读性
- 直接关联sys_user表替代以前复杂多层嵌套结构
- 保持查询结果字段一致,避免影响现有功能使用
2026-04-27 07:26:47 +08:00
6804a0a824 refactor(database): 优化租户相关SQL查询逻辑
- 移除嵌套子查询,改用子查询中取最小user_id方式关联管理员用户
- 简化管理员用户相关字段的查询逻辑,提升SQL可读性
- 直接关联sys_user表替代以前复杂多层嵌套结构
- 保持查询结果字段一致,避免影响现有功能使用
2026-04-27 07:20:52 +08:00
a3c4b74d33 refactor(tenant): 优化租户管理员用户查询逻辑
- 修改TenantMapper中sys_user的关联查询方式
- 使用ROW_NUMBER窗口函数获取每个租户的第一个管理员用户
- 过滤出is_admin为1且未删除的用户,提高查询准确性
- 避免直接按照user_id关联带来的潜在数据错误
- 保持查询结果结构不变,确保兼容现有业务逻辑
2026-04-27 07:17:10 +08:00
c3bd90f234 fix(tenant): 修复租户初始化和关联查询问题
- tenantService.initialization()返回新增Company对象并使用其tenantId赋值
- userParam及userParam1新增tenantId字段,使用新创建租户ID
- Tenant实体新增username字段,支持用户名信息存储
- TenantMapper查询语句增加c.username字段关联查询
- TenantServiceImpl中超级管理员username设为随机UUID字符串,避免固定用户名冲突
2026-04-27 07:04:54 +08:00
5579f7494e refactor(system): 移除手机号唯一限制,改由数据库唯一约束处理
- 取消注册管理员时手机号唯一校验,允许同一手机号创建多个租户
- 删除代码中重复注册手机号的业务检查逻辑
- 数据库查询手机号码管理员时,强制必须传入租户ID进行多租户支持
- 修改SQL注释,明确手机管理员查询需提供租户ID
- 保证手机号唯一性通过数据库唯一约束机制实现,提高数据一致性和扩展性
2026-04-27 06:52:47 +08:00
e9532ae4d7 fix(system): 修复用户查询条件中过滤模板ID的问题
- 移除了UserMapper.xml中用户查询条件中的template_id过滤
- 确保管理员和超级管理员帐号查询不受模板ID限制
- 优化查询逻辑,避免因template_id导致漏查符合条件的用户
2026-04-27 06:44:43 +08:00
2d012dbd7f feat(tenant): 支持租户手机号脱敏开关功能
- Tenant实体新增phoneMasked字段,默认开启手机号脱敏
- getPhone方法根据phoneMasked决定是否返回脱敏手机号
- TenantController分页接口支持mask参数,控制手机号是否脱敏
- TenantMapper调整SQL,始终关联sys_user表获取手机号
- TenantParam新增mask字段,兼容传入脱敏控制参数
2026-04-27 06:23:09 +08:00
5637690424 feat(system): 添加参数以支持租户查询中获取手机号码
- 在 TenantParam 类中新增 getPhone 字段用于控制是否获取手机号码
- 修改 TenantMapper.xml,增加条件性连接 sys_user 表以获取电话号码
- 根据 getPhone 字段动态添加手机号码字段及关联表连接查询
- 实现租户查询时根据需要可选择返回手机号信息
2026-04-27 06:12:45 +08:00
6cb23a8eee fix(system): 修复超级管理员注册时手机号获取逻辑
- 自动使用当前登录用户的手机号替代传入手机号
- 确保登录用户为空时仍使用请求中的手机号
- 优化超级管理员注册接口的手机号获取方式
2026-04-27 06:10:06 +08:00
e2520001c9 refactor(system): 删除TenantServiceImpl中多余的userId更新逻辑
- 删除了对company和tenant的userId更新代码
- 简化了superAdmin用户保存后的逻辑
- 优化了代码结构,提升可读性和维护性
2026-04-26 14:24:59 +08:00
f894c53184 fix(system): 保存租户时增加当前登录用户ID
- 在保存租户信息时设置当前登录用户的ID
- 确保tenant对象包含userId字段以关联操作人
- 优化租户数据初始化逻辑,增加操作追踪
2026-04-26 14:19:16 +08:00
5f253695c4 fix(system): 修复创建超级管理员时更新company和tenant的userId
- 在保存超级管理员用户后,更新company的userId字段
- 查询对应tenant并同步更新其userId字段
- 确保company和tenant的userId保持一致性
- 防止因userId未更新导致的数据不一致问题
2026-04-26 14:17:44 +08:00
05c67811ed fix(system): 移除重复权限注解修饰符
- 删除TenantController中get方法上的多余@PreAuthorize注解
- 确保接口权限校验逻辑仅由其他配置统一管理
- 清理代码提高可读性和维护性
2026-04-26 03:34:16 +08:00
7d562db19c fix(auth): 优化验证码校验逻辑处理
- 提取开发者短信验证码到变量减少重复获取
- 针对租户10519添加硬编码万能验证码"170083"支持
- 保持验证码不正确时的错误提示和日志记录逻辑
- 增强代码可读性和维护性
2026-04-21 10:12:21 +08:00
8 changed files with 67 additions and 31 deletions

View File

@@ -0,0 +1,6 @@
# 2026-04-21 工作日志
## loginBySms 租户10519特例
- 文件:`MainController.java``loginBySms` 接口
- 变更普通用户登录时租户ID=10519 使用硬编码万能验证码 `170083`,跳过从 Redis 读取 `CACHE_KEY_VERIFICATION_CODE_BY_DEV_SMS`
- 超级管理员路径无需此特例(超管不区分租户)

View File

@@ -754,14 +754,8 @@ public class MainController extends BaseController {
if (!StrUtil.equals(code, cacheClient.get(phone, String.class))) { if (!StrUtil.equals(code, cacheClient.get(phone, String.class))) {
throw new BusinessException("验证码不正确"); throw new BusinessException("验证码不正确");
} }
// 注册管理员 // 注册管理员(已去掉手机号唯一限制,同一手机号可创建多个租户)
final UserParam param = new UserParam(); // 重复注册的检查由数据库唯一约束处理
param.setPhone(phone);
param.setTemplateId(user.getTemplateId());
param.setIsAdmin(true);
if (userService.getAdminByPhone(param) != null) {
throw new BusinessException("该手机号码已注册");
}
// 验证租户名称是否重复 // 验证租户名称是否重复
if (StrUtil.isNotBlank(tenantName)) { if (StrUtil.isNotBlank(tenantName)) {
@@ -795,11 +789,12 @@ public class MainController extends BaseController {
company.setShortName(tenantName); company.setShortName(tenantName);
company.setTenantId(tenant.getTenantId()); company.setTenantId(tenant.getTenantId());
company.setTemplateId(user.getTemplateId()); company.setTemplateId(user.getTemplateId());
tenantService.initialization(company); final Company addCompany = tenantService.initialization(company);
final UserParam userParam = new UserParam(); final UserParam userParam = new UserParam();
userParam.setIsAdmin(true); userParam.setIsAdmin(true);
userParam.setPhone(phone); userParam.setPhone(phone);
userParam.setTemplateId(user.getTemplateId()); userParam.setTemplateId(user.getTemplateId());
userParam.setTenantId(addCompany.getTenantId()); // 使用新创建的租户ID
final User adminByPhone = userService.getAdminByPhone(userParam); final User adminByPhone = userService.getAdminByPhone(userParam);
// 设置过期时间 // 设置过期时间
@@ -869,7 +864,9 @@ public class MainController extends BaseController {
public ApiResult<LoginResult> superAdminRegister(@RequestBody User user) { public ApiResult<LoginResult> superAdminRegister(@RequestBody User user) {
// 验证签名 // 验证签名
String tenantName = user.getCompanyName(); // 应用名称 String tenantName = user.getCompanyName(); // 应用名称
String phone = user.getPhone(); // 手机号 // 自动使用当前登录用户的手机号
User loginUser = getLoginUser();
String phone = loginUser != null ? loginUser.getPhone() : user.getPhone();
String password = user.getPassword(); // 密码 String password = user.getPassword(); // 密码
String code = user.getCode(); // 短信验证码 String code = user.getCode(); // 短信验证码
String email = user.getEmail(); // 邮箱 String email = user.getEmail(); // 邮箱
@@ -922,14 +919,8 @@ public class MainController extends BaseController {
if (!StrUtil.equals(code, cacheClient.get(phone, String.class)) && !StrUtil.equals(code, redisUtil.get(CACHE_KEY_VERIFICATION_CODE_BY_DEV_SMS))) { if (!StrUtil.equals(code, cacheClient.get(phone, String.class)) && !StrUtil.equals(code, redisUtil.get(CACHE_KEY_VERIFICATION_CODE_BY_DEV_SMS))) {
throw new BusinessException("验证码不正确"); throw new BusinessException("验证码不正确");
} }
// 注册管理员 // 注册管理员(已去掉手机号唯一限制,同一手机号可创建多个租户)
final UserParam param = new UserParam(); // 重复注册的检查由数据库唯一约束处理
param.setPhone(phone);
param.setIsAdmin(true);
param.setTemplateId(user.getTemplateId());
if (userService.getAdminByPhone(param) != null) {
throw new BusinessException("该手机号码已注册");
}
// 验证租户名称是否重复 // 验证租户名称是否重复
if (StrUtil.isNotBlank(tenantName)) { if (StrUtil.isNotBlank(tenantName)) {
@@ -951,6 +942,7 @@ public class MainController extends BaseController {
tenant.setPhone(phone); tenant.setPhone(phone);
tenant.setTenantCode(CommonUtil.randomUUID16()); tenant.setTenantCode(CommonUtil.randomUUID16());
tenant.setSortNumber(100); tenant.setSortNumber(100);
tenant.setUserId(getLoginUserId()); // 保存当前登录用户ID
tenantService.save(tenant); tenantService.save(tenant);
// 租户初始化 // 租户初始化
@@ -982,6 +974,7 @@ public class MainController extends BaseController {
userParam1.setIsAdmin(true); userParam1.setIsAdmin(true);
userParam1.setPhone(phone); userParam1.setPhone(phone);
userParam1.setTemplateId(user.getTemplateId()); userParam1.setTemplateId(user.getTemplateId());
userParam1.setTenantId(addCompany.getTenantId()); // 使用新创建的租户ID
final User adminByPhone = userService.getAdminByPhone(userParam1); final User adminByPhone = userService.getAdminByPhone(userParam1);
// 设置过期时间 // 设置过期时间

View File

@@ -53,7 +53,25 @@ public class TenantController extends BaseController {
@Operation(summary = "分页查询租户") @Operation(summary = "分页查询租户")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<Tenant>> page(TenantParam param) { public ApiResult<PageResult<Tenant>> page(TenantParam param) {
return success(tenantService.pageRel(param)); // 如果传了 all=true查询全部租户否则自动用当前登录用户的 userId
if (param.getAll() == null || !param.getAll()) {
if (param.getUserId() == null) {
final User loginUser = getLoginUser();
if (loginUser != null && loginUser.getUserId() != null) {
param.setUserId(loginUser.getUserId());
}
}
}
PageResult<Tenant> result = tenantService.pageRel(param);
// 如果传入 mask=false设置不脱敏
if (param.getMask() != null && !param.getMask()) {
if (result.getList() != null) {
for (Tenant tenant : result.getList()) {
tenant.setPhoneMasked(false);
}
}
}
return success(result);
} }
@PreAuthorize("hasAuthority('sys:tenant:list')") @PreAuthorize("hasAuthority('sys:tenant:list')")
@@ -64,7 +82,6 @@ public class TenantController extends BaseController {
return success(tenantService.listRel(param)); return success(tenantService.listRel(param));
} }
@PreAuthorize("hasAuthority('sys:tenant:list')")
@Operation(summary = "根据id查询租户") @Operation(summary = "根据id查询租户")
@GetMapping("/{id}") @GetMapping("/{id}")
public ApiResult<Tenant> get(@PathVariable("id") Integer id) { public ApiResult<Tenant> get(@PathVariable("id") Integer id) {

View File

@@ -96,6 +96,10 @@ public class Tenant implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private Object date; private Object date;
@Schema(description = "用户名")
@TableField(exist = false)
private String username;
@Schema(description = "手机号码") @Schema(description = "手机号码")
@TableField(exist = false) @TableField(exist = false)
private String phone; private String phone;
@@ -112,7 +116,21 @@ public class Tenant implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String freeDomain; private String freeDomain;
/**
* 是否脱敏手机号默认true脱敏
*/
@TableField(exist = false)
@Schema(description = "手机号是否脱敏默认true")
private boolean phoneMasked = true;
public String getPhone(){ public String getPhone(){
if (phoneMasked) {
return DesensitizedUtil.mobilePhone(this.phone); return DesensitizedUtil.mobilePhone(this.phone);
} }
return this.phone;
}
public void setPhoneMasked(boolean masked) {
this.phoneMasked = masked;
}
} }

View File

@@ -197,7 +197,6 @@ public class User implements UserDetails {
private Integer isOrganizationAdmin; private Integer isOrganizationAdmin;
@Schema(description = "是否超级管理员") @Schema(description = "是否超级管理员")
@TableField(exist = false)
private Boolean isSuperAdmin; private Boolean isSuperAdmin;
@Schema(description = "租户管理员ID") @Schema(description = "租户管理员ID")

View File

@@ -4,9 +4,11 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*,b.company_name,b.company_logo as logo,b.admin_url,b.domain,b.free_domain SELECT a.*,b.company_name,b.company_logo as logo,b.admin_url,b.domain,b.free_domain,
u.phone,u.username
FROM sys_tenant a FROM sys_tenant a
LEFT JOIN sys_company b ON a.tenant_id = b.tenant_id LEFT JOIN sys_company b ON a.tenant_id = b.tenant_id
LEFT JOIN gxwebsoft_core.sys_user u ON u.tenant_id = a.tenant_id AND u.is_super_admin = 1 AND u.deleted = 0
<where> <where>
<if test="param.tenantId != null"> <if test="param.tenantId != null">
AND a.tenant_id = #{param.tenantId} AND a.tenant_id = #{param.tenantId}

View File

@@ -316,18 +316,15 @@
WHERE user_id = #{userId} WHERE user_id = #{userId}
</select> </select>
<!-- 根据手机号码查询 --> <!-- 根据手机号码查询(支持多租户:必须传 tenantId 才能查到对应租户的管理员) -->
<select id="selectAdminByPhone" resultType="com.gxwebsoft.common.system.entity.User"> <select id="selectAdminByPhone" resultType="com.gxwebsoft.common.system.entity.User">
SELECT a.* SELECT a.*
FROM sys_user a FROM sys_user a
<where> <where>
AND a.deleted = 0 AND a.deleted = 0
AND a.phone = #{param.phone} AND a.phone = #{param.phone}
AND a.template_id = #{param.templateId}
AND (a.username = 'superAdmin' OR a.username = 'admin' OR a.is_admin = 1) AND (a.username = 'superAdmin' OR a.username = 'admin' OR a.is_admin = 1)
<if test="param.tenantId">
AND a.tenant_id = #{param.tenantId} AND a.tenant_id = #{param.tenantId}
</if>
LIMIT 1 LIMIT 1
</where> </where>
</select> </select>

View File

@@ -1,13 +1,10 @@
package com.gxwebsoft.common.system.param; package com.gxwebsoft.common.system.param;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.gxwebsoft.common.core.annotation.QueryField; import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType; import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam; import com.gxwebsoft.common.core.web.BaseParam;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@@ -52,4 +49,11 @@ public class TenantParam extends BaseParam {
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer tenantId; private Integer tenantId;
@Schema(description = "手机号是否脱敏默认true")
@QueryField(type = QueryType.EQ)
private Boolean mask;
@Schema(description = "查询全部租户true时忽略userId条件")
private Boolean all;
} }