gateway
This commit is contained in:
@@ -13,11 +13,13 @@ CREATE TABLE sys.tb_sys_user (
|
||||
phone VARCHAR(500), -- 电话号码
|
||||
phone_hash VARCHAR(200), -- 电话hash
|
||||
wechat_id VARCHAR(50), -- 微信ID
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
create_time TIMESTAMPTZ NOT NULL DEFAULT now(), -- 创建时间(使用带时区时间)
|
||||
update_time TIMESTAMPTZ DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time TIMESTAMPTZ DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除(使用 BOOLEAN)
|
||||
status INTEGER NOT NULL DEFAULT 1, -- 状态
|
||||
remark VARCHAR(255) DEFAULT NULL,
|
||||
PRIMARY KEY (user_id),
|
||||
UNIQUE (optsn),
|
||||
UNIQUE (email),
|
||||
@@ -59,6 +61,7 @@ CREATE TABLE sys.tb_sys_user_info (
|
||||
level INTEGER DEFAULT 1, -- 等级
|
||||
id_card VARCHAR(50), -- 身份证号
|
||||
address VARCHAR(255), -- 地址
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
remark VARCHAR(500) DEFAULT NULL, -- 备注
|
||||
create_time TIMESTAMPTZ NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time TIMESTAMPTZ DEFAULT NULL, -- 更新时间(触发器维护)
|
||||
|
||||
95
urbanLifelineServ/.vscode/launch.json
vendored
95
urbanLifelineServ/.vscode/launch.json
vendored
@@ -1,6 +1,13 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "java",
|
||||
"name": "AesEncryptUtil",
|
||||
"request": "launch",
|
||||
"mainClass": "org.xyzh.common.utils.crypto.AesEncryptUtil",
|
||||
"projectName": "common-utils"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Gateway (8180)",
|
||||
@@ -8,8 +15,12 @@
|
||||
"mainClass": "org.xyzh.gateway.GatewayApplication",
|
||||
"projectName": "gateway",
|
||||
"cwd": "${workspaceFolder}/gateway",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8180"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8180"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
@@ -19,8 +30,12 @@
|
||||
"mainClass": "org.xyzh.auth.AuthApp",
|
||||
"projectName": "auth",
|
||||
"cwd": "${workspaceFolder}/auth",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8181"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8181"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
@@ -30,8 +45,12 @@
|
||||
"mainClass": "org.xyzh.system.SystemApp",
|
||||
"projectName": "system",
|
||||
"cwd": "${workspaceFolder}/system",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8182"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8182"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
@@ -41,8 +60,12 @@
|
||||
"mainClass": "org.xyzh.log.LogApp",
|
||||
"projectName": "log",
|
||||
"cwd": "${workspaceFolder}/log",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8183"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8183"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
@@ -52,8 +75,12 @@
|
||||
"mainClass": "org.xyzh.file.FileApp",
|
||||
"projectName": "file",
|
||||
"cwd": "${workspaceFolder}/file",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8184"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8184"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
@@ -63,8 +90,12 @@
|
||||
"mainClass": "org.xyzh.message.MessageApp",
|
||||
"projectName": "message",
|
||||
"cwd": "${workspaceFolder}/message",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8185"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8185"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
@@ -74,8 +105,12 @@
|
||||
"mainClass": "org.xyzh.bidding.BiddingApp",
|
||||
"projectName": "bidding",
|
||||
"cwd": "${workspaceFolder}/bidding",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8186"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8186"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
@@ -85,8 +120,12 @@
|
||||
"mainClass": "org.xyzh.platform.PlatformApp",
|
||||
"projectName": "platform",
|
||||
"cwd": "${workspaceFolder}/platform",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8187"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8187"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
@@ -96,8 +135,12 @@
|
||||
"mainClass": "org.xyzh.workcase.WorkcaseApp",
|
||||
"projectName": "workcase",
|
||||
"cwd": "${workspaceFolder}/workcase",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8188"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8188"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
@@ -107,8 +150,12 @@
|
||||
"mainClass": "org.xyzh.crontab.CrontabApp",
|
||||
"projectName": "crontab",
|
||||
"cwd": "${workspaceFolder}/crontab",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8189"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8189"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
@@ -118,8 +165,12 @@
|
||||
"mainClass": "org.xyzh.agent.AgentApp",
|
||||
"projectName": "agent",
|
||||
"cwd": "${workspaceFolder}/agent",
|
||||
"args": ["--spring.profiles.active=dev"],
|
||||
"vmArgs": ["-Dserver.port=8190"],
|
||||
"args": [
|
||||
"--spring.profiles.active=dev"
|
||||
],
|
||||
"vmArgs": [
|
||||
"-Dserver.port=8190"
|
||||
],
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# ================== Server ==================
|
||||
server:
|
||||
port: 8190
|
||||
servlet:
|
||||
context-path: /urban-lifeline/agent
|
||||
# servlet:
|
||||
# context-path: /urban-lifeline/agent # 微服务架构下,context-path由Gateway管理
|
||||
|
||||
# ================== Auth ====================
|
||||
urban-lifeline:
|
||||
|
||||
@@ -18,5 +18,17 @@
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
</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>
|
||||
@@ -7,6 +7,7 @@ import org.xyzh.common.vo.BaseVO;
|
||||
|
||||
import org.xyzh.common.dto.sys.TbSysUserDTO;
|
||||
import org.xyzh.common.dto.sys.TbSysUserInfoDTO;
|
||||
import org.xyzh.common.utils.crypto.AesEncryptUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -34,7 +35,7 @@ public class SysUserVO extends BaseVO {
|
||||
|
||||
@Schema(description = "邮箱")
|
||||
private String email;
|
||||
|
||||
|
||||
@Schema(description = "手机")
|
||||
private String phone;
|
||||
|
||||
@@ -47,8 +48,8 @@ public class SysUserVO extends BaseVO {
|
||||
@Schema(description = "用户状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "用户类型")
|
||||
private String userType;
|
||||
@Schema(description = "创建人")
|
||||
private String creator;
|
||||
|
||||
// TbSysUserInfoDTO对应字段
|
||||
@Schema(description = "用户名")
|
||||
@@ -79,6 +80,11 @@ public class SysUserVO extends BaseVO {
|
||||
@Schema(description = "用户视图权限列表")
|
||||
private List<PermissionVO> viewPermissions;
|
||||
|
||||
public void setPhone(String phone){
|
||||
this.phone = phone;
|
||||
this.phoneHash = AesEncryptUtil.maskPhone(phone);
|
||||
}
|
||||
|
||||
public static TbSysUserDTO toDTO(SysUserVO vo) {
|
||||
if (vo == null) {
|
||||
return null;
|
||||
@@ -91,10 +97,8 @@ public class SysUserVO extends BaseVO {
|
||||
dto.setPhone(vo.getPhone());
|
||||
dto.setWechatId(vo.getWechatId());
|
||||
dto.setStatus(vo.getStatus());
|
||||
dto.setUserType(vo.getUserType());
|
||||
dto.setOptsn(vo.getOptsn());
|
||||
dto.setCreator(vo.getCreator());
|
||||
dto.setUpdater(vo.getUpdater());
|
||||
dto.setDeptPath(vo.getDeptPath());
|
||||
dto.setRemark(vo.getRemark());
|
||||
dto.setCreateTime(vo.getCreateTime());
|
||||
@@ -120,7 +124,6 @@ public class SysUserVO extends BaseVO {
|
||||
// 继承自 BaseDTO 的字段
|
||||
userInfoDTO.setOptsn(userVO.getOptsn());
|
||||
userInfoDTO.setCreator(userVO.getCreator());
|
||||
userInfoDTO.setUpdater(userVO.getUpdater());
|
||||
userInfoDTO.setDeptPath(userVO.getDeptPath());
|
||||
userInfoDTO.setRemark(userVO.getRemark());
|
||||
userInfoDTO.setCreateTime(userVO.getCreateTime());
|
||||
|
||||
@@ -5,10 +5,12 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableDubbo // 启用 Dubbo 服务
|
||||
@EnableDiscoveryClient // 启用 Nacos 服务注册与发现(用于 Gateway 路由)
|
||||
@ComponentScan(basePackages = {
|
||||
"org.xyzh.auth", // 当前auth模块
|
||||
"org.xyzh.common" // 公共模块
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.xyzh.common.dto.sys.TbSysPermissionDTO;
|
||||
import org.xyzh.common.dto.sys.TbSysViewDTO;
|
||||
import org.xyzh.common.redis.service.RedisService;
|
||||
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.DubboService;
|
||||
import org.slf4j.Logger;
|
||||
@@ -67,6 +68,9 @@ public class AuthServiceImpl implements AuthService{
|
||||
@Autowired
|
||||
private LoginStrategyFactory loginStrategyFactory;
|
||||
|
||||
@Autowired
|
||||
private AesEncryptUtil aesEncryptUtil;
|
||||
|
||||
@Override
|
||||
public ResultDomain<LoginDomain> getCaptcha(LoginParam loginParam) {
|
||||
try {
|
||||
@@ -236,7 +240,8 @@ public class AuthServiceImpl implements AuthService{
|
||||
|
||||
// 5. 验证凭据
|
||||
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, "密码错误");
|
||||
return ResultDomain.failure("密码错误");
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.xyzh.auth.strategy.LoginStrategy;
|
||||
import org.xyzh.common.core.domain.LoginParam;
|
||||
import org.xyzh.common.dto.sys.TbSysUserDTO;
|
||||
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.PhoneValidateMethod;
|
||||
import org.xyzh.api.system.service.SysUserService;
|
||||
@@ -77,6 +78,7 @@ public class PasswordLoginStrategy implements LoginStrategy {
|
||||
@Override
|
||||
public boolean verifyCredential(String inputCredential, String storedCredential) {
|
||||
// 使用BCrypt的matches方法验证密码(内部会自动处理salt)
|
||||
logger.info(passwordEncoder.encode(inputCredential));
|
||||
return passwordEncoder.matches(inputCredential, storedCredential);
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,11 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.xyzh.auth.strategy.LoginStrategy;
|
||||
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.vo.SysUserVO;
|
||||
import org.xyzh.common.redis.service.RedisService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @description PhoneLoginStrategy.java文件描述 手机号登录策略
|
||||
@@ -19,6 +20,7 @@ import org.xyzh.common.redis.service.RedisService;
|
||||
*/
|
||||
@Component
|
||||
public class PhoneLoginStrategy implements LoginStrategy {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PhoneLoginStrategy.class);
|
||||
|
||||
@Autowired
|
||||
private SysUserService userService;
|
||||
@@ -57,7 +59,6 @@ public class PhoneLoginStrategy implements LoginStrategy {
|
||||
|
||||
@Override
|
||||
public boolean verifyCredential(String inputCredential, String storedCredential) {
|
||||
// 密码验证
|
||||
return passwordEncoder.matches(inputCredential, storedCredential);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
# ================== Server ==================
|
||||
server:
|
||||
port: 8181
|
||||
servlet:
|
||||
context-path: /urban-lifeline/auth
|
||||
# servlet:
|
||||
# context-path: /urban-lifeline/auth # 微服务架构下,context-path由Gateway管理,服务本身不需要设置
|
||||
|
||||
# ================== Auth ====================
|
||||
urban-lifeline:
|
||||
auth:
|
||||
enabled: false # 认证服务自己不需要认证
|
||||
whitelist:
|
||||
- /** # 认证服务的所有接口都放行
|
||||
auth:
|
||||
enabled: false # 认证服务自己不需要认证
|
||||
gateway-mode: false # 不使用gateway模式(auth服务作为独立服务)
|
||||
whitelist:
|
||||
- /** # 认证服务的所有接口都放行
|
||||
security:
|
||||
aes:
|
||||
secret-key: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI= # Base64 编码,32字节(256位)
|
||||
# AES-256 密钥(Base64编码,必须与所有服务保持一致)
|
||||
# 警告:这是开发环境密钥,生产环境请使用密钥管理系统
|
||||
secret-key: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=
|
||||
# ================== Spring ==================
|
||||
spring:
|
||||
application:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# ================== Server ==================
|
||||
server:
|
||||
port: 8186
|
||||
servlet:
|
||||
context-path: /urban-lifeline/bidding
|
||||
# servlet:
|
||||
# context-path: /urban-lifeline/bidding # 微服务架构下,context-path由Gateway管理
|
||||
|
||||
# ================== Auth ====================
|
||||
urban-lifeline:
|
||||
|
||||
@@ -30,6 +30,11 @@
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xyzh.common</groupId>
|
||||
<artifactId>common-utils</artifactId>
|
||||
<version>${urban-lifeline.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -3,6 +3,10 @@ package org.xyzh.common.dto.sys;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -29,6 +33,7 @@ public class TbSysUserDTO extends BaseDTO {
|
||||
@Schema(description = "邮箱")
|
||||
private String email;
|
||||
|
||||
@TableField(typeHandler = EncryptedStringTypeHandler.class)
|
||||
@Schema(description = "手机(加密)")
|
||||
private String phone;
|
||||
|
||||
@@ -41,7 +46,10 @@ public class TbSysUserDTO extends BaseDTO {
|
||||
@Schema(description = "用户状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "用户类型")
|
||||
private String userType;
|
||||
|
||||
public void setPhone(String phone){
|
||||
this.phone = phone;
|
||||
this.phoneHash = AesEncryptUtil.maskPhone(phone);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,7 +36,10 @@
|
||||
<artifactId>mybatis</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- Spring Boot (用于加密工具) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -35,13 +35,24 @@ public class AesEncryptUtil {
|
||||
* 从配置文件读取密钥,如果没有则生成新密钥
|
||||
*/
|
||||
public AesEncryptUtil(@Value("${security.aes.secret-key:}") String secretKeyString) {
|
||||
if (secretKeyString == null || secretKeyString.isEmpty()) {
|
||||
// 生产环境应该从配置中心或密钥管理系统获取
|
||||
try {
|
||||
if (secretKeyString == null || secretKeyString.isEmpty()) {
|
||||
// 生产环境应该从配置中心或密钥管理系统获取
|
||||
this.secretKey = generateKey();
|
||||
System.err.println("警告: 未配置 AES 密钥,使用临时生成的密钥。生产环境请配置 security.aes.secret-key");
|
||||
} else {
|
||||
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);
|
||||
System.out.println("✓ AES-256 加密工具初始化成功");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("❌ AES 密钥初始化失败: " + e.getMessage());
|
||||
// 生成临时密钥以避免启动失败
|
||||
this.secretKey = generateKey();
|
||||
System.err.println("警告: 未配置 AES 密钥,使用临时生成的密钥。生产环境请配置 security.aes.secret-key");
|
||||
} else {
|
||||
byte[] decodedKey = Base64.getDecoder().decode(secretKeyString);
|
||||
this.secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, ALGORITHM);
|
||||
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) {
|
||||
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) {
|
||||
return phone;
|
||||
}
|
||||
@@ -187,4 +221,26 @@ public class AesEncryptUtil {
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 未能注入,加密功能可能无法正常工作");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
# ================== Server ==================
|
||||
server:
|
||||
port: 8189
|
||||
servlet:
|
||||
context-path: /urban-lifeline/crontab
|
||||
# servlet:
|
||||
# context-path: /urban-lifeline/crontab # 微服务架构下,context-path由Gateway管理
|
||||
|
||||
# ================== Auth ====================
|
||||
urban-lifeline:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# ================== Server ==================
|
||||
server:
|
||||
port: 8184
|
||||
servlet:
|
||||
context-path: /urban-lifeline/file
|
||||
# servlet:
|
||||
# context-path: /urban-lifeline/file # 微服务架构下,context-path由Gateway管理
|
||||
|
||||
# ================== Auth ====================
|
||||
urban-lifeline:
|
||||
|
||||
@@ -28,19 +28,8 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
<!-- 排除旧的 gateway-server,使用新的 webflux 版本 -->
|
||||
<exclusion>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-gateway-server</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- 明确使用新的 WebFlux Gateway Server(推荐) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-gateway-server-webflux</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Nacos 服务注册与发现 -->
|
||||
<dependency>
|
||||
|
||||
@@ -7,6 +7,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.xyzh.common.auth.config.SecurityConfig;
|
||||
import org.xyzh.common.auth.config.WebMvcConfig;
|
||||
import org.xyzh.common.auth.config.GatewayAuthConfig;
|
||||
|
||||
/**
|
||||
* @description Gateway 网关启动类
|
||||
@@ -23,8 +25,12 @@ import org.xyzh.common.auth.config.SecurityConfig;
|
||||
"org.xyzh.common" // 公共模块(包括 common-auth)
|
||||
},
|
||||
excludeFilters = {
|
||||
// 排除 Spring MVC 的 SecurityConfig,Gateway 使用 WebFlux Security
|
||||
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
|
||||
// 排除 Spring MVC 相关配置,Gateway 使用 WebFlux
|
||||
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
|
||||
SecurityConfig.class, // Spring MVC Security配置
|
||||
WebMvcConfig.class, // Spring MVC配置
|
||||
GatewayAuthConfig.class // 微服务Gateway模式配置(使用Servlet Filter)
|
||||
})
|
||||
}
|
||||
)
|
||||
public class GatewayApplication {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,6 @@
|
||||
spring:
|
||||
cloud:
|
||||
gateway:
|
||||
server:
|
||||
webflux:
|
||||
routes:
|
||||
# 开发环境可以添加更详细的路由配置或测试路由
|
||||
|
||||
# Nacos 管理界面路由(开发专用)
|
||||
- id: nacos-console
|
||||
uri: http://${NACOS_SERVER_ADDR:localhost:8848}
|
||||
predicates:
|
||||
- Path=/nacos/**
|
||||
# 开发环境专用配置
|
||||
# 注意:不要在这里配置routes,会覆盖application.yml的配置
|
||||
# 路由配置统一在application.yml中管理
|
||||
|
||||
# 开发环境日志
|
||||
logging:
|
||||
|
||||
@@ -17,102 +17,119 @@ spring:
|
||||
namespace: dev
|
||||
group: DEFAULT_GROUP
|
||||
config:
|
||||
enabled: false # 禁用Nacos配置中心,使用本地配置
|
||||
server-addr: ${NACOS_SERVER_ADDR:localhost:8848}
|
||||
file-extension: yml
|
||||
namespace: dev
|
||||
group: DEFAULT_GROUP
|
||||
|
||||
# Gateway 路由配置(使用新的 webflux 配置路径)
|
||||
# Gateway 路由配置
|
||||
gateway:
|
||||
server:
|
||||
webflux:
|
||||
# 服务发现路由(自动路由)
|
||||
discovery:
|
||||
locator:
|
||||
enabled: false # 关闭自动路由,使用手动配置
|
||||
|
||||
# 手动配置路由
|
||||
routes:
|
||||
# ==================== 认证服务路由 ====================
|
||||
- id: auth-service
|
||||
uri: lb://auth-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/auth/**
|
||||
filters:
|
||||
# 不需要重写,直接转发保持原路径
|
||||
- name: RequestRateLimiter
|
||||
args:
|
||||
redis-rate-limiter.replenishRate: 100
|
||||
redis-rate-limiter.burstCapacity: 200
|
||||
# 服务发现路由(自动路由)
|
||||
discovery:
|
||||
locator:
|
||||
enabled: false # 关闭自动路由,使用手动配置
|
||||
|
||||
# 手动配置路由
|
||||
routes:
|
||||
# ==================== 认证服务路由 ====================
|
||||
- id: auth-service
|
||||
uri: lb://auth-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/auth/**
|
||||
filters:
|
||||
- StripPrefix=1 # 去掉前缀:/urban-lifeline/auth/login → /auth/login
|
||||
- name: RequestRateLimiter
|
||||
args:
|
||||
redis-rate-limiter.replenishRate: 100
|
||||
redis-rate-limiter.burstCapacity: 200
|
||||
|
||||
# ==================== 系统服务路由 ====================
|
||||
- id: system-service
|
||||
uri: lb://system-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/system/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
# ==================== 系统服务路由 ====================
|
||||
- id: system-service
|
||||
uri: lb://system-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/system/**
|
||||
|
||||
# ==================== 日志服务路由 ====================
|
||||
- id: log-service
|
||||
uri: lb://log-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/log/**
|
||||
|
||||
# ==================== 文件服务路由 ====================
|
||||
- id: file-service
|
||||
uri: lb://file-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/file/**
|
||||
|
||||
# ==================== 消息服务路由 ====================
|
||||
- id: message-service
|
||||
uri: lb://message-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/message/**
|
||||
|
||||
# ==================== 招投标服务路由 ====================
|
||||
- id: bidding-service
|
||||
uri: lb://bidding-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/bidding/**
|
||||
|
||||
# ==================== 平台服务路由 ====================
|
||||
- id: platform-service
|
||||
uri: lb://platform-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/platform/**
|
||||
|
||||
# ==================== 工单服务路由 ====================
|
||||
- id: workcase-service
|
||||
uri: lb://workcase-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/workcase/**
|
||||
|
||||
# ==================== 定时任务服务路由 ====================
|
||||
- id: crontab-service
|
||||
uri: lb://crontab-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/crontab/**
|
||||
|
||||
# ==================== AI Agent 服务路由 ====================
|
||||
- id: agent-service
|
||||
uri: lb://agent-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/agent/**
|
||||
|
||||
# 全局跨域配置
|
||||
globalcors:
|
||||
cors-configurations:
|
||||
'[/**]':
|
||||
allowedOriginPatterns: "*"
|
||||
allowedMethods:
|
||||
- GET
|
||||
- POST
|
||||
- PUT
|
||||
- DELETE
|
||||
- OPTIONS
|
||||
allowedHeaders: "*"
|
||||
allowCredentials: true
|
||||
maxAge: 3600
|
||||
# ==================== 日志服务路由 ====================
|
||||
- id: log-service
|
||||
uri: lb://log-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/log/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
# ==================== 文件服务路由 ====================
|
||||
- id: file-service
|
||||
uri: lb://file-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/file/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
# ==================== 消息服务路由 ====================
|
||||
- id: message-service
|
||||
uri: lb://message-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/message/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
# ==================== 招投标服务路由 ====================
|
||||
- id: bidding-service
|
||||
uri: lb://bidding-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/bidding/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
# ==================== 平台服务路由 ====================
|
||||
- id: platform-service
|
||||
uri: lb://platform-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/platform/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
# ==================== 工单服务路由 ====================
|
||||
- id: workcase-service
|
||||
uri: lb://workcase-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/workcase/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
# ==================== 定时任务服务路由 ====================
|
||||
- id: crontab-service
|
||||
uri: lb://crontab-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/crontab/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
# ==================== AI Agent 服务路由 ====================
|
||||
- id: agent-service
|
||||
uri: lb://agent-service
|
||||
predicates:
|
||||
- Path=/urban-lifeline/agent/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
# 全局跨域配置
|
||||
globalcors:
|
||||
cors-configurations:
|
||||
'[/**]':
|
||||
allowedOriginPatterns: "*"
|
||||
allowedMethods:
|
||||
- GET
|
||||
- POST
|
||||
- PUT
|
||||
- DELETE
|
||||
- OPTIONS
|
||||
allowedHeaders: "*"
|
||||
allowCredentials: true
|
||||
maxAge: 3600
|
||||
datasource:
|
||||
# 按你的实际库名改一下,比如 urban-lifeline_system
|
||||
url: jdbc:postgresql://127.0.0.1:5432/urban_lifeline # 换成你的 PG 库名
|
||||
@@ -137,7 +154,7 @@ spring:
|
||||
# 认证配置
|
||||
auth:
|
||||
enabled: true
|
||||
gateway-mode: true
|
||||
# gateway-mode 是给下游微服务用的,gateway本身不需要此配置
|
||||
token-header: Authorization
|
||||
token-prefix: "Bearer "
|
||||
# 认证接口白名单(login/logout/captcha/refresh)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# ================== Server ==================
|
||||
server:
|
||||
port: 8183
|
||||
servlet:
|
||||
context-path: /urban-lifeline/log
|
||||
# servlet:
|
||||
# context-path: /urban-lifeline/log # 微服务架构下,context-path由Gateway管理
|
||||
|
||||
# ================== Auth ====================
|
||||
urban-lifeline:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# ================== Server ==================
|
||||
server:
|
||||
port: 8185
|
||||
servlet:
|
||||
context-path: /urban-lifeline/message
|
||||
# servlet:
|
||||
# context-path: /urban-lifeline/message # 微服务架构下,context-path由Gateway管理
|
||||
|
||||
# ================== Auth ====================
|
||||
urban-lifeline:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# ================== Server ==================
|
||||
server:
|
||||
port: 8187
|
||||
servlet:
|
||||
context-path: /urban-lifeline/platform
|
||||
# servlet:
|
||||
# context-path: /urban-lifeline/platform # 微服务架构下,context-path由Gateway管理
|
||||
|
||||
# ================== Auth ====================
|
||||
urban-lifeline:
|
||||
|
||||
@@ -82,8 +82,7 @@ public class SysUserServiceImpl implements SysUserService {
|
||||
if (StringUtils.isBlank(dto.getUserId())) {
|
||||
dto.setUserId(IDUtils.generateID());
|
||||
}
|
||||
dto.setPhone(aesEncryptUtil.encrypt(userVO.getPhone()));
|
||||
dto.setPhoneHash(AesEncryptUtil.maskPhone(userVO.getPhone()));
|
||||
dto.setPhone(userVO.getPhone());
|
||||
dto.setCreateTime(now);
|
||||
dto.setDeleted(false);
|
||||
|
||||
@@ -142,8 +141,7 @@ public class SysUserServiceImpl implements SysUserService {
|
||||
// 检查手机号是否存在
|
||||
if (StringUtils.isNotBlank(userVO.getPhone())) {
|
||||
filter = new SysUserVO();
|
||||
filter.setPhone(aesEncryptUtil.encrypt(userVO.getPhone()));
|
||||
filter.setPhoneHash(AesEncryptUtil.maskPhone(userVO.getPhone()));
|
||||
filter.setPhone(userVO.getPhone());
|
||||
List<SysUserVO> users = userMapper.getUserByFilter(filter);
|
||||
if (users != null && !users.isEmpty()) {
|
||||
logger.warn("手机号已存在: {}", userVO.getPhone());
|
||||
@@ -228,8 +226,7 @@ public class SysUserServiceImpl implements SysUserService {
|
||||
public ResultDomain<SysUserVO> getLoginUser(SysUserVO filter) {
|
||||
// 登录查询语义与 getUser 相同(可根据用户名/手机号/邮箱查询)
|
||||
if(NonUtils.isNotNull(filter.getPhone())){
|
||||
filter.setPhone(aesEncryptUtil.encrypt(filter.getPhone()));
|
||||
filter.setPhoneHash(AesEncryptUtil.maskPhone(filter.getPhone()));
|
||||
filter.setPhone(filter.getPhone());
|
||||
}
|
||||
SysUserVO userVO = userMapper.getUserByFilter(filter).get(0);
|
||||
return ResultDomain.success("查询成功", userVO);
|
||||
|
||||
@@ -35,6 +35,13 @@ urban-lifeline:
|
||||
# - /api/public/**
|
||||
|
||||
|
||||
# ================== Security ==================
|
||||
security:
|
||||
aes:
|
||||
# AES-256 密钥(Base64编码)
|
||||
# 警告:这是开发环境密钥,生产环境请使用密钥管理系统
|
||||
secret-key: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=
|
||||
|
||||
# ================== Spring ==================
|
||||
spring:
|
||||
# ================== DataSource ==================
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# ================== Server ==================
|
||||
server:
|
||||
port: 8182
|
||||
servlet:
|
||||
context-path: /urban-lifeline/system
|
||||
# servlet:
|
||||
# context-path: /urban-lifeline/system # 微服务架构下,context-path由Gateway管理
|
||||
# ================== Auth ====================
|
||||
urban-lifeline:
|
||||
auth:
|
||||
|
||||
@@ -8,17 +8,13 @@
|
||||
<id column="user_id" property="userId" jdbcType="VARCHAR"/>
|
||||
<result column="avatar" property="avatar" jdbcType="VARCHAR"/>
|
||||
<result column="gender" property="gender" jdbcType="INTEGER"/>
|
||||
<result column="family_name" property="familyName" jdbcType="VARCHAR"/>
|
||||
<result column="given_name" property="givenName" jdbcType="VARCHAR"/>
|
||||
<result column="full_name" property="fullName" jdbcType="VARCHAR"/>
|
||||
<result column="username" property="username" jdbcType="VARCHAR"/>
|
||||
<result column="level" property="level" jdbcType="INTEGER"/>
|
||||
<result column="id_card" property="idCard" jdbcType="VARCHAR"/>
|
||||
<result column="address" property="address" jdbcType="VARCHAR"/>
|
||||
<!-- 基础字段 -->
|
||||
<result column="optsn" property="optsn" 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="create_time" property="createTime" jdbcType="DATE"/>
|
||||
<result column="update_time" property="updateTime" jdbcType="DATE"/>
|
||||
@@ -28,8 +24,8 @@
|
||||
|
||||
<!-- 基础列 -->
|
||||
<sql id="Base_Column_List">
|
||||
user_id, avatar, gender, family_name, given_name, full_name, level, id_card, address,
|
||||
optsn, creator, updater, dept_path, remark, create_time, update_time, delete_time, deleted
|
||||
user_id, avatar, gender, username, level, id_card, address,
|
||||
optsn, creator, remark, create_time, update_time, delete_time, deleted
|
||||
</sql>
|
||||
|
||||
<!-- 插入系统用户信息(按表字段 + 默认值动态列,仅修改 insert) -->
|
||||
@@ -42,9 +38,7 @@
|
||||
<!-- 可空/有默认值字段:按是否有入参动态拼接 -->
|
||||
<if test="avatar != null and avatar != ''">avatar,</if>
|
||||
<if test="gender != null">gender,</if>
|
||||
<if test="familyName != null and familyName != ''">family_name,</if>
|
||||
<if test="givenName != null and givenName != ''">given_name,</if>
|
||||
<if test="fullName != null and fullName != ''">full_name,</if>
|
||||
<if test="username != null and username != ''">username,</if>
|
||||
<if test="level != null">level,</if>
|
||||
<if test="idCard != null and idCard != ''">id_card,</if>
|
||||
<if test="address != null and address != ''">address,</if>
|
||||
@@ -61,9 +55,7 @@
|
||||
<!-- 可空/有默认值字段对应的值 -->
|
||||
<if test="avatar != null and avatar != ''">#{avatar},</if>
|
||||
<if test="gender != null">#{gender},</if>
|
||||
<if test="familyName != null and familyName != ''">#{familyName},</if>
|
||||
<if test="givenName != null and givenName != ''">#{givenName},</if>
|
||||
<if test="fullName != null and fullName != ''">#{fullName},</if>
|
||||
<if test="username != null and username != ''">#{username},</if>
|
||||
<if test="level != null">#{level},</if>
|
||||
<if test="idCard != null and idCard != ''">#{idCard},</if>
|
||||
<if test="address != null and address != ''">#{address},</if>
|
||||
@@ -84,14 +76,8 @@
|
||||
<if test="gender != null">
|
||||
gender = #{gender},
|
||||
</if>
|
||||
<if test="familyName != null">
|
||||
family_name = #{familyName},
|
||||
</if>
|
||||
<if test="givenName != null">
|
||||
given_name = #{givenName},
|
||||
</if>
|
||||
<if test="fullName != null">
|
||||
full_name = #{fullName},
|
||||
<if test="username != null">
|
||||
username = #{username},
|
||||
</if>
|
||||
<if test="level != null">
|
||||
level = #{level},
|
||||
@@ -102,12 +88,6 @@
|
||||
<if test="address != null">
|
||||
address = #{address},
|
||||
</if>
|
||||
<if test="updater != null and updater != ''">
|
||||
updater = #{updater},
|
||||
</if>
|
||||
<if test="deptPath != null and deptPath != ''">
|
||||
dept_path = #{deptPath},
|
||||
</if>
|
||||
<if test="remark != null">
|
||||
remark = #{remark},
|
||||
</if>
|
||||
@@ -147,14 +127,8 @@
|
||||
<if test="filter.userId != null and filter.userId != ''">
|
||||
AND user_id = #{filter.userId}
|
||||
</if>
|
||||
<if test="filter.fullName != null and filter.fullName != ''">
|
||||
AND full_name LIKE CONCAT('%', #{filter.fullName}, '%')
|
||||
</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 test="filter.username != null and filter.username != ''">
|
||||
AND username LIKE CONCAT('%', #{filter.username}, '%')
|
||||
</if>
|
||||
<if test="filter.idCard != null and filter.idCard != ''">
|
||||
AND id_card = #{filter.idCard}
|
||||
@@ -162,9 +136,6 @@
|
||||
<if test="filter.gender != null">
|
||||
AND gender = #{filter.gender}
|
||||
</if>
|
||||
<if test="filter.deptPath != null and filter.deptPath != ''">
|
||||
AND dept_path LIKE CONCAT(#{filter.deptPath}, '%')
|
||||
</if>
|
||||
AND (deleted IS NULL OR deleted = false)
|
||||
</where>
|
||||
ORDER BY create_time DESC
|
||||
@@ -179,14 +150,8 @@
|
||||
<if test="filter.userId != null and filter.userId != ''">
|
||||
AND user_id = #{filter.userId}
|
||||
</if>
|
||||
<if test="filter.fullName != null and filter.fullName != ''">
|
||||
AND full_name LIKE CONCAT('%', #{filter.fullName}, '%')
|
||||
</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 test="filter.username != null and filter.username != ''">
|
||||
AND username LIKE CONCAT('%', #{filter.username}, '%')
|
||||
</if>
|
||||
<if test="filter.idCard != null and filter.idCard != ''">
|
||||
AND id_card = #{filter.idCard}
|
||||
@@ -194,9 +159,6 @@
|
||||
<if test="filter.gender != null">
|
||||
AND gender = #{filter.gender}
|
||||
</if>
|
||||
<if test="filter.deptPath != null and filter.deptPath != ''">
|
||||
AND dept_path LIKE CONCAT(#{filter.deptPath}, '%')
|
||||
</if>
|
||||
AND (deleted IS NULL OR deleted = false)
|
||||
</where>
|
||||
ORDER BY create_time DESC
|
||||
@@ -211,14 +173,8 @@
|
||||
<if test="filter.userId != null and filter.userId != ''">
|
||||
AND user_id = #{filter.userId}
|
||||
</if>
|
||||
<if test="filter.fullName != null and filter.fullName != ''">
|
||||
AND full_name LIKE CONCAT('%', #{filter.fullName}, '%')
|
||||
</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 test="filter.username != null and filter.username != ''">
|
||||
AND username LIKE CONCAT('%', #{filter.username}, '%')
|
||||
</if>
|
||||
<if test="filter.idCard != null and filter.idCard != ''">
|
||||
AND id_card = #{filter.idCard}
|
||||
@@ -226,9 +182,6 @@
|
||||
<if test="filter.gender != null">
|
||||
AND gender = #{filter.gender}
|
||||
</if>
|
||||
<if test="filter.deptPath != null and filter.deptPath != ''">
|
||||
AND dept_path LIKE CONCAT(#{filter.deptPath}, '%')
|
||||
</if>
|
||||
AND (deleted IS NULL OR deleted = false)
|
||||
</where>
|
||||
</select>
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
<id column="user_id" property="userId" jdbcType="VARCHAR"/>
|
||||
<result column="password" property="password" 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="status" property="status" jdbcType="INTEGER"/>
|
||||
|
||||
<!-- BaseDTO 中在该表实际存在的字段 -->
|
||||
<result column="optsn" property="optsn" jdbcType="VARCHAR"/>
|
||||
<result column="creator" property="creator" jdbcType="VARCHAR"/>
|
||||
<result column="create_time" property="createTime" jdbcType="DATE"/>
|
||||
<result column="update_time" property="updateTime" jdbcType="DATE"/>
|
||||
<result column="delete_time" property="deleteTime" jdbcType="DATE"/>
|
||||
@@ -26,15 +27,15 @@
|
||||
<id column="user_id" property="userId" jdbcType="VARCHAR"/>
|
||||
<result column="password" property="password" 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="status" property="status" jdbcType="INTEGER"/>
|
||||
<result column="creator" property="creator" jdbcType="VARCHAR"/>
|
||||
|
||||
<!-- 用户信息关联字段 -->
|
||||
<result column="avatar" property="avatar" jdbcType="VARCHAR"/>
|
||||
<result column="gender" property="gender" jdbcType="INTEGER"/>
|
||||
<result column="family_name" property="familyName" jdbcType="VARCHAR"/>
|
||||
<result column="given_name" property="givenName" jdbcType="VARCHAR"/>
|
||||
<result column="full_name" property="fullName" jdbcType="VARCHAR"/>
|
||||
<result column="username" property="username" jdbcType="VARCHAR"/>
|
||||
<result column="level" property="level" jdbcType="INTEGER"/>
|
||||
<result column="id_card" property="idCard" jdbcType="VARCHAR"/>
|
||||
<result column="address" property="address" jdbcType="VARCHAR"/>
|
||||
@@ -78,7 +79,7 @@
|
||||
#{password},
|
||||
<!-- 可空/有默认值字段对应的值 -->
|
||||
<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="createTime != null">#{createTime},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
@@ -102,7 +103,7 @@
|
||||
email = #{email},
|
||||
</if>
|
||||
<if test="phone != null and phone != ''">
|
||||
phone = #{phone},
|
||||
phone = #{phone, typeHandler=org.xyzh.common.utils.crypto.EncryptedStringTypeHandler},
|
||||
</if>
|
||||
<if test="wechatId != null and wechatId != ''">
|
||||
wechat_id = #{wechatId},
|
||||
@@ -110,12 +111,6 @@
|
||||
<if test="status != null and status != ''">
|
||||
status = #{status},
|
||||
</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 != ''">
|
||||
dept_path = #{deptPath},
|
||||
</if>
|
||||
@@ -145,7 +140,7 @@
|
||||
SELECT
|
||||
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,
|
||||
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
|
||||
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}
|
||||
@@ -155,9 +150,9 @@
|
||||
<!-- 根据条件查询用户列表 -->
|
||||
<select id="getUserByFilter" resultMap="UserVOResultMap">
|
||||
SELECT
|
||||
u.user_id, u.username, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_type,
|
||||
u.optsn, u.creator, u.updater, u.dept_path, 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
|
||||
u.user_id, ui.username, u.password, u.email, u.phone, u.wechat_id, u.status,
|
||||
u.optsn, u.creator, u.remark, u.create_time, u.update_time, u.delete_time, u.deleted,
|
||||
ui.avatar, ui.gender, ui.username, ui.level, ui.id_card, ui.address
|
||||
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)
|
||||
<where>
|
||||
@@ -167,9 +162,7 @@
|
||||
<if test="filter.email != null and filter.email != ''">
|
||||
AND u.email = #{filter.email}
|
||||
</if>
|
||||
<if test="filter.phone != null and filter.phone != ''">
|
||||
AND u.phone = #{filter.phone}
|
||||
</if>
|
||||
<!-- 手机号查询统一使用phoneHash,不使用phone字段 -->
|
||||
<if test="filter.phoneHash != null and filter.phoneHash != ''">
|
||||
AND u.phone_hash = #{filter.phoneHash}
|
||||
</if>
|
||||
@@ -188,9 +181,9 @@
|
||||
<!-- 根据条件查询用户分页列表 -->
|
||||
<select id="getUserPageByFilter" resultMap="UserVOResultMap">
|
||||
SELECT
|
||||
u.user_id, u.username, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_type,
|
||||
u.optsn, u.creator, u.updater, u.dept_path, 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
|
||||
u.user_id, ui.username, u.password, u.email, u.phone, u.wechat_id, u.status,
|
||||
u.optsn, u.creator, u.remark, u.create_time, u.update_time, u.delete_time, u.deleted,
|
||||
ui.avatar, ui.gender, ui.username, ui.level, ui.id_card, ui.address
|
||||
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)
|
||||
<where>
|
||||
@@ -198,23 +191,18 @@
|
||||
AND u.user_id = #{filter.userId}
|
||||
</if>
|
||||
<if test="filter.username != null and filter.username != ''">
|
||||
AND u.username LIKE CONCAT('%', #{filter.username}, '%')
|
||||
AND ui.username LIKE CONCAT('%', #{filter.username}, '%')
|
||||
</if>
|
||||
<if test="filter.email != null and filter.email != ''">
|
||||
AND u.email = #{filter.email}
|
||||
</if>
|
||||
<if test="filter.phone != null and filter.phone != ''">
|
||||
AND u.phone = #{filter.phone}
|
||||
<!-- 手机号查询统一使用phoneHash,不使用phone字段 -->
|
||||
<if test="filter.phoneHash != null and filter.phoneHash != ''">
|
||||
AND u.phone_hash = #{filter.phoneHash}
|
||||
</if>
|
||||
<if test="filter.status != null and filter.status != ''">
|
||||
AND u.status = #{filter.status}
|
||||
</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)
|
||||
</where>
|
||||
ORDER BY u.create_time DESC
|
||||
@@ -232,8 +220,9 @@
|
||||
<if test="filter.email != null and filter.email != ''">
|
||||
AND email = #{filter.email}
|
||||
</if>
|
||||
<if test="filter.phone != null and filter.phone != ''">
|
||||
AND phone = #{filter.phone}
|
||||
<!-- 手机号查询统一使用phoneHash,不使用phone字段 -->
|
||||
<if test="filter.phoneHash != null and filter.phoneHash != ''">
|
||||
AND phone_hash = #{filter.phoneHash}
|
||||
</if>
|
||||
<if test="filter.status != null">
|
||||
AND status = #{filter.status}
|
||||
|
||||
@@ -29,13 +29,10 @@
|
||||
<result column="phone" property="phone" jdbcType="VARCHAR"/>
|
||||
<result column="wechat_id" property="wechatId" 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="gender" property="gender" jdbcType="INTEGER"/>
|
||||
<result column="family_name" property="familyName" jdbcType="VARCHAR"/>
|
||||
<result column="given_name" property="givenName" jdbcType="VARCHAR"/>
|
||||
<result column="full_name" property="fullName" jdbcType="VARCHAR"/>
|
||||
<result column="username" property="username" jdbcType="VARCHAR"/>
|
||||
<result column="level" property="level" jdbcType="INTEGER"/>
|
||||
<result column="id_card" property="idCard" jdbcType="VARCHAR"/>
|
||||
<result column="address" property="address" jdbcType="VARCHAR"/>
|
||||
@@ -137,15 +134,15 @@
|
||||
<!-- 根据用户ID查询系统用户角色关系 -->
|
||||
<select id="getUserRoleByUserId" resultMap="UserDeptRoleVOResultMap" parameterType="java.lang.String">
|
||||
SELECT
|
||||
u.user_id, u.username, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_type,
|
||||
ui.avatar, ui.gender, ui.family_name, ui.given_name, ui.full_name, ui.level, ui.id_card, ui.address,
|
||||
u.user_id, u.password, u.email, u.phone, u.wechat_id, u.status,
|
||||
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,
|
||||
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
|
||||
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_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)
|
||||
WHERE ur.user_id = #{userId}
|
||||
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 DISTINCT
|
||||
u.user_id, u.username, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_type,
|
||||
ui.avatar, ui.gender, ui.family_name, ui.given_name, ui.full_name, ui.level, ui.id_card, ui.address,
|
||||
u.user_id, u.password, u.email, u.phone, u.wechat_id, u.status,
|
||||
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,
|
||||
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
|
||||
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_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)
|
||||
<where>
|
||||
<if test="filter.userId != null and filter.userId != ''">
|
||||
@@ -184,8 +180,8 @@
|
||||
<!-- 根据条件查询系统用户角色关系分页列表 -->
|
||||
<select id="getUserRolePageByFilter" resultMap="UserDeptRoleVOResultMap">
|
||||
SELECT DISTINCT
|
||||
u.user_id, u.username, u.password, u.email, u.phone, u.wechat_id, u.status, u.user_type,
|
||||
ui.avatar, ui.gender, ui.family_name, ui.given_name, ui.full_name, ui.level, ui.id_card, ui.address,
|
||||
u.user_id, u.password, u.email, u.phone, u.wechat_id, u.status,
|
||||
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,
|
||||
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
|
||||
@@ -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)
|
||||
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,
|
||||
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
|
||||
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_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)
|
||||
<where>
|
||||
<if test="filter.userId != null and filter.userId != ''">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# ================== Server ==================
|
||||
server:
|
||||
port: 8188
|
||||
servlet:
|
||||
context-path: /urban-lifeline/workcase
|
||||
# servlet:
|
||||
# context-path: /urban-lifeline/workcase # 微服务架构下,context-path由Gateway管理
|
||||
|
||||
# ================== Auth ====================
|
||||
urban-lifeline:
|
||||
|
||||
@@ -115,9 +115,9 @@
|
||||
}
|
||||
const usedRemotes = [
|
||||
{
|
||||
entryGlobalName: "http://localhost:5000/remoteEntry.js",
|
||||
entryGlobalName: "shared",
|
||||
name: "shared",
|
||||
type: "var",
|
||||
type: "module",
|
||||
entry: "http://localhost:5000/remoteEntry.js",
|
||||
shareScope: "default",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user