# 【修改接口·管理后台】司机档案 6 接口（详情新增 relatedOrders mock 字段 + 全模块快照）

> **PR**: #2796（详情加 relatedOrders mock 字段） | **服务**: hl-fleet-service | **更新时间**: 2026-05-21
>
> **存放目录**: `changelogs-v2/2026-05/`
> **影响范围**: 管理后台「车管 / 司机档案」页（列表 + 详情 + 新增 + 编辑 + 软删 + Excel 批量导入）

---

## ⚠️ 关键变化

| # | 接口 | 状态 | 说明 |
|---|---|---|---|
| §3.2 | GET `/admin/fleet/drivers/{driverId}` | **🔧 修改** | 响应**新增 `relatedOrders` 字段**（mock 占位，固定 3 条假数据） |
| 其余 5 接口 | — | 首推 | 契约自模块首次落地（PR #2724）以来未变化，本次首推完整 changelog |

> **`relatedOrders` 字段是 mock**！固定返回 3 条假数据，所有司机返回相同内容。前端可基于字段做 UI 但**不要硬编码业务逻辑**（如"看到张总订单 = 司机已派单"）。详见 §3.2 + §9 + §12。

---

## 1. 接口背景

司机档案是车队所有司机的主数据：基本信息 / 驾照 / 紧急联系人 / 保险 / 历史统计 / 标签 / 多类目附件（身份证/驾驶证/肖像/健康证/培训证/荣誉/从业资格/其他 8 类）。

PR #2796 在司机详情 §3.2 响应里加了 `relatedOrders` 字段，让前端可以提前对接「司机详情 → 关联订单列表」的 UI 区块。但由于派车模块（订单 ↔ 司机关联）尚未对接到 fleet 服务，**当前返回固定 3 条 mock 假数据**，待后续真实化（详见 #2791）。

---

## 2. 变更清单

| # | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|----------|------|
| 1 | GET | `/admin/fleet/drivers/page` | 首推 | 分页列表 |
| 2 | GET | `/admin/fleet/drivers/{driverId}` | **修改** | 详情，**新增 `relatedOrders` mock 字段** |
| 3 | POST | `/admin/fleet/drivers` | 首推 | 新增（含标签 + 附件批量提交） |
| 4 | PUT | `/admin/fleet/drivers/{driverId}` | 首推 | 编辑（attachments diff + tags 全量覆盖） |
| 5 | DELETE | `/admin/fleet/drivers/{driverId}` | 首推 | 软删 |
| 6 | POST | `/admin/fleet/drivers/import` | 首推 | Excel 批量导入（按身份证去重） |

---

## 3. 接口详情

### 3.1 分页查询

**GET** `/admin/fleet/drivers/page`

- **使用场景**：司机档案列表页，支持「2026 年赛季在册 / 续费待回复 / 往年档案 / 黑名单 / 全部」5 个 tab 切换（前端按 `season` 字段传值）
- **认证**：管理后台 JWT
- **幂等**：是

**Query 入参**：

| 字段 | 类型 | 必填 | 默认 | 校验 | 说明 |
|---|---|---|---|---|---|
| `page` | int | ❌ | 1 | `>= 1` | 页码 |
| `pageSize` | int | ❌ | 20 | `1-100` | 每页条数 |
| `keyword` | string | ❌ | — | — | 姓名模糊匹配 |
| `driverStatus` | string | ❌ | — | `idle/busy/rest/pending` | 状态精确（见 §6.2） |
| `season` | string | ❌ | — | `active/pending/archived/blacklist` | 赛季精确（见 §6.3，对应前端 5 tab） |
| `tagName` | string | ❌ | — | — | 标签名精确（拥有该标签的司机） |
| `primaryVehiclePlate` | string | ❌ | — | — | 常驻车车牌精确匹配 |
| `insuranceType` | string | ❌ | — | `annual/perTrip/none` | 保险类型精确（见 §6.4） |

**出参**：`Result<PageResult<DriverPageItemRespVO>>` （phone/idCard 脱敏；列表项含 tags，**不含**附件详情）

