diff --git a/changelogs/2026-04/2026-04-19_product-v2_list-filter-and-publish-validation-fix.md b/changelogs/2026-04/2026-04-19_product-v2_list-filter-and-publish-validation-fix.md new file mode 100644 index 0000000..e5768df --- /dev/null +++ b/changelogs/2026-04/2026-04-19_product-v2_list-filter-and-publish-validation-fix.md @@ -0,0 +1,100 @@ +# fix(product-v2): 产品列表多值筛选 + 小蒙马上架校验四项修复 + +> **服务**: hl-product-service-v2 (端口 8083) +> **PR**: #881 +> **Issue**: #876 / #877 +> **Merge commit**: `406afb28` +> **日期**: 2026-04-19 +> **影响范围**: 管理端产品列表筛选 + 上架预检接口行为 +> **前端是否需要改动**: **无需改动**(前端继续按原方式调用即可,行为自动变正常) + +--- + +## 一、背景 + +本次修复两个 BUG: + +### BUG-1:产品列表 productType 多值筛选失效(返回空) +- 前端传 `GET /admin/product/item/list?status=PUBLISHED&productType=CORE,GROUP` 时返回空 +- 实际测试环境 DB 有 9 条符合条件的产品 +- 根因:后端 VO 字段是 `String`,Spring 把 `"CORE,GROUP"` 当字面值绑定,SQL 变成 `WHERE product_type = 'CORE,GROUP'` → 零结果 +- **如果前端之前有 "只传单值 productType" 或"前端本地过滤多值" 的 workaround,现在可以删掉** + +### BUG-2:小蒙马(GROUP)产品上架预检 4 条过时/错误提示 +- `GET /admin/product/item/{id}/validate-publish` 对 GROUP 产品返回 4 条与实际配置不符的错误 +- 根因:代码未跟进需求变更,校验逻辑查了错的表 / 未按产品类型分流 +- **前端展示这些错误文案的弹窗/列表无需改动**,后端校验逻辑变严谨后这些错误自然消失 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 前端改动 | +|---|------|------|------|---------|---------| +| 1 | 产品列表 | GET | `/admin/product/item/list` | **Query 参数 `productType` 支持多值**(原单值) | 无需(原传法继续工作) | +| 2 | 产品下拉列表 | GET | `/admin/product/item/simple-list` | 同上 | 无需 | +| 3 | 产品上架预检 | GET | `/admin/product/item/{id}/validate-publish` | **行为修复**(响应结构不变) | 无需 | + +--- + +## 三、接口详情 + +### 1. `GET /admin/product/item/list` 和 `/simple-list` + +`productType` 参数从 **String** 变为 **List**,同时保持**向下兼容**,支持三种传参写法: + +| 写法 | 语义 | 后端解析结果 | +|------|------|-------------| +| `productType=CORE` | 单值 | `["CORE"]` → `WHERE product_type IN ('CORE')` | +| `productType=CORE,GROUP` | 逗号分隔 | `["CORE","GROUP"]` → `WHERE product_type IN ('CORE','GROUP')` | +| `productType=CORE&productType=GROUP` | 多值重复 key | `["CORE","GROUP"]` → `WHERE product_type IN ('CORE','GROUP')` | +| 不传 | 全部类型 | 无 productType 过滤条件 | + +Axios / fetch 默认行为下传 `params: { productType: 'CORE,GROUP' }` 或 `params: { productType: ['CORE', 'GROUP'] }` 都会被后端正确识别。 + +**前端实际修复效果**: +- 原:`?productType=CORE,GROUP` → `total: 0`(bug) +- 现:`?productType=CORE,GROUP` → `total: 9`(正确返回 CORE + GROUP 全部符合条件的产品) + +### 2. `GET /admin/product/item/{id}/validate-publish` + +**响应结构不变**,仅修复校验逻辑不再产生以下 4 条**已过时**的错误提示: + +| # | 不再出现的文案 | 修复说明 | +|---|---------------|---------| +| 1 | `订金支付方式(payment_type=DEPOSIT)必须配置尾款到期天数 balance_due_days` | 需求已取消,校验代码已删除 | +| 2 | `缺少酒店节点,订单详情住宿弹窗将为空` | v2 酒店独立到 `product_day_hotel` 表,校验改查这个表 | +| 3 | `缺少餐饮节点,订单详情餐饮弹窗将为空` | v2 餐饮写在 `product_itinerary_day.breakfast/lunch/dinner`,校验改扫描三餐字段 | +| 4 | `路线总览未配置实际用车车型(product_route_info.vehicle_model_id),订单用车弹窗将无法展示车型信息` | 小蒙马(GROUP)按 `vehicle_type` 自动匹配专用车,此校验仅对 CORE/CUSTOM 生效 | + +对**酒店/餐饮/车型仍然确实缺配置**的产品,新的校验会继续报错(以新的文案),前端展示无需调整。 + +保留/新增的典型错误文案参考: + +- `所有行程日餐饮均自理,订单详情餐饮弹窗将为空`(取代老的"缺少餐饮节点") +- `缺少酒店配置,订单详情住宿弹窗将为空`(取代老的"缺少酒店节点") + +--- + +## 四、前端行动项 + +1. **产品列表多值筛选**:如果前端有以下 workaround,可以移除: + - 前端循环调用 `productType=CORE` + `productType=GROUP` 再合并 + - 前端本地过滤(全量拉取后 `.filter`) + - 隐藏多选框强制单选 +2. **上架预检错误展示**:无需改动。测试环境验证小蒙马产品 `id=2044306857534636034` 现在点"发布"应该能直接上架。 +3. **其他产品类型**:CORE/CUSTOM 的上架预检行为**与此前完全一致**,车型校验仍生效。 + +--- + +## 五、测试环境已验证 + +```bash +# Bug 1 验证 +GET /admin/product/item/list?status=PUBLISHED&productType=CORE,GROUP +→ { code: 200, data: { total: 9, records: [...9 条...] } } + +# Bug 2 验证 +GET /admin/product/item/2044306857534636034/validate-publish +→ { code: 200, data: [] } +```