# 【修改接口·管理后台】✨ 出行人类型中文名 travelerTypeName 新增字段 (#3951)

> **PR**: #3954 | **服务**: hl-order-service-v3 | **更新时间**: 2026-06-18

## 1. 接口背景

出行人列表、添加出行人、订单详情等接口原先只返回 `travelerType` 英文枚举值（ADULT / CHILD / YOUNG_CHILD / BABY），前端需要自行维护一套映射表才能展示中文。本次新增 `travelerTypeName` 字段，由后端查数据字典 `traveler_type` 派生中文名后直接下发，前端可零配置展示类型标签。原 `travelerType` 字段保留不变，属纯新增、非破坏性变更。

## 2. 变更清单

| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 订单出行人列表 | GET | /v3/admin/order/{id}/traveler/list | 新增出参字段 | 每个出行人元素新增 `travelerTypeName` |
| 2 | 添加出行人 | POST | /v3/admin/order/{id}/traveler/add | 新增出参字段 | 返回的 TravelerVO 新增 `travelerTypeName` |
| 3 | 订单详情 | GET | /v3/admin/order/{id} | 新增出参字段 | overview.customerInfo.travelers[] 元素新增 `travelerTypeName` |

## 3. 接口详情

### 3.1 订单出行人列表

- **使用场景**：订单详情页「出行人」Tab 加载出行人清单时调用。
- **认证**：需要 JWT（管理员角色）。
- **幂等性**：是（只读）。
- **限流**：无。

入参无变化。出参 `List<TravelerVO>` 每个元素新增 `travelerTypeName` 字段（String）。

### 3.2 添加出行人

- **使用场景**：在订单详情页为订单添加一位出行人后，接口直接返回包含完整信息的 TravelerVO。
- **认证**：需要 JWT（管理员角色）。
- **幂等性**：否（写入操作）。
- **限流**：无。

入参无变化。出参 `TravelerVO` 新增 `travelerTypeName` 字段（String）。

### 3.3 订单详情

- **使用场景**：订单详情页首次加载，获取订单全量信息。
- **认证**：需要 JWT（管理员角色）。
- **幂等性**：是（只读）。
- **限流**：无。

入参无变化。出参 `overview.customerInfo.travelers[]` 数组中每个 `TravelerPlainVO` 元素新增 `travelerTypeName` 字段（String）。

## 4. 接口入参

### 4.1 路径参数 / Query 参数

| 接口 | 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|------|
| GET /v3/admin/order/{id}/traveler/list | id | String（Long） | 是 | 路径参数，订单 ID |
| POST /v3/admin/order/{id}/traveler/add | id | String（Long） | 是 | 路径参数，订单 ID |
| GET /v3/admin/order/{id} | id | String（Long） | 是 | 路径参数，订单 ID |

### 4.2 请求体字段

三个接口入参均无变化。POST /v3/admin/order/{id}/traveler/add 的请求体字段与原契约相同，本次未改动。

## 5. 出参（响应）

### 5.1 TravelerVO 字段（接口 1、2 出参元素）

| 字段 | 类型 | 变更 | 说明 |
|------|------|------|------|
| id | String | 不变 | 出行人记录 ID |
| orderId | String | 不变 | 所属订单 ID |
| name | String | 不变 | 出行人姓名（脱敏后） |
| phone | String | 不变 | 手机号（脱敏后） |
| idCard | String | 不变 | 身份证号（脱敏后） |
| travelerType | String | 不变 | 出行人类型枚举值，见 §6 |
| travelerTypeName | String | **新增** | 出行人类型中文名，由数据字典 `traveler_type` 派生 |
| gender | String | 不变 | 性别字典码 |
| nationality | String | 不变 | 国籍 |

### 5.2 TravelerPlainVO 字段（接口 3 订单详情 overview.customerInfo.travelers[] 元素）

| 字段 | 类型 | 变更 | 说明 |
|------|------|------|------|
| name | String | 不变 | 出行人姓名（脱敏后） |
| phone | String | 不变 | 手机号（脱敏后） |
| travelerType | String | 不变 | 出行人类型枚举值，见 §6 |
| travelerTypeName | String | **新增** | 出行人类型中文名，由数据字典 `traveler_type` 派生 |

## 6. 枚举 / 数据字典

### 6.1 travelerType（数据字典：traveler_type）

**所属字段**：`travelerType`（出参，保留不变）与 `travelerTypeName`（出参，新增中文名） | **类型**：`String`

| 枚举值 | 中文名（travelerTypeName） | 说明 |
|--------|--------------------------|------|
| `ADULT` | 成人 | 成年旅客 |
| `CHILD` | 儿童 | 儿童旅客（含独立占位） |
| `YOUNG_CHILD` | 小童 | 小童旅客（不占位或半占位） |
| `BABY` | 幼童 | 婴幼儿（不占位） |

> 字典降级说明：若数据字典 `traveler_type` 中对应 key 缺失，后端使用枚举内置 label 兜底，前端无需处理。

## 7. 错误码

本次为纯新增字段，无新增错误码。原有错误码不变。