| 字段 | 类型 | 说明 |
|---|---|---|
| `records[].id` | string | 司机 ID |
| `records[].name` | string | 姓名 |
| `records[].phone` | string | 手机号（脱敏，如 `138****1234`） |
| `records[].idCard` | string | 身份证号（脱敏，如 `150102******1234`） |
| `records[].gender` | string | 性别 |
| `records[].years` | int | 驾龄 |
| `records[].driverStatus` | string | 状态（见 §6.2） |
| `records[].season` | string | 赛季（见 §6.3） |
| `records[].primaryVehiclePlate` | string | 常驻车车牌 |
| `records[].insuranceType` | string | 保险类型（见 §6.4） |
| `records[].tags[]` | array | 标签列表 |
| `records[].createTime` | datetime | — |
| `total` / `page` / `pageSize` | int | 分页元数据 |

**典型示例 请求**（5 tab 之一：在册）：
```
GET /admin/fleet/drivers/page?page=1&pageSize=20&season=active
Authorization: Bearer <token>
（无请求体）
```

**典型示例 响应**：
```json
{
  "code": 200,
  "data": {
    "records": [
      {
        "id": "1234567890123456789",
        "name": "张三",
        "phone": "138****1234",
        "idCard": "150102******1234",
        "gender": "男",
        "years": 8,
        "driverStatus": "idle",
        "season": "active",
        "primaryVehiclePlate": "蒙A-88888",
        "insuranceType": "annual",
        "tags": ["老司机", "蒙语流利"],
        "createTime": "2025-05-21 14:00:00"
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 20
  },
  "msg": "成功"
}
```

**前端 tab → season 取值映射**：

| 前端 tab | 后端参数 |
|---|---|
| 全部 | （不传 season） |
| 2026 年赛季在册 | `season=active` |
| 续费待回复 | `season=pending` |
| 往年档案 | `season=archived` |
| 黑名单 | `season=blacklist` |

> "2026 年"是装饰文案（取自前端业务文案约定），后端 `season` 字段不带年份维度。

**错误码**：400 参数校验 / 401 未登录

---

### 3.2 详情 🔧 修改（新增 `relatedOrders` mock 字段）

**GET** `/admin/fleet/drivers/{driverId}`

- **使用场景**：详情页 / 编辑前预填
- **认证**：管理后台 JWT
- **幂等**：是

**路径入参**：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `driverId` | Long | ✅ | 司机 ID |

**出参**：`Result<DriverDetailRespVO>`

主体字段（含 §3.1 全部字段）+ 以下扩展：

| 字段 | 类型 | 说明 |
|---|---|---|
| `nation` | string | 民族 |
| `preferredTypeKey` | string | 常开车型大类 key |
| `preferredModel` | string | 常开车型名 |
| `vehicleSource` | string | 车源（own/company） |
| `activeYearsJson` | string | 历次在册年份 JSON 数组字符串（如 `"[2023,2024,2025]"`） |
| `license` | object | 驾照信息（见下） |
| `emergency` | object | 紧急联系人（见下） |
| `insurance` | object | 保险信息（见下） |
| `stats` | object | 历史统计（见下） |
| `tags[]` | array | 标签列表 |
| `attachments` | object<string, array> | 附件按类目分组（key=category，value=该类目附件列表） |
| **`relatedOrders[]`** | **array** | **关联订单（mock 占位，固定 3 条，详见警示）** |
| `createTime` / `updateTime` | datetime | — |

**`license`**（`DriverLicenseVO`，DB 字段平铺，API 嵌套返回）：

| 字段 | 类型 | 说明 |
|---|---|---|
| `no` | string | 驾照号 |
| `type` | string | 准驾车型（A1/A2/B1/B2 等） |
| `expire` | date | 有效期 |
| `issuedBy` | string | 发证机关 |

**`emergency`**（`DriverEmergencyVO`）：

| 字段 | 类型 | 说明 |
|---|---|---|
| `name` | string | 紧急联系人姓名 |
| `phone` | string | 手机号 |
| `relation` | string | 关系（父亲 / 妻子 等） |

**`insurance`**（`DriverInsuranceVO`）：

