feat: MP+admin 产品详情返回备品清单含 coverUrl (#2266)
这个提交包含在:
父节点
36a4f810b0
当前提交
f2bcc3a5e4
@ -0,0 +1,126 @@
|
|||||||
|
# product-v2: 小程序 + 管理端产品详情返回备品清单(含封面图)
|
||||||
|
|
||||||
|
> **服务**: hl-product-service-v2 (端口 8083) + hl-resource-service (端口 8082)
|
||||||
|
> **PR**: #2272
|
||||||
|
> **Issue**: #2266
|
||||||
|
> **日期**: 2026-05-14
|
||||||
|
> **影响范围**: 小程序产品详情新增 `supplies` 数组 / 管理端产品详情 `supplies[].coverUrl` 新增字段
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 关键变化
|
||||||
|
|
||||||
|
小程序产品详情接口此前**完全没返回备品清单**,前端无法展示。本次补齐:
|
||||||
|
|
||||||
|
1. **小程序详情 `GET /mp/product/{id}` 顶层新增 `supplies` 数组**(此前完全没有这个字段)
|
||||||
|
2. **管理端详情 `GET /admin/product/item/{id}` `supplies[]` 子对象新增 `coverUrl` 字段**
|
||||||
|
3. 数据库 `product_supplies` 表新增 `cover_url` 列,Flyway V20260514_001 已在测试服跑完一次性 JOIN 回填:**引用资源库 supplies_item 的备品 100% 命中(73/73)**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、变更接口清单
|
||||||
|
|
||||||
|
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||||
|
|---|------|------|------|----------|------|
|
||||||
|
| 1 | 小程序产品详情 | GET | `/mp/product/{id}` | **新增字段** | 顶层 `supplies: SuppliesVO[]` |
|
||||||
|
| 2 | 管理端产品详情 | GET | `/admin/product/item/{id}` | 字段扩展 | `supplies[]` 子对象新增 `coverUrl` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、接口详情
|
||||||
|
|
||||||
|
### 1. 小程序产品详情 `GET /mp/product/{id}`
|
||||||
|
|
||||||
|
**VO**: `MpProductDetailRespVO.SuppliesVO`(新内嵌静态类)
|
||||||
|
|
||||||
|
#### 新增响应字段
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"productId": "2045623908178046978",
|
||||||
|
"name": "带孩子,看一次真正的草原。",
|
||||||
|
"...": "其他既有字段保持不变",
|
||||||
|
"supplies": [
|
||||||
|
{
|
||||||
|
"id": 2045635184023285762,
|
||||||
|
"suppliesName": "团队识别手环",
|
||||||
|
"category": "个人装备",
|
||||||
|
"coverUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/test/material/2026/03/07/xxx.png",
|
||||||
|
"sortOrder": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2045635184027480066,
|
||||||
|
"suppliesName": "防晒喷雾",
|
||||||
|
"category": "个人装备",
|
||||||
|
"coverUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/test/material/2026/03/07/yyy.png",
|
||||||
|
"sortOrder": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 可能为 null | 说明 |
|
||||||
|
|------|------|------------|------|
|
||||||
|
| `supplies` | `List<SuppliesVO>` 或 `null` | ✅ | 产品没备品时整个字段为 `null`,前端按 null 兜底空数组即可 |
|
||||||
|
| `supplies[].id` | `Long`(雪花) | ❌ | 备品行 ID(C 端通常用不到,可忽略) |
|
||||||
|
| `supplies[].suppliesName` | `String` | ❌ | 备品名称(已是快照,展示用) |
|
||||||
|
| `supplies[].category` | `String` 或 `null` | ✅ | 分类(中文文本或字典编码均可能,示例 `个人装备`/`保暖装备`/`CAMPING` 等,**前端不要做硬枚举映射**,直接展示文本) |
|
||||||
|
| `supplies[].coverUrl` | `String` 或 `null` | ✅ | 备品封面图 URL(快照),自定义备品或历史回填失败可能为 null,**前端务必做默认占位图兜底** |
|
||||||
|
| `supplies[].sortOrder` | `Integer` | ❌ | 排序字段,后端已按 ASC 返回,前端按数组顺序渲染即可 |
|
||||||
|
|
||||||
|
#### 排序
|
||||||
|
|
||||||
|
后端 `selectByProductId` 已 `orderByAsc(sortOrder)` 排序,前端直接按数组顺序展示。
|
||||||
|
|
||||||
|
### 2. 管理端产品详情 `GET /admin/product/item/{id}`
|
||||||
|
|
||||||
|
**VO**: `ProductDetailRespVO.SuppliesVO`(既有内嵌类,仅扩展字段)
|
||||||
|
|
||||||
|
`supplies[]` 子对象新增 `coverUrl: String`,语义同上(快照,可能为 null)。其他既有字段(`id` / `productId` / `suppliesResourceId` / `suppliesName` / `category` / `hasCost` / `billingType` / `unitPrice` / `quantity` / `sortOrder`)保持不变。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、前端兜底要求
|
||||||
|
|
||||||
|
**重要**:`coverUrl` 字段**可能为 null**,出现场景:
|
||||||
|
|
||||||
|
1. **手工添加的自定义备品**(没勾选资源库 supplies_item,只填了名字) — 后端没有源头查 cover,直接 null
|
||||||
|
2. **历史数据中 supplies_item 关联资源已删 / material 已删 / oss_url 为空** — 一次性 JOIN 回填时被防御逻辑排除
|
||||||
|
|
||||||
|
**前端必须做默认占位图**,例如:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const cover = supply.coverUrl || '/static/supplies-default.png';
|
||||||
|
```
|
||||||
|
|
||||||
|
或 CSS:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.supplies-cover { background: url(/static/supplies-default.png) no-repeat center; }
|
||||||
|
.supplies-cover img { object-fit: cover; }
|
||||||
|
```
|
||||||
|
|
||||||
|
测试服回填命中率参考:**174 条 product_supplies 中 73 条有 supplies_resource_id,全部命中真实 OSS URL;另外 101 条是手工/旧数据,coverUrl 为 null**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、已知限制(后续优化)
|
||||||
|
|
||||||
|
- **手工(非组合)单品在编辑保存时 coverUrl 暂留 null**:本次未引入新 Feign,只通过 DB 一次性回填覆盖历史,新增/编辑手工备品 coverUrl 仍是 NULL,**前端兜底是必须的**
|
||||||
|
- **从备品组合("从组合选择"按钮)添加的备品 coverUrl 在保存时自动同步**:`SuppliesComboService.expandBatch` 已接入 MaterialService 批量解析,组合展开自然带 URL
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、测试服真测证据
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 测试服 9443 网关
|
||||||
|
curl https://api.test.1814.love:9443/mp/product/2045623908178046978
|
||||||
|
```
|
||||||
|
|
||||||
|
返回顶层 `supplies` 数组 4 条全部带 coverUrl 真实 OSS URL,按 sortOrder 0→1→2→3 升序。
|
||||||
|
|
||||||
|
Admin 端用 `test_admin (admin_id=1002)` 测试 productId=2053665899663024129(用户截图同一产品):3 条备品(团队识别手环 / 防晒喷雾 / 便携矿泉水)全部带 coverUrl ✅
|
||||||
正在加载...
x
在新工单中引用
屏蔽一个用户