文件
hl-api-changelog/changelogs-v2/2026-09/18_7916_团期物资列表与候选补分类中文名categoryName-修改接口-管理后台.md
T
Mimingguang e6be4be31d
changelog-filename-gate / validate (push) Failing after 1s
docs(changelog): #7916 团期物资 categoryName 前端已实现并验证(hl-admin 08d13de3)
frontend_status pending→verified,frontend_ref=08d13de33b27948c31cb1e511ad59f342420e88c,
verified_at=2026-09-18,status_note 追加实现摘要。
2026-09-18 11:50:41 +08:00

15 KiB
原始文件 Blame 文件历史

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 7916 团期物资列表与候选列表出参新增分类中文名 categoryName(字典外取值按原值显示) admin jw(GIT) 修改接口 deployed verified verified mmg 08d13de33b27948c31cb1e511ad59f342420e88c 2026-09-18 团期物资列表 GET /v3/admin/order/group-batch/{groupBatchId}/supplies 与候选列表 .../supplies/candidates 出参各纯新增一个 categoryName;既有 category 原值一字不改,入参与错误码零变化。翻译三段回落:命中字典 supplies_category 的码译中文;值本身已是中文原样返回;字典外取值(TEST 存量的 EQUIPMENT / PROTECTION,共 140 行)按原值显示,不编造也不置空。字典 Feign 不可达时整批回落原值且接口仍 200(TEST 实测注入过)。后端已合并 dev-v3 并部署 TEST。[mmg 2026-09-18 已实现并验证] SuppliesPanel/SuppliesPickerModal 分类列由自查字典(getDictLabel||code)改显后端 categoryName(categoryName||category||'—'),SuppliesPanel 随删闲置 dictStore;筛选仍传 categoryCode 码、提交仍用 category 原值,categoryName 仅展示不分组不回传;SuppliesPanel.spec 加 categoryName 优先/回落断言,定向 7/7+checkpoint 全绿。 2026-09-18 dev-v3

团期物资: 列表与候选列表出参新增分类中文名 categoryName

服务: hl-order-service-v3 (端口 8086) PR: #7920 Issue: #7916 日期: 2026-09-18 影响范围: 管理后台团期详情「物资清单」与「从备品库选择」候选弹窗的分类列


⚠️ 关键变化

  • 本次两个接口的出参各纯新增一个 categoryName,既有 category 原值一字不改。
  • 前端以前可能以为:拿到 category 自己查字典 supplies_category 就能译出中文。这个做法译不出线上多数行——TEST 实测 order_batch_supplies.category 存量 442 行里有 140 行是字典里根本没有的 EQUIPMENT / PROTECTION,另有 301 行存的本来就是中文。
  • 实际现在是:后端按三段回落给出 categoryName,字典外的取值原样回传(显示出来仍是 EQUIPMENT),不是后端漏译,是该列的存量脏值,归一另列工单。

一、背景

order_batch_supplies.category 是下单时固化的快照,写入来源有三个且口径各异(产品备品中文与大写码混杂、备品库基本是字典码、管理员手工新增无校验),因此同一列并存三套词表。

维度 TEST 实测(2026-09-18,hl_order_service_v3)
中文标签(如 个人装备) 301 行
字典码(如 safety_protection) 1 行
字典外大写码 EQUIPMENT 70 行
字典外大写码 PROTECTION 70 行
字典 supplies_category 取值 8 项,全是小写码,无 EQUIPMENT / PROTECTION

二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 查询团期备品列表 GET /v3/admin/order/group-batch/{groupBatchId}/supplies 出参新增字段 每行新增 categoryName,category 不变
2 团期物资候选列表 GET /v3/admin/order/group-batch/{groupBatchId}/supplies/candidates 出参新增字段 每项新增 categoryName,与列表同一套翻译规则

三、接口详情

1. 查询团期备品列表 GET /v3/admin/order/group-batch/{groupBatchId}/supplies

VO: GroupBatchSuppliesRespVO

使用场景

管理后台团期详情页「物资清单」区域加载已固化/已手工追加的备品行;分类列改为显示 categoryName,排序、筛选、提交仍用 category 原值。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 雪花 ID 团期主订单 ID

出参 Result<List<GroupBatchSuppliesRespVO>>

字段 类型 说明
id String 备品行 ID(19 位雪花,字符串输出)
groupBatchId String 团期 ID
suppliesName String 备品名称
category String 分类原值(本次不变):可能是字典码、中文标签或字典外取值,可为 null
categoryName String 本次新增:分类展示名;category 为 null/空白时为 null
hasCost Boolean 是否计费
billingType String 计费方式 PER_PERSON / PER_QUANTITY
unitPrice String 单价
quantity Integer 数量
sortOrder Integer 排序号
remark String 备注