| 字段 | 类型 | 说明 |
|---|---|---|
| `type` | string | 保险类型（见 §6.4） |
| `company` | string | 保险公司（annual 必填） |
| `policyNo` | string | 年保单号（annual 必填） |
| `annualPremium` | string | 年保险费（BigDecimal 序列化） |
| `annualStart` | date | 年保险起始日 |
| `annualEnd` | date | 年保险结束日 |
| `perDayRate` | string | 行程保险日费率（perTrip 必填） |

**`stats`**（`DriverStatsVO`，详情专用）：

| 字段 | 类型 | 说明 |
|---|---|---|
| `totalOrders` | int | 历史接单总数 |
| `avgRating` | string | 平均评分 0-5（BigDecimal 序列化） |
| `lastOrderAt` | date | 最近接单日期 |

**`attachments`**：`Map<String, List<DriverAttachmentRespVO>>`，key=类目（见 §6.1），value=该类目下的附件列表（按 sortNo 升序）：

| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | string | 附件 ID |
| `driverId` | string | 所属司机 ID |
| `category` | string | 类目（见 §6.1） |
| `sortNo` | int | 同类目排序（0-based） |
| `url` | string | OSS URL |
| `mimeType` | string | 例 `image/jpeg` |

**`relatedOrders[]`**（**⚠️ mock 占位**）：

| 字段 | 类型 | 说明 |
|---|---|---|
| `orderId` | string | 订单 ID（前端跳转用） |
| `orderNo` | string | 订单号（如 `HL2026060100123`） |
| `groupNo` | string | 团号（如 `T2026-001`） |
| `customerName` | string | 客户姓名 |
| `tripStartDate` | date | 行程起始日 |
| `tripEndDate` | date | 行程结束日 |
| `destination` | string | 目的地概要 |
| `orderStatus` | string | 订单状态（`pending` / `in_progress` / `completed`） |
| `vehicleType` | string | 车型快照 |
| `licensePlate` | string | 车牌快照 |

> **mock 真相**（来自代码 `DriverService.buildMockRelatedOrders()`）：
> - 当前**固定返回 3 条假数据**（李先生 in_progress / 王女士 completed / 张总 pending）
> - 所有 driverId 返回的内容**完全相同**
> - 真实化时机：派车模块对接 fleet 服务后，由 DriverService 改为 Feign 调 order 服务按 staffId 反查（Issue #2791）

**典型示例 响应**（节选）：
```json
{
  "code": 200,
  "data": {
    "id": "1234567890123456789",
    "name": "张三",
    "phone": "138****1234",
    "idCard": "150102******1234",
    "gender": "男",
    "nation": "蒙古族",
    "years": 8,
    "driverStatus": "idle",
    "season": "active",
    "activeYearsJson": "[2023,2024,2025]",
    "primaryVehiclePlate": "蒙A-88888",
    "preferredTypeKey": "suv",
    "preferredModel": "丰田汉兰达",
    "vehicleSource": "company",
    "license": {
      "no": "15010219800101XXXX",
      "type": "B2",
      "expire": "2030-01-01",
      "issuedBy": "内蒙古公安厅交通管理局"
    },
    "emergency": {
      "name": "张三丰",
      "phone": "13800000000",
      "relation": "妻子"
    },
    "insurance": {
      "type": "annual",
      "company": "中国人保财险",
      "policyNo": "PICC-2024-XXX",
      "annualPremium": "3000.00",
      "annualStart": "2024-01-01",
      "annualEnd": "2025-01-01",
      "perDayRate": null
    },
    "stats": {
      "totalOrders": 128,
      "avgRating": "4.85",
      "lastOrderAt": "2025-05-18"
    },
    "tags": ["老司机", "蒙语流利"],
    "attachments": {
      "id_card": [
        { "id": "...", "driverId": "...", "category": "id_card", "sortNo": 0, "url": "https://oss/.../front.jpg", "mimeType": "image/jpeg" },
        { "id": "...", "driverId": "...", "category": "id_card", "sortNo": 1, "url": "https://oss/.../back.jpg", "mimeType": "image/jpeg" }
      ],
      "driver_license": [...],
      "portrait": [...]
    },
    "relatedOrders": [
      {
        "orderId": "900000000000000001",
        "orderNo": "HL2026060100123",
        "groupNo": "T2026-001",
        "customerName": "李先生",
        "tripStartDate": "2026-06-01",
        "tripEndDate": "2026-06-05",
        "destination": "呼伦贝尔草原 / 阿尔山 / 海拉尔",
        "orderStatus": "in_progress",
        "vehicleType": "丰田汉兰达",
        "licensePlate": "蒙A-12345"
      },
      {
        "orderId": "900000000000000002",
        "orderNo": "HL2026051800456",
        "groupNo": "T2026-002",
        "customerName": "王女士",
        "tripStartDate": "2026-05-18",
        "tripEndDate": "2026-05-22",
        "destination": "额尔古纳 / 室韦 / 莫尔道嘎",
        "orderStatus": "completed",
        "vehicleType": "丰田考斯特",
        "licensePlate": "蒙A-66666"
      },
      {
        "orderId": "900000000000000003",
        "orderNo": "HL2026070200789",
        "groupNo": "T2026-003",
        "customerName": "张总",
        "tripStartDate": "2026-07-02",
        "tripEndDate": "2026-07-08",
        "destination": "满洲里 / 套娃景区 / 国门",
        "orderStatus": "pending",
        "vehicleType": "奔驰威霆",
        "licensePlate": "蒙A-88888"
      }
    ],
    "createTime": "2025-05-21 14:00:00",
    "updateTime": "2025-05-21 14:00:00"
  },
  "msg": "成功"
}
```

