This commit is contained in:
2025-12-11 18:30:35 +08:00
parent 99937e9feb
commit 8b211fbad6
35 changed files with 527 additions and 302 deletions

View File

@@ -13,11 +13,13 @@ CREATE TABLE sys.tb_sys_user (
phone VARCHAR(500), -- 电话号码 phone VARCHAR(500), -- 电话号码
phone_hash VARCHAR(200), -- 电话hash phone_hash VARCHAR(200), -- 电话hash
wechat_id VARCHAR(50), -- 微信ID wechat_id VARCHAR(50), -- 微信ID
creator VARCHAR(50) DEFAULT NULL, -- 创建者
create_time TIMESTAMPTZ NOT NULL DEFAULT now(), -- 创建时间(使用带时区时间) create_time TIMESTAMPTZ NOT NULL DEFAULT now(), -- 创建时间(使用带时区时间)
update_time TIMESTAMPTZ DEFAULT NULL, -- 更新时间(由触发器维护) update_time TIMESTAMPTZ DEFAULT NULL, -- 更新时间(由触发器维护)
delete_time TIMESTAMPTZ DEFAULT NULL, -- 删除时间 delete_time TIMESTAMPTZ DEFAULT NULL, -- 删除时间
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除(使用 BOOLEAN deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除(使用 BOOLEAN
status INTEGER NOT NULL DEFAULT 1, -- 状态 status INTEGER NOT NULL DEFAULT 1, -- 状态
remark VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (user_id), PRIMARY KEY (user_id),
UNIQUE (optsn), UNIQUE (optsn),
UNIQUE (email), UNIQUE (email),
@@ -59,6 +61,7 @@ CREATE TABLE sys.tb_sys_user_info (
level INTEGER DEFAULT 1, -- 等级 level INTEGER DEFAULT 1, -- 等级
id_card VARCHAR(50), -- 身份证号 id_card VARCHAR(50), -- 身份证号
address VARCHAR(255), -- 地址 address VARCHAR(255), -- 地址
creator VARCHAR(50) DEFAULT NULL, -- 创建者
remark VARCHAR(500) DEFAULT NULL, -- 备注 remark VARCHAR(500) DEFAULT NULL, -- 备注
create_time TIMESTAMPTZ NOT NULL DEFAULT now(), -- 创建时间 create_time TIMESTAMPTZ NOT NULL DEFAULT now(), -- 创建时间
update_time TIMESTAMPTZ DEFAULT NULL, -- 更新时间(触发器维护) update_time TIMESTAMPTZ DEFAULT NULL, -- 更新时间(触发器维护)

View File

@@ -1,6 +1,13 @@
{ {
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{
"type": "java",
"name": "AesEncryptUtil",
"request": "launch",
"mainClass": "org.xyzh.common.utils.crypto.AesEncryptUtil",
"projectName": "common-utils"
},
{ {
"type": "java", "type": "java",
"name": "Gateway (8180)", "name": "Gateway (8180)",
@@ -8,8 +15,12 @@
"mainClass": "org.xyzh.gateway.GatewayApplication", "mainClass": "org.xyzh.gateway.GatewayApplication",
"projectName": "gateway", "projectName": "gateway",
"cwd": "${workspaceFolder}/gateway", "cwd": "${workspaceFolder}/gateway",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8180"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8180"
],
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
@@ -19,8 +30,12 @@
"mainClass": "org.xyzh.auth.AuthApp", "mainClass": "org.xyzh.auth.AuthApp",
"projectName": "auth", "projectName": "auth",
"cwd": "${workspaceFolder}/auth", "cwd": "${workspaceFolder}/auth",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8181"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8181"
],
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
@@ -30,8 +45,12 @@
"mainClass": "org.xyzh.system.SystemApp", "mainClass": "org.xyzh.system.SystemApp",
"projectName": "system", "projectName": "system",
"cwd": "${workspaceFolder}/system", "cwd": "${workspaceFolder}/system",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8182"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8182"
],
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
@@ -41,8 +60,12 @@
"mainClass": "org.xyzh.log.LogApp", "mainClass": "org.xyzh.log.LogApp",
"projectName": "log", "projectName": "log",
"cwd": "${workspaceFolder}/log", "cwd": "${workspaceFolder}/log",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8183"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8183"
],
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
@@ -52,8 +75,12 @@
"mainClass": "org.xyzh.file.FileApp", "mainClass": "org.xyzh.file.FileApp",
"projectName": "file", "projectName": "file",
"cwd": "${workspaceFolder}/file", "cwd": "${workspaceFolder}/file",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8184"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8184"
],
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
@@ -63,8 +90,12 @@
"mainClass": "org.xyzh.message.MessageApp", "mainClass": "org.xyzh.message.MessageApp",
"projectName": "message", "projectName": "message",
"cwd": "${workspaceFolder}/message", "cwd": "${workspaceFolder}/message",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8185"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8185"
],
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
@@ -74,8 +105,12 @@
"mainClass": "org.xyzh.bidding.BiddingApp", "mainClass": "org.xyzh.bidding.BiddingApp",
"projectName": "bidding", "projectName": "bidding",
"cwd": "${workspaceFolder}/bidding", "cwd": "${workspaceFolder}/bidding",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8186"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8186"
],
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
@@ -85,8 +120,12 @@
"mainClass": "org.xyzh.platform.PlatformApp", "mainClass": "org.xyzh.platform.PlatformApp",
"projectName": "platform", "projectName": "platform",
"cwd": "${workspaceFolder}/platform", "cwd": "${workspaceFolder}/platform",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8187"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8187"
],
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
@@ -96,8 +135,12 @@
"mainClass": "org.xyzh.workcase.WorkcaseApp", "mainClass": "org.xyzh.workcase.WorkcaseApp",
"projectName": "workcase", "projectName": "workcase",
"cwd": "${workspaceFolder}/workcase", "cwd": "${workspaceFolder}/workcase",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8188"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8188"
],
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
@@ -107,8 +150,12 @@
"mainClass": "org.xyzh.crontab.CrontabApp", "mainClass": "org.xyzh.crontab.CrontabApp",
"projectName": "crontab", "projectName": "crontab",
"cwd": "${workspaceFolder}/crontab", "cwd": "${workspaceFolder}/crontab",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8189"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8189"
],
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
@@ -118,8 +165,12 @@
"mainClass": "org.xyzh.agent.AgentApp", "mainClass": "org.xyzh.agent.AgentApp",
"projectName": "agent", "projectName": "agent",
"cwd": "${workspaceFolder}/agent", "cwd": "${workspaceFolder}/agent",
"args": ["--spring.profiles.active=dev"], "args": [
"vmArgs": ["-Dserver.port=8190"], "--spring.profiles.active=dev"
],
"vmArgs": [
"-Dserver.port=8190"
],
"console": "integratedTerminal" "console": "integratedTerminal"
} }
], ],

View File

@@ -1,8 +1,8 @@
# ================== Server ================== # ================== Server ==================
server: server:
port: 8190 port: 8190
servlet: # servlet:
context-path: /urban-lifeline/agent # context-path: /urban-lifeline/agent # 微服务架构下context-path由Gateway管理
# ================== Auth ==================== # ================== Auth ====================
urban-lifeline: urban-lifeline:

View File

@@ -18,5 +18,17 @@
<maven.compiler.source>21</maven.compiler.source> <maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target> <maven.compiler.target>21</maven.compiler.target>
</properties> </properties>
<dependencies>
<dependency>
<groupId>org.xyzh.common</groupId>
<artifactId>common-dto</artifactId>
<version>${urban-lifeline.version}</version>
</dependency>
<dependency>
<groupId>org.xyzh.common</groupId>
<artifactId>common-utils</artifactId>
<version>${urban-lifeline.version}</version>
</dependency>
</dependencies>
</project> </project>

View File