请求示例

GET /v3/admin/order/group-batch/2100509904627191810/supplies
Authorization: Bearer {admin-jwt}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    { "id": "2100509905000000001", "suppliesName": "团队识别手环1", "category": "个人装备", "categoryName": "个人装备", "quantity": 1 },
    { "id": "2100509905000000002", "suppliesName": "户外急救箱", "category": "safety_protection", "categoryName": "安全防护", "quantity": 1 }
  ],
  "success": true
}

空数据 / 降级响应

{ "code": 200, "message": "成功", "data": [], "success": true }

字典服务不可达时不降级整个接口,只是 categoryName 全批等于 category:

{
  "code": 200,
  "message": "成功",
  "data": [
    { "id": "2100509905000000002", "suppliesName": "户外急救箱", "category": "safety_protection", "categoryName": "safety_protection" }
  ],
  "success": true
}

错误响应

{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "success": false
}

业务边界

  • 鉴权:管理后台 JWT + 团期查看权限(GroupBatchPermissionGuard VIEW),未登录 401。
  • category 为 null 或纯空白 → categoryName 为 null,不是空串、不是字符串 "null"。
  • category 命中字典 → 中文标签;已是中文标签 → 原样返回;字典外取值 → 原样返回,后端不编造分类。
  • 只读接口,天然幂等;整页只加载一次字典,不按行调用。

2. 团期物资候选列表 GET /v3/admin/order/group-batch/{groupBatchId}/supplies/candidates

VO: SuppliesCandidateRespVO

使用场景

管理后台团期物资「从备品库选择」弹窗,列出资源域备品库中上架未软删的备品,并标出哪些已加入本团清单;分类列同样改用 categoryName。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 雪花 ID 团期主订单 ID
categoryCode Query String ❌ 字典 supplies_category 的值 按分类筛选,筛选仍用码,不用中文名
keyword Query String ❌ - 匹配名称或副标题

出参 Result<List<SuppliesCandidateRespVO>>

字段 类型 说明
suppliesId String 备品库 ID
suppliesName String 备品名称
subtitle String 副标题
category String 分类码原值(本次不变),来自备品库 category_code
categoryName String 本次新增:分类展示名,规则与列表接口完全一致
billingType String 计费方式(已归一为 PER_PERSON / PER_QUANTITY)
hasCost Boolean 是否计费
unitPrice String 单价
selected Boolean 是否已加入本团清单

请求示例

GET /v3/admin/order/group-batch/2099919772194836482/supplies/candidates?categoryCode=camping_equipment
Authorization: Bearer {admin-jwt}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    { "suppliesId": "2074063318837792770", "suppliesName": "折叠桌椅套装", "category": "camping_equipment", "categoryName": "露营设备" },
    { "suppliesId": "2074063318837792771", "suppliesName": "对讲机", "category": "electronics", "categoryName": "电子设备" }
  ],
  "success": true
}

空数据 / 降级响应

资源域备品库不可达或无候选时返回空数组,不 500:

{ "code": 200, "message": "成功", "data": [], "success": true }

错误响应

{
  "code": 589500,
  "message": "团期不存在",
  "data": null,
  "success": false
}

业务边界

  • 鉴权同列表接口(VIEW 权限)。
  • categoryCode 筛选只认字典码,传中文名筛不出结果。
  • 备品库里存在字典外的 category_code(TEST 现存 1 条 TENT,已下架)→ categoryName 回传 TENT。
  • 只读接口,整页只加载一次字典。

四、契约约束与正确调用方式(接口类必写)

本节只写后端返回值的契约,不写 UI 渲染建议。

场景 category categoryName
✅ 字典码 safety_protection 安全防护
✅ 存量中文 个人装备 个人装备
✅ 字典外取值 EQUIPMENT EQUIPMENT(原值,非空、非 null)
✅ 空分类 null null
✅ 字典不可达 safety_protection safety_protection(整批回落)

调用方必须注意

  • 写入与筛选一律用 category / categoryCode 原值,categoryName 只用于展示,不要拿它回传给任何写接口。
  • 不要假设 categoryName 一定是中文:字典外取值原样回传,这是刻意的(编造分类比显示英文码更有害)。
  • 不要用 categoryName 做分组键:同一分类可能因存量三套词表而出现 个人装备 与 personal_gear 两个不同的 category,却都展示成「个人装备」。分组仍应按 category。