**错误码**：**600205** 司机不存在 / 401 未登录

---

### 3.3 新增

**POST** `/admin/fleet/drivers`

- **使用场景**：新增司机（含 tags 批量 + 附件批量提交，**同一事务**）
- **认证**：管理后台 JWT
- **幂等**：否（身份证 / 手机号重复抛 600200 / 600203）

**Body 入参**（`DriverSaveReqVO`）：

| 字段 | 类型 | 必填 | 校验 | 说明 |
|---|---|---|---|---|
| `name` | string | ✅ | `@Size(max=32)` | 姓名 |
| `phone` | string | ✅ | `@Pattern(^\d{11}$)` | 手机号 11 位（**编辑时忽略**） |
| `idCard` | string | ✅ | `@Size(min=18,max=32)` | 身份证号（**编辑时忽略**） |
| `gender` | string | ❌ | `@Size(max=4)` | 性别（男 / 女） |
| `nation` | string | ❌ | `@Size(max=16)` | 民族 |
| `years` | int | ❌ | — | 驾龄（年） |
| `driverStatus` | string | ❌ | `@Pattern(idle\|busy\|rest\|pending)` | 状态 |
| `season` | string | ❌ | `@Pattern(active\|pending\|archived\|blacklist)` | 赛季 |
| `primaryVehiclePlate` | string | ❌ | `@Size(max=16)` | 常驻车车牌 |
| `preferredTypeKey` | string | ❌ | `@Size(max=16)` | 常开车型大类 key |
| `preferredModel` | string | ❌ | `@Size(max=64)` | 常开车型名 |
| `vehicleSource` | string | ❌ | `@Size(max=16)` | 车源（own / company） |
| `license` | object | ❌ | — | 驾照嵌套对象（同 §3.2） |
| `emergency` | object | ❌ | — | 紧急联系人嵌套对象（同 §3.2） |
| `insurance` | object | ❌ | — | 保险嵌套对象（同 §3.2） |
| `tags[]` | array | ❌ | `@Size(max=20)` | 标签列表（**全量覆盖**） |
| `attachments[]` | array | ❌ | — | 附件数组（见 §3.3 attachment 表） |

**`attachments[]` 单项**（`DriverAttachmentReqVO`）：

| 字段 | 类型 | 必填 | 校验 | 说明 |
|---|---|---|---|---|
| `id` | Long | ❌ | — | 新增项不传 |
| `category` | string | ✅ | `@Size(max=32)` | 类目（见 §6.1） |
| `url` | string | ✅ | `@Size(max=512)` | OSS URL |
| `mimeType` | string | ✅ | `@Size(max=64)` | 例 `image/jpeg` |
| `sortNo` | int | ❌ | — | 不传时按入参顺序自动重写 0..N-1 |

