# 订单列表/详情新增 productType + productTypeName 字段

- **变更类型**: 修改接口（既有接口新增出参字段）
- **端类型**: 管理后台
- **日期**: 2026-06-19
- **Issue**: [#4009](https://git.1814.love:8443/wx/HL/issues/4009)
- **PR**: [#4010](https://git.1814.love:8443/wx/HL/pulls/4010)
- **Commit**: [36880d1e2](https://git.1814.love:8443/wx/HL/commit/36880d1e2)
- **后端负责人**: 腰苏图

---

## ① 接口背景

订单创建时，产品类型（核心产品/自驾路书/私人定制/小蒙马）会从产品快照固化到订单主表。此前该字段从未通过接口返回，前端无法在订单列表和详情中区分产品类型。本次在两个接口的出参中同时补充 `productType`（枚举码）和 `productTypeName`（数据字典中文名），方便前端按产品类型展示差异化 UI。

历史订单已完成回填，无快照的兜底为 `CORE`；理论上正常订单都有值，极少数脏数据可能为 `null`，前端需做防御处理。

---

## ② 变更清单

| 接口 | 变更内容 |
|------|---------|
| `GET /v3/admin/order/list` | 每条列表项新增出参字段 `productType`、`productTypeName` |
| `GET /v3/admin/order/{id}` | 详情 `data.main` 节点新增出参字段 `productType`、`productTypeName` |

两个接口均为**向后兼容新增**，原有字段不变，前端不必修改已有调用逻辑，但需接线新字段用于 UI 渲染。

---

## ③ 接口详情

### 3.1 订单列表

- **方法 + 路径**: `GET /v3/admin/order/list`
- **描述**: 管理后台订单列表，支持分页与多条件筛选
- **认证**: 必须携带管理后台 JWT Token（`Authorization: Bearer <token>`）
- **幂等性**: 只读，天然幂等
- **限流**: 无特殊限流

### 3.2 订单详情

- **方法 + 路径**: `GET /v3/admin/order/{id}`
- **描述**: 管理后台订单详情聚合接口，返回 main / travelers / itinerary 等多节点
- **认证**: 必须携带管理后台 JWT Token（`Authorization: Bearer <token>`）
- **幂等性**: 只读，天然幂等
- **限流**: 无特殊限流

---

## ④ 接口入参

### 4.1 订单列表（Query 参数，节选常用）

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| pageNo | Integer | 否 | 页码，默认 1 |
| pageSize | Integer | 否 | 每页条数，默认 20 |
| keyword | String | 否 | 关键词搜索 |
| status | String | 否 | 订单状态筛选 |
| ... | ... | ... | 其余参数不变，本次无入参改动 |

### 4.2 订单详情（路径参数）

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | Long | 是 | 订单 ID（雪花 ID，字符串形式传入） |

---

## ⑤ 出参字段

### 5.1 订单列表（OrderListItemRespVO，新增字段）

以下为本次新增字段，其余原有字段不变：

| 字段名 | 类型 | 可空 | 说明 |
|--------|------|------|------|
| `productType` | String | 是（null 为极少数历史脏数据） | 产品类型枚举码，见枚举 § ⑥ |
| `productTypeName` | String | 是（与 productType 同步，null when productType null） | 产品类型中文名，来源数据字典 product_type，如 `私人定制` |

### 5.2 订单详情（data.main 节点，新增字段）

新增字段位于 `data.main` 对象下：

| 字段名 | 类型 | 可空 | 说明 |
|--------|------|------|------|
| `productType` | String | 是（null 为极少数历史脏数据） | 产品类型枚举码，见枚举 § ⑥ |
| `productTypeName` | String | 是（与 productType 同步，null when productType null） | 产品类型中文名，来源数据字典 product_type，如 `私人定制` |

---

## ⑥ 枚举 / 数据字典

### ProductType — 产品类型（数据字典 product_type）

> `productTypeName` 来源是**数据字典 `product_type`**（由运维在 `sys_dict` 中维护），**不是后端硬编码枚举**。后端在列表/详情整页加载时统一查字典回填，前端直接使用 `productTypeName` 展示，无需自行映射。

| 枚举值（productType） | 中文名（productTypeName） | 说明 |
|-----------------------|--------------------------|------|
| `CORE` | 核心产品 | 核心旅游产品；历史无快照订单兜底此值 |
| `ROUTE` | 自驾路书 | 自驾路书产品 |
| `CUSTOM` | 私人定制 | 私人定制行程产品 |
| `GROUP` | 小蒙马 | 团期/团队产品 |

> `productType` 字段值固定为以上 4 个枚举码之一，或为 `null`（极少数历史脏数据，正常订单不会出现）。

---

## ⑦ 错误码

本次改动为新增出参字段，不引入新的错误码。常规接口错误码如下：

| 错误码 | 说明 |
|--------|------|
| `200` | 成功 |
| `401` | 未认证，请检查 Token |
| `403` | 无权限 |
| `404` | 订单不存在（详情接口，id 错误时） |

---

## ⑧ 示例

### 8.1 典型成功 — 订单列表

**请求**：
```
GET /v3/admin/order/list?pageNo=1&pageSize=10
Authorization: Bearer <token>
```

**响应**（节选单条）：
```json
{
  "code": 200,
  "data": {
    "list": [
      {
        "id": "1876543210000001",
        "orderNo": "HL202606190001",
        "status": "PENDING_PAYMENT",
        "productName": "丽江深度定制5日",
        "productType": "CUSTOM",
        "productTypeName": "私人定制",
        "totalAmount": "12800.00",
        "createTime": "2026-06-19T10:00:00"
      }
    ],
    "total": 100,
    "pageNo": 1,
    "pageSize": 10
  }
}
```

### 8.2 典型成功 — 订单详情

**请求**：
```
GET /v3/admin/order/1876543210000001
Authorization: Bearer <token>
```

**响应**（节选 data.main）：
```json
{
  "code": 200,
  "data": {
    "main": {
      "id": "1876543210000001",
      "orderNo": "HL202606190001",
      "status": "PENDING_PAYMENT",
      "productType": "CUSTOM",
      "productTypeName": "私人定制",
      "totalAmount": "12800.00"
    },
    "travelers": [],
    "itinerary": null
  }
}
```

### 8.3 边界情况 — 历史脏数据 productType 为 null

极少数历史脏数据（无产品快照且未被回填）可能返回 null，前端需防御处理：

```json
{
  "code": 200,
  "data": {
    "list": [
      {
        "id": "1000000000000001",
        "orderNo": "HL202501010001",
        "productType": null,
        "productTypeName": null
      }
    ]
  }
}
```

> 前端建议：`productType === null` 时不渲染产品类型标签，或显示兜底文案「-」。

### 8.4 业务失败 — 详情接口 id 不存在

**请求**：
```
GET /v3/admin/order/9999999999999999
Authorization: Bearer <token>
```

**响应**：
```json
{
  "code": 587010,
  "msg": "订单不存在"
}
```

---

## ⑨ 业务边界

**适用**：
- 所有状态的订单（已完成、取消、退款中等）均会返回 `productType` 字段
- `GROUP` 类型订单为团期产品（中文名：小蒙马），前端可据此渲染团期专属 UI（如团期编号、报名人数等）

**不适用**：
- 此字段不影响订单的任何操作权限，不参与状态流转判断

**特殊边界**：
- 历史订单已全量回填，回填口径：有产品快照取快照值，无快照兜底 `CORE`
- 订单创建后 `productType` 不可变，与产品侧修改无关（固化快照）

---

## ⑩ 修改前后对比

### 字段级对比

| 字段 | 修改前 | 修改后 |
|------|--------|--------|
| `productType` | 不返回（字段不存在） | 返回枚举字符串，如 `"CUSTOM"` |
| `productTypeName` | 不返回（字段不存在） | 返回数据字典中文名，如 `"私人定制"` |

**影响接口**：
- `GET /v3/admin/order/list` → 列表每条 item 新增两字段
- `GET /v3/admin/order/{id}` → 详情 `data.main` 节点新增两字段

---

## ⑪ 影响评估 / 回滚

**兼容性**：
- 向后兼容新增，前端零破坏，原有字段全部保留
- 前端现有代码无需修改即可正常运行；如需渲染新字段，按需接线

**前端同步上线**：
- 不强制要求与前端同步，后端已部署前端可按节奏接线

**回滚方案**：
- 后端回滚只需撤回 PR #4010 对应提交，前端无感知（字段消失即可，不会报错）

---

## ⑫ 注意事项

1. **防御 null**：`productType` 和 `productTypeName` 理论上有值，但请在渲染时做 null 判断，避免历史脏数据导致前端报错
2. **两字段配套**：`productType` 为枚举码（用于逻辑判断），`productTypeName` 为数据字典中文名（用于展示），两者同步出现或同步为 null，前端无需自行映射枚举
3. **不可变字段**：`productType` 在订单层面不可变，前端无需考虑实时刷新或监听变化
4. **label 修正说明**：本文件于 2026-06-19 修正了 ROUTE/CUSTOM/GROUP 的中文名（见 PR #4022），原 changelog 初稿使用了后端枚举注释值，实际 label 以数据字典 product_type 为准

---

## ⑬ 关联 / 联系人

- **Issue**: [#4009 订单列表/详情补充 productType 字段](https://git.1814.love:8443/wx/HL/issues/4009)
- **PR**: [#4010 feat(order-v3): order_main 加 product_type 列 + 列表/详情返回 productType](https://git.1814.love:8443/wx/HL/pulls/4010)
- **Feature Commit**: [849e3be9a](https://git.1814.love:8443/wx/HL/commit/849e3be9a)
- **Merge Commit**: [36880d1e2](https://git.1814.love:8443/wx/HL/commit/36880d1e2)
- **Label 修正 Issue**: [#4021 productTypeName 改走数据字典 product_type](https://git.1814.love:8443/wx/HL/issues/4021)
- **Label 修正 PR**: [#4022](https://git.1814.love:8443/wx/HL/pulls/4022)
- **后端负责人**: 腰苏图
