From 30e337b920c083095ad8f073cdc5da022163a023 Mon Sep 17 00:00:00 2001 From: API Changelog Bot Date: Fri, 17 Apr 2026 19:17:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=A7=E5=93=81=E6=9C=8D=E5=8A=A1=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=8F=90=E7=A4=BA=E6=89=B9=E9=87=8F=E4=BA=BA=E6=80=A7?= =?UTF-8?q?=E5=8C=96=20(=E5=8E=BB=E8=8B=B1=E6=96=87=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E7=A0=81+=E5=8E=BB=E5=86=85=E9=83=A8ID)=20-=20PR=20#765?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...04-17_product-v2-error-message-humanize.md | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 changelogs/2026-04/2026-04-17_product-v2-error-message-humanize.md diff --git a/changelogs/2026-04/2026-04-17_product-v2-error-message-humanize.md b/changelogs/2026-04/2026-04-17_product-v2-error-message-humanize.md new file mode 100644 index 0000000..f29d750 --- /dev/null +++ b/changelogs/2026-04/2026-04-17_product-v2-error-message-humanize.md @@ -0,0 +1,159 @@ +# 文案优化:产品服务错误提示批量人性化(去英文状态码/去内部ID) + +> **服务**: hl-product-service-v2 (端口 8083) +> **PR**: #765 +> **Issue**: #764 +> **日期**: 2026-04-17 +> **影响范围**: 管理端产品删除/编辑/价格配置/班期管理 + 小程序端报价/库存扣减/报名 的错误提示文案 +> **前置 PR**: #762(2026-04-17_refund-policy-error-message-humanize.md) + +--- + +## 背景 + +延续 #762 的思路,对 `hl-product-service-v2` 里其他对用户可见的 `BusinessException` / `NotFoundException` 文案做一轮批量改造,避免向普通运营展示: + +1. **英文状态码**(`PUBLISHED` / `PENDING_REVIEW` / `DRAFT` 等) +2. **内部主键 ID**(`productId=2045018xxx` / `batchId=xxx` 等) +3. **开发术语**(如"调用此接口") + +技术 ID 全部下沉到 `log.warn` 供后端排查,不再污染用户 toast。 + +## 改动范围 + +**只改异常消息文案与服务端日志**,校验规则、接口签名、返回结构、HTTP code 全部不变。 +前端**无需改造**,toast 显示新文案即可。 + +--- + +## 文案前后对照 + +### 产品删除/编辑状态校验 + +| 场景 | 旧文案 | 新文案 | +|------|--------|--------| +| 已上架产品删除 | `当前状态不允许删除: PUBLISHED` | `当前状态「已上架」不允许删除` | +| 已下单产品编辑 | `当前状态不允许编辑: ORDERED` | `当前状态「已下单」不允许编辑` | +| 待审核产品编辑 | `当前状态不允许编辑: PENDING_REVIEW` | `当前状态「待审核」不允许编辑` | + +状态码→中文映射表(通过新增的 `ProductStatusEnum.nameOfOrCode` 容错方法): + +| code | 中文 | +|------|------| +| DRAFT | 草稿 | +| PENDING_REVIEW | 待审核 | +| PUBLISHED | 已上架 | +| UNPUBLISHED | 已下架 | +| REJECTED | 已驳回 | +| COMPLETED | 已完成 | +| ORDERED | 已下单 | +| `null` / 空 | 未知 | +| 未知值 | 原值回显(降级) | + +### 价格日历/成人售价 + +| 场景 | 旧文案 | 新文案 | +|------|--------|--------| +| 价格日历缺失 | `日期 xxx 档位1 未设置价格日历(产品ID=2045018xxx)` | `日期 xxx 档位1 未设置价格日历,请先配置价格` | +| 成人售价未设置 | `日期 xxx 档位1 的成人售价未设置(产品ID=2045018xxx)` | `日期 xxx 档位1 的成人售价未设置,请先配置价格` | + +### 班期管理 + +| 场景 | 旧文案 | 新文案 | +|------|--------|--------| +| 班期不存在(查询/删除/修改/取消/配员) | `班期不存在: 20450185xxx` | `班期不存在或已删除` | + +### 库存与报名(InternalProductService,被 order-service-v2 Feign 调用) + +| 场景 | 旧文案 | 新文案 | +|------|--------|--------| +| 库存扣减失败 | `库存不足或日期不存在, productId=xxx, date=2026-05-10` | `该日期库存不足或未开放,请重新选择出发日期` | +| 报名入团失败 | `报名失败(名额不足或房间不足), batchId=xxx` | `报名失败,该班期剩余名额或房间不足` | +| 非定制产品调用 | `仅定制产品可调用此接口, productId=xxx` | `该操作仅支持定制类产品` | + +--- + +## 接口影响(均无签名变化) + +| 接口 | 变化 | +|------|------| +| `DELETE /admin/product/item/{id}` | 错误 `message` 文案变更 | +| `PUT /admin/product/item/{id}/*`(所有编辑类接口) | 状态拒绝文案变更 | +| `POST /admin/product/price-calendar/batch` | 价格相关文案变更 | +| `POST/PUT/DELETE /admin/product/schedule/*` | 班期不存在文案变更 | +| `POST /admin/product/schedule/team/*` | 班期不存在文案变更 | +| `POST /internal/product/simple-quote` | 成人售价文案变更 | +| `POST /internal/product/deduct-stock` | 库存扣减失败文案变更 | +| `POST /internal/product/enroll-batch` | 报名失败文案变更 | +| `POST /internal/product/custom/change-status` | 非定制产品文案变更 | + +HTTP 状态码、`code`、JSON 结构均保持原样。 + +--- + +## 保留未改的文案 + +以下文案**主动保留**,因为它们不属于"不友好"范畴: + +1. **公式编辑器**(FormulaGroupService / FormulaStepService / FormulaVarService) + - 例如:`公式组编码已存在: {code}` / `变量名已存在: {name}` + - 原因:公式编辑功能的使用者是技术人员,编码本身就是用户自己输入的值,回显是必要上下文 +2. **纯中文/数字约束类** + - `请填写【轻奢】正价的成人售价` — 档位名+价格类型 label 均为中文 + - `档位序号99不存在,本产品只有5档` — 数字是必要定位信息 + - `该班期已有3个报名订单,不允许删除` — 数字为必要业务信息 + - `批量创建跨度不能超过12个月` + - `小童优惠额不能超过儿童售价` + +--- + +## 排查信息的去向 + +所有移除的 ID/代码都下沉到 `log.warn`,后端排查时通过日志+时间戳即可定位: + +``` +WARN ProductDeleteService - 产品当前状态不允许删除: productId=1001, status=PUBLISHED +WARN ProductHelperService - 产品当前状态不允许编辑: productId=1001, status=ORDERED +WARN ProductPricingService - 价格日历未设置: productId=1001, date=2026-05-10, tierSeq=1 +WARN ProductPricingService - 成人售价未设置: productId=1001, date=2026-05-10, tierSeq=1 +WARN ProductPricingService - 班期不存在(删除): productId=1001, batchId=8001 +WARN GroupBatchStaffService - 班期不存在(操作员工): productId=1001, batchId=8001 +WARN InternalProductService - 库存扣减失败: productId=1001, date=2026-05-10, count=2 +WARN InternalProductService - 报名入团失败: batchId=8001, people=2, rooms=1 +WARN InternalProductService - 非定制产品调用定制产品状态变更: productId=1001, productType=CORE +``` + +--- + +## 前端适配建议 + +- **无需改代码**:直接显示后端返回 `message` 即可 +- 如果之前对 error message 做过字符串匹配/正则提取 `productId=...`、`batchId=...`、英文状态码等,需要移除相关逻辑 —— 新消息不含这些 +- 状态码中文展示(如果前端自己有映射表)可以沿用本 changelog 顶部的对照表 + +--- + +## 单元测试 + +- `ProductStatusEnumTest` — 新增 3 个用例(合法/null/未知),共 11 个全部通过 +- `ProductHelperServiceTest` — 强化「checkEditable PUBLISHED/PENDING_REVIEW」用例断言:必须含中文状态名、必须不含英文码 +- `ProductDeleteServiceTest` — 强化「deleteProduct PUBLISHED」用例断言:必须含「已上架」、必须不含 `PUBLISHED` +- `GroupBatchStaffServiceTest` — 强化「queryTeam 班期不存在」用例断言:必须含「班期不存在或已删除」、必须不含 batchId +- 受影响测试合计 98/98 通过(覆盖 7 个测试类) + +--- + +## 部署 + +- 仅需重启 `hl-product-service-v2`(端口 8083 + 8183) +- 无 DDL 变更 +- 无配置变更 + +--- + +## 向后兼容性 + +- ✅ 接口签名、响应结构、HTTP code 完全不变 +- ✅ 前端可不改代码直接升级 +- ✅ `ProductStatusEnum.nameOfOrCode` 容错降级(未知状态码原值回显,新状态加入枚举前不会挂) +- ⚠️ 如果前端之前解析过错误消息中的 `productId=` / `batchId=` / 英文状态码,需要移除相关逻辑