**出参**：`Result<DriverCreateRespVO>`

| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | string | 新增司机 ID |
| `attachmentIds[]` | array<Long> | 附件 ID 列表（按入参顺序） |

**典型示例 请求**（节选）：
```
POST /admin/fleet/drivers
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "张三",
  "phone": "13812341234",
  "idCard": "150102198001011234",
  "gender": "男",
  "nation": "蒙古族",
  "years": 8,
  "driverStatus": "idle",
  "season": "active",
  "primaryVehiclePlate": "蒙A-88888",
  "preferredTypeKey": "suv",
  "preferredModel": "丰田汉兰达",
  "vehicleSource": "company",
  "license": {
    "no": "15010219800101XXXX",
    "type": "B2",
    "expire": "2030-01-01",
    "issuedBy": "内蒙古公安厅交通管理局"
  },
  "emergency": {
    "name": "张三丰",
    "phone": "13800000000",
    "relation": "妻子"
  },
  "insurance": {
    "type": "annual",
    "company": "中国人保财险",
    "policyNo": "PICC-2024-XXX",
    "annualPremium": "3000.00",
    "annualStart": "2024-01-01",
    "annualEnd": "2025-01-01"
  },
  "tags": ["老司机", "蒙语流利"],
  "attachments": [
    { "category": "id_card", "url": "https://oss/.../id-front.jpg", "mimeType": "image/jpeg" },
    { "category": "id_card", "url": "https://oss/.../id-back.jpg", "mimeType": "image/jpeg" },
    { "category": "driver_license", "url": "https://oss/.../license.jpg", "mimeType": "image/jpeg" },
    { "category": "portrait", "url": "https://oss/.../portrait.jpg", "mimeType": "image/jpeg" }
  ]
}
```

**异常 请求**（身份证重复）：
```json
{ "code": 600200, "msg": "身份证已存在", "data": null }
```

**异常 请求**（驾照过期）：
```json
{ "code": 600201, "msg": "驾照已过期", "data": null }
```

**错误码**：400 参数校验 / **600200** 身份证已存在 / **600201** 驾照已过期 / **600203** 手机号已存在 / **601002** 附件类目非法 / **601003** 类目张数达上限 / 401 未登录

---

### 3.4 编辑（attachments diff + tags 全量覆盖）

**PUT** `/admin/fleet/drivers/{driverId}`

- **使用场景**：编辑司机基本信息 + 标签全量覆盖 + 附件增删改一次性提交
- **认证**：管理后台 JWT
- **幂等**：是

**路径入参**：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `driverId` | Long | ✅ | 司机 ID |

**Body 入参**：同 §3.3（共用 `DriverSaveReqVO`），但：

- **`idCard` / `phone` 后端忽略**（不可改）
- **`tags[]` 全量覆盖**：物理删除旧 tags + 批量 INSERT 新 tags（空数组 = 清空所有标签）
- **`attachments[]` diff 语义**：有 id 命中 → 保留；无 id → INSERT；DB 有但未传 → 软删

**附件 diff 语义**（与车辆档案 §3.4 一致）：

| 入参 attachments[] 项 | DB 中的对应行 | 行为 |
|---|---|---|
| 有 `id` + DB 命中 | 存在 | 保留（可更新 sortNo） |
| 无 `id`（新增项） | — | INSERT |
| — | 存在但本次未传 | 软删 |

> **特别说明（前 3 类目"换证留历史"语义）**：`id_card` / `driver_license` / `portrait` 旧附件不在本次入参里 → 自动软删；新 url 无 id → INSERT。前端"换证"时不需要先调删除接口，直接组装新 attachments 数组即可。

**出参**：`Result<DriverUpdateRespVO>`

| 字段 | 类型 | 说明 |
|---|---|---|
| `kept` | int | 保留的附件数 |
| `inserted` | int | 新插入的附件数 |
| `softDeleted` | int | 软删的附件数 |
| `tagsReplaced` | int | 覆盖写入的标签数 |