@@ -7,6 +7,7 @@ import org.xyzh.common.vo.BaseVO;
import org.xyzh.common.dto.sys.TbSysUserDTO; import org.xyzh.common.dto.sys.TbSysUserDTO;
import org.xyzh.common.dto.sys.TbSysUserInfoDTO; import org.xyzh.common.dto.sys.TbSysUserInfoDTO;
import org.xyzh.common.utils.crypto.AesEncryptUtil;
import java.util.List; import java.util.List;
@@ -47,8 +48,8 @@ public class SysUserVO extends BaseVO {
@Schema(description = "用户状态") @Schema(description = "用户状态")
private String status; private String status;
@Schema(description = "用户类型") @Schema(description = "创建人")
private String userType; private String creator;
// TbSysUserInfoDTO对应字段 // TbSysUserInfoDTO对应字段
@Schema(description = "用户名") @Schema(description = "用户名")
@@ -79,6 +80,11 @@ public class SysUserVO extends BaseVO {
@Schema(description = "用户视图权限列表") @Schema(description = "用户视图权限列表")
private List<PermissionVO> viewPermissions; private List<PermissionVO> viewPermissions;
public void setPhone(String phone){
this.phone = phone;
this.phoneHash = AesEncryptUtil.maskPhone(phone);
}
public static TbSysUserDTO toDTO(SysUserVO vo) { public static TbSysUserDTO toDTO(SysUserVO vo) {
if (vo == null) { if (vo == null) {
return null; return null;
@@ -91,10 +97,8 @@ public class SysUserVO extends BaseVO {
dto.setPhone(vo.getPhone()); dto.setPhone(vo.getPhone());
dto.setWechatId(vo.getWechatId()); dto.setWechatId(vo.getWechatId());
dto.setStatus(vo.getStatus()); dto.setStatus(vo.getStatus());
dto.setUserType(vo.getUserType());
dto.setOptsn(vo.getOptsn()); dto.setOptsn(vo.getOptsn());
dto.setCreator(vo.getCreator()); dto.setCreator(vo.getCreator());
dto.setUpdater(vo.getUpdater());
dto.setDeptPath(vo.getDeptPath()); dto.setDeptPath(vo.getDeptPath());
dto.setRemark(vo.getRemark()); dto.setRemark(vo.getRemark());
dto.setCreateTime(vo.getCreateTime()); dto.setCreateTime(vo.getCreateTime());
@@ -120,7 +124,6 @@ public class SysUserVO extends BaseVO {
// 继承自 BaseDTO 的字段 // 继承自 BaseDTO 的字段
userInfoDTO.setOptsn(userVO.getOptsn()); userInfoDTO.setOptsn(userVO.getOptsn());
userInfoDTO.setCreator(userVO.getCreator()); userInfoDTO.setCreator(userVO.getCreator());
userInfoDTO.setUpdater(userVO.getUpdater());
userInfoDTO.setDeptPath(userVO.getDeptPath()); userInfoDTO.setDeptPath(userVO.getDeptPath());
userInfoDTO.setRemark(userVO.getRemark()); userInfoDTO.setRemark(userVO.getRemark());
userInfoDTO.setCreateTime(userVO.getCreateTime()); userInfoDTO.setCreateTime(userVO.getCreateTime());

View File

@@ -5,10 +5,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication @SpringBootApplication
@EnableDubbo // 启用 Dubbo 服务 @EnableDubbo // 启用 Dubbo 服务
@EnableDiscoveryClient // 启用 Nacos 服务注册与发现(用于 Gateway 路由)
@ComponentScan(basePackages = { @ComponentScan(basePackages = {
"org.xyzh.auth", // 当前auth模块 "org.xyzh.auth", // 当前auth模块
"org.xyzh.common" // 公共模块 "org.xyzh.common" // 公共模块

View File

@@ -24,6 +24,7 @@ import org.xyzh.common.dto.sys.TbSysPermissionDTO;
import org.xyzh.common.dto.sys.TbSysViewDTO; import org.xyzh.common.dto.sys.TbSysViewDTO;
import org.xyzh.common.redis.service.RedisService; import org.xyzh.common.redis.service.RedisService;
import org.xyzh.common.utils.IDUtils; import org.xyzh.common.utils.IDUtils;
import org.xyzh.common.utils.crypto.AesEncryptUtil;
import org.apache.dubbo.config.annotation.DubboReference; import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -67,6 +68,9 @@ public class AuthServiceImpl implements AuthService{
@Autowired @Autowired
private LoginStrategyFactory loginStrategyFactory; private LoginStrategyFactory loginStrategyFactory;
@Autowired
private AesEncryptUtil aesEncryptUtil;
@Override @Override
public ResultDomain<LoginDomain> getCaptcha(LoginParam loginParam) { public ResultDomain<LoginDomain> getCaptcha(LoginParam loginParam) {
try { try {
@@ -236,7 +240,8 @@ public class AuthServiceImpl implements AuthService{
// 5. 验证凭据 // 5. 验证凭据
if ("password".equals(loginType)) { if ("password".equals(loginType)) {
if (!strategy.verifyCredential(loginParam.getPassword(), user.getPassword())) { String pwd = aesEncryptUtil.decrypt(loginParam.getPassword());
if (!strategy.verifyCredential(pwd, user.getPassword())) {
logLoginAttempt(loginParam, user, false, loginAttempt, "密码错误"); logLoginAttempt(loginParam, user, false, loginAttempt, "密码错误");
return ResultDomain.failure("密码错误"); return ResultDomain.failure("密码错误");
} }

View File

@@ -7,6 +7,7 @@ import org.xyzh.auth.strategy.LoginStrategy;
import org.xyzh.common.core.domain.LoginParam; import org.xyzh.common.core.domain.LoginParam;
import org.xyzh.common.dto.sys.TbSysUserDTO; import org.xyzh.common.dto.sys.TbSysUserDTO;
import org.xyzh.common.utils.NonUtils; import org.xyzh.common.utils.NonUtils;
import org.xyzh.common.utils.crypto.AesEncryptUtil;
import org.xyzh.common.utils.validation.method.EmailValidateMethod; import org.xyzh.common.utils.validation.method.EmailValidateMethod;
import org.xyzh.common.utils.validation.method.PhoneValidateMethod; import org.xyzh.common.utils.validation.method.PhoneValidateMethod;
import org.xyzh.api.system.service.SysUserService; import org.xyzh.api.system.service.SysUserService;
@@ -77,6 +78,7 @@ public class PasswordLoginStrategy implements LoginStrategy {
@Override @Override
public boolean verifyCredential(String inputCredential, String storedCredential) { public boolean verifyCredential(String inputCredential, String storedCredential) {
// 使用BCrypt的matches方法验证密码内部会自动处理salt // 使用BCrypt的matches方法验证密码内部会自动处理salt
logger.info(passwordEncoder.encode(inputCredential));
return passwordEncoder.matches(inputCredential, storedCredential); return passwordEncoder.matches(inputCredential, storedCredential);
} }
} }

View File

@@ -5,10 +5,11 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.xyzh.auth.strategy.LoginStrategy; import org.xyzh.auth.strategy.LoginStrategy;
import org.xyzh.common.core.domain.LoginParam; import org.xyzh.common.core.domain.LoginParam;
import org.xyzh.common.dto.sys.TbSysUserDTO;
import org.xyzh.api.system.service.SysUserService; import org.xyzh.api.system.service.SysUserService;
import org.xyzh.api.system.vo.SysUserVO; import org.xyzh.api.system.vo.SysUserVO;
import org.xyzh.common.redis.service.RedisService; import org.xyzh.common.redis.service.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* @description PhoneLoginStrategy.java文件描述 手机号登录策略 * @description PhoneLoginStrategy.java文件描述 手机号登录策略
@@ -19,6 +20,7 @@ import org.xyzh.common.redis.service.RedisService;
*/ */
@Component @Component
public class PhoneLoginStrategy implements LoginStrategy { public class PhoneLoginStrategy implements LoginStrategy {
private static final Logger logger = LoggerFactory.getLogger(PhoneLoginStrategy.class);
@Autowired @Autowired
private SysUserService userService; private SysUserService userService;
@@ -57,7 +59,6 @@ public class PhoneLoginStrategy implements LoginStrategy {
@Override @Override
public boolean verifyCredential(String inputCredential, String storedCredential) { public boolean verifyCredential(String inputCredential, String storedCredential) {
// 密码验证
return passwordEncoder.matches(inputCredential, storedCredential); return passwordEncoder.matches(inputCredential, storedCredential);
} }

View File

@@ -1,18 +1,20 @@
# ================== Server ================== # ================== Server ==================
server: server:
port: 8181 port: 8181
servlet: # servlet:
context-path: /urban-lifeline/auth # context-path: /urban-lifeline/auth # 微服务架构下context-path由Gateway管理服务本身不需要设置
# ================== Auth ==================== # ================== Auth ====================
urban-lifeline: auth:
auth:
enabled: false # 认证服务自己不需要认证 enabled: false # 认证服务自己不需要认证
gateway-mode: false # 不使用gateway模式auth服务作为独立服务
whitelist: whitelist:
- /** # 认证服务的所有接口都放行 - /** # 认证服务的所有接口都放行
security: security:
aes: aes:
secret-key: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI= # Base64 编码,32字节256位 # AES-256 密钥(Base64编码必须与所有服务保持一致
# 警告:这是开发环境密钥,生产环境请使用密钥管理系统
secret-key: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=
# ================== Spring ================== # ================== Spring ==================
spring: spring:
application: application:

View File

@@ -1,8 +1,8 @@
# ================== Server ================== # ================== Server ==================
server: server:
port: 8186 port: 8186
servlet: # servlet:
context-path: /urban-lifeline/bidding # context-path: /urban-lifeline/bidding # 微服务架构下context-path由Gateway管理
# ================== Auth ==================== # ================== Auth ====================
urban-lifeline: urban-lifeline:

View File

@@ -30,6 +30,11 @@
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.xyzh.common</groupId>
<artifactId>common-utils</artifactId>
<version>${urban-lifeline.version}</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -3,6 +3,10 @@ package org.xyzh.common.dto.sys;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.xyzh.common.dto.BaseDTO; import org.xyzh.common.dto.BaseDTO;
import org.xyzh.common.utils.crypto.AesEncryptUtil;
import org.xyzh.common.utils.crypto.EncryptedStringTypeHandler;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
/** /**
@@ -29,6 +33,7 @@ public class TbSysUserDTO extends BaseDTO {
@Schema(description = "邮箱") @Schema(description = "邮箱")
private String email; private String email;
@TableField(typeHandler = EncryptedStringTypeHandler.class)
@Schema(description = "手机(加密)") @Schema(description = "手机(加密)")
private String phone; private String phone;
@@ -41,7 +46,10 @@ public class TbSysUserDTO extends BaseDTO {
@Schema(description = "用户状态") @Schema(description = "用户状态")
private String status; private String status;
@Schema(description = "用户类型")
private String userType; public void setPhone(String phone){
this.phone = phone;
this.phoneHash = AesEncryptUtil.maskPhone(phone);
}
} }

View File

@@ -36,7 +36,10 @@
<artifactId>mybatis</artifactId> <artifactId>mybatis</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- Spring Boot (用于加密工具) --> <!-- Spring Boot (用于加密工具) -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@@ -35,13 +35,24 @@ public class AesEncryptUtil {
* 从配置文件读取密钥,如果没有则生成新密钥 * 从配置文件读取密钥,如果没有则生成新密钥
*/ */
public AesEncryptUtil(@Value("${security.aes.secret-key:}") String secretKeyString) { public AesEncryptUtil(@Value("${security.aes.secret-key:}") String secretKeyString) {
try {
if (secretKeyString == null || secretKeyString.isEmpty()) { if (secretKeyString == null || secretKeyString.isEmpty()) {
// 生产环境应该从配置中心或密钥管理系统获取 // 生产环境应该从配置中心或密钥管理系统获取
this.secretKey = generateKey(); this.secretKey = generateKey();
System.err.println("警告: 未配置 AES 密钥,使用临时生成的密钥。生产环境请配置 security.aes.secret-key"); System.err.println("警告: 未配置 AES 密钥,使用临时生成的密钥。生产环境请配置 security.aes.secret-key");
} else { } else {
byte[] decodedKey = Base64.getDecoder().decode(secretKeyString); byte[] decodedKey = Base64.getDecoder().decode(secretKeyString);
if (decodedKey.length != 32) {
throw new IllegalArgumentException("AES-256 密钥长度必须是 32 字节,当前: " + decodedKey.length);
}
this.secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, ALGORITHM); this.secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, ALGORITHM);
System.out.println("✓ AES-256 加密工具初始化成功");
}
} catch (Exception e) {
System.err.println("❌ AES 密钥初始化失败: " + e.getMessage());
// 生成临时密钥以避免启动失败
this.secretKey = generateKey();
System.err.println("已生成临时密钥,请尽快配置正确的 security.aes.secret-key");
} }
} }
@@ -169,9 +180,32 @@ public class AesEncryptUtil {
} }
/** /**
* 脱敏显示手机号 * 生成手机号Hash用于数据库查询
* 使用SHA-256生成固定Hash相同手机号总是得到相同Hash
*/ */
public static String maskPhone(String phone) { public static String maskPhone(String phone) {
if (phone == null || phone.isEmpty()) {
return phone;
}
try {
java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(phone.getBytes(java.nio.charset.StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (Exception e) {
throw new RuntimeException("生成手机号Hash失败", e);
}
}
/**
* 脱敏显示手机号(用于前端显示)
*/
public static String maskPhoneDisplay(String phone) {
if (phone == null || phone.length() < 11) { if (phone == null || phone.length() < 11) {
return phone; return phone;
} }
@@ -187,4 +221,26 @@ public class AesEncryptUtil {
} }
return idCard.substring(0, 6) + "********" + idCard.substring(14); return idCard.substring(0, 6) + "********" + idCard.substring(14);
} }
public static void main(String[] args) {
AesEncryptUtil aesEncryptUtil = new AesEncryptUtil("MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=");
String phone = "17857100375";
// 测试加密(每次都不同,不能用于查询)
String encryptedPhone1 = aesEncryptUtil.encryptPhone(phone);
String encryptedPhone2 = aesEncryptUtil.encryptPhone(phone);
System.out.println("第一次加密: " + encryptedPhone1);
System.out.println("第二次加密: " + encryptedPhone2);
System.out.println("两次加密相同? " + encryptedPhone1.equals(encryptedPhone2));
// 测试Hash用于查询相同手机号总是得到相同Hash
String hash1 = AesEncryptUtil.maskPhone(phone);
String hash2 = AesEncryptUtil.maskPhone(phone);
System.out.println("\n第一次Hash: " + hash1);
System.out.println("第二次Hash: " + hash2);
System.out.println("两次Hash相同? " + hash1.equals(hash2));
// 测试脱敏显示
System.out.println("\n脱敏显示: " + AesEncryptUtil.maskPhoneDisplay(phone));
}
} }

View File

@@ -0,0 +1,37 @@
package org.xyzh.common.utils.crypto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import jakarta.annotation.PostConstruct;
/**
* TypeHandler 配置类
* 用于初始化 EncryptedStringTypeHandler 中的 AesEncryptUtil
*
* @author yslg
* @since 2025-12-11
*/
@Configuration
@ConditionalOnClass(AesEncryptUtil.class)
public class TypeHandlerConfig {
private final AesEncryptUtil aesEncryptUtil;
@Autowired(required = false)
public TypeHandlerConfig(AesEncryptUtil aesEncryptUtil) {
this.aesEncryptUtil = aesEncryptUtil;
}
@PostConstruct
public void init() {
// 初始化 TypeHandler 中的静态 AesEncryptUtil 实例
if (aesEncryptUtil != null) {
EncryptedStringTypeHandler.setAesEncryptUtil(aesEncryptUtil);
System.out.println("✓ TypeHandler 已初始化 AES 加密工具");
} else {
System.err.println("警告: AesEncryptUtil 未能注入,加密功能可能无法正常工作");
}
}
}

View File

@@ -1,8 +1,8 @@
# ================== Server ================== # ================== Server ==================
server: server:
port: 8189 port: 8189
servlet: # servlet:
context-path: /urban-lifeline/crontab # context-path: /urban-lifeline/crontab # 微服务架构下context-path由Gateway管理
# ================== Auth ==================== # ================== Auth ====================
urban-lifeline: urban-lifeline:

View File

@@ -1,8 +1,8 @@
# ================== Server ================== # ================== Server ==================
server: server:
port: 8184 port: 8184
servlet: # servlet:
context-path: /urban-lifeline/file # context-path: /urban-lifeline/file # 微服务架构下context-path由Gateway管理
# ================== Auth ==================== # ================== Auth ====================
urban-lifeline: urban-lifeline:

View File

@@ -28,20 +28,9 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId> <artifactId>spring-boot-starter-logging</artifactId>
</exclusion> </exclusion>
<!-- 排除旧的 gateway-server使用新的 webflux 版本 -->
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-server</artifactId>
</exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<!-- 明确使用新的 WebFlux Gateway Server推荐 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-server-webflux</artifactId>
</dependency>
<!-- Nacos 服务注册与发现 --> <!-- Nacos 服务注册与发现 -->
<dependency> <dependency>
<groupId>com.alibaba.cloud</groupId> <groupId>com.alibaba.cloud</groupId>

View File

@@ -7,6 +7,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.FilterType;
import org.xyzh.common.auth.config.SecurityConfig; import org.xyzh.common.auth.config.SecurityConfig;
import org.xyzh.common.auth.config.WebMvcConfig;
import org.xyzh.common.auth.config.GatewayAuthConfig;
/** /**
* @description Gateway 网关启动类 * @description Gateway 网关启动类
@@ -23,8 +25,12 @@ import org.xyzh.common.auth.config.SecurityConfig;
"org.xyzh.common" // 公共模块(包括 common-auth "org.xyzh.common" // 公共模块(包括 common-auth
}, },
excludeFilters = { excludeFilters = {
// 排除 Spring MVC 的 SecurityConfigGateway 使用 WebFlux Security // 排除 Spring MVC 相关配置Gateway 使用 WebFlux
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class) @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
SecurityConfig.class, // Spring MVC Security配置
WebMvcConfig.class, // Spring MVC配置
GatewayAuthConfig.class // 微服务Gateway模式配置使用Servlet Filter
})
} }
) )
public class GatewayApplication { public class GatewayApplication {

View File

@@ -0,0 +1,32 @@
package org.xyzh.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
/**
* Gateway WebFlux Security 配置
* 完全禁用Spring Security的默认行为由AuthGlobalFilter处理认证
*
* @author yslg
* @since 2025-12-11
*/
@Configuration
@EnableWebFluxSecurity
public class GatewaySecurityConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.formLogin(ServerHttpSecurity.FormLoginSpec::disable)
.httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
.logout(ServerHttpSecurity.LogoutSpec::disable)
.authorizeExchange(exchange -> exchange
.anyExchange().permitAll() // 允许所有请求由AuthGlobalFilter处理认证
)
.build();
}
}

View File

@@ -0,0 +1,59 @@
package org.xyzh.gateway.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Gateway诊断控制器 - 用于检查路由配置
*
* @author yslg
* @since 2025-12-11
*/
@RestController
@RequestMapping("/gateway-diagnostic")
public class GatewayDiagnosticController {
@Autowired
private RouteLocator routeLocator;
/**
* 获取所有路由信息
* 访问: http://localhost:8180/gateway-diagnostic/routes
*/
@GetMapping("/routes")
public Flux<Map<String, Object>> getRoutes() {
return routeLocator.getRoutes()
.map(route -> {
Map<String, Object> routeInfo = new HashMap<>();
routeInfo.put("id", route.getId());
routeInfo.put("uri", route.getUri().toString());
routeInfo.put("order", route.getOrder());
routeInfo.put("predicates", route.getPredicate().toString());
routeInfo.put("filters", route.getFilters().toString());
return routeInfo;
});
}
/**
* 健康检查
* 访问: http://localhost:8180/gateway-diagnostic/health
*/
@GetMapping("/health")
public Map<String, Object> health() {
Map<String, Object> health = new HashMap<>();
health.put("status", "UP");
health.put("message", "Gateway is running");
health.put("timestamp", System.currentTimeMillis());
return health;
}
}

View File

@@ -1,16 +1,6 @@
spring: # 开发环境专用配置
cloud: # 注意不要在这里配置routes会覆盖application.yml的配置
gateway: # 路由配置统一在application.yml中管理
server:
webflux:
routes:
# 开发环境可以添加更详细的路由配置或测试路由
# Nacos 管理界面路由(开发专用)
- id: nacos-console
uri: http://${NACOS_SERVER_ADDR:localhost:8848}
predicates:
- Path=/nacos/**
# 开发环境日志 # 开发环境日志
logging: logging:

View File

@@ -17,15 +17,14 @@ spring:
namespace: dev namespace: dev
group: DEFAULT_GROUP group: DEFAULT_GROUP
config: config:
enabled: false # 禁用Nacos配置中心使用本地配置
server-addr: ${NACOS_SERVER_ADDR:localhost:8848} server-addr: ${NACOS_SERVER_ADDR:localhost:8848}
file-extension: yml file-extension: yml
namespace: dev namespace: dev
group: DEFAULT_GROUP group: DEFAULT_GROUP
# Gateway 路由配置(使用新的 webflux 配置路径) # Gateway 路由配置
gateway: gateway:
server:
webflux:
# 服务发现路由(自动路由) # 服务发现路由(自动路由)
discovery: discovery:
locator: locator:
@@ -39,7 +38,7 @@ spring:
predicates: predicates:
- Path=/urban-lifeline/auth/** - Path=/urban-lifeline/auth/**
filters: filters:
# 不需要重写,直接转发保持原路径 - StripPrefix=1 # 去掉前缀:/urban-lifeline/auth/login → /auth/login
- name: RequestRateLimiter - name: RequestRateLimiter
args: args:
redis-rate-limiter.replenishRate: 100 redis-rate-limiter.replenishRate: 100
@@ -50,54 +49,72 @@ spring:
uri: lb://system-service uri: lb://system-service
predicates: predicates:
- Path=/urban-lifeline/system/** - Path=/urban-lifeline/system/**
filters:
- StripPrefix=1
# ==================== 日志服务路由 ==================== # ==================== 日志服务路由 ====================
- id: log-service - id: log-service
uri: lb://log-service uri: lb://log-service
predicates: predicates:
- Path=/urban-lifeline/log/** - Path=/urban-lifeline/log/**
filters:
- StripPrefix=1
# ==================== 文件服务路由 ==================== # ==================== 文件服务路由 ====================
- id: file-service - id: file-service
uri: lb://file-service uri: lb://file-service
predicates: predicates:
- Path=/urban-lifeline/file/** - Path=/urban-lifeline/file/**
filters:
- StripPrefix=1
# ==================== 消息服务路由 ==================== # ==================== 消息服务路由 ====================
- id: message-service - id: message-service
uri: lb://message-service uri: lb://message-service
predicates: predicates:
- Path=/urban-lifeline/message/** - Path=/urban-lifeline/message/**
filters:
- StripPrefix=1
# ==================== 招投标服务路由 ==================== # ==================== 招投标服务路由 ====================
- id: bidding-service - id: bidding-service
uri: lb://bidding-service uri: lb://bidding-service
predicates: predicates:
- Path=/urban-lifeline/bidding/** - Path=/urban-lifeline/bidding/**
filters:
- StripPrefix=1
# ==================== 平台服务路由 ==================== # ==================== 平台服务路由 ====================
- id: platform-service - id: platform-service
uri: lb://platform-service uri: lb://platform-service
predicates: predicates:
- Path=/urban-lifeline/platform/** - Path=/urban-lifeline/platform/**
filters:
- StripPrefix=1
# ==================== 工单服务路由 ==================== # ==================== 工单服务路由 ====================
- id: workcase-service - id: workcase-service
uri: lb://workcase-service uri: lb://workcase-service
predicates: predicates:
- Path=/urban-lifeline/workcase/** - Path=/urban-lifeline/workcase/**
filters:
- StripPrefix=1
# ==================== 定时任务服务路由 ==================== # ==================== 定时任务服务路由 ====================
- id: crontab-service - id: crontab-service
uri: lb://crontab-service uri: lb://crontab-service
predicates: predicates:
- Path=/urban-lifeline/crontab/** - Path=/urban-lifeline/crontab/**
filters:
- StripPrefix=1
# ==================== AI Agent 服务路由 ==================== # ==================== AI Agent 服务路由 ====================
- id: agent-service - id: agent-service
uri: lb://agent-service uri: lb://agent-service
predicates: predicates:
- Path=/urban-lifeline/agent/** - Path=/urban-lifeline/agent/**
filters:
- StripPrefix=1
# 全局跨域配置 # 全局跨域配置
globalcors: globalcors:
@@ -137,7 +154,7 @@ spring:
# 认证配置 # 认证配置
auth: auth:
enabled: true enabled: true
gateway-mode: true # gateway-mode 是给下游微服务用的gateway本身不需要此配置
token-header: Authorization token-header: Authorization
token-prefix: "Bearer " token-prefix: "Bearer "
# 认证接口白名单login/logout/captcha/refresh # 认证接口白名单login/logout/captcha/refresh

View File

@@ -1,8 +1,8 @@
# ================== Server ================== # ================== Server ==================
server: server:
port: 8183 port: 8183
servlet: # servlet:
context-path: /urban-lifeline/log # context-path: /urban-lifeline/log # 微服务架构下context-path由Gateway管理
# ================== Auth ==================== # ================== Auth ====================
urban-lifeline: urban-lifeline:

View File

@@ -1,8 +1,8 @@
# ================== Server ================== # ================== Server ==================
server: server:
port: 8185 port: 8185
servlet: # servlet:
context-path: /urban-lifeline/message # context-path: /urban-lifeline/message # 微服务架构下context-path由Gateway管理
# ================== Auth ==================== # ================== Auth ====================
urban-lifeline: urban-lifeline:

View File

@@ -1,8 +1,8 @@
# ================== Server ================== # ================== Server ==================
server: server:
port: 8187 port: 8187
servlet: # servlet:
context-path: /urban-lifeline/platform # context-path: /urban-lifeline/platform # 微服务架构下context-path由Gateway管理
# ================== Auth ==================== # ================== Auth ====================
urban-lifeline: urban-lifeline:

View File

@@ -82,8 +82,7 @@ public class SysUserServiceImpl implements SysUserService {
if (StringUtils.isBlank(dto.getUserId())) { if (StringUtils.isBlank(dto.getUserId())) {
dto.setUserId(IDUtils.generateID()); dto.setUserId(IDUtils.generateID());
} }
dto.setPhone(aesEncryptUtil.encrypt(userVO.getPhone())); dto.setPhone(userVO.getPhone());
dto.setPhoneHash(AesEncryptUtil.maskPhone(userVO.getPhone()));
dto.setCreateTime(now); dto.setCreateTime(now);
dto.setDeleted(false); dto.setDeleted(false);
@@ -142,8 +141,7 @@ public class SysUserServiceImpl implements SysUserService {
// 检查手机号是否存在 // 检查手机号是否存在
if (StringUtils.isNotBlank(userVO.getPhone())) { if (StringUtils.isNotBlank(userVO.getPhone())) {
filter = new SysUserVO(); filter = new SysUserVO();
filter.setPhone(aesEncryptUtil.encrypt(userVO.getPhone())); filter.setPhone(userVO.getPhone());
filter.setPhoneHash(AesEncryptUtil.maskPhone(userVO.getPhone()));
List<SysUserVO> users = userMapper.getUserByFilter(filter); List<SysUserVO> users = userMapper.getUserByFilter(filter);
if (users != null && !users.isEmpty()) { if (users != null && !users.isEmpty()) {
logger.warn("手机号已存在: {}", userVO.getPhone()); logger.warn("手机号已存在: {}", userVO.getPhone());
@@ -228,8 +226,7 @@ public class SysUserServiceImpl implements SysUserService {
public ResultDomain<SysUserVO> getLoginUser(SysUserVO filter) { public ResultDomain<SysUserVO> getLoginUser(SysUserVO filter) {
// 登录查询语义与 getUser 相同(可根据用户名/手机号/邮箱查询) // 登录查询语义与 getUser 相同(可根据用户名/手机号/邮箱查询)
if(NonUtils.isNotNull(filter.getPhone())){ if(NonUtils.isNotNull(filter.getPhone())){
filter.setPhone(aesEncryptUtil.encrypt(filter.getPhone())); filter.setPhone(filter.getPhone());
filter.setPhoneHash(AesEncryptUtil.maskPhone(filter.getPhone()));
} }
SysUserVO userVO = userMapper.getUserByFilter(filter).get(0); SysUserVO userVO = userMapper.getUserByFilter(filter).get(0);
return ResultDomain.success("查询成功", userVO); return ResultDomain.success("查询成功", userVO);

View File

@@ -35,6 +35,13 @@ urban-lifeline:
# - /api/public/** # - /api/public/**
# ================== Security ==================
security:
aes:
# AES-256 密钥Base64编码
# 警告:这是开发环境密钥,生产环境请使用密钥管理系统
secret-key: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=
# ================== Spring ================== # ================== Spring ==================
spring: spring:
# ================== DataSource ================== # ================== DataSource ==================

View File

@@ -1,8 +1,8 @@
# ================== Server ================== # ================== Server ==================
server: server:
port: 8182 port: 8182
servlet: # servlet:
context-path: /urban-lifeline/system # context-path: /urban-lifeline/system # 微服务架构下context-path由Gateway管理
# ================== Auth ==================== # ================== Auth ====================
urban-lifeline: urban-lifeline:
auth: auth:

View File

@@ -8,17 +8,13 @@
<id column="user_id" property="userId" jdbcType="VARCHAR"/> <id column="user_id" property="userId" jdbcType="VARCHAR"/>
<result column="avatar" property="avatar" jdbcType="VARCHAR"/> <result column="avatar" property="avatar" jdbcType="VARCHAR"/>
<result column="gender" property="gender" jdbcType="INTEGER"/> <result column="gender" property="gender" jdbcType="INTEGER"/>
<result column="family_name" property="familyName" jdbcType="VARCHAR"/> <result column="username" property="username" jdbcType="VARCHAR"/>
<result column="given_name" property="givenName" jdbcType="VARCHAR"/>
<result column="full_name" property="fullName" jdbcType="VARCHAR"/>
<result column="level" property="level" jdbcType="INTEGER"/> <result column="level" property="level" jdbcType="INTEGER"/>
<result column="id_card" property="idCard" jdbcType="VARCHAR"/> <result column="id_card" property="idCard" jdbcType="VARCHAR"/>
<result column="address" property="address" jdbcType="VARCHAR"/> <result column="address" property="address" jdbcType="VARCHAR"/>
<!-- 基础字段 --> <!-- 基础字段 -->
<result column="optsn" property="optsn" jdbcType="VARCHAR"/> <result column="optsn" property="optsn" jdbcType="VARCHAR"/>
<result column="creator" property="creator" jdbcType="VARCHAR"/> <result column="creator" property="creator" jdbcType="VARCHAR"/>
<result column="updater" property="updater" jdbcType="VARCHAR"/>
<result column="dept_path" property="deptPath" jdbcType="VARCHAR"/>
<result column="remark" property="remark" jdbcType="VARCHAR"/> <result column="remark" property="remark" jdbcType="VARCHAR"/>
<result column="create_time" property="createTime" jdbcType="DATE"/> <result column="create_time" property="createTime" jdbcType="DATE"/>
<result column="update_time" property="updateTime" jdbcType="DATE"/> <result column="update_time" property="updateTime" jdbcType="DATE"/>
@@ -28,8 +24,8 @@
<!-- 基础列 --> <!-- 基础列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
user_id, avatar, gender, family_name, given_name, full_name, level, id_card, address, user_id, avatar, gender, username, level, id_card, address,
optsn, creator, updater, dept_path, remark, create_time, update_time, delete_time, deleted optsn, creator, remark, create_time, update_time, delete_time, deleted
</sql> </sql>
<!-- 插入系统用户信息(按表字段 + 默认值动态列,仅修改 insert --> <!-- 插入系统用户信息(按表字段 + 默认值动态列,仅修改 insert -->
@@ -42,9 +38,7 @@
<!-- 可空/有默认值字段:按是否有入参动态拼接 --> <!-- 可空/有默认值字段:按是否有入参动态拼接 -->
<if test="avatar != null and avatar != ''">avatar,</if> <if test="avatar != null and avatar != ''">avatar,</if>
<if test="gender != null">gender,</if> <if test="gender != null">gender,</if>
<if test="familyName != null and familyName != ''">family_name,</if> <if test="username != null and username != ''">username,</if>
<if test="givenName != null and givenName != ''">given_name,</if>
<if test="fullName != null and fullName != ''">full_name,</if>
<if test="level != null">level,</if> <if test="level != null">level,</if>
<if test="idCard != null and idCard != ''">id_card,</if> <if test="idCard != null and idCard != ''">id_card,</if>
<if test="address != null and address != ''">address,</if> <if test="address != null and address != ''">address,</if>
@@ -61,9 +55,7 @@
<!-- 可空/有默认值字段对应的值 --> <!-- 可空/有默认值字段对应的值 -->
<if test="avatar != null and avatar != ''">#{avatar},</if> <if test="avatar != null and avatar != ''">#{avatar},</if>
<if test="gender != null">#{gender},</if> <if test="gender != null">#{gender},</if>
<if test="familyName != null and familyName != ''">#{familyName},</if> <if test="username != null and username != ''">#{username},</if>
<if test="givenName != null and givenName != ''">#{givenName},</if>
<if test="fullName != null and fullName != ''">#{fullName},</if>
<if test="level != null">#{level},</if> <if test="level != null">#{level},</if>
<if test="idCard != null and idCard != ''">#{idCard},</if> <if test="idCard != null and idCard != ''">#{idCard},</if>
<if test="address != null and address != ''">#{address},</if> <if test="address != null and address != ''">#{address},</if>
@@ -84,14 +76,8 @@
<if test="gender != null"> <if test="gender != null">
gender = #{gender}, gender = #{gender},
</if> </if>
<if test="familyName != null"> <if test="username != null">
family_name = #{familyName}, username = #{username},
</if>
<if test="givenName != null">
given_name = #{givenName},
</if>
<if test="fullName != null">
full_name = #{fullName},
</if> </if>
<if test="level != null"> <if test="level != null">
level = #{level}, level = #{level},
@@ -102,12 +88,6 @@
<if test="address != null"> <if test="address != null">
address = #{address}, address = #{address},
</if> </if>
<if test="updater != null and updater != ''">
updater = #{updater},
</if>
<if test="deptPath != null and deptPath != ''">
dept_path = #{deptPath},
</if>
<if test="remark != null"> <if test="remark != null">
remark = #{remark}, remark = #{remark},
</if> </if>
@@ -147,14 +127,8 @@
<if test="filter.userId != null and filter.userId != ''"> <if test="filter.userId != null and filter.userId != ''">
AND user_id = #{filter.userId} AND user_id = #{filter.userId}
</if> </if>
<if test="filter.fullName != null and filter.fullName != ''"> <if test="filter.username != null and filter.username != ''">
AND full_name LIKE CONCAT('%', #{filter.fullName}, '%') AND username LIKE CONCAT('%', #{filter.username}, '%')
</if>
<if test="filter.familyName != null and filter.familyName != ''">
AND family_name LIKE CONCAT('%', #{filter.familyName}, '%')
</if>
<if test="filter.givenName != null and filter.givenName != ''">
AND given_name LIKE CONCAT('%', #{filter.givenName}, '%')
</if> </if>
<if test="filter.idCard != null and filter.idCard != ''"> <if test="filter.idCard != null and filter.idCard != ''">
AND id_card = #{filter.idCard} AND id_card = #{filter.idCard}
@@ -162,9 +136,6 @@
<if test="filter.gender != null"> <if test="filter.gender != null">
AND gender = #{filter.gender} AND gender = #{filter.gender}
</if> </if>
<if test="filter.deptPath != null and filter.deptPath != ''">
AND dept_path LIKE CONCAT(#{filter.deptPath}, '%')
</if>
AND (deleted IS NULL OR deleted = false) AND (deleted IS NULL OR deleted = false)
</where> </where>
ORDER BY create_time DESC ORDER BY create_time DESC
@@ -179,14 +150,8 @@
<if test="filter.userId != null and filter.userId != ''"> <if test="filter.userId != null and filter.userId != ''">
AND user_id = #{filter.userId} AND user_id = #{filter.userId}
</if> </if>
<if test="filter.fullName != null and filter.fullName != ''"> <if test="filter.username != null and filter.username != ''">
AND full_name LIKE CONCAT('%', #{filter.fullName}, '%') AND username LIKE CONCAT('%', #{filter.username}, '%')
</if>
<if test="filter.familyName != null and filter.familyName != ''">
AND family_name LIKE CONCAT('%', #{filter.familyName}, '%')
</if>
<if test="filter.givenName != null and filter.givenName != ''">
AND given_name LIKE CONCAT('%', #{filter.givenName}, '%')
</if> </if>
<if test="filter.idCard != null and filter.idCard != ''"> <if test="filter.idCard != null and filter.idCard != ''">
AND id_card = #{filter.idCard} AND id_card = #{filter.idCard}
@@ -194,9 +159,6 @@
<if test="filter.gender != null"> <if test="filter.gender != null">
AND gender = #{filter.gender} AND gender = #{filter.gender}
</if> </if>
<if test="filter.deptPath != null and filter.deptPath != ''">
AND dept_path LIKE CONCAT(#{filter.deptPath}, '%')
</if>
AND (deleted IS NULL OR deleted = false) AND (deleted IS NULL OR deleted = false)
</where> </where>
ORDER BY create_time DESC ORDER BY create_time DESC
@@ -211,14 +173,8 @@
<if test="filter.userId != null and filter.userId != ''"> <if test="filter.userId != null and filter.userId != ''">
AND user_id = #{filter.userId} AND user_id = #{filter.userId}
</if> </if>
<if test="filter.fullName != null and filter.fullName != ''"> <if test="filter.username != null and filter.username != ''">
AND full_name LIKE CONCAT('%', #{filter.fullName}, '%') AND username LIKE CONCAT('%', #{filter.username}, '%')
</if>
<if test="filter.familyName != null and filter.familyName != ''">
AND family_name LIKE CONCAT('%', #{filter.familyName}, '%')
</if>
<if test="filter.givenName != null and filter.givenName != ''">
AND given_name LIKE CONCAT('%', #{filter.givenName}, '%')
</if> </if>
<if test="filter.idCard != null and filter.idCard != ''"> <if test="filter.idCard != null and filter.idCard != ''">
AND id_card = #{filter.idCard} AND id_card = #{filter.idCard}
@@ -226,9 +182,6 @@
<if test="filter.gender != null"> <if test="filter.gender != null">
AND gender = #{filter.gender} AND gender = #{filter.gender}
</if> </if>
<if test="filter.deptPath != null and filter.deptPath != ''">
AND dept_path LIKE CONCAT(#{filter.deptPath}, '%')
</if>
AND (deleted IS NULL OR deleted = false) AND (deleted IS NULL OR deleted = false)
</where> </where>
</select> </select>

View File

@@ -8,12 +8,13 @@
<id column="user_id" property="userId" jdbcType="VARCHAR"/> <id column="user_id" property="userId" jdbcType="VARCHAR"/>
<result column="password" property="password" jdbcType="VARCHAR"/> <result column="password" property="password" jdbcType="VARCHAR"/>
<result column="email" property="email" jdbcType="VARCHAR"/> <result column="email" property="email" jdbcType="VARCHAR"/>
<result column="phone" property="phone" jdbcType="VARCHAR"/> <result column="phone" property="phone" jdbcType="VARCHAR" typeHandler="org.xyzh.common.utils.crypto.EncryptedStringTypeHandler"/>
<result column="wechat_id" property="wechatId" jdbcType="VARCHAR"/> <result column="wechat_id" property="wechatId" jdbcType="VARCHAR"/>
<result column="status" property="status" jdbcType="INTEGER"/> <result column="status" property="status" jdbcType="INTEGER"/>
<!-- BaseDTO 中在该表实际存在的字段 --> <!-- BaseDTO 中在该表实际存在的字段 -->
<result column="optsn" property="optsn" jdbcType="VARCHAR"/> <result column="optsn" property="optsn" jdbcType="VARCHAR"/>
<result column="creator" property="creator" jdbcType="VARCHAR"/>
<result column="create_time" property="createTime" jdbcType="DATE"/> <result column="create_time" property="createTime" jdbcType="DATE"/>
<result column="update_time" property="updateTime" jdbcType="DATE"/> <result column="update_time" property="updateTime" jdbcType="DATE"/>
<result column="delete_time" property="deleteTime" jdbcType="DATE"/> <result column="delete_time" property="deleteTime" jdbcType="DATE"/>
@@ -26,15 +27,15 @@
<id column="user_id" property="userId" jdbcType="VARCHAR"/> <id column="user_id" property="userId" jdbcType="VARCHAR"/>
<result column="password" property="password" jdbcType="VARCHAR"/> <result column="password" property="password" jdbcType="VARCHAR"/>
<result column="email" property="email" jdbcType="VARCHAR"/> <result column="email" property="email" jdbcType="VARCHAR"/>
<result column="phone" property="phone" jdbcType="VARCHAR"/> <result column="phone" property="phone" jdbcType="VARCHAR" typeHandler="org.xyzh.common.utils.crypto.EncryptedStringTypeHandler"/>
<result column="wechat_id" property="wechatId" jdbcType="VARCHAR"/> <result column="wechat_id" property="wechatId" jdbcType="VARCHAR"/>
<result column="status" property="status" jdbcType="INTEGER"/> <result column="status" property="status" jdbcType="INTEGER"/>
<result column="creator" property="creator" jdbcType="VARCHAR"/>
<!-- 用户信息关联字段 --> <!-- 用户信息关联字段 -->
<result column="avatar" property="avatar" jdbcType="VARCHAR"/> <result column="avatar" property="avatar" jdbcType="VARCHAR"/>
<result column="gender" property="gender" jdbcType="INTEGER"/> <result column="gender" property="gender" jdbcType="INTEGER"/>
<result column="family_name" property="familyName" jdbcType="VARCHAR"/> <result column="username" property="username" jdbcType="VARCHAR"/>
<result column="given_name" property="givenName" jdbcType="VARCHAR"/>
<result column="full_name" property="fullName" jdbcType="VARCHAR"/>
<result column="level" property="level" jdbcType="INTEGER"/> <result column="level" property="level" jdbcType="INTEGER"/>
<result column="id_card" property="idCard" jdbcType="VARCHAR"/> <result column="id_card" property="idCard" jdbcType="VARCHAR"/>
<result column="address" property="address" jdbcType="VARCHAR"/> <result column="address" property="address" jdbcType="VARCHAR"/>
@@ -78,7 +79,7 @@
#{password}, #{password},
<!-- 可空/有默认值字段对应的值 --> <!-- 可空/有默认值字段对应的值 -->
<if test="email != null and email != ''">#{email},</if> <if test="email != null and email != ''">#{email},</if>
<if test="phone != null and phone != ''">#{phone},</if> <if test="phone != null and phone != ''">#{phone, typeHandler=org.xyzh.common.utils.crypto.EncryptedStringTypeHandler},</if>
<if test="wechatId != null and wechatId != ''">#{wechatId},</if> <if test="wechatId != null and wechatId != ''">#{wechatId},</if>
<if test="createTime != null">#{createTime},</if> <if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if> <if test="updateTime != null">#{updateTime},</if>
@@ -102,7 +103,7 @@
email = #{email}, email = #{email},
</if> </if>
<if test="phone != null and phone != ''"> <if test="phone != null and phone != ''">
phone = #{phone}, phone = #{phone, typeHandler=org.xyzh.common.utils.crypto.EncryptedStringTypeHandler},
</if> </if>
<if test="wechatId != null and wechatId != ''"> <if test="wechatId != null and wechatId != ''">
wechat_id = #{wechatId}, wechat_id = #{wechatId},
@@ -110,12 +111,6 @@
<if test="status != null and status != ''"> <if test="status != null and status != ''">
status = #{status}, status = #{status},
</if> </if>
<if test="userType != null and userType != ''">
user_type = #{userType},
</if>
<if test="updater != null and updater != ''">
updater = #{updater},
</if>
<if test="deptPath != null and deptPath != ''"> <if test="deptPath != null and deptPath != ''">
dept_path = #{deptPath}, dept_path = #{deptPath},
</if> </if>
@@ -145,7 +140,7 @@
SELECT SELECT
u.user_id, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_id, u.password, u.email, u.phone, u.wechat_id, u.status,
u.optsn, u.create_time, u.update_time, u.delete_time, u.deleted, u.optsn, u.create_time, u.update_time, u.delete_time, u.deleted,
ui.avatar, ui.gender, ui.family_name, ui.given_name, ui.full_name, ui.level, ui.id_card, ui.address ui.avatar, ui.gender, ui.username, ui.level, ui.id_card, ui.address
FROM sys.tb_sys_user u FROM sys.tb_sys_user u
LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false) LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false)
WHERE u.user_id = #{userId} WHERE u.user_id = #{userId}
@@ -155,9 +150,9 @@
<!-- 根据条件查询用户列表 --> <!-- 根据条件查询用户列表 -->
<select id="getUserByFilter" resultMap="UserVOResultMap"> <select id="getUserByFilter" resultMap="UserVOResultMap">
SELECT SELECT
u.user_id, u.username, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_type, u.user_id, ui.username, u.password, u.email, u.phone, u.wechat_id, u.status,
u.optsn, u.creator, u.updater, u.dept_path, u.remark, u.create_time, u.update_time, u.delete_time, u.deleted, u.optsn, u.creator, u.remark, u.create_time, u.update_time, u.delete_time, u.deleted,
ui.avatar, ui.gender, ui.family_name, ui.given_name, ui.full_name, ui.level, ui.id_card, ui.address ui.avatar, ui.gender, ui.username, ui.level, ui.id_card, ui.address
FROM sys.tb_sys_user u FROM sys.tb_sys_user u
LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false) LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false)
<where> <where>
@@ -167,9 +162,7 @@
<if test="filter.email != null and filter.email != ''"> <if test="filter.email != null and filter.email != ''">
AND u.email = #{filter.email} AND u.email = #{filter.email}
</if> </if>
<if test="filter.phone != null and filter.phone != ''"> <!-- 手机号查询统一使用phoneHash不使用phone字段 -->
AND u.phone = #{filter.phone}
</if>
<if test="filter.phoneHash != null and filter.phoneHash != ''"> <if test="filter.phoneHash != null and filter.phoneHash != ''">
AND u.phone_hash = #{filter.phoneHash} AND u.phone_hash = #{filter.phoneHash}
</if> </if>
@@ -188,9 +181,9 @@
<!-- 根据条件查询用户分页列表 --> <!-- 根据条件查询用户分页列表 -->
<select id="getUserPageByFilter" resultMap="UserVOResultMap"> <select id="getUserPageByFilter" resultMap="UserVOResultMap">
SELECT SELECT
u.user_id, u.username, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_type, u.user_id, ui.username, u.password, u.email, u.phone, u.wechat_id, u.status,
u.optsn, u.creator, u.updater, u.dept_path, u.remark, u.create_time, u.update_time, u.delete_time, u.deleted, u.optsn, u.creator, u.remark, u.create_time, u.update_time, u.delete_time, u.deleted,
ui.avatar, ui.gender, ui.family_name, ui.given_name, ui.full_name, ui.level, ui.id_card, ui.address ui.avatar, ui.gender, ui.username, ui.level, ui.id_card, ui.address
FROM sys.tb_sys_user u FROM sys.tb_sys_user u
LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false) LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false)
<where> <where>
@@ -198,23 +191,18 @@
AND u.user_id = #{filter.userId} AND u.user_id = #{filter.userId}
</if> </if>
<if test="filter.username != null and filter.username != ''"> <if test="filter.username != null and filter.username != ''">
AND u.username LIKE CONCAT('%', #{filter.username}, '%') AND ui.username LIKE CONCAT('%', #{filter.username}, '%')
</if> </if>
<if test="filter.email != null and filter.email != ''"> <if test="filter.email != null and filter.email != ''">
AND u.email = #{filter.email} AND u.email = #{filter.email}
</if> </if>
<if test="filter.phone != null and filter.phone != ''"> <!-- 手机号查询统一使用phoneHash不使用phone字段 -->
AND u.phone = #{filter.phone} <if test="filter.phoneHash != null and filter.phoneHash != ''">
AND u.phone_hash = #{filter.phoneHash}
</if> </if>
<if test="filter.status != null and filter.status != ''"> <if test="filter.status != null and filter.status != ''">
AND u.status = #{filter.status} AND u.status = #{filter.status}
</if> </if>
<if test="filter.userType != null and filter.userType != ''">
AND u.user_type = #{filter.userType}
</if>
<if test="filter.deptPath != null and filter.deptPath != ''">
AND u.dept_path LIKE CONCAT(#{filter.deptPath}, '%')
</if>
AND (u.deleted IS NULL OR u.deleted = false) AND (u.deleted IS NULL OR u.deleted = false)
</where> </where>
ORDER BY u.create_time DESC ORDER BY u.create_time DESC
@@ -232,8 +220,9 @@
<if test="filter.email != null and filter.email != ''"> <if test="filter.email != null and filter.email != ''">
AND email = #{filter.email} AND email = #{filter.email}
</if> </if>
<if test="filter.phone != null and filter.phone != ''"> <!-- 手机号查询统一使用phoneHash不使用phone字段 -->
AND phone = #{filter.phone} <if test="filter.phoneHash != null and filter.phoneHash != ''">
AND phone_hash = #{filter.phoneHash}
</if> </if>
<if test="filter.status != null"> <if test="filter.status != null">
AND status = #{filter.status} AND status = #{filter.status}

View File

@@ -29,13 +29,10 @@
<result column="phone" property="phone" jdbcType="VARCHAR"/> <result column="phone" property="phone" jdbcType="VARCHAR"/>
<result column="wechat_id" property="wechatId" jdbcType="VARCHAR"/> <result column="wechat_id" property="wechatId" jdbcType="VARCHAR"/>
<result column="status" property="status" jdbcType="VARCHAR"/> <result column="status" property="status" jdbcType="VARCHAR"/>
<result column="user_type" property="userType" jdbcType="VARCHAR"/>
<!-- 用户信息字段 --> <!-- 用户信息字段 -->
<result column="avatar" property="avatar" jdbcType="VARCHAR"/> <result column="avatar" property="avatar" jdbcType="VARCHAR"/>
<result column="gender" property="gender" jdbcType="INTEGER"/> <result column="gender" property="gender" jdbcType="INTEGER"/>
<result column="family_name" property="familyName" jdbcType="VARCHAR"/> <result column="username" property="username" jdbcType="VARCHAR"/>
<result column="given_name" property="givenName" jdbcType="VARCHAR"/>
<result column="full_name" property="fullName" jdbcType="VARCHAR"/>
<result column="level" property="level" jdbcType="INTEGER"/> <result column="level" property="level" jdbcType="INTEGER"/>
<result column="id_card" property="idCard" jdbcType="VARCHAR"/> <result column="id_card" property="idCard" jdbcType="VARCHAR"/>
<result column="address" property="address" jdbcType="VARCHAR"/> <result column="address" property="address" jdbcType="VARCHAR"/>
@@ -137,15 +134,15 @@
<!-- 根据用户ID查询系统用户角色关系 --> <!-- 根据用户ID查询系统用户角色关系 -->
<select id="getUserRoleByUserId" resultMap="UserDeptRoleVOResultMap" parameterType="java.lang.String"> <select id="getUserRoleByUserId" resultMap="UserDeptRoleVOResultMap" parameterType="java.lang.String">
SELECT SELECT
u.user_id, u.username, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_type, u.user_id, u.password, u.email, u.phone, u.wechat_id, u.status,
ui.avatar, ui.gender, ui.family_name, ui.given_name, ui.full_name, ui.level, ui.id_card, ui.address, ui.avatar, ui.gender, ui.username, ui.level, ui.id_card, ui.address,
d.dept_id, d.name AS dept_name, d.parent_id, d.description AS dept_description, d.dept_id, d.name AS dept_name, d.parent_id, d.description AS dept_description,
r.role_id, r.name AS role_name, r.description AS role_description, r.scope, r.owner_dept_id, r.status AS role_status, r.role_id, r.name AS role_name, r.description AS role_description, r.scope, r.owner_dept_id, r.status AS role_status,
ur.optsn, ur.creator, ur.updater, ur.dept_path, ur.remark, ur.create_time, ur.update_time, ur.delete_time, ur.deleted ur.optsn, ur.creator, ur.updater, ur.dept_path, u.remark, ur.create_time, ur.update_time, ur.delete_time, ur.deleted
FROM sys.tb_sys_user_role ur FROM sys.tb_sys_user_role ur
LEFT JOIN sys.tb_sys_user u ON ur.user_id = u.user_id AND (u.deleted IS NULL OR u.deleted = false) LEFT JOIN sys.tb_sys_user u ON ur.user_id = u.user_id AND (u.deleted IS NULL OR u.deleted = false)
LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false) LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false)
LEFT JOIN sys.tb_sys_dept d ON u.dept_path LIKE CONCAT('%/', d.dept_id, '/%') AND (d.deleted IS NULL OR d.deleted = false) LEFT JOIN sys.tb_sys_dept d ON d.dept_id = ur.dept_id
LEFT JOIN sys.tb_sys_role r ON ur.role_id = r.role_id AND (r.deleted IS NULL OR r.deleted = false) LEFT JOIN sys.tb_sys_role r ON ur.role_id = r.role_id AND (r.deleted IS NULL OR r.deleted = false)
WHERE ur.user_id = #{userId} WHERE ur.user_id = #{userId}
AND (ur.deleted IS NULL OR ur.deleted = false) AND (ur.deleted IS NULL OR ur.deleted = false)
@@ -155,16 +152,15 @@
<!-- 根据条件查询系统用户角色关系列表 --> <!-- 根据条件查询系统用户角色关系列表 -->
<select id="getUserRoleByFilter" resultMap="UserDeptRoleVOResultMap" parameterType="org.xyzh.common.dto.sys.TbSysUserRoleDTO"> <select id="getUserRoleByFilter" resultMap="UserDeptRoleVOResultMap" parameterType="org.xyzh.common.dto.sys.TbSysUserRoleDTO">
SELECT DISTINCT SELECT DISTINCT
u.user_id, u.username, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_type, u.user_id, u.password, u.email, u.phone, u.wechat_id, u.status,
ui.avatar, ui.gender, ui.family_name, ui.given_name, ui.full_name, ui.level, ui.id_card, ui.address, ui.avatar, ui.gender, ui.username, ui.level, ui.id_card, ui.address,
d.dept_id, d.name AS dept_name, d.parent_id, d.description AS dept_description, d.dept_id, d.name AS dept_name, d.parent_id, d.description AS dept_description,
r.role_id, r.name AS role_name, r.description AS role_description, r.scope, r.owner_dept_id, r.status AS role_status, r.role_id, r.name AS role_name, r.description AS role_description, r.scope, r.owner_dept_id, r.status AS role_status,
ur.optsn, ur.creator, ur.updater, ur.dept_path, u.remark, ur.create_time, ur.update_time, ur.delete_time, ur.deleted
ur.optsn, ur.creator, ur.updater, ur.dept_path, ur.remark, ur.create_time, ur.update_time, ur.delete_time, ur.deleted
FROM sys.tb_sys_user_role ur FROM sys.tb_sys_user_role ur
LEFT JOIN sys.tb_sys_user u ON ur.user_id = u.user_id AND (u.deleted IS NULL OR u.deleted = false) LEFT JOIN sys.tb_sys_user u ON ur.user_id = u.user_id AND (u.deleted IS NULL OR u.deleted = false)
LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false) LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false)
LEFT JOIN sys.tb_sys_dept d ON u.dept_path LIKE CONCAT('%/', d.dept_id, '/%') AND (d.deleted IS NULL OR d.deleted = false) LEFT JOIN sys.tb_sys_dept d ON d.dept_id = ur.dept_id
LEFT JOIN sys.tb_sys_role r ON ur.role_id = r.role_id AND (r.deleted IS NULL OR r.deleted = false) LEFT JOIN sys.tb_sys_role r ON ur.role_id = r.role_id AND (r.deleted IS NULL OR r.deleted = false)
<where> <where>
<if test="filter.userId != null and filter.userId != ''"> <if test="filter.userId != null and filter.userId != ''">
@@ -184,8 +180,8 @@
<!-- 根据条件查询系统用户角色关系分页列表 --> <!-- 根据条件查询系统用户角色关系分页列表 -->
<select id="getUserRolePageByFilter" resultMap="UserDeptRoleVOResultMap"> <select id="getUserRolePageByFilter" resultMap="UserDeptRoleVOResultMap">
SELECT DISTINCT SELECT DISTINCT
u.user_id, u.username, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_type, u.user_id, u.password, u.email, u.phone, u.wechat_id, u.status,
ui.avatar, ui.gender, ui.family_name, ui.given_name, ui.full_name, ui.level, ui.id_card, ui.address, ui.avatar, ui.gender, ui.username, ui.level, ui.id_card, ui.address,
d.dept_id, d.name AS dept_name, d.parent_id, d.description AS dept_description, d.dept_id, d.name AS dept_name, d.parent_id, d.description AS dept_description,
r.role_id, r.name AS role_name, r.description AS role_description, r.scope, r.owner_dept_id, r.status AS role_status, r.role_id, r.name AS role_name, r.description AS role_description, r.scope, r.owner_dept_id, r.status AS role_status,
(SELECT m.module_id FROM sys.tb_sys_role_permission rp2 (SELECT m.module_id FROM sys.tb_sys_role_permission rp2
@@ -203,11 +199,11 @@
LEFT JOIN sys.tb_sys_module m ON p2.module_id = m.module_id AND (m.deleted IS NULL OR m.deleted = false) LEFT JOIN sys.tb_sys_module m ON p2.module_id = m.module_id AND (m.deleted IS NULL OR m.deleted = false)
WHERE rp2.role_id = r.role_id AND (rp2.deleted IS NULL OR rp2.deleted = false) WHERE rp2.role_id = r.role_id AND (rp2.deleted IS NULL OR rp2.deleted = false)
ORDER BY rp2.create_time ASC LIMIT 1) AS module_description, ORDER BY rp2.create_time ASC LIMIT 1) AS module_description,
ur.optsn, ur.creator, ur.updater, ur.dept_path, ur.remark, ur.create_time, ur.update_time, ur.delete_time, ur.deleted ur.optsn, ur.creator, ur.updater, ur.dept_path, u.remark, ur.create_time, ur.update_time, ur.delete_time, ur.deleted
FROM sys.tb_sys_user_role ur FROM sys.tb_sys_user_role ur
LEFT JOIN sys.tb_sys_user u ON ur.user_id = u.user_id AND (u.deleted IS NULL OR u.deleted = false) LEFT JOIN sys.tb_sys_user u ON ur.user_id = u.user_id AND (u.deleted IS NULL OR u.deleted = false)
LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false) LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id AND (ui.deleted IS NULL OR ui.deleted = false)
LEFT JOIN sys.tb_sys_dept d ON u.dept_path LIKE CONCAT('%/', d.dept_id, '/%') AND (d.deleted IS NULL OR d.deleted = false) LEFT JOIN sys.tb_sys_dept d ON d.dept_id = ur.dept_id AND (d.deleted IS NULL OR d.deleted = false)
LEFT JOIN sys.tb_sys_role r ON ur.role_id = r.role_id AND (r.deleted IS NULL OR r.deleted = false) LEFT JOIN sys.tb_sys_role r ON ur.role_id = r.role_id AND (r.deleted IS NULL OR r.deleted = false)
<where> <where>
<if test="filter.userId != null and filter.userId != ''"> <if test="filter.userId != null and filter.userId != ''">

View File

@@ -1,8 +1,8 @@
# ================== Server ================== # ================== Server ==================
server: server:
port: 8188 port: 8188
servlet: # servlet:
context-path: /urban-lifeline/workcase # context-path: /urban-lifeline/workcase # 微服务架构下context-path由Gateway管理
# ================== Auth ==================== # ================== Auth ====================
urban-lifeline: urban-lifeline:

View File

@@ -115,9 +115,9 @@
} }
const usedRemotes = [ const usedRemotes = [
{ {
entryGlobalName: "http://localhost:5000/remoteEntry.js", entryGlobalName: "shared",
name: "shared", name: "shared",
type: "var", type: "module",
entry: "http://localhost:5000/remoteEntry.js", entry: "http://localhost:5000/remoteEntry.js",
shareScope: "default", shareScope: "default",
} }