# 小程序产品详情 - 住宿信息补酒店封面图 / 类型 / 城市 - **日期**: 2026-04-19 - **Commit**: [2625331f](https://git.1814.love:8443/wx/HL/commit/2625331f) (分支 `fix/0419-business-hotfixes`,批量 PR 待合) - **类型**: FIX - **状态**: 已 commit + push,待批量 PR 合入 dev + 部署测试环境 - **服务**: hl-product-service-v2(端口 8083,通过网关暴露 `/mp/product/**`) --- ## 一、为什么加这三个字段 原型(`小蒙马.pen` → `S6-住宿安排`)的每晚住宿卡片结构: ``` ┌────────┬──────────────────────┐ │ │ 第N晚·城市名(小标签) │ │ 封面图 │ 酒店名称(粗体) │ │ 100x100│ 一句话描述 │ └────────┴──────────────────────┘ ``` 此前后端返回的 `HotelInfo` **只有 hotelName + 档位字段**,前端拿不到封面图 URL、酒店类型(五星/四星等)、酒店所在城市,小程序端显示为空白图位。 根因:`MpProductDetailAssembler.fetchResourceDetails(...)` 原先只收集 `nodeType=HOTEL` 节点的 hotelId 去批量查 `ResourceDetailDTO`,而 `product_day_hotel` 表里的 hotelId **从未进入批量查参数**,所以 HotelInfo 始终拿不到酒店详情。 --- ## 二、变更接口清单 | # | 方法 | 路径 | 影响 | |---|------|------|------| | 1 | GET | `/mp/product/{id}` | 返回的 `itinerary[].hotels[]` 每项新增 `coverUrl` / `hotelType` / `city` 三字段 | **其他接口**(如 `/mp/product/{id}/day/{dayNumber}/hotels` 住宿详情弹窗)已有 `coverUrl`,**不变**。 --- ## 三、字段定义 ### `MpProductDetailRespVO.HotelInfo` 新增字段 | 字段 | 类型 | 说明 | 示例 | 可能为 null | |---|---|---|---|---| | `coverUrl` | String | 酒店封面图 URL(来自资源服务的酒店 cover) | `"https://oss.1814.love/hotel/9001/cover.jpg"` | ✅ 当酒店资源未配封面或 Feign 异常时为 null | | `hotelType` | String | 酒店类型(字典 `hotel_type`:`FIVE_STAR` / `FOUR_STAR` / `BOUTIQUE` / `HOMESTAY` / ...) | `"FIVE_STAR"` | ✅ 可能为 null | | `city` | String | 酒店所在城市 | `"海拉尔"` | ✅ 可能为 null | ### 既有字段(不变) `hotelName` / `tierSeq` / `tierName` / `roomTypeId` / `roomTypeName` / `roomCount`。 此外,本次修复顺带加强了 `hotelName` 的补齐语义:当资源服务返回了 `name`,**会覆盖 DB 快照字段**(更新鲜),快照只作为 Feign 降级时的兜底。 --- ## 四、响应示例对比 ### 前 ```json { "code": 200, "data": { "productId": 1001, "name": "小蒙马·呼伦贝尔5日", "itinerary": [{ "dayNumber": 1, "hotels": [{ "hotelName": "海拉尔精选酒店", "tierSeq": 1, "tierName": "标准", "roomTypeName": "大床房", "roomCount": 1 }] }] } } ``` ### 后 ```json { "code": 200, "data": { "productId": 1001, "name": "小蒙马·呼伦贝尔5日", "itinerary": [{ "dayNumber": 1, "hotels": [{ "hotelName": "海拉尔精选酒店", "tierSeq": 1, "tierName": "标准", "roomTypeName": "大床房", "roomCount": 1, "coverUrl": "https://oss.1814.love/hotel/9001/cover.jpg", "hotelType": "FIVE_STAR", "city": "海拉尔" }] }] } } ``` --- ## 五、前端渲染建议 原型 `S6-住宿安排` 每日住宿卡片: ```html
第{{ day.dayNumber }}晚·{{ hotel.city }} {{ hotel.hotelName }} {{ hotel.tierName }} · {{ hotel.roomTypeName }}
``` ### ⚠️ 容错要求 - `coverUrl` / `hotelType` / `city` **三个字段均可能为 null**(Feign 失败 / 酒店资源未配封面 / 老数据没录入城市),前端务必做 null/空字符串判断: - `coverUrl` 为空时显示默认占位图(避免整个卡片布局错乱) - `city` 为空时可以只显示"第N晚" - `hotelType` 用于可选的类型标签展示,为空时整个标签隐藏即可 --- ## 六、不兼容变更 **无**。纯新增字段,前端不读不受影响;既有字段(`hotelName` / 档位 / 房型)全部保留,语义不变。 --- ## 七、运维注意事项(⚠️ 发布后必做) 本接口有 **5 分钟 Redis 缓存**(key 前缀 `mp:product:detail:`)。测试 / 生产部署 `hl-product-service-v2` 后**必须清一次缓存**,否则 C 端最长 5 分钟内仍返回旧缓存(无封面图): ```bash # 测试环境(192.168.100.236 或 1.182.108.58) redis-cli -h -p 6379 --scan --pattern 'mp:product:detail:*' | xargs -r redis-cli -h -p 6379 del # 或者粗暴重启服务强制清本地进程缓存(Redis 不会自动失效) ``` --- ## 八、回归验证 测试环境部署完成后: ```bash # 选一个小蒙马 GROUP 产品的 productId curl "https://api.test.1814.love/mp/product/{productId}" \ -H "Authorization: Bearer {mp-token}" \ | jq '.data.itinerary[0].hotels[0] | {hotelName, coverUrl, hotelType, city}' ``` **预期**:三个新字段都在响应 JSON 中出现;若酒店资源已配封面,`coverUrl` 为完整 http(s) URL;`city` / `hotelType` 应与后台管理端该酒店的配置一致。 如果 `coverUrl` 仍为 null: 1. 先确认 Redis 缓存已清(见第七节) 2. 再排查酒店资源是否在资源服务后台配了封面图(管理端 → 酒店管理 → 编辑 → 封面图)