**典型示例 响应**：
```json
{
  "code": 200,
  "data": { "kept": 3, "inserted": 1, "softDeleted": 2, "tagsReplaced": 3 },
  "msg": "成功"
}
```

**错误码**：400 参数校验 / **600201** 驾照已过期 / **600205** 司机不存在 / **601002** 类目非法 / **601003** 类目张数达上限 / 401 未登录

---

### 3.5 软删

**DELETE** `/admin/fleet/drivers/{driverId}`

- **使用场景**：下架司机
- **认证**：管理后台 JWT
- **幂等**：是

**路径入参**：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `driverId` | Long | ✅ | 司机 ID |

**出参**：`Result<Void>`

**典型示例 响应**：
```json
{ "code": 200, "data": null, "msg": "成功" }
```

**异常 请求**（**业务流水 PR 上线后才生效**）：
```json
{ "code": 600204, "msg": "司机有未完成派单，不能删除", "data": null }
```

**错误码**：**600204** 有未完成派单（占位，业务流水 PR 上线后生效） / **600205** 司机不存在 / 401 未登录

---

### 3.6 Excel 批量导入

**POST** `/admin/fleet/drivers/import`

- **使用场景**：运营批量录入司机
- **认证**：管理后台 JWT
- **幂等**：是（按身份证去重，已存在则**更新**，不存在则**新增**）

**入参**（multipart/form-data）：

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `file` | file | ✅ | Excel（`.xlsx` / `.xls`）或 CSV |

**表头约定（第 1 行 15 列，顺序固定）**：

```
姓名 | 手机号 | 身份证号 | 性别 | 民族 | 驾龄(年) |
驾照号 | 准驾车型 | 驾照有效期(yyyy-MM-dd) | 发证机关 |
紧急联系人姓名 | 紧急联系人手机 | 与司机关系 |
保险类型(annual/perTrip/none) | 常驻车车牌
```

**出参**：`Result<DriverImportRespVO>`（**字段名与车辆导入不同**）

| 字段 | 类型 | 说明 |
|---|---|---|
| `total` | int | 总行数（不含表头） |
| `insertedCount` | int | 新增成功数 |
| `renewedCount` | int | 更新成功数（按身份证去重，已存在则更新） |
| `errorCount` | int | 失败行数 |
| `errors[]` | array | 失败行详情 |

**典型示例 响应**：
```json
{
  "code": 200,
  "data": {
    "total": 10,
    "insertedCount": 6,
    "renewedCount": 2,
    "errorCount": 2,
    "errors": [
      { "row": 3, "name": "张三", "msg": "驾照已过期" },
      { "row": 7, "name": "李四", "msg": "手机号格式错误" }
    ]
  },
  "msg": "成功"
}
```

> ⚠️ 与车辆导入的出参字段不同：车辆是 `success/failed/errorRows`，司机是 `insertedCount/renewedCount/errorCount/errors`。前端**不能**复用同一份解析逻辑。

**错误码**：400 文件解析失败 / 401 未登录

---

## 6. 枚举 / 数据字典

### 6.1 附件类目（`category`，`DriverAttachmentCategoryEnum`）

**所属字段**：`DriverAttachmentReqVO.category` / `DriverAttachmentRespVO.category` | **类型**：`String` | **必填**：✅

**真枚举**（后端硬编码 8 类目，含同类目张数上限）：

| 值 | 中文 | 张数上限 | 备注 |
|---|---|---|---|
| `id_card` | 身份证 | 2 | "换证留历史"语义（支持正反 2 张或新旧 2 套） |
| `driver_license` | 驾驶证 | 2 | "换证留历史" |
| `portrait` | 肖像照 | 2 | "换证留历史" |
| `health_cert` | 健康证 | 2 | — |
| `training_cert` | 培训证书 | 5 | — |
| `award` | 荣誉奖励 | 5 | — |
| `qualification` | 从业资格证 | 3 | — |
| `other` | 其他附件 | 5 | — |

> 超出上限触发 **601003** "该类目张数已达上限"。

### 6.2 司机状态（`driverStatus`，`DriverStatusEnum`）

