# 小程序首页第二屏 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)**