From f18e187aa5b1e974430975f79217fcd1c9ff7ff4 Mon Sep 17 00:00:00 2001 From: wx Date: Tue, 21 Apr 2026 14:53:39 +0800 Subject: [PATCH] =?UTF-8?q?2026-04-21=20=E4=B8=BB=E9=A2=98=E5=8D=A1?= =?UTF-8?q?=E7=89=87=E8=B7=B3=E8=BD=AC=E6=94=B9=E8=B7=AF=E5=BE=84=E7=9B=B4?= =?UTF-8?q?=E8=B7=B3=20+=20PRODUCT=20=E5=AD=98=20productId+productType=20(?= =?UTF-8?q?#1085)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...pic-link-type-paths-and-product-payload.md | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 changelogs/2026-04/2026-04-21_topic-link-type-paths-and-product-payload.md diff --git a/changelogs/2026-04/2026-04-21_topic-link-type-paths-and-product-payload.md b/changelogs/2026-04/2026-04-21_topic-link-type-paths-and-product-payload.md new file mode 100644 index 0000000..d63a9a8 --- /dev/null +++ b/changelogs/2026-04/2026-04-21_topic-link-type-paths-and-product-payload.md @@ -0,0 +1,146 @@ +# 主题卡片跳转类型改路径直跳 + PRODUCT 存 productId+productType + +**日期**:2026-04-21 +**PR**:#1085 +**合并到 dev commit**:55d601d7 +**后端服务**:hl-user-service(需重启) +**影响**: +- 管理端「首页配置 → 品牌故事 → 主题卡片」跳转类型下拉 + 指定产品选择 +- 小程序「首页第二屏」点击主题卡片跳转逻辑 + +> 本次是对 #1081(2026-04-21 早上)的迭代。#1081 建立了跳转类型字段,本次调整字典 value 语义 + PRODUCT 的 payload 存储方式。 + +--- + +## 为什么改 + +#1081 之前把 4 种跳转类型的 `dict_value` 定为枚举 code(`SEASON` / `CORE_LIST` / `MENGMA` / `PRODUCT`),前端还要维护一张 code → 路径的 switch 表。改完后三种列表类直接把路径放到 `dict_value`,前端拿到直接跳,不用 switch。只有「指定产品」保留枚举 `PRODUCT`,因为路径需要运行时拼产品 id/类型。 + +--- + +## 字典改动(已同步本地 + 测试服 192.168.100.236) + +**dict_type**:`theme_card_link_type`(不变,dict_type_id=8090,category=BUSINESS) + +**dict_data**: + +| dict_value(变化) | dict_label | sort_order | +|-------------------|-----------|-----------| +| `packages/product/season/list/list` | 季节之旅 | 10 | +| `packages/product/core/list/list` | 核心产品 | 20 | +| `packages/product/mengma/list/list` | 亲子游学 | 30 | +| `PRODUCT`(保留枚举) | 指定产品 | 40 | + +**迁移**:本地 + 测试服 DB 已通过 UPDATE 同步;`sys_topic.link_type` 从 VARCHAR(20) 扩到 VARCHAR(200)(因路径超长)。 + +--- + +## 接口签名变化 + +### 1. `TopicRequest`(POST /admin/topic/create、PUT /admin/topic/update 入参) + +**新增两个字段**: + +| 字段 | 类型 | 是否必填 | 说明 | +|------|------|---------|------| +| `productId` | `Long` | **PRODUCT 类型必填** | 指定的产品 ID | +| `productType` | `String` | **PRODUCT 类型必填** | 产品类型(字典 `product_type`:CORE / GROUP / CUSTOM) | + +**`linkType` / `linkTarget` 语义调整**: + +| linkType 值 | linkTarget 怎么传 | productId / productType 怎么传 | +|-------------|------------------|---------------------------------| +| `packages/product/season/list/list` | 不传(后端会忽略) | 不传 | +| `packages/product/core/list/list` | 不传 | 不传 | +| `packages/product/mengma/list/list` | 不传 | 不传 | +| `PRODUCT` | **不要传**(后端会忽略并合成 JSON) | **必填** productId + productType | + +> ⚠️ 校验:`linkType=PRODUCT` 时 productId 或 productType 缺失,后端直接抛 `{"code":400,"message":"指定产品跳转必须填写产品ID和产品类型"}`。 + +**请求示例(路径直跳)**: +```json +{ + "title": "季节之旅", + "coverUrl": "https://oss.../cover.png", + "linkType": "packages/product/season/list/list" +} +``` + +**请求示例(指定产品)**: +```json +{ + "title": "亲子系列", + "coverUrl": "https://oss.../cover.png", + "linkType": "PRODUCT", + "productId": 2045345825172639746, + "productType": "CORE" +} +``` + +### 2. `TopicVO`(GET /admin/topic/{id} 或列表返回) + +**新增两个回显字段**: + +| 字段 | 类型 | 何时有值 | +|------|------|---------| +| `productId` | `Long` | 仅 `linkType=PRODUCT` 时非空 | +| `productType` | `String` | 仅 `linkType=PRODUCT` 时非空 | + +`linkTarget` 字段行为: +- `linkType=PRODUCT`:仍然是 JSON 字符串(`{"productId":xxx,"productType":"CORE"}`),**前端直接读新的 productId/productType 字段即可**,不用再解析 linkTarget +- 其它 linkType:目前后端写入时为空字符串,前端忽略即可 + +**响应示例(指定产品)**: +```json +{ + "id": "2046xxx", + "title": "亲子系列", + "linkType": "PRODUCT", + "linkTarget": "{\"productId\":2045345825172639746,\"productType\":\"CORE\"}", + "productId": 2045345825172639746, + "productType": "CORE" +} +``` + +--- + +## 管理端前端要做的事 + +1. **跳转类型下拉**:拉 `/admin/dict/data?dictType=theme_card_link_type`,直接用 `dict_label` 显示 + `dict_value` 作为 linkType +2. **选中 PRODUCT 时弹产品选择器**:用户选完产品后拿到 productId + productType,保存时塞进 `TopicRequest.productId` / `productType`(不要再传 linkTarget) +3. **选中非 PRODUCT(路径)时**:直接把字典 value 作为 linkType 提交,不用管 linkTarget / productId / productType +4. **回显**:编辑页如果 topic.linkType='PRODUCT',用 `topic.productId` + `topic.productType` 反查产品名展示;否则按路径下拉项高亮对应项即可 + +--- + +## 小程序前端要做的事 + +点击主题卡片时: +- `linkType=PRODUCT` → 按 `productId` + `productType` 拼产品详情路径(具体格式由前端约定) +- 其它(路径) → `wx.navigateTo({ url: '/' + linkType })` 直接跳 + +老小程序(未感知此次变化):`linkType` 拿到字符串路径也能直接 navigate,只有 PRODUCT 类型会走不到详情(但原本 #1081 就约定 PRODUCT 依赖 target 字段,老端本来就没处理),不属于回归。 + +--- + +## 兼容性与老数据 + +- 本 PR 合并前数据库里 `sys_topic` 是空表,没有历史数据要迁移 +- TopicVO.toVO 对 legacy 纯数值字符串 linkTarget(形如 `"12345"`)做了 `log.warn` 容忍,不会 500,productId/productType 返 null;如未来真有脏数据可手工修 +- 老版本小程序拿到新的路径型 linkType 仍能直接 navigateTo,不会崩 + +--- + +## 测试 + +- 单测 `TopicServiceTest` **31 个用例全绿** + - 新增 6 个:`createTopic_productType_serializesLinkTargetAsJson` / `createTopic_product_missingProductId` / `createTopic_product_missingProductType` / `createTopic_seasonPath_keepsLinkTargetAsIs` / `updateTopic_product_rebuildsLinkTarget` / `toVO_product_withLegacyLinkTarget_tolerated` +- 测试服字典已同步(dict_type + 4 条 dict_data + link_type 列宽) +- 测试服 hl-user-service 已触发 Deploy Panel 重新部署 + +--- + +## 重启 + +- **hl-user-service** 必须重启(新代码) +- 其它服务无依赖,不用重启