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

@@ -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);

View File

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

View File

@@ -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:

View File

@@ -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>

View File

@@ -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}

View File

@@ -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 != ''">