129 行
4.8 KiB
Markdown
129 行
4.8 KiB
Markdown
# 产品等级功能 (PR #129, #131, #132)
|
||
|
||
> 日期: 2026-04-02 | 服务: hl-product-service | 需重启: 是
|
||
|
||
## 新增字典
|
||
|
||
等级数据通过 `sys_dict` 管理,字典类型:`product_grade`
|
||
|
||
| dict_value | dict_label | sort_order |
|
||
|-----------|-----------|-----------|
|
||
| LIGHT_LUXURY | 轻奢 | 1 |
|
||
| HIGH_END | 高档 | 2 |
|
||
|
||
**前端获取方式**:调用 `GET /dict/all` 或 `GET /admin/dict/data/product_grade` 即可获取等级选项列表。后续新增等级(如"经济"、"至尊")由运营在字典管理中添加,无需改代码。
|
||
|
||
## 新增功能
|
||
|
||
### 产品等级分组
|
||
同一行程的不同档次(如轻奢版、高档版)可以关联为一组,小程序列表页合并为一张卡片,详情页可切换等级。
|
||
|
||
## 接口变更
|
||
|
||
### 1. 产品列表接口(C端)
|
||
**接口**: `GET /mp/product/list`
|
||
**变更类型**: 返回字段新增
|
||
|
||
列表中同等级分组的产品只返回一条(主等级),附带所有等级选项。
|
||
|
||
**新增返回字段**:
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `productGrade` | String | 产品等级编码,null=无等级。值: `LIGHT_LUXURY`=轻奢, `HIGH_END`=高档 |
|
||
| `productGradeLabel` | String | 等级中文标签,如"轻奢" |
|
||
| `gradeGroupId` | String | 等级分组ID,null=独立产品 |
|
||
| `gradeOptions` | Array | 同组所有等级选项(含自己),null=无等级 |
|
||
| `gradeOptions[].productId` | String | 该等级对应的产品ID |
|
||
| `gradeOptions[].productGrade` | String | 等级编码 |
|
||
| `gradeOptions[].productGradeLabel` | String | 等级中文 |
|
||
| `gradeOptions[].startPrice` | Number | 该等级起步价 |
|
||
| `gradeOptions[].startPriceLabel` | String | "起" 或 "订金起" |
|
||
|
||
**返回示例(有等级的产品)**:
|
||
```json
|
||
{
|
||
"productId": "123",
|
||
"name": "呼伦贝尔5天亲子深度游",
|
||
"productGrade": "LIGHT_LUXURY",
|
||
"productGradeLabel": "轻奢",
|
||
"gradeGroupId": "123",
|
||
"gradeOptions": [
|
||
{"productId": "123", "productGrade": "LIGHT_LUXURY", "productGradeLabel": "轻奢", "startPrice": 3999, "startPriceLabel": "起"},
|
||
{"productId": "456", "productGrade": "HIGH_END", "productGradeLabel": "高档", "startPrice": 6999, "startPriceLabel": "起"}
|
||
]
|
||
}
|
||
```
|
||
|
||
**返回示例(无等级的产品,不受影响)**:
|
||
```json
|
||
{
|
||
"productId": "789",
|
||
"name": "丽江3天自由行",
|
||
"productGrade": null,
|
||
"gradeGroupId": null,
|
||
"gradeOptions": null
|
||
}
|
||
```
|
||
|
||
### 2. 产品详情接口(C端)
|
||
**接口**: `GET /mp/product/{productId}`
|
||
**变更类型**: 返回字段新增
|
||
|
||
product 对象中新增相同的等级字段(productGrade, productGradeLabel, gradeGroupId, gradeOptions)。
|
||
|
||
**前端切换等级的方式**: 用 `gradeOptions` 中其他等级的 `productId` 重新调用此接口即可,无需新接口。
|
||
|
||
### 3. 推荐产品列表(C端)
|
||
**接口**: `GET /mp/product/recommend`(内部Feign)
|
||
同样新增等级字段,同等级分组去重。
|
||
|
||
### 4. 管理端产品列表
|
||
**接口**: `GET /admin/product/item/list`
|
||
新增字段: `productGrade`, `productGradeLabel`, `gradeGroupId`(不含gradeOptions,管理端不去重)
|
||
|
||
### 5. 管理端产品详情
|
||
**接口**: `GET /admin/product/item/{productId}`
|
||
新增字段同C端详情。
|
||
|
||
### 6. [新增] 等级分组查询
|
||
**接口**: `GET /admin/product/item/grade-groups`
|
||
**参数**: `lineId`(可选,按产品线筛选)
|
||
**用途**: 管理端创建等级产品时,查询已有等级分组列表用于关联
|
||
**返回**: 分组列表,每组含 gradeGroupId、groupName、products[]
|
||
|
||
### 7. 产品保存接口
|
||
**接口**: `POST /admin/product/item/save`
|
||
**新增请求字段**:
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `productGrade` | String | 产品等级,不传=无等级 |
|
||
| `gradeGroupId` | Long | 等级分组ID,关联已有组时传入 |
|
||
| `gradeSort` | Integer | 等级排序,越小越前 |
|
||
|
||
**校验规则**:
|
||
- 同一等级分组内不能有重复等级
|
||
- 同一等级分组内的产品必须在同一产品线
|
||
- 同一产品线只能包含同一类型的产品
|
||
|
||
## 前端开发指引
|
||
|
||
### 列表页
|
||
- 判断 `gradeOptions != null && gradeOptions.length > 1` 时,显示等级价格标签
|
||
- 卡片示例: `[轻奢 ¥3,999起] [高档 ¥6,999起]`
|
||
- `gradeOptions == null` 的产品照常展示
|
||
|
||
### 详情页
|
||
- 判断 `gradeOptions != null && gradeOptions.length > 1` 时,顶部显示等级切换tab
|
||
- 当前等级高亮(匹配 productId)
|
||
- 点击其他等级 → 用该等级的 productId 重新请求详情接口
|
||
- 报价/下单用当前页面的 productId,不受影响
|
||
|
||
## DDL(已在测试/正式服务器执行)
|
||
```sql
|
||
ALTER TABLE product
|
||
ADD COLUMN product_grade VARCHAR(16) DEFAULT NULL COMMENT '产品等级' AFTER product_type,
|
||
ADD COLUMN grade_group_id BIGINT DEFAULT NULL COMMENT '等级分组ID' AFTER product_grade,
|
||
ADD COLUMN grade_sort INT DEFAULT 0 COMMENT '等级排序' AFTER grade_group_id,
|
||
ADD INDEX idx_grade_group_id (grade_group_id);
|
||
```
|