# 产品版本分组（基于产品线）+ 产品线详情接口 (PR #129-#137)

> 日期: 2026-04-02 | 服务: hl-product-service, hl-mp-service | 需重启: 是

## 功能概述

1. **产品版本分组**：同一产品线下的已上架产品自动视为不同版本，列表合并为一张卡片，详情页可切换版本
2. **产品线详情接口**：一次请求返回产品线信息 + 所有产品摘要 + 第一个产品完整详情
3. **产品线绑定产品类型**：创建产品线时指定类型，创建产品时按类型筛选产品线

## 核心概念

- 产品名本身就是版本名（如"呼伦贝尔5天·轻奢版"、"呼伦贝尔5天·高档版"）
- 同一产品线下有 2 个以上已上架产品时，自动返回版本切换选项（`gradeOptions`）
- 产品线只有 1 个产品时，表现和之前完全一样

---

## 接口变更

### 1. 产品列表（C端）
**接口**: `GET /mp/product/list`

同一产品线的产品只返回一条，附带所有版本选项。

**新增返回字段**:
| 字段 | 类型 | 说明 |
|------|------|------|
| `gradeOptions` | Array | 同产品线版本选项，null=独立产品或仅一个版本 |
| `gradeOptions[].productId` | String | 该版本的产品ID |
| `gradeOptions[].name` | String | 产品名（即版本名） |
| `gradeOptions[].startPrice` | Number | 起步价 |
| `gradeOptions[].startPriceLabel` | String | "起" 或 "订金起" |

**返回示例（有多版本）**:
```json
{
  "productId": "123",
  "name": "呼伦贝尔5天·轻奢版",
  "gradeOptions": [
    {"productId": "123", "name": "呼伦贝尔5天·轻奢版", "startPrice": 3999, "startPriceLabel": "起"},
    {"productId": "456", "name": "呼伦贝尔5天·高档版", "startPrice": 6999, "startPriceLabel": "起"}
  ]
}
```

**无版本的产品（不受影响）**:
```json
{
  "productId": "789",
  "name": "丽江3天自由行",
  "gradeOptions": null
}
```

### 2. 产品详情（C端）
**接口**: `GET /mp/product/{productId}`

product 对象中新增 `gradeOptions`（同上，null=无版本切换）。

**切换版本方式**: 用 `gradeOptions` 中其他版本的 `productId` 重新调用此接口。

### 3. [新增] 产品线详情
**接口**: `GET /mp/product/line/{lineId}`
**用途**: 小程序产品线详情页，一次请求加载全部数据
**返回结构**:
```json
{
  "line": {
    "lineId": "123",
    "lineName": "呼伦贝尔亲子游",
    "productType": "CORE",
    "productCount": 2
  },
  "products": [
    // 该产品线下所有已上架产品摘要（不去重）
    {"productId": "123", "name": "轻奢版", "startPrice": 3999, ...},
    {"productId": "456", "name": "高档版", "startPrice": 6999, ...}
  ],
  "defaultProduct": {
    // 第一个产品的完整详情（含行程、酒店、评价等聚合数据）
    // 结构同 GET /mp/product/{productId} 返回的 product 对象
  }
}
```

### 4. 产品线接口变更
**接口**: `GET /admin/product/line/active`
**新增参数**: `productType`（可选，CORE/GROUP/CUSTOM/ROUTE）
**行为**: 传参时只返回该类型的产品线 + 未绑定类型的产品线

**接口**: `POST /admin/product/line`（创建产品线）
**新增请求字段**: `productType`（可选，绑定产品类型）

**产品线VO新增字段**: `productType`

### 5. 已删除接口
- `GET /admin/product/item/grade-groups` — 不再需要

---

## 前端开发指引

### 列表页
- `gradeOptions != null && gradeOptions.length > 1` 时，显示版本选项
- 卡片示例: `[轻奢版 ￥3,999起] [高档版 ￥6,999起]`（用 name + startPrice）
- `gradeOptions == null` 的产品照常展示

### 详情页
- `gradeOptions != null && gradeOptions.length > 1` 时，顶部显示版本切换tab
- 当前版本高亮（匹配 productId）
- 点击其他版本 → 用该 productId 重新请求详情
- 报价/下单用当前 productId

### 产品线详情页（新页面）
- 调用 `GET /mp/product/line/{lineId}`
- `defaultProduct` 直接渲染产品详情
- `products` 列表做顶部版本切换tab
- 切换版本时调用 `GET /mp/product/{productId}` 获取新详情

### 管理端-创建产品
- 选择产品类型后，产品线下拉调用 `GET /admin/product/line/active?productType=CORE`
- 创建产品线时可指定 `productType`

---

## DDL
```sql
-- 产品线加类型（已执行）
ALTER TABLE product_line ADD COLUMN product_type VARCHAR(16) DEFAULT NULL AFTER name;

-- grade_group_id 已删除（已执行）
```
