fix(sql): 菜单SQL 改用自增分配 id,修复主键冲突
CI/CD Deploy (Admin) / 构建后端镜像并部署 (push) Successful in 1m6s

实测执行时发现硬编码 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)
- 两文件均已实测通过(含连续执行两次的幂等验证)
This commit is contained in:
zhangjiaxun
2026-10-20 22:40:36 +08:00
parent 4aba70b047
commit bf3939c415
2 changed files with 64 additions and 36 deletions
+53 -30
View File
@@ -6,44 +6,67 @@
-- 拼成 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', '文本比对', '左右文本并排比对,支持字符级高亮、忽略空白与结果导出',
VALUES (0, 'tools', '工具列表', '与系统管理同级的工具集合',
1, 'ios-apps', '', '', 20, 'admin', NOW(), 0);
SET @tools_id = LAST_INSERT_ID();
-- ---------- 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);
-- ---------- 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 @diff_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`;
-- ---------- 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;
-- 预期返回 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`;
-- ---------- 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`;
+9 -4
View File
@@ -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());