hl-api-changelog/changelogs/2026-04/2026-04-17_product-v2-error-message-humanize.md

6.9 KiB

文案优化:产品服务错误提示批量人性化(去英文状态码/去内部ID

服务: hl-product-service-v2 (端口 8083) PR: #765 Issue: #764 日期: 2026-04-17 影响范围: 管理端产品删除/编辑/价格配置/班期管理 + 小程序端报价/库存扣减/报名 的错误提示文案 前置 PR: #7622026-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= / 英文状态码,需要移除相关逻辑