-- ============================================================ -- 数据权限按业务模块可配:一次性迁移脚本(单事务) -- 工单 03 决策:建两表 + 插内置模块 + CROSS JOIN 旧值 + DROP 旧列 -- 部署时手动执行,单事务保证原子性 -- ============================================================ BEGIN; -- 1. 建模块注册表 CREATE TABLE IF NOT EXISTS sys_data_scope_module ( id bigint NOT NULL AUTO_INCREMENT, code varchar(50) NOT NULL COMMENT '模块编码(稳定标识)', name varchar(100) NOT NULL COMMENT '模块名称', sort int NOT NULL DEFAULT 0 COMMENT '排序', status varchar(10) NOT NULL DEFAULT 'enabled' COMMENT '状态:enabled/disabled', builtin boolean NOT NULL DEFAULT false COMMENT '内置模块标记', create_time datetime DEFAULT NULL, update_time datetime DEFAULT NULL, creator_id varchar(36) DEFAULT NULL, updater_id varchar(36) DEFAULT NULL, deleted boolean DEFAULT false, PRIMARY KEY (id), UNIQUE KEY uk_module_code (code) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据权限模块注册表'; -- 2. 插入内置模块 INSERT INTO sys_data_scope_module (code, name, sort, builtin) SELECT * FROM ( SELECT 'lead' AS code, '线索' AS name, 1 AS sort, true AS builtin UNION ALL SELECT 'opportunity', '商机', 2, true UNION ALL SELECT 'customer', '客户', 3, true UNION ALL SELECT 'project', '项目', 4, true ) AS new_modules WHERE NOT EXISTS ( SELECT 1 FROM sys_data_scope_module WHERE code = new_modules.code ); -- 3. 建角色×模块档位表 CREATE TABLE IF NOT EXISTS sys_role_data_scope ( id bigint NOT NULL AUTO_INCREMENT, role_id bigint NOT NULL COMMENT '角色ID', module_code varchar(50) NOT NULL COMMENT '模块编码(引用 sys_data_scope_module.code)', data_scope tinyint NOT NULL COMMENT '数据范围 1=本人 2=本部门 3=本部门及子部门 4=全部', create_time datetime DEFAULT NULL, update_time datetime DEFAULT NULL, creator_id varchar(36) DEFAULT NULL, updater_id varchar(36) DEFAULT NULL, deleted boolean DEFAULT false, PRIMARY KEY (id), UNIQUE KEY uk_role_module (role_id, module_code) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色×模块数据范围档位'; -- 4. 迁移:旧单值复制到每模块(仅迁移 sys_role 有 data_scope 列时执行) -- 使用 INFORMATION_SCHEMA 检查列是否存在,避免列已删除后重复执行报错 SET @col_exists = ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'sys_role' AND COLUMN_NAME = 'data_scope' ); -- 构建动态 SQL 执行迁移 SET @sql = IF(@col_exists > 0, 'INSERT INTO sys_role_data_scope (role_id, module_code, data_scope, create_time, update_time, deleted) SELECT r.id, m.code, r.data_scope, NOW(), NOW(), false FROM sys_role r CROSS JOIN sys_data_scope_module m WHERE r.data_scope IS NOT NULL AND NOT EXISTS ( SELECT 1 FROM sys_role_data_scope rsd WHERE rsd.role_id = r.id AND rsd.module_code = m.code )', 'SELECT "sys_role.data_scope column already removed, skipping migration" AS msg' ); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 5. 删旧列(仅在列存在时执行) SET @sql2 = IF(@col_exists > 0, 'ALTER TABLE sys_role DROP COLUMN data_scope', 'SELECT "sys_role.data_scope column already removed" AS msg' ); PREPARE stmt2 FROM @sql2; EXECUTE stmt2; DEALLOCATE PREPARE stmt2; COMMIT;