五、数据库行为

零变更:本次无 Flyway 迁移,不新增/修改任何表与列。categoryName 是读取时按数据字典翻译出来的派生展示字段,不落库;order_batch_supplies.category 只读不写,存量脏值不回填。


六、边界行为

  • 未登录 → 401(网关拦截)
  • 无团期查看权限 → 权限守卫拒绝
  • 团期不存在 → 589500
  • 字典服务降级 → categoryName 全批等于 category,接口仍 200,不阻断页面
  • 老数据兼容 → category 为 null 的历史行 → categoryName 为 null,不异常

六.5、枚举 / 数据字典

categoryName 的取值来源(数据字典 supplies_category)

所属字段: GroupBatchSuppliesRespVO.categoryName / SuppliesCandidateRespVO.categoryName | 类型: String

值 中文 说明
personal_gear 个人装备 字典项
camping_equipment 露营设备 字典项
riding_gear 骑行装备 字典项
electronics 电子设备 字典项
safety_protection 安全防护 字典项
entertainment 娱乐器材 字典项
warmth_gear 保暖装备 字典项
vehicle_accessories 车载装备 字典项
EQUIPMENT / PROTECTION / TENT (无) 不在字典内的存量取值,原样回传

六.6、修改前后对比

字段级对比

字段 改前 改后
GroupBatchSuppliesRespVO.category 分类原值 不变
GroupBatchSuppliesRespVO.categoryName 不存在 新增,三段回落的展示名,可为 null
SuppliesCandidateRespVO.category 分类码原值 不变
SuppliesCandidateRespVO.categoryName 不存在 新增,同一套规则

行为级对比

行为 改前 改后
前端显示分类中文 需自查字典,且线上多数行查不到 直接用 categoryName
字典服务不可达 与本字段无关 接口仍 200,categoryName 整批等于 category
字典查询次数 — 每次请求整页一次,不按行调用
入参 / 错误码 — 零变化

六.7、影响评估

  • 是否破坏向后兼容: 否(纯新增出参字段,既有字段与错误码零变化)
  • 前端是否必须同步上线: 否(不接入则与现状一致)
  • 前端 workaround 清理点: 前端若已有「按 category 自查字典译中文」的逻辑,可改用 categoryName;但不要顺手把字典外取值改成显示空白,那是存量脏值,另有工单归一。

七、不影响范围

  • 仅影响: 管理后台团期物资清单、团期物资候选弹窗两个只读接口的出参
  • 零影响:
    • 小程序端备品清单与其分组接口(本次未改)
    • 物资新增 / 改数量 / 软删 / 确认物资等写接口(取值域未收紧,手工新增仍可自由填)
    • 终止退款链路取备品行的内部调用(刻意不走翻译,避免在写事务内发跨服务字典调用)
    • 数据库(零 Flyway、存量不回填)

八、测试环境已验证

部署:dev-v3@a18569162(合并 PR #7920 后)部署至 TEST,hl-order-service-v3 双实例滚动完成。

GET /v3/admin/order/group-batch/2100509904627191810/supplies
  → 200;category=个人装备 → categoryName=个人装备 ✓(存量中文原样)
  → 200;category=safety_protection → categoryName=安全防护 ✓(字典码译中文)

GET /v3/admin/order/group-batch/2099463556951941122/supplies
  → 200;category=EQUIPMENT → categoryName=EQUIPMENT ✓(字典外原值)
  → 200;category=PROTECTION → categoryName=PROTECTION ✓

GET /v3/admin/order/group-batch/2099919772194836482/supplies/candidates
  → 200;15 项全部带 categoryName,personal_gear→个人装备、camping_equipment→露营设备 ✓

category 为空的行(临时夹具,取证后已删)
  → 200;category=null → categoryName=null ✓(非空串、非 "null")

字典不可达注入(临时改 sys_dict_type.dict_type 使 supplies_category 查不到,重启后冷缓存)
  → 列表 200;safety_protection → safety_protection ✓(整批回落原值)
  → 候选 200;personal_gear → personal_gear、camping_equipment → camping_equipment ✓
  → 还原字典后翻译恢复 ✓

验证团期: 2100509904627191810(三段全覆盖)、2099463556951941122(字典外取值)、2099919772194836482(候选列表)


十、相关文档

  • 关联 Issue: wx/HL#7916
  • 关联 PR: wx/HL#7920
  • 同类先例(子订单 roomTypeName): 见 changelogs-v2/2026-09/14_7536_*

关联 / 联系人

链接

联系人

  • 后端负责人: @jw