**所属字段**：`DriverSaveReqVO.driverStatus` / `DriverPageReqVO.driverStatus` / `DriverPageItemRespVO.driverStatus` / `DriverDetailRespVO.driverStatus` | **类型**：`String` | **必填**：❌

**`@Pattern` 强校验枚举**：

| 值 | 中文 | 说明 |
|---|---|---|
| `idle` | 空闲 | 可接单 |
| `busy` | 在途 | 正在执行派单 |
| `rest` | 休假 | 暂不接单 |
| `pending` | 待激活 | 新入职 / 回归尚未完成入驻 |

### 6.3 赛季（`season`，`SeasonEnum`）

**所属字段**：同 driverStatus | **类型**：`String` | **必填**：❌

**`@Pattern` 强校验枚举**：

| 值 | 中文 | 说明 |
|---|---|---|
| `active` | 在册 | 当前赛季正常在职 |
| `pending` | 待续签 | 赛季到期已发出续签邀请 |
| `archived` | 已归档 | 本赛季已退出 |
| `blacklist` | 黑名单 | 永久拉黑 |

### 6.4 保险类型（`insuranceType`，`InsuranceTypeEnum`）

**所属字段**：`DriverInsuranceVO.type` / `DriverPageReqVO.insuranceType` / `DriverPageItemRespVO.insuranceType` | **类型**：`String` | **必填**：❌

| 值 | 中文 | 必填字段 |
|---|---|---|
| `annual` | 年保险 | 需填 `company` / `policyNo` / `annualPremium` / `annualStart` / `annualEnd` |
| `perTrip` | 行程保险 | 需填 `perDayRate`（按行程计费） |
| `none` | 无保险 | — |

### 6.5 订单状态（`orderStatus`，**mock 字段**）

**所属字段**：`DriverDetailRespVO.relatedOrders[].orderStatus` | **类型**：`String` | **mock 占位**

| 值 | 中文 |
|---|---|
| `pending` | 待出行 |
| `in_progress` | 进行中 |
| `completed` | 已完成 |

> ⚠️ 这是 **mock 数据**里的取值，真实派车模块对接后值列表可能扩展（如 `canceled` / `refunded` 等）。前端**不要硬编码状态映射**，等真实化后由后端文档明确。

---

## 7. 错误码（全模块汇总）

| code | 含义 | 触发条件 | 涉及接口 |
|---|---|---|---|
| 400 | 参数校验失败 | 字段缺失/长度/枚举/手机号格式/MIME 非法 | 所有写入接口 |
| 401 | 未登录 | JWT 无效或缺失 | 全部 6 接口 |
| **600200** | 身份证已存在 | `idCard` 全局唯一约束 | §3.3 |
| **600201** | 驾照已过期 | `license.expire < 今日`（新增 / 编辑主动校验） | §3.3 §3.4 |
| **600203** | 手机号已存在 | `phone` 全局唯一约束 | §3.3 |
| **600204** | 司机有未完成派单 | 业务流水 PR 上线后才触发（目前占位） | §3.5 |
| **600205** | 司机不存在 | `driverId` 无效或软删 | §3.2 §3.4 §3.5 |
| **601001** | 实体不存在 | 附件关联的主司机不存在 | §3.3 §3.4 |
| **601002** | 附件类目非法 | `category` 不在 §6.1 枚举内 | §3.3 §3.4 |
| **601003** | 该类目张数已达上限 | 超出 §6.1 张数上限 | §3.3 §3.4 |
| **601004** | 文件超出大小限制 | 应用层 + OSS HEAD 校验 | §3.3 §3.4 |
| **601005** | 文件类型非法 | MIME 不在白名单 | §3.3 §3.4 |

> 错误码段位 600200-600205 归属司机档案（无与车辆 / 车型管理库冲突）；601001-601005 归属附件管理子段（车辆 / 司机共用）。
>
> **未列错误码 600202**（司机已黑名单）：占位常量，业务流水 PR 上线后才会触发。

---

## 9. 业务边界

