# 驾驶员默认角色缺失排查与修复 ## 1. 背景 - 驾驶员默认角色常量定义见 [ISysUserLoginPortService.java:L29-L37](file:///G:/code/shw/hot/wucaixing-full/wucaixing-backend/src/main/java/com/hotwj/platform/resourceManagement/company/service/ISysUserLoginPortService.java#L29-L37) - 默认驾驶员角色 ID:`2010339247320825857` - 驾驶员登录端口:`port-driver` 源码定义: ```java Long DRIVER_ROLE_ID = 2010339247320825857L; String DRIVER_PORT = "port-driver"; ``` ## 2. 表结构确认 已核对同步库 `sys_user_role` 表结构,核心字段如下: - `user_id` - `role_id` - `company_id` - `login_port` 说明: - 该表当前只需要写入以上 4 个字段即可完成角色补齐。 - 因此修复 SQL 可直接对 `sys_user_role` 执行 `insert into ... select ...`。 ## 3. 排查 SQL ### 3.1 统计缺失默认驾驶员角色的数量 ```sql select count(*) as missing_driver_default_role_count from ( select sulp.user_id, sulp.company_id from sys_user_login_port sulp left join sys_user_role sur on sur.user_id = sulp.user_id and sur.company_id = sulp.company_id and sur.login_port = sulp.login_port and sur.role_id = 2010339247320825857 where sulp.login_port = 'port-driver' and sulp.status = 1 group by sulp.user_id, sulp.company_id having count(sur.role_id) = 0 ) t; ``` ### 3.2 查看具体是哪个公司、哪个驾驶员账号缺失 ```sql select sulp.company_id, c.company_name as company_name, sulp.user_id, sulp.username, d.id as driver_id, d.name as driver_name, d.phone as driver_phone, sulp.login_port from sys_user_login_port sulp left join sys_user_role sur on sur.user_id = sulp.user_id and sur.company_id = sulp.company_id and sur.login_port = sulp.login_port and sur.role_id = 2010339247320825857 left join hot_driver d on d.company_id = sulp.company_id and ( convert(d.phone using utf8mb4) collate utf8mb4_general_ci = convert(sulp.username using utf8mb4) collate utf8mb4_general_ci or convert(d.id using utf8mb4) collate utf8mb4_general_ci = cast(sulp.user_id as char character set utf8mb4) collate utf8mb4_general_ci ) left join sys_company c on c.id = sulp.company_id where sulp.login_port = 'port-driver' and sulp.status = 1 group by sulp.company_id, c.company_name, sulp.user_id, sulp.username, d.id, d.name, d.phone, sulp.login_port having count(sur.role_id) = 0 order by sulp.company_id, d.name, sulp.user_id; ``` 说明: - 该 SQL 以 `sys_user_login_port` 为准,筛选已开通驾驶员端口的账号。 - 再检查 `sys_user_role` 中是否缺失默认驾驶员角色。 - 通过 `sys_company` 补充公司名,通过 `hot_driver` 尝试补充驾驶员姓名和手机号。 - 如果库中 `hot_driver` 与 `sys_user_login_port` 的字符集排序规则不一致,需要像上面这样显式 `collate`,否则会报 `Illegal mix of collations`。 ## 4. 修复 SQL ### 4.1 建议先预览待插入数据 ```sql select distinct sulp.user_id, 2010339247320825857 as role_id, sulp.company_id, sulp.login_port from sys_user_login_port sulp where sulp.login_port = 'port-driver' and sulp.status = 1 and not exists ( select 1 from sys_user_role sur where sur.user_id = sulp.user_id and sur.company_id = sulp.company_id and sur.login_port = sulp.login_port and sur.role_id = 2010339247320825857 ) order by sulp.company_id, sulp.user_id; ``` ### 4.2 正式修复缺失默认驾驶员角色 ```sql insert into sys_user_role ( user_id, role_id, company_id, login_port ) select distinct sulp.user_id, 2010339247320825857 as role_id, sulp.company_id, sulp.login_port from sys_user_login_port sulp where sulp.login_port = 'port-driver' and sulp.status = 1 and not exists ( select 1 from sys_user_role sur where sur.user_id = sulp.user_id and sur.company_id = sulp.company_id and sur.login_port = sulp.login_port and sur.role_id = 2010339247320825857 ); ``` 说明: - 该 SQL 只补缺失数据,不会重复插入已存在的默认驾驶员角色。 - 使用 `not exists` 作为幂等保护。 - 使用 `distinct` 避免 `sys_user_login_port` 中重复数据导致重复插入。 ## 5. 修复后校验 SQL ### 5.1 再次统计缺失数量 ```sql select count(*) as missing_driver_default_role_count from ( select sulp.user_id, sulp.company_id from sys_user_login_port sulp left join sys_user_role sur on sur.user_id = sulp.user_id and sur.company_id = sulp.company_id and sur.login_port = sulp.login_port and sur.role_id = 2010339247320825857 where sulp.login_port = 'port-driver' and sulp.status = 1 group by sulp.user_id, sulp.company_id having count(sur.role_id) = 0 ) t; ``` 预期: - 结果应为 `0` ### 5.2 抽样检查修复后的角色记录 ```sql select sur.user_id, sur.role_id, sur.company_id, sur.login_port from sys_user_role sur where sur.role_id = 2010339247320825857 and sur.login_port = 'port-driver' order by sur.company_id, sur.user_id; ``` ## 6. 回滚 SQL 如果本次补齐后需要回滚,只回滚本次补的默认驾驶员角色数据,可使用: ```sql delete sur from sys_user_role sur where sur.role_id = 2010339247320825857 and sur.login_port = 'port-driver' and exists ( select 1 from sys_user_login_port sulp where sulp.user_id = sur.user_id and sulp.company_id = sur.company_id and sulp.login_port = sur.login_port and sulp.login_port = 'port-driver' and sulp.status = 1 ); ``` 注意: - 这条回滚 SQL 会删除所有驾驶员端口上的默认驾驶员角色。 - 如果线上本来就有正确数据,不建议直接使用该回滚 SQL。 - 更稳妥的方式是:先把本次待插入数据导出备份,再按备份名单精确回滚。 ## 7. 推荐执行顺序 1. 先执行 3.1,确认缺失数量 2. 再执行 3.2,确认具体公司和驾驶员账号 3. 执行 4.1,预览待补数据 4. 执行 4.2,正式插入 5. 执行 5.1 和 5.2,确认修复完成 ## 8. 风险说明 - 当前修复只补齐“默认驾驶员角色”本身,不会补菜单权限。 - 如果默认驾驶员角色本身未绑定菜单权限,还需要继续检查: - `sys_role_permission` - `sys_menu` - 如果 `hot_driver` 与登录账号的关联规则不是 `phone = username` 或 `driver.id = cast(user_id as char)`,则 3.2 中驾驶员姓名可能为空,但不影响角色修复 SQL 的执行。