首页第二屏 v2 - 去蒙层+内嵌卡片+类型校验(PR #823)

这个提交包含在:
API Changelog Bot 2026-04-18 15:03:02 +08:00
父节点 3db5be896e
当前提交 6f3fcf2397

查看文件

@ -0,0 +1,180 @@
# 小程序首页第二屏 v2 - 去蒙层 + 内嵌卡片 + 类型校验
- **日期**: 2026-04-18
- **PR**: [#823](https://git.1814.love:8443/wx/HL/pulls/823) (Closes #822)
- **状态**: 已合并 + 测试环境 DDL/服务全就绪 + E2E 通过
---
## 变更概览
1. 删 `coverMaskType` 字段(全链路)
2. 品牌故事内嵌 2 张主题卡片(`cards` 数组,最多 2 张)
3. 修 PR #811 缓存失效 bug
4. 链接目标(产品/产品线)只允许 **CORE/GROUP** 类型,响应加 `linkTargetType`
---
## 1. Admin `PUT /admin/home-config/brand-story` 请求体变更
### 删除字段
- ~~`coverMaskType`~~
### 新增字段
- `cards`: `BrandCard[]`(最多 2 张)
```json
{
"title": "每一条线路,我们都亲自走过。",
"subtitle": null,
"description": "整个呼伦贝尔...",
"coverUrl": "https://cdn.1814.love/home/team-photo.jpg",
"publish": true,
"cards": [
{
"title": "季节之旅",
"subtitle": "夏·秋·冬三季体验",
"coverUrl": "https://cdn.1814.love/cards/season.jpg",
"linkType": "PRODUCT_LINE",
"linkTarget": "2045004175602868226"
},
{
"title": "亲子研学",
"subtitle": "边玩边学·深度体验",
"coverUrl": "https://cdn.1814.love/cards/study.jpg",
"linkType": "NONE",
"linkTarget": ""
}
]
}
```
**BrandCard 字段**:
| 字段 | 类型 | 必填 | 说明 |
|-----|------|------|-----|
| title | String | ✓ | 标题(如"季节之旅" |
| subtitle | String | - | 副标题 |
| coverUrl | String | ✓ | 背景图 URL必须 https |
| linkType | String | ✓ | NONE/PRODUCT/PRODUCT_LINE/ARTICLE/URL/MINI_PAGE |
| linkTarget | String | - | 跳转目标id 或 url |
### 业务校验
- `cards` 最多 2 张(`@Size(max=2)`
- **PRODUCT/PRODUCT_LINE 时 linkTarget 对应的产品/产品线类型必须是 `CORE` 或 `GROUP`**,其他类型返回:
```json
{"code":500, "message":"卡片只能关联核心或小蒙马类型的产品/产品线", "data":null, "success":false}
```
---
## 2. Admin/MP GET 响应新增
### 响应结构
- Admin `GET /admin/home-config/brand-story` 返回的 `data` 里,`coverMaskType` 字段**已移除**,新增 `cards`
- MP `GET /mp/home-config/screen2` 返回 `data.cards`(原 `data.topics` **移除**
```json
{
"code": 200,
"data": {
"brandStory": {
"title": "每一条线路,我们都亲自走过。",
"subtitle": null,
"description": "...",
"coverUrl": "..."
},
"cards": [
{
"title": "季节之旅",
"subtitle": "夏·秋·冬三季体验",
"coverUrl": "...",
"linkType": "PRODUCT_LINE",
"linkTarget": "2045004175602868226",
"linkTargetType": "CORE"
},
...
]
},
"success": true
}
```
**`linkTargetType`** 字段说明:
- `CORE` / `GROUP` / `null`
- 仅 PRODUCT/PRODUCT_LINE 类型时填充,其他返 null
- 批量回填Feign 调 product-v2 一次性批查),避免 N+1
---
## 3. 轮播图 `/admin/banner` 变更
### 请求(保存)
- linkType=PRODUCT/PRODUCT_LINE 时后端校验 linkId 的 productType 必须 CORE/GROUP,否则返
```
{"code":500, "message":"轮播图只能关联核心或小蒙马类型的产品/产品线", ...}
```
### 响应
- BannerVO 新增 `linkTargetType` 字段CORE/GROUP/null
- 列表查询也批量回填,前端展示"核心"/"小蒙马"标签不用二次查询
---
## 4. MP 缓存
- Key: `home:screen2:mp:{env}`
- TTL 30 分钟
- **修复**: PR #811 发布后不失效的 bug 已修(`HomeBrandStoryService.publish()` 现在真正调用 `evictAfterCommit()`
---
## 5. 前端改造清单
### 管理端 (hl-ui)
1. **品牌故事表单**
- 删除"蒙层类型"下拉
- 新增"主题卡片"section,固定 2 张子表单(每张:标题/副标题/背景图/跳转类型/跳转目标)
- 跳转类型选择器选中 PRODUCT/PRODUCT_LINE 时,目标选择器**只显示 `productType=CORE``GROUP`** 的产品/产品线
- 展示页可读取 `linkTargetType` 显示标签("核心"/"小蒙马"
2. **轮播图表单 (`/mp-config/home/banner`)**
- 选择器同上:只显示 CORE/GROUP
- 列表页展示 `linkTargetType` 标签(当 linkType=PRODUCT/PRODUCT_LINE
### 小程序端
- 首页第二屏渲染:
- `data.brandStory` 是主文案块
- `data.cards` 是 2 张卡片(如原来的 `data.topics` 结构,但字段略不同)
- 卡片点击按 `linkType` + `linkTarget` 跳转
---
## 6. 产品/产品线选择器接口
前端选择器可用现有接口过滤 `productType`,或调新内部接口(如果暴露到管理端):
- 管理端已有 `GET /admin/product-line/enabled`(列表接口)— 按 `productType` filter
- 如需求进一步精确,可联系后端加 `GET /admin/product-line/enabled?productTypes=CORE,GROUP`
---
## 7. 测试环境验证
- [x] DDL 已跑sys_home_brand_story 无 cover_mask_type,有 cards JSON
- [x] E2E: PUT cards → MP GET 立即可见(缓存 evict 生效)
- [x] E2E: cards linkType=PRODUCT_LINE linkTarget=假 id → 抛业务异常 "卡片只能关联核心或小蒙马类型的产品/产品线"
- [x] Admin GET 响应无 coverMaskType,MP GET 响应 `cards` 替代 `topics`
---
## 8. 关联 PR
- #811 首页第二屏 v1
- #813 Gateway 路由补丁
- #815 菜单 + 轮播图 PRODUCT_LINE 字典
- **#823 本 PR (v2)**