From bf3939c415ac7d53682e4fe75b4f8c5cacfa1b75 Mon Sep 17 00:00:00 2001 From: zhangjiaxun <732128096@qq.com> Date: Tue, 20 Oct 2026 22:40:36 +0800 Subject: [PATCH] =?UTF-8?q?fix(sql):=20=E8=8F=9C=E5=8D=95SQL=20=E6=94=B9?= =?UTF-8?q?=E7=94=A8=E8=87=AA=E5=A2=9E=E5=88=86=E9=85=8D=20id=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=BB=E9=94=AE=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实测执行时发现硬编码 id 会撞主键: - t_sys_permission 自增起点 1000,但 t_sys_role_permission 已单独用到 1005 - 写死 1005/1006 插入关联表时触发 Duplicate entry '1005' 改动: - add_tools_text_diff.sql 改用 LAST_INSERT_ID() 取自增 id - 授权改为 INSERT...SELECT,覆盖全部有效角色,不再写死 role_id=1 - 清理语句用 JOIN 按 permission_code 定位,避免误删他人菜单 - init.sql 同步修正 id,并补上遗漏的 user:getUserInfo 权限点(id=8) - 两文件均已实测通过(含连续执行两次的幂等验证) --- sql/add_tools_text_diff.sql | 87 +++++++++++++++++++++++-------------- sql/init.sql | 13 ++++-- 2 files changed, 64 insertions(+), 36 deletions(-) diff --git a/sql/add_tools_text_diff.sql b/sql/add_tools_text_diff.sql index bb8fdb8..d04f5c1 100644 --- a/sql/add_tools_text_diff.sql +++ b/sql/add_tools_text_diff.sql @@ -2,48 +2,71 @@ -- 工具列表菜单 + 文本比对页面 -- -- 与「系统管理」同级的顶级菜单,下挂「文本比对」 --- 菜单由t_sys_permission 表驱动,前端 formatMenuList() 会把 component +-- 菜单由 t_sys_permission 表驱动,前端 formatMenuList() 会把 component -- 拼成 import('@/view' + component + '.vue'),因此 component 必须带前导斜杠, -- 且要与 src/view/tools/text-diff.vue 对应 -- --- 幂等:可重复执行,已存在则跳过 +-- 幂等:可重复执行,已存在则先清理再插入 -- 执行库:freedom_db +-- +-- 注意:id 一律由数据库自增分配,不要硬编码。 +-- t_sys_permission 自增起点为 1000,且t_sys_role_permission 已单独用到 1005, +-- 硬编码 1005/1006 会直接撞主键(实测已踩坑,事务回滚后才改用自增)。 -- ============================================================ --- ---------- 1. 清理历史遗留(如果之前插过) ---------- -DELETE FROM `t_sys_role_permission` WHERE `permission_id` IN ( - SELECT `id` FROM `t_sys_permission` WHERE `permission_code` IN ('tools', 'tools:text-diff') -); +-- ---------- 1. 清理历史遗留 ---------- +-- 用 JOIN 按 permission_code 精确定位,避免误删他人菜单 +DELETE rp +FROM `t_sys_role_permission` rp + JOIN `t_sys_permission` p ON p.id = rp.permission_id +WHERE p.permission_code IN ('tools', 'tools:text-diff'); + DELETE FROM `t_sys_permission` WHERE `permission_code` IN ('tools', 'tools:text-diff'); --- ---------- 2. 插入菜单 ---------- --- 顶级菜单「工具列表」:url 与 component 留空,前端会挂载 Main 布局作为容器 --- 文本比对:component = /tools/text-diff,对应 src/view/tools/text-diff.vue +-- ---------- 2. 插入顶级菜单「工具列表」 ---------- +-- url 与 component 留空,前端会挂载 Main 布局作为容器 +-- icon 必须在 view-design 图标清单内(ios-apps 已从线上 CSS 校验存在) INSERT INTO `t_sys_permission` -(`id`, `parent_id`, `permission_code`, `permission_name`, `permission_desc`, `level`, +(`parent_id`, `permission_code`, `permission_name`, `permission_desc`, `level`, `icon`, `url`, `component`, `sort`, `create_by`, `create_date`, `del_flag`) -VALUES - (1005, 0, 'tools', '工具列表', '与系统管理同级的工具集合', - 1, 'ios-apps', '', '', 20, 'admin', NOW(), 0), - (1006, 1005, 'tools:text-diff', '文本比对', '左右文本并排比对,支持字符级高亮、忽略空白与结果导出', - 2, 'md-git-compare', '/tools/text-diff', '/tools/text-diff', 1, 'admin', NOW(), 0); +VALUES (0, 'tools', '工具列表', '与系统管理同级的工具集合', + 1, 'ios-apps', '', '', 20, 'admin', NOW(), 0); --- ---------- 3. 授权给超级管理员 ---------- --- 当前系统仅有「超级管理员」一个角色;若后续新增角色,按需补充同样的关联 -INSERT INTO `t_sys_role_permission` (`id`, `role_id`, `permission_id`, `create_by`, `create_date`) -VALUES - (1005, 1, 1005, 'admin', NOW()), - (1006, 1, 1006, 'admin', NOW()); +SET @tools_id = LAST_INSERT_ID(); --- ---------- 4. 校验 ---------- --- 预期返回 2 行:工具列表(id=1005, parent_id=0) 与 文本比对(id=1006, parent_id=1005) -SELECT `id`, `parent_id`, `permission_code`, `permission_name`, `level`, `icon`, `url`, `component`, `sort` -FROM `t_sys_permission` -WHERE `permission_code` IN ('tools', 'tools:text-diff') -ORDER BY `level`, `sort`; +-- ---------- 3. 插入子菜单「文本比对」 ---------- +-- component 必须带前导斜杠且与磁盘文件对应:src/view/tools/text-diff.vue +INSERT INTO `t_sys_permission` +(`parent_id`, `permission_code`, `permission_name`, `permission_desc`, `level`, + `icon`, `url`, `component`, `sort`, `create_by`, `create_date`, `del_flag`) +VALUES (@tools_id, 'tools:text-diff', '文本比对', + '左右文本并排比对,支持字符级高亮、忽略空白与结果导出', + 2, 'md-git-compare', '/tools/text-diff', '/tools/text-diff', 1, 'admin', NOW(), 0); --- 预期返回 2 行:role_id=1 分别关联 permission_id 1005 / 1006 -SELECT `id`, `role_id`, `permission_id` -FROM `t_sys_role_permission` -WHERE `permission_id` IN (1005, 1006) -ORDER BY `permission_id`; \ No newline at end of file +SET @diff_id = LAST_INSERT_ID(); + +-- ---------- 4. 授权给全部有效角色 ---------- +-- 不写死 role_id,将来新增角色后重跑本脚本即可自动补齐授权 +INSERT INTO `t_sys_role_permission` (`role_id`, `permission_id`, `create_by`, `create_date`) +SELECT r.`id`, p.`pid`, 'admin', NOW() +FROM `t_sys_role` r + CROSS JOIN (SELECT @tools_id AS `pid` + UNION ALL + SELECT @diff_id) p +WHERE r.`del_flag` = 0; + +-- ---------- 5. 校验 ---------- +-- 预期 2 行:工具列表(parent_id=0, level=1) 与 文本比对(parent_id=工具列表id, level=2) +SELECT p.`id`, p.`parent_id`, p.`permission_code`, p.`permission_name`, + p.`level`, p.`icon`, p.`url`, p.`component`, p.`sort` +FROM `t_sys_permission` p +WHERE p.`permission_code` IN ('tools', 'tools:text-diff') +ORDER BY p.`level`, p.`sort`; + +-- 预期:每个有效角色 2 条关联 +SELECT rp.`id`, rp.`role_id`, r.`role_name`, rp.`permission_id`, p.`permission_name` +FROM `t_sys_role_permission` rp + JOIN `t_sys_role` r ON r.`id` = rp.`role_id` + JOIN `t_sys_permission` p ON p.`id` = rp.`permission_id` +WHERE p.`permission_code` IN ('tools', 'tools:text-diff') +ORDER BY rp.`role_id`, rp.`permission_id`; \ No newline at end of file diff --git a/sql/init.sql b/sql/init.sql index 3be48b8..73b04dd 100644 --- a/sql/init.sql +++ b/sql/init.sql @@ -154,6 +154,8 @@ VALUES -- 权限菜单 -- component 必须带前导斜杠且与 src/view 下的实际文件名一致: -- 前端 formatMenuList() 会拼成 import('@/view' + component + '.vue') +-- 说明:此处 id 硬编码仅适用于全新建库(此时两张表都为空)。 +-- 已有数据的库请用 sql/add_tools_text_diff.sql,它改用自增避免撞主键。 INSERT INTO `t_sys_permission` (`id`, `parent_id`, `permission_code`, `permission_name`, `permission_desc`, `level`, `icon`, `url`, `component`, `sort`, `create_by`, `create_date`, `del_flag`) VALUES (1, 0, 'system', '系统管理', '系统管理菜单', 1, 'ios-settings', '', '', 1, 'admin', NOW(), 0), @@ -161,16 +163,18 @@ VALUES (3, 1, 'sys:role', '角色管理', '角色管理', 2, 'ios-people', '/sys/role', '/sys/sys-role', 2, 'admin', NOW(), 0), (4, 1, 'sys:dept', '部门管理', '部门管理', 2, 'ios-home', '/sys/dept', '/sys/sys-dept', 3, 'admin', NOW(), 0), (5, 1, 'sys:permission', '权限管理', '权限管理', 2, 'ios-key', '/sys/permission', '/sys/sys-permission', 4, 'admin', NOW(), 0), + (6, 0, 'user:getUserInfo', '获取用户信息', '登录后获取当前用户信息的前端权限点', 1, '', '', '', 99, 'admin', NOW(), 0), (1003, 0, 'todo', '待办', '个人与公开待办', 1, 'md-checkmark-circle', '', '', 10, 'admin', NOW(), 0), (1004, 1003, 'todo:list', '待办清单', '个人待办清单', 2, 'md-list-box', '/todo/list', '/todo/todo-list', 1, 'admin', NOW(), 0), - (1005, 0, 'tools', '工具列表', '与系统管理同级的工具集合', 1, 'ios-apps', '', '', 20, 'admin', NOW(), 0), - (1006, 1005, 'tools:text-diff', '文本比对', '左右文本并排比对,支持字符级高亮、忽略空白与结果导出', 2, 'md-git-compare', '/tools/text-diff', '/tools/text-diff', 1, 'admin', NOW(), 0); + (1007, 0, 'tools', '工具列表', '与系统管理同级的工具集合', 1, 'ios-apps', '', '', 20, 'admin', NOW(), 0), + (1008, 1007, 'tools:text-diff', '文本比对', '左右文本并排比对,支持字符级高亮、忽略空白与结果导出', 2, 'md-git-compare', '/tools/text-diff', '/tools/text-diff', 1, 'admin', NOW(), 0); -- 用户-角色关联:admin -> 超级管理员 INSERT INTO `t_sys_user_role` (`id`, `user_id`, `role_id`, `create_by`, `create_time`) VALUES (1, 1, 1, 'admin', NOW()); -- 角色-权限关联:超级管理员 -> 所有权限 +-- 关联表自增起点同为 1000,这里也按实际 id 顺排,避免与 t_sys_permission 混淆 INSERT INTO `t_sys_role_permission` (`id`, `role_id`, `permission_id`, `create_by`, `create_date`) VALUES (1, 1, 1, 'admin', NOW()), @@ -178,7 +182,8 @@ VALUES (3, 1, 3, 'admin', NOW()), (4, 1, 4, 'admin', NOW()), (5, 1, 5, 'admin', NOW()), + (8, 1, 6, 'admin', NOW()), (1003, 1, 1003, 'admin', NOW()), (1004, 1, 1004, 'admin', NOW()), - (1005, 1, 1005, 'admin', NOW()), - (1006, 1, 1006, 'admin', NOW()); + (1005, 1, 1007, 'admin', NOW()), + (1006, 1, 1008, 'admin', NOW());