fastbee/fastbee-service/fastbee-system-service/src/main/resources/mapper/system/SysUserSettingMapper.xml
2026-10-05 18:26:40 +08:00

132 lines
6.6 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fastbee.system.mapper.SysUserSettingMapper">
<resultMap type="com.fastbee.system.domain.SysUserSetting" id="SysUserSettingResult">
<result property="settingId" column="setting_id" />
<result property="userId" column="user_id" />
<result property="loginRedirect" column="login_redirect" />
<result property="pinnedTags" column="pinned_tags" />
<result property="queryGatewayChild" column="query_gateway_child" />
<result property="showChild" column="show_child" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
</resultMap>
<resultMap type="com.fastbee.system.domain.LoginRedirectOption" id="LoginRedirectOptionResult">
<result property="path" column="path" />
<result property="menuName" column="menu_name" />
</resultMap>
<sql id="selectUserSettingVo">
select setting_id, user_id, login_redirect, pinned_tags, query_gateway_child, show_child,
create_by, create_time, update_by, update_time, remark
from sys_user_setting
</sql>
<select id="selectByUserId" parameterType="Long" resultMap="SysUserSettingResult">
<include refid="selectUserSettingVo"/>
where user_id = #{userId}
</select>
<!--
部分更新:只更新**显式传入**(非 null)的列。
设置页每次只提交用户真正改动过的那几项,因此保存 A 配置不可能把 B 配置冲成默认值——
这是把写入从「整体覆盖」拆成「单量提交」的关键:
· Boolean 为 null = 本次不改这一项(显式传 false 与不传是两回事,包装类型能区分)
· String 为 null = 本次不改这一项
刻意不碰 pinned_tags:它由 tags-view 的独立写入路径维护,混进来会互相覆盖。
调用方必须先 insertDefaultIfAbsent 保证行存在,否则 UPDATE 0 行会静默丢改动。
-->
<update id="updateSetting" parameterType="com.fastbee.system.domain.SysUserSetting">
update sys_user_setting
<set>
<if test="loginRedirect != null">login_redirect = #{loginRedirect},</if>
<if test="queryGatewayChild != null">query_gateway_child = #{queryGatewayChild},</if>
<if test="showChild != null">show_child = #{showChild},</if>
update_by = #{updateBy},
update_time = #{updateTime}
</set>
where user_id = #{userId}
</update>
<!--
确保设置行存在:不存在则插入默认行,已存在则**什么都不改**。
两处调用:① 固定标签的增量写入要在一行上做「锁定读 → 改 → 写」,行必须先存在;
② 设置页的部分更新前先兜一行,否则 UPDATE 0 行会静默丢改动。
刻意不用 ON DUPLICATE 写其它列:那会覆盖 login_redirect / query_gateway_child / show_child,
把用户已保存的设置冲回默认值;这里用 user_id = user_id 作为 no-op 更新。
-->
<insert id="insertDefaultIfAbsent">
insert into sys_user_setting
(user_id, login_redirect, pinned_tags, query_gateway_child, show_child, create_by, create_time, update_by, update_time)
values
(#{userId}, #{loginRedirect}, '[]', #{queryGatewayChild}, #{showChild}, #{operator}, #{now}, #{operator}, #{now})
on duplicate key update
user_id = user_id
</insert>
<!--
锁定读固定标签。固定标签的写入是「读-改-写」,必须靠行锁把并发请求串行化:
没有 FOR UPDATE 时两个并发请求各自读到同一份旧值,后写的会把先写的覆盖掉——
这正是原先「前端全量 PUT」丢标签的服务端成因。
-->
<select id="selectPinnedTagsForUpdate" resultType="java.lang.String">
select pinned_tags
from sys_user_setting
where user_id = #{userId}
for update
</select>
<!--
整列覆盖写固定标签。与设置页的部分更新是两条独立写入路径:
若把 pinned_tags 并进 updateSetting,保存登录跳转等配置时会把固定标签一并覆盖掉。
**只在 addPinnedTag / removePinnedTag 的事务内调用**,且在 SELECT ... FOR UPDATE
之后落下,入参是锁内读出并改好的完整数组;对外不再有全量覆盖写的入口。
-->
<update id="updatePinnedTags" parameterType="com.fastbee.system.domain.SysUserSetting">
update sys_user_setting
set pinned_tags = #{pinnedTags},
update_by = #{updateBy},
update_time = #{updateTime}
where user_id = #{userId}
</update>
<!--
登录落地页候选项:取可作为页签的菜单,拼出完整路由 path。
过滤条件缺一不可:
menu_type='C' 只要页签,排除按钮(F)与目录(M)
status='0' 排除停用
visible='0' 排除菜单树里隐藏的
is_frame=1 排除外链(is_frame=0,component 为 http 地址),防止开放重定向
component 非空 路由必须有对应组件
p.menu_type='M' 只取一级页签。父级是页签(C)的是二级嵌套操作页
(如设备管理下的「设备分享列表」),不适合作为登录落地页。
路径拼接:父菜单 path 为空(顶级菜单 parent_id=0)时用 IFNULL 兜住,
再用 TRIM(TRAILING '/') 清掉尾部斜杠,避免 CONCAT 产出 '//system' 或 '/xxx/'。
排序按父目录 order_num 再按自身 order_num,与左侧菜单树顺序一致。
-->
<select id="selectLoginRedirectOptions" resultMap="LoginRedirectOptionResult">
select concat('/', trim(trailing '/' from concat(ifnull(p.path, ''), '/', m.path))) as path,
m.menu_name
from sys_menu m
left join sys_menu p on m.parent_id = p.menu_id
where m.menu_type = 'C'
and m.status = '0'
and m.visible = '0'
and m.is_frame = '1'
and m.component is not null
and m.component != ''
and m.path is not null
and m.path != ''
and p.menu_type = 'M'
order by p.order_num, m.order_num
</select>
</mapper>