# 资源服务 + 产品行程节点: 新增「图标」「卖点简介」2 字段 > **服务**: hl-resource-service (端口 8082) + hl-product-service-v2 (端口 8083) > **PR**: [#2076](https://git.1814.love:8443/wx/HL/pulls/2076) — 已合并 dev + 测试服部署 > **PR (hotfix admin VO 补字段)**: [#2081](https://git.1814.love:8443/wx/HL/pulls/2081) — 已合并 dev + 测试服部署 > **PR (hotfix Flyway pilot marker 解锁)**: [#2077](https://git.1814.love:8443/wx/HL/pulls/2077) — 与本功能间接相关 > **Issue**: [#2068](https://git.1814.love:8443/wx/HL/issues/2068) > **日期**: 2026-05-12 > **影响范围**: 管理端「资源管理 → 景区/活动/服务」 + 「产品编辑 → 行程编排/产品卖点」 + 小程序「今日体验」 > **状态**: ✅ **测试服已验证** (api.test.1814.love:9443) --- ## ⚠️ 关键变化 **资源端 3 类资源**(景区 scenic-spot / 活动 activity / 服务 service-item) **+ 产品行程节点** product_itinerary_node,**各新增 2 个字段**: - `iconMaterialId` — 图标素材 ID(指向素材库) - `sellingPoint` — 卖点简介(VARCHAR 500) 业务联动: - 资源端**有这两个字段就是默认值** - 产品行程节点保存时,**前端如果不传**这两字段,后端**自动从资源端拷贝默认值**到节点快照 - 产品行程节点保存时,**前端如果显式传值**,以前端为准(产品端可改) - 产品端改了节点的 icon/selling 也**不回写资源**(资源端永远是真相源) --- ## 一、测试服已验证 (硬性凭证) ``` hl-resource-service 测试服: POST/PUT/GET /admin/scenic/spot iconMaterialId + sellingPoint 能存能取 ✓ POST/PUT/GET /admin/activity/item iconMaterialId + sellingPoint 能存能取 ✓ POST/PUT/GET /admin/service/item iconMaterialId + sellingPoint 能存能取 ✓ GET .../page (列表) ListVO 含 iconMaterialId/iconUrl/sellingPoint ✓ hl-product-service-v2 测试服: POST /admin/product/item/.../itinerary 节点 SAVE 落库 ✓ GET /admin/product/item/{id} 节点 VO 返回 iconMaterialId + sellingPoint ✓ 「资源默认值复制」: 前端不传 → 节点字段=资源端 iconMaterialId/sellingPoint ✓ 「前端覆盖优先」: 前端传值 → 节点字段=前端值 ✓ 「不回写资源」: 改节点后资源端字段不变 ✓ ``` 异常路径: ``` sellingPoint 传 501 字符 → HTTP 200 code=400 "卖点简介不能超过500个字符" ✓ ``` --- ## 二、变更接口清单 ### 资源端 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 1 | 景区 创建 | POST | `/admin/scenic/spot` | 请求体新增 2 字段 | iconMaterialId, sellingPoint | | 2 | 景区 更新 | PUT | `/admin/scenic/spot` | 请求体新增 2 字段 | 同上 | | 3 | 景区 详情 | GET | `/admin/scenic/spot/{id}` | 响应体新增 3 字段 | iconMaterialId, iconUrl, sellingPoint | | 4 | 景区 列表 | GET | `/admin/scenic/spots` | 响应体新增 3 字段 | 列表项含 3 字段 | | 5-8 | 活动 同上 | - | `/admin/activity/item*` | 同景区 4 接口 | - | | 9-12 | 服务 同上 | - | `/admin/service/item*` | 同景区 4 接口 | - | ### 产品端 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 13 | 行程保存 | PUT | `/admin/product/item/{id}/itinerary` | 节点 NodeItem 入参新增 2 字段 | iconMaterialId, sellingPoint(可选) | | 14 | 产品详情 | GET | `/admin/product/item/{id}` | 节点 NodeRespVO 响应新增 3 字段 | iconMaterialId, iconUrl, sellingPoint | | 15 | mp 详情 | GET | `/mp/product/{id}` | 节点 NodeInfo 响应新增 3 字段 | 同上,小程序「今日体验」用 | --- ## 三、前端字段约束 | 字段 | 类型 | 必填 | 约束 | 备注 | |------|------|------|------|------| | iconMaterialId | Long(产品节点) / String(资源端,String 表示的 BIGINT) | 否 | - | 指向素材库的素材 ID | | iconUrl | String | 否(仅 Resp) | - | 后端解析素材后的 OSS URL,**前端只在响应中读,不传** | | sellingPoint | String | 否 | 最多 500 字符 | 卖点简介文字 | --- ## 四、UI 层面建议(参考) ### 资源管理页 3 类资源(景区/活动/服务)的**新建/编辑表单**新增 2 个字段: - **图标**: 素材库选择器(选小尺寸图,推荐 64x64),保存 materialId - **卖点简介**: 多行文本框,提示"最多 500 字" 详情页/列表卡片可直接展示这两字段(用 iconUrl + sellingPoint)。 ### 产品编辑页 **行程编排** 步骤(图1 的「活动安排」红框): - 节点点击图标时弹出**素材选择器** → 选完保存到节点的 iconMaterialId - 节点详情面板新增**卖点简介**输入框(多行,500 字) - **新建节点时**,选完资源(景区/活动/服务) → 后端自动用资源端默认值预填,前端可改 - **修改节点的 icon/卖点 不会回写到资源**,只影响当前产品的这个节点 **产品卖点页**(图2 的「快速理解」红框): - 这个页面和「行程编排」**共用同一份 product_itinerary_node 数据** - 也就是说在「行程编排」改了节点的 icon/卖点,「产品卖点」页面会立刻看到更新 --- ## 五、风险/兼容性 - **不破坏现有调用**: 只追加字段,旧请求不传 → null,旧响应消费方忽略新字段无影响 - **Bean Validation**: sellingPoint 后端用 @Size(max=500) 校验,前端最好也加前置校验避免 round-trip - **不回写资源铁规**: 后端 ProductItineraryService.convertNode() 已硬保证,前端无需关心 --- ## 六、需要前端做的事 1. ⏰ **3 类资源管理页** 加 2 个字段:图标素材选择器 + 卖点简介文本框(都不必填) 2. ⏰ **产品编辑 → 行程编排** 加节点的 icon/卖点编辑(都不必填,空就用资源默认) 3. ⏰ **产品编辑 → 产品卖点** 页面如果是独立路由,字段读取同 product_itinerary_node 节点 4. ⏰ 「今日体验」小程序节点前显示图标(iconUrl 字段) + 节点卖点(sellingPoint) 5. 如有疑问可直接对照 swagger: `https://api.test.1814.love:9443/hl-resource-service/v2/api-docs?group=资源服务` 以及 `https://api.test.1814.love:9443/hl-product-service-v2/v2/api-docs?group=产品服务`(账号 hulalv / HuLaLv@Doc2026)