初始化

缺陷:主题配色需要优化整体的同风格
This commit is contained in:
2026-08-14 23:21:21 +08:00
parent 6e2769c528
commit bcf54c2727
152 changed files with 13521 additions and 141 deletions

112
database/sql/rbac_audit.sql Normal file
View File

@@ -0,0 +1,112 @@
-- ============================================================
-- 账号与角色迁移前数据体检(只读,可直接粘进 Navicat / phpMyAdmin 执行)
--
-- 与 `php artisan lgp:rbac-audit` 等价,供未安装依赖时使用。
-- 库cc_new_stash老业务表 cc_ 与新系统表 nl_ 同库)
-- ============================================================
-- ------------------------------------------------------------
-- [1] 迁移规模
-- ------------------------------------------------------------
SELECT 'cc_user 待迁账号' AS item, COUNT(*) AS cnt FROM cc_user WHERE deleted_at = 0
UNION ALL SELECT 'cc_role 待迁角色', COUNT(*) FROM cc_role WHERE deleted_at = 0
UNION ALL SELECT 'cc_department 部门(复用不迁)', COUNT(*) FROM cc_department WHERE deleted_at = 0
UNION ALL SELECT 'cc_user_role_relation 用户角色关系', COUNT(*) FROM cc_user_role_relation
UNION ALL SELECT 'cc_role_menu_relation 角色菜单关系', COUNT(*) FROM cc_role_menu_relation
UNION ALL SELECT 'nl_admin 现有账号', COUNT(*) FROM nl_admin WHERE deleted_at = 0
UNION ALL SELECT 'nl_role 现有角色', COUNT(*) FROM nl_role WHERE deleted_at = 0;
-- ------------------------------------------------------------
-- [2] 绑定了多个角色的用户
-- 新库 nl_admin.role_id 是单字段,多绑的必须人工决定取哪个
-- ------------------------------------------------------------
SELECT ur.user_id, u.account, u.nick_name,
COUNT(*) AS role_count,
GROUP_CONCAT(ur.role_id ORDER BY ur.role_id) AS role_ids
FROM cc_user_role_relation ur
JOIN cc_user u ON u.id = ur.user_id
WHERE u.deleted_at = 0
GROUP BY ur.user_id, u.account, u.nick_name
HAVING role_count > 1;
-- [2b] 完全没有角色关系的账号(迁过去 role_id=0看不到任何菜单
SELECT u.id, u.account, u.nick_name
FROM cc_user u
WHERE u.deleted_at = 0
AND NOT EXISTS (SELECT 1 FROM cc_user_role_relation ur WHERE ur.user_id = u.id);
-- ------------------------------------------------------------
-- [3] 重复手机号
-- 新库登录是 WHERE phone = ? LIMIT 1重复会登录到错误的人
-- ------------------------------------------------------------
SELECT phone, COUNT(*) AS c,
GROUP_CONCAT(id ORDER BY id) AS user_ids,
GROUP_CONCAT(account ORDER BY id) AS accounts
FROM cc_user
WHERE deleted_at = 0
GROUP BY phone
HAVING c > 1;
-- ------------------------------------------------------------
-- [4] 手机号长度异常
-- 新库 nl_admin.phone 是 char(11),超长会被截断,空值无法登录
-- ------------------------------------------------------------
SELECT id, account, nick_name, phone, CHAR_LENGTH(phone) AS len
FROM cc_user
WHERE deleted_at = 0
AND (phone = '' OR CHAR_LENGTH(phone) <> 11);
-- ------------------------------------------------------------
-- [5] 老角色清单(含账号数与菜单数)
-- 新库 nl_role.value 必填,需为每个角色指定英文标识
-- ------------------------------------------------------------
SELECT r.id, r.name, r.`desc`, r.status AS `status_0正常_1禁用`, r.color,
(SELECT COUNT(*) FROM cc_user_role_relation ur
JOIN cc_user u ON u.id = ur.user_id
WHERE ur.role_id = r.id AND u.deleted_at = 0) AS user_count,
(SELECT COUNT(*) FROM cc_role_menu_relation rm
WHERE rm.role_id = r.id) AS menu_count
FROM cc_role r
WHERE r.deleted_at = 0
ORDER BY r.id;
-- ------------------------------------------------------------
-- [6] 角色 ID 撞车
-- nl_role.id=1 是超级管理员且代码里硬判断 role_id===1 全量放行
-- 老库 id=1 未必是超管,按原 ID 迁会把普通角色提权成超管
-- ------------------------------------------------------------
SELECT '老 cc_role' AS src, id, name FROM cc_role WHERE id = 1
UNION ALL
SELECT '新 nl_role', id, name FROM nl_role WHERE id = 1;
SELECT MAX(id) AS old_role_max_id, MAX(id) + 100 AS suggested_new_max
FROM cc_role WHERE deleted_at = 0;
-- ------------------------------------------------------------
-- [7] 密码格式
-- 惰性升级依赖无盐 sha140 位 hex非此格式只能走重置
-- ------------------------------------------------------------
SELECT
SUM(CHAR_LENGTH(password) = 40 AND password REGEXP '^[0-9a-f]{40}$') AS sha1_ok,
SUM(password = '') AS empty_pwd,
SUM(password <> '' AND NOT (CHAR_LENGTH(password) = 40 AND password REGEXP '^[0-9a-f]{40}$')) AS other_format
FROM cc_user
WHERE deleted_at = 0;
-- ------------------------------------------------------------
-- [8] 部门悬空引用cc_user.department 指向已不存在的部门)
-- ------------------------------------------------------------
SELECT u.id, u.account, u.department
FROM cc_user u
WHERE u.deleted_at = 0
AND u.department > 0
AND NOT EXISTS (SELECT 1 FROM cc_department d WHERE d.id = u.department AND d.deleted_at = 0);
-- ------------------------------------------------------------
-- [9] account 与 phone 不一致的账号
-- account 从不参与登录(老 UserService::login 查的是 phone
-- 迁移时把原 account 写进 nl_admin.desc 留痕即可,不新增列
-- ------------------------------------------------------------
SELECT COUNT(*) AS account_phone_diff
FROM cc_user
WHERE deleted_at = 0 AND account <> phone;

View File

@@ -0,0 +1,124 @@
-- ============================================================
-- RBAC 表结构补丁(幂等,可重复执行)
-- 文件database/sql/rbac_migrate_ddl.sql
--
-- 用途:给 nl_admin / nl_role 补齐迁移与日常接口所需列
-- - nl_admin.department_id → 解除 admin/my-info 报 Unknown column
-- - nl_admin.legacy_password* → 老无盐 sha1 惰性升级
-- - nl_role.status / color → 角色禁用与标签色
--
-- 用法(任选其一):
-- 1. Navicat选中库 cc_new_stash → 新建查询 → 整份粘贴 → 运行
-- (本文件不用 DELIMITER / 存储过程Navicat 可直接跑)
-- 2. mysql 客户端:
-- mysql -h... -u... -p cc_new_stash < database/sql/rbac_migrate_ddl.sql
--
-- 说明:
-- - 用 information_schema + PREPARE 实现「列/索引已存在则跳过」
-- - 不依赖 Laravel DB_PREFIX
-- - uk_phone 唯一索引在文末【可选】段,有重复手机号时会失败
-- ============================================================
-- ------------------------------------------------------------
-- nl_admin.department_id
-- ------------------------------------------------------------
SET @db := DATABASE();
SET @exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'nl_admin' AND COLUMN_NAME = 'department_id'
);
SET @sql := IF(@exists = 0,
'ALTER TABLE `nl_admin` ADD COLUMN `department_id` int NOT NULL DEFAULT 0 COMMENT ''所属部门ID对应 cc_department.id'' AFTER `role_id`',
'SELECT ''skip nl_admin.department_id'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ------------------------------------------------------------
-- nl_admin.legacy_password
-- ------------------------------------------------------------
SET @exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'nl_admin' AND COLUMN_NAME = 'legacy_password'
);
SET @sql := IF(@exists = 0,
'ALTER TABLE `nl_admin` ADD COLUMN `legacy_password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '''' COMMENT ''老系统无盐sha1密码登录成功后清空'' AFTER `password`',
'SELECT ''skip nl_admin.legacy_password'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ------------------------------------------------------------
-- nl_admin.legacy_password_expire_at
-- ------------------------------------------------------------
SET @exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'nl_admin' AND COLUMN_NAME = 'legacy_password_expire_at'
);
SET @sql := IF(@exists = 0,
'ALTER TABLE `nl_admin` ADD COLUMN `legacy_password_expire_at` int NOT NULL DEFAULT 0 COMMENT ''遗留密码失效时间,过期强制走重置'' AFTER `legacy_password`',
'SELECT ''skip nl_admin.legacy_password_expire_at'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ------------------------------------------------------------
-- nl_admin 索引 idx_role / idx_department
-- ------------------------------------------------------------
SET @exists := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'nl_admin' AND INDEX_NAME = 'idx_role'
);
SET @sql := IF(@exists = 0,
'ALTER TABLE `nl_admin` ADD INDEX `idx_role`(`role_id` ASC, `deleted_at` ASC) USING BTREE',
'SELECT ''skip idx_role'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'nl_admin' AND INDEX_NAME = 'idx_department'
);
SET @sql := IF(@exists = 0,
'ALTER TABLE `nl_admin` ADD INDEX `idx_department`(`department_id` ASC, `deleted_at` ASC) USING BTREE',
'SELECT ''skip idx_department'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ------------------------------------------------------------
-- nl_role.status / color (你当前 audit 缺的就是这两列)
-- ------------------------------------------------------------
SET @exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'nl_role' AND COLUMN_NAME = 'status'
);
SET @sql := IF(@exists = 0,
'ALTER TABLE `nl_role` ADD COLUMN `status` tinyint(1) NOT NULL DEFAULT 0 COMMENT ''状态 0正常 1禁用'' AFTER `desc`',
'SELECT ''skip nl_role.status'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'nl_role' AND COLUMN_NAME = 'color'
);
SET @sql := IF(@exists = 0,
'ALTER TABLE `nl_role` ADD COLUMN `color` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '''' COMMENT ''角色标签颜色'' AFTER `status`',
'SELECT ''skip nl_role.color'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ------------------------------------------------------------
-- 修正种子:超管 status 必须是 00正常 1禁用
-- ------------------------------------------------------------
UPDATE `nl_admin` SET `status` = 0 WHERE `id` = 1 AND `status` = 1;
-- ============================================================
-- 【可选】uk_phone —— 先跑 lgp:rbac-audit 确认手机号无重复后再执行
-- ============================================================
-- SET @exists := (
-- SELECT COUNT(*) FROM information_schema.STATISTICS
-- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'nl_admin' AND INDEX_NAME = 'uk_phone'
-- );
-- SET @sql := IF(@exists = 0,
-- 'ALTER TABLE `nl_admin` ADD UNIQUE INDEX `uk_phone`(`phone` ASC) USING BTREE',
-- 'SELECT ''skip uk_phone'' AS msg'
-- );
-- PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;