- ✅ **PII 脱敏**：`phone` / `idCard` 在 §3.1 列表项 + §3.2 详情**响应**中均脱敏返回（`138****1234` / `150102******1234`）；DB 存明文。前端展示时**直接用响应值**即可
- ✅ **编辑不可改 idCard / phone**：§3.4 入参中的 `idCard` / `phone` 后端**忽略**，要改身份证 / 手机号需联系后端管理员（业务上极少发生）
- ✅ **驾照过期校验**：§3.3 §3.4 主动校验 `license.expire < 今日`（不影响存量数据，仅写入时校验）
- ✅ **tags 全量覆盖语义**：§3.4 `tags=[]` = 清空所有标签；`tags=null` 也视为不修改（不传字段 = 不动），建议前端**显式传空数组**清空
- ✅ **附件 diff 语义**：与车辆档案 §3.4 一致；id_card/driver_license/portrait 三类支持"换证留历史"（旧软删 + 新插入由 diff 天然完成）
- ✅ **唯一约束**：`idCard` / `phone` **全局**唯一
- ⚠️ **relatedOrders mock 占位**：见 §3.2 / §12

---

## 10. 修改前后对比（仅 §3.2 详情）

### 10.1 字段级对比

| 字段 | 改前 | 改后 |
|---|---|---|
| `DriverDetailRespVO` | 无 `relatedOrders` 字段 | 新增 `relatedOrders[]` 字段（mock 数据） |

### 10.2 行为级对比

| 行为 | 改前 | 改后 |
|---|---|---|
| 调 §3.2 详情 | 响应里无关联订单信息 | 响应额外含 3 条 mock 订单 |

---

## 11. 影响评估

- **是否破坏向后兼容**：否（仅新增字段，老前端忽略该字段照常工作）
- **前端是否必须同步上线**：否（前端可按节奏对接 relatedOrders UI 区块）
- **影响已有数据**：无（mock 数据来自代码，不入库）

---

## 12. 注意事项

- **⚠️ `relatedOrders` 是 mock**：
  - 固定 3 条假数据，**所有司机返回相同内容**
  - 前端**不要硬编码**业务逻辑（如"看到张总订单 = 司机已派单 / 不能软删"等推断）
  - 真实化时机：派车模块对接 fleet 服务后，由 `DriverService.buildMockRelatedOrders` 替换为 Feign 实现（Issue #2791）
  - 真实化后字段名 / 字段类型与本 changelog 一致（已约定的契约），但**取值范围可能扩展**（如 orderStatus 增加 `canceled`）
- **分页参数名**：`page` / `pageSize`（**不是** pageNo）
- **Long 主键序列化**：`id` / `attachments[].id` / `relatedOrders[].orderId` 等 Long 字段 JSON 返回为 String，前端**不要**当 Number 解析
- **车辆导入 vs 司机导入字段名不同**：见 §3.6 警示
- **5 个 tab 实现**：见 §3.1 表格，纯通过 `season` 参数实现，无新接口
- **错误码段位连续**：600200-600205 全在司机档案段，无避让

---

## 13. 关联 / 联系人

### 13.1 链接

- **Issue（relatedOrders mock）**: [#2791](https://git.1814.love:8443/wx/HL/issues/2791)
- **PR（relatedOrders mock）**: [#2796](https://git.1814.love:8443/wx/HL/pulls/2796)
- **Merge commit**: [`ec0380439`](https://git.1814.love:8443/wx/HL/commit/ec03804390c7bd39f1b4ec3ddc3bd86aeb8ef47c)
- **API 文档**: `docs/order-v3/api/API-SPEC-FLEET-V1.5.html` §3 司机档案
- **DB 文档**: `docs/order-v3/database/DATABASE-SCHEMA-FLEET-V1.5.html` §2.4 + §2.7
- **同期相关 changelog**:
  - 车型管理库 9 接口（[`21_2785_车型管理库-新增接口-管理后台.md`](./21_2785_车型管理库-新增接口-管理后台.md)）
  - 车辆档案 6 接口（[`21_车辆档案-修改接口-管理后台.md`](./21_车辆档案-修改接口-管理后台.md)）

### 13.2 联系人

- **后端负责人**: @yst（腰苏图）
- **前端对接（管理后台）**: 待指派