| code | 含义 | 触发场景 |
|------|------|----------|
| 581201 | 订单不存在 | orderId 无效 |
| 581211 | 出行人不存在 | 指定出行人 ID 不属于该订单 |
| 401 | 未认证 | 未携带或 JWT 过期 |
| 403 | 无权限 | 当前角色无此操作权限 |

## 8. 示例（3 组：典型 / 边界 / 异常）

### 8.1 典型成功 — 查询出行人列表（含新字段）

请求：
```
GET /v3/admin/order/2067178767255560193/traveler/list
Authorization: Bearer <token>
```

响应：
```json
{
  "code": 200,
  "data": [
    {
      "id": "2067178767255560201",
      "orderId": "2067178767255560193",
      "name": "张*明",
      "phone": "138****8888",
      "idCard": "110101********1234",
      "travelerType": "ADULT",
      "travelerTypeName": "成人",
      "gender": "MALE",
      "nationality": "中国"
    },
    {
      "id": "2067178767255560202",
      "orderId": "2067178767255560193",
      "name": "张*",
      "phone": "",
      "idCard": "",
      "travelerType": "YOUNG_CHILD",
      "travelerTypeName": "小童",
      "gender": "FEMALE",
      "nationality": "中国"
    }
  ],
  "message": "ok",
  "success": true
}
```

### 8.2 边界情况 — 全类型出行人（BABY 幼童）

请求：
```
GET /v3/admin/order/2067178767255560194/traveler/list
Authorization: Bearer <token>
```

响应（含 BABY 类型，travelerTypeName 正常返回中文）：
```json
{
  "code": 200,
  "data": [
    {
      "id": "2067178767255560211",
      "orderId": "2067178767255560194",
      "name": "李*强",
      "travelerType": "ADULT",
      "travelerTypeName": "成人",
      "gender": "MALE",
      "nationality": "中国"
    },
    {
      "id": "2067178767255560212",
      "orderId": "2067178767255560194",
      "name": "李*",
      "travelerType": "CHILD",
      "travelerTypeName": "儿童",
      "gender": "MALE",
      "nationality": "中国"
    },
    {
      "id": "2067178767255560213",
      "orderId": "2067178767255560194",
      "name": "李小宝",
      "travelerType": "BABY",
      "travelerTypeName": "幼童",
      "gender": "FEMALE",
      "nationality": "中国"
    }
  ],
  "message": "ok",
  "success": true
}
```

### 8.3 业务失败 — 订单 ID 不存在

请求：
```
GET /v3/admin/order/9999999999999999999/traveler/list
Authorization: Bearer <token>
```

响应：
```json
{
  "code": 581201,
  "data": null,
  "message": "订单不存在",
  "success": false
}
```

## 9. 业务边界

- 适用：订单处于任何状态均可查询出行人列表（只读接口）。
- 适用：出行人类型覆盖 ADULT / CHILD / YOUNG_CHILD / BABY 四种，每种均有对应中文名。
- 特殊边界：若数据字典维护缺失某枚举值，`travelerTypeName` 降级返回枚举内置中文名（不会返回 null），前端无需做 null 保护。
- 特殊边界：`travelerType` 原字段值不变，前端若已有本地映射逻辑，可继续保留或切换为直接展示 `travelerTypeName`，两者语义等价。

## 10. 修改前后对比

### 10.1 字段级对比

| VO | 字段 | 改前 | 改后 |
|----|------|------|------|
| TravelerVO | travelerTypeName | 不存在 | **新增** String，出行人类型中文名 |
| TravelerPlainVO | travelerTypeName | 不存在 | **新增** String，出行人类型中文名 |
| TravelerVO | travelerType | 原样返回英文枚举值 | 保留不变 |

### 10.2 行为级对比

| 行为 | 改前 | 改后 |
|------|------|------|
| 类型中文展示 | 前端自行维护 ADULT→成人 等映射表 | 后端直接下发 travelerTypeName，前端可直接渲染 |
| 数据字典缺失 | 无此逻辑 | 降级用枚举内置 label 兜底，前端无感知 |

## 11. 影响评估 / 回滚

### 11.1 影响评估

- **是否破坏向后兼容**：**否**，纯新增字段，原字段不变、原结构不变。
- **前端是否必须同步上线**：**否**，旧前端代码不读新字段也不会出错，可按需对接。

### 11.2 回滚方案

- **回滚方式**：revert PR #3954 并重新部署 hl-order-service-v3，返回字段恢复为无 travelerTypeName 的旧结构。

## 12. 注意事项

- 前端 workaround 清理点：若前端已有本地 `travelerType → 中文` 映射对象/函数，上线后可切换为直接读取 `travelerTypeName`，原映射逻辑可清理。
- `travelerTypeName` 由后端数据字典派生，字典修改后立即生效（无需前端发版），字典当前值为：ADULT=成人 / CHILD=儿童 / YOUNG_CHILD=小童 / BABY=幼童。

## 13. 关联 / 联系人

### 13.1 链接

- **Issue**: [#3951](https://git.1814.love:8443/wx/HL/issues/3951)
- **PR**: [#3954](https://git.1814.love:8443/wx/HL/pulls/3954)
- **Merge commit**: [16d77c9a5](https://git.1814.love:8443/wx/HL/commit/16d77c9a5)

### 13.2 联系人

- **后端负责人**: @yaosutu
