# 驾驶员默认角色缺失排查与修复

## 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 的执行。

