# 修复 商品选择列表接口 500 错误 - **日期**: 2026-04-17 - **服务**: hl-product-service-v2(端口 8083) - **类型**: BUG 修复(非破坏性) - **前端影响**: **无需改动** --- ## 修复说明 ### 现象 调用订单创建「选择商品」弹窗的商品列表接口时,**100% 返回 500**: ```json { "code": 500, "message": "服务器内部错误", "data": null, "success": false } ``` 该接口一上线就无法使用,前端弹窗里产品列表始终为空。 ### 根因 Mapper 使用 `selectAll(ProductDO.class)` 把 `ProductDO` 所有字段映射到 VO。其中: - 实体 `ProductDO.tiers` 是 **String 类型(存 JSON 字符串)** - VO `ProductSimpleItemRespVO.tiers` 是 **`List`(结构化列表)** MyBatis-Plus Join 在构造 ResultMap 阶段发现同名字段类型不一致,抛 `IllegalStateException`,整个请求返回 500。 ### 修复方式 Mapper 改为**显式 selectFields**,只映射基础字段;`tiers` 字段由 Service 层单独查 `ProductTierDO` 表并解析为结构化列表再塞回 VO。 对前端而言:**接口路径、请求参数、响应结构完全不变**,原来调不通的接口现在正常返回数据。 --- ## 接口信息 ### 请求 ``` GET /admin/product/item/simple-list ``` **Header**: ``` Authorization: Bearer {token} tenant-id: {租户ID} ``` ### 查询参数 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | productType | String | 否 | 产品类型(`CORE`=核心产品,`GROUP`=小蒙马),不传=全部 | | keyword | String | 否 | 搜索关键词(匹配产品名称) | | pageNo | Integer | 否 | 页码,默认 1 | | pageSize | Integer | 否 | 每页条数,默认 50 | > 后端固定只返回**已上架**(status=PUBLISHED)的产品,前端不需要传 status。 ### 响应字段 外层(`data`): | 字段 | 类型 | 说明 | |------|------|------| | records | Array | 产品列表 | | total | Long | 总数 | `records` 数组中每一项: | 字段 | 类型 | 说明 | |------|------|------| | productId | Long | 产品ID(JSON 序列化为字符串防精度丢失) | | productNo | String | 产品编号(如 `C260416002`) | | name | String | 产品名称 | | tripDays | Integer | 行程天数 | | lineName | String | 所属产品线名称(LEFT JOIN 查出) | | tiers | Array | 该产品的档位列表(可能为空数组) | `tiers` 数组中每一项(档位): | 字段 | 类型 | 说明 | |------|------|------| | tierSeq | Integer | 档位序号(1 开始) | | tierName | String | 档位名称(如 `舒适`、`豪华`) | | tierDescription | String | 档位描述,可能为空字符串 | --- ## 完整请求示例 ``` GET /admin/product/item/simple-list?productType=CORE&pageNo=1&pageSize=20 Authorization: Bearer eyJxxx... tenant-id: 1 ``` ## 完整响应示例 ```json { "code": 200, "message": "成功", "data": { "records": [ { "productId": "2044704111294672897", "productNo": "C260416002", "name": "嗨冰雪3.0南线(6天5晚)", "tripDays": 6, "lineName": "嗨冰雪", "tiers": [ { "tierSeq": 1, "tierName": "舒适", "tierDescription": "" }, { "tierSeq": 2, "tierName": "豪华", "tierDescription": "" } ] } ], "total": 5 }, "success": true } ``` --- ## 前端无需改动 > 🟢 **该修复纯属后端 Bug 修复,前端不需要任何调整。** > > - 接口路径:**不变** > - 请求参数:**不变** > - 响应字段结构:**不变** > - 错误码/成功码:**不变** > > 此前调用此接口拿到 500 的地方,现在可以正常拿到数据;已经写好的调用代码无需修改。 如果之前前端为了"兼容 500"加过 try/catch 降级逻辑,可以保留,不会有副作用。 --- ## 重启服务 - `hl-product-service-v2`(端口 8083) --- ## 关联信息 - **Issue**: #745 - **PR**: #746(已合并到 dev) - **Commit**: `cfd901e5`