23 KiB
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 | 8252 | 订单列表新增团期关键词筛选,团单行新增团期名与期次展示字段 | admin | wx(GIT) | 修改接口 | deployed | verified | verified | mmg | 5f27c0094745c60cde7de866bb3450eee61fd91d | 2026-09-23 | GET /v3/admin/order 新增入参 groupBatchKeyword(长度上限 64),出参 OrderListItemRespVO 新增 groupBatchName 与 groupBatchLabel。前端需在订单列表增加团期关键词筛选,并在团单行产品名后渲染「第N期 团期名」,故 frontend_status 记 pending。前端已交付(2026-09-23):列表头新增「团期」关键词输入框原样透传 groupBatchKeyword(maxlength 64 输入侧截断;清空省略=不传;六页签计数同口径透传);ProductCell 产品名后渲染「第N期 团期名」,label/name 逐段 trim 判空省略、全空整行不渲染,判团单仍用 groupOrder/groupBatchId。新建 spec 8 例+存量 6 例回归全绿,checkpoint 全量含生产构建通过。 | 2026-09-23 | dev-v3 |
订单列表团期筛选与团单行团期展示(管理后台)
服务: hl-order-service-v3 PR: #8261 Issue: #8252 日期: 2026-09-23 合并提交: b6e84bdd9 影响范围: 管理后台订单列表的筛选条件(新增团期关键词)与团单行展示(新增团期名 + 期次)
一、接口背景
订单列表原本只支持按 groupBatchId 筛团期,而那是 19 位雪花 ID:运营在团期看板上看到的是「第3期 10月8日出发团」这样的文案,
记不住、也没法粘贴到订单列表去筛。团期看板自己支持按团期名 / 期次搜索,订单列表不支持,同一句话在两个页面搜出不同结果。
本次给订单列表补上同样口径的团期关键词筛选,并把团期名与期次直接补到团单行上,运营从看板跳到订单列表后能直接看到自己在看哪个团期。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 管理后台订单列表 | GET | /v3/admin/order |
修改接口 | 入参新增 groupBatchKeyword;出参 OrderListItemRespVO 新增 groupBatchName 与 groupBatchLabel;其余入参、其余出参、权限码、错误码均未变 |
同一个 Controller 方法同时挂载集合根与
/v3/admin/order/list两条路径(@GetMapping({"", "/list"})), 两个地址的入参、出参、错误码、数据权限完全一致,本条目统称「订单列表接口」。
三、接口详情
1. 管理后台订单列表 GET /v3/admin/order
VO: OrderListItemRespVO
使用场景
管理后台「订单管理」列表页:首次进入、翻页、切换六个页签、修改任意筛选项时调用。
本次与该页相关的两件事:列表头部新增「团期」关键词输入框(按团期名 / 期次 / 团号搜)。
团单行的产品名后面渲染「第N期 团期名」,数据由本接口出参的 groupBatchName 与 groupBatchLabel 提供。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchKeyword | Query | String | 否 | 长度 ≤64;全角空格与 NBSP 归一后为空串等同不传;groupBatchId 非空时本参数被忽略 | 本次新增。团期关键词:按「团号模糊 ∪ 团期名模糊 ∪ 期次精确」解析出命中的团期后,只返回挂在这些团期下的订单。支持照抄页面渲染的文案,如 第3期 10月8日出发团。非空时强制按团单口径筛(等价于 orderKind=GROUP) |
| groupBatchId | Query | Long | 否 | 19 位正整数 | 运营团期 ID(既有字段,本次未改)。非空时本参数优先:groupBatchKeyword 被忽略,且强制按团单口径筛 |
| orderKind | Query | String | 否 | ALL / GROUP / NORMAL;缺省 NORMAL | 订单归属类型(既有字段,本次未改)。传了 groupBatchId 或非空 groupBatchKeyword 时,本参数被后端的团期口径覆盖为 GROUP |
| pageNo | Query | Integer | 否 | ≥1,缺省 1 | 页码(既有字段)。等价别名 page,两者写哪个都生效 |
| pageSize | Query | Integer | 否 | 1~100,缺省 20 | 每页条数(既有字段) |
| statusGroup | Query | String | 否 | ALL / BEFORE_TRIP / ON_TRIP / SETTLEMENT / ABNORMAL / AFTERSALE | 页签分组(既有字段)。与 orderStatus 下拉为 AND 关系 |
| orderStatus | Query | String | 否 | PENDING_PAY / CUSTOMIZING / PENDING_DEPARTURE / TRAVELLING / COMPLETED / CANCELLED,多值用逗号 | 粗状态过滤(既有字段) |
| flowStatus | Query | String | 否 | 细状态枚举,多值用逗号 | 细状态过滤(既有字段) |
| keyword | Query | String | 否 | 无 | 通用关键词:团号 / 客户姓名 / 产品名 / 订单号 任一 LIKE(既有字段,与本次的团期关键词是两个独立参数) |
| tagNames | Query | List<String> | 否 | 多标签 OR,任一命中即返 | 标签过滤(既有字段) |
| consultantName | Query | String | 否 | LIKE 匹配 | 定制师姓名(既有字段) |
| departureDateFrom | Query | Date | 否 | yyyy-MM-dd | 出发日期区间起(既有字段) |
| departureDateTo | Query | Date | 否 | yyyy-MM-dd,早于起日返 100001 | 出发日期区间止(既有字段) |
| createSource | Query | String | 否 | CONSULTANT / CUSTOMER / 其他来源枚举 | 订单来源过滤(既有字段) |
| cancelled | Query | Boolean | 否 | 缺省 false | 是否包含已取消订单(既有字段) |
出参 Result<PageResult<OrderListItemRespVO>>
| 字段 | 类型 | 说明 |
|---|---|---|
| records | Array | 订单行列表,元素结构见下方「行内字段」 |
| total | Integer | 命中总条数(不受 pageSize 影响) |
| page | Integer | 当前页码 |
| pageSize | Integer | 每页条数 |
| records[].groupBatchName | String | 本次新增。团期名称快照(取自下方「业务边界」所述的下单时快照口径)。非团单与团期已软删(解散)两种情况均为 null,不返空串 |
| records[].groupBatchLabel | String | 本次新增。期次序号裸数字串,如 "3",不含「第」「期」二字,由前端拼成「第3期」。存量未刷新快照的团期可能为 null |
| records[].groupBatchId | Long | 既有字段,本次未改。运营团期 ID(JSON 中为字符串)。非空即团单,这是判别团单的唯一依据 |
| records[].groupOrder | Boolean | 既有字段,本次未改。是否团单,与 groupBatchId 同源(groupBatchId != null 的派生值) |
| records[].productName | String | 既有字段,本次未改。产品名快照。「第N期 团期名」渲染在产品名之后 |
| records[].orderNo | String | 既有字段,本次未改。订单号(创单瞬间生成,永不变) |
| records[].id | Long | 既有字段,本次未改。订单 ID(JSON 中为字符串) |
| records[].customerName | String | 既有字段,本次未改。客户姓名 |
| records[].departureDate | Date | 既有字段,本次未改。出发日,未定日期时为 null |
| records[].orderStatus / orderStatusName | String | 既有字段,本次未改。粗状态枚举值与中文名 |
| records[].flowStatus / flowStatusName | String | 既有字段,本次未改。细状态枚举值与中文名 |
| records[].totalAmount / payableAmount / paidAmount / refundAmount / balanceAmount | BigDecimal | 既有字段,本次未改。金额在 JSON 中为字符串 |
| records[].consultantName | String | 既有字段,本次未改。定制师姓名 |
单行 VO 本次从 44 个字段变为 46 个:新增
groupBatchName、groupBatchLabel,其余 44 个字段逐字未变。
请求示例
GET /v3/admin/order?pageNo=1&pageSize=20&orderKind=ALL&groupBatchKeyword=%E7%AC%AC3%E6%9C%9F+10%E6%9C%888%E6%97%A5%E5%87%BA%E5%8F%91%E5%9B%A2 HTTP/1.1
Host: api.test.1814.love
Authorization: Bearer <admin token>
Accept: application/json
# 无请求体。
# 关键词解码后为「第3期 10月8日出发团」;等价别名地址:GET /v3/admin/order/list(参数与响应逐字一致)。
# 只按团期名筛:GET /v3/admin/order?pageNo=1&pageSize=20&groupBatchKeyword=%E4%BA%91%E5%8D%97
响应示例
{
"code": 200,
"message": "成功",
"data": {
"records": [
{
"id": "2102309919002943489",
"orderNo": "HL20260922161158291",
"teamNo": "26-2355",
"productName": "王骁测试团期产品",
"productType": "GROUP",
"productTypeName": "小蒙马",
"productCoverImg": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/test/material/2026/03/07/ed278d1da74c3827cb06b7f0cf6091fe.jpg",
"tierName": "轻奢",
"customerName": "王二麻子",
"customerPhoneMasked": "185****0000",
"peopleSummary": "4 大",
"departureDate": "2026-10-08",
"tripDays": 3,
"tripNights": 2,
"orderStatus": "CUSTOMIZING",
"orderStatusName": "定制中",
"flowStatus": "AWAITING_PROFILE",
"flowStatusName": "待补全信息",
"flowStep": 1,
"flowStepTotal": 6,
"flowStepCode": "PROFILE",
"flowStepName": "补全信息",
"currentSubFlows": null,
"totalAmount": "15920.00",
"payableAmount": "15920.00",
"paidAmount": "2000.00",
"refundAmount": "0.00",
"balanceAmount": "13920.00",
"consultantName": "刘畅",
"createSource": "CONSULTANT",
"createSourceLabel": "定制师创建",
"tags": [],
"createdAt": "2026-09-22 16:11:58",
"depositAmount": "2000.00",
"depositRatio": null,
"paymentMode": "DEPOSIT",
"singleRoomSurcharge": "0.00",
"agencyId": "2051922156798779394",
"refundPolicyId": "2047249965792579585",
"productSubtitle": "发短信给对方搞定",
"aftersaleStatus": "NONE",
"aftersaleStatusName": "无售后",
"groupBatchId": "2100856430494973953",
"groupOrder": true,
"groupBatchName": "10月8日出发团",
"groupBatchLabel": "3"
}
],
"total": 2,
"page": 1,
"pageSize": 5
},
"traceId": null,
"success": true
}
空数据 / 降级响应
两种空值形态语义不同,前端要分别处理。
其一:关键词没有任何命中团期时,接口返 200 与空页(records: []、total: 0),同时六个页签的计数一并归零——列表数字与页签数字不会各说各话。
{
"code": 200,
"message": "成功",
"data": {
"records": [],
"total": 0,
"page": 1,
"pageSize": 5
},
"traceId": null,
"success": true
}
其二:行本身存在,但该行拿不到团期信息。非团单行、以及团期已软删(解散)的团单行,groupBatchName 与 groupBatchLabel 都是 null(不是空串)。
{
"code": 200,
"message": "成功",
"data": {
"records": [
{
"id": "2097270761474469890",
"orderNo": "HL20260908182809530",
"productName": "测试小蒙马-多档-固定金额",
"orderStatus": "CUSTOMIZING",
"groupBatchId": "2097270759599616002",
"groupOrder": true,
"groupBatchName": null,
"groupBatchLabel": null
}
],
"total": 3,
"page": 1,
"pageSize": 5
},
"traceId": null,
"success": true
}
错误响应
{
"code": 100001,
"message": "团期关键词长度不能超过 64",
"data": null,
"traceId": null,
"success": false
}
| 错误码 | 触发条件 |
|---|---|
| 100001 | groupBatchKeyword 超过 64 个字符(注意:不是 HTTP 400,是业务码 100001,HTTP 状态仍为 200) |
| 100001 | groupBatchId 传了非数字(既有行为,本次未改) |
| 100001 | pageNo 小于 1、pageSize 超出 1~100、orderKind 传非法值、出发日区间倒置 |
| 401 | 未登录(网关拦截) |
| 403 | 缺少管理端订单列表访问权限 |
业务边界
- 团期名与期次都取自 order 侧快照:
groupBatchName/groupBatchLabel读的是订单侧记录的团期快照,而团期看板展示的是 product 侧实时重算值;快照只在该团期有新订单进入时刷新,两者可能不一致。这是两个页面各自的既定口径,不是本接口的缺陷。 groupBatchLabel可能为 null:存量未刷新的团期拿不到期次,此时只渲染团期名,不得渲染「第null期」「第期」。groupBatchName同理,为 null 时整段不渲染。- 非团单与「团期已软删(解散)」两种情况下两字段均为 null(不是空串);若团期名本身是空字符串的脏数据,则返回
"",前端需按空文案处理而不是渲染出「第N期 」这样带空格残缺文案。 - 软删团期的历史订单仍能按团单筛出来(
groupOrder=true、groupBatchId非空),只是团期名与期次为 null——这是既定行为,前端不要据此把行判成普通订单。 - 本接口的
groupBatchName是团期名快照,与下单接口(订单创建响应)里那个恒为 null 的groupBatchName不是同一个语义,不要把两个接口的字段名合并成同一个前端模型复用。 - 关键词口径与团期看板一致:团号 LIKE ∪ 团期名 LIKE ∪ 期次精确匹配,且支持「第3期 云南」这类复合输入(期次精确 AND 名称/团号模糊)。期次是精确匹配,「第1期」不会连带命中第 10、11、21 期。
- 命中团期超过 500 个时结果被截断(只取前 500 个团期对应的订单),属公开的失败模式:关键词过宽时 total 会偏小。
- 命中为空时返回空页且六个页签计数同步为 0;不传
groupBatchKeyword时,本接口行为与本次改动前完全一致(含只传一个全角空格或 NBSP 的情况,逐项等同不传)。 - 权限码零变化:定制师等非管理员角色仍只看本人名下订单,权限口径与本次改动前逐字一致,访问本接口不会出现 589507。
- 已知差异(契约边界):某些团期名本身形如「3期特惠」时,团期看板按整串匹配,而订单列表会把它解析成「期次 3 + 名称 特惠」,因此同一个输入在两个页面可能给出不同结果。
四、契约约束与正确调用方式
✅ 正确 / ❌ 错误 payload 对照
| 场景 | 查询串 |
|---|---|
| ✅ 按团期名筛 | groupBatchKeyword=10月8日出发团,返回挂在该团期下的订单 |
| ✅ 按期次筛 | groupBatchKeyword=第3期,期次精确匹配,不含第 10、11、21 期 |
| ✅ 复合输入(照抄页面文案) | groupBatchKeyword=第3期 云南深度8日,拆成「期次 = 3」且「名称含 云南深度8日」 |
| ✅ 只填一个全角空格 | groupBatchKeyword=%E3%80%80,等同于不传,行为与改动前逐项一致 |
| ✅ 精确跳转(从团期看板带 ID 跳过来) | groupBatchId=2100856430494973953 |
| ❌ 两个参数都传且互不匹配 | groupBatchId=<团期ID>&groupBatchKeyword=不存在的团期名 → 以 ID 为准,关键词被忽略 |
| ❌ 关键词超过 64 字符 | 65 个字符 → 100001「团期关键词长度不能超过 64」 |
| ❌ 把期次写成中文数字 | groupBatchKeyword=第三期 → 不是期次形态,按团期名/团号整串模糊匹配,通常零命中 |
前端渲染规则
- 团单行文案 = 产品名 + 「第{groupBatchLabel}期 {groupBatchName}」,任一段为 null 或空串时该段整段省略,不要留下多余空格。
- 判断一行是不是团单请继续读
groupOrder/groupBatchId,不要用groupBatchName != null反推(软删团期的团单两字段为 null)。 - 筛选框可以同时展示「团期名」与「第N期」两种写法;提交时把用户输入原样传给
groupBatchKeyword即可,后端负责解析。 - 筛选框在提交前建议做一次前端长度校验(≤64),避免让用户提交后只拿到一个 100001。
五、数据库行为
零数据库变更。本次不新增表、列、索引或数据迁移,也不写入任何数据:
groupBatchKeyword 的匹配是对既有团期数据的只读查询,出参两字段是对既有订单侧快照的只读回填,整页一次批量查询,不产生写操作。
六、边界行为
- 未登录 → 401(网关拦截)。
- 无管理端权限 → 403。
groupBatchKeyword超过 64 字符 → 业务码 100001,HTTP 状态仍是 200。groupBatchId传非数字 → 业务码 100001(既有行为)。- 关键词无命中团期 → 200 + 空页,且六个页签计数全为 0。
- 班期 / 团期数据在 order 侧无快照(非团单、软删团期)→ 两个新字段为 null,不返空串。
- 团期名本身是空字符串的脏数据 → 返回
""。 - 排期区间倒置(departureDateFrom > departureDateTo)→ 100001。
- pageSize 超过 100 → 100001。
六.6、修改前后对比
字段级对比
| 字段 | 改前 | 改后 |
|---|---|---|
OrderListReqVO.groupBatchKeyword |
不存在 | 新增,String,≤64,Query 参数 |
OrderListItemRespVO.groupBatchName |
不存在(前端取到 undefined) | 返回团期名快照;非团单 / 软删团期为 null |
OrderListItemRespVO.groupBatchLabel |
不存在(前端取到 undefined) | 返回期次裸数字串,如 "3";存量未刷新快照为 null |
| 单行 VO 字段数 | 44 | 46 |
| 其余 44 个出参字段 | — | 逐字未变 |
| 其余 15 个入参字段 | — | 逐字未变(新增参数是新增项,不改既有字段语义) |
行为级对比
| 行为 | 改前 | 改后 |
|---|---|---|
| 按团期名 / 期次筛选 | 不支持,只能传 19 位 groupBatchId | 新增 groupBatchKeyword,口径与团期看板一致 |
| 期次匹配方式 | — | 期次精确匹配(第1期不命中第 10、11、21 期) |
| 两个团期参数同传 | 不存在第二个参数 | 以 groupBatchId 为准,关键词被忽略 |
| 空白关键词 | — | 归一后为空等同于不传,行为与改动前逐项一致 |
| 关键词无命中 | — | 空页 + 六页签计数全 0 |
| 团单行展示 | 只有 groupBatchId / groupOrder | 追加 groupBatchName / groupBatchLabel 供渲染「第N期 团期名」 |
| 权限码 / 数据权限 | 仅 ADMIN / SUPER_ADMIN 看全量,其余角色只看本人订单 | 逐字未变 |
六.7、影响评估
- 是否破坏向后兼容:否。入参是新增的可选参数,出参是新增的可选字段;不传关键词、不读新字段的老调用方行为逐字未变。
- 前端是否必须同步上线:否,但需要适配:列表要加团期关键词筛选入口,团单行要渲染团期名 + 期次。老前端不改也不会报错,只是看不到本次的两个能力。
- 性能:团期关键词的匹配落在团期名 / 期次的模糊查询上,命中团期条数有 500 的上限,超过即截断;订单侧仍是既有的分页查询,团期名与期次按页一次批量回填,不会按行查询。
- 前端 workaround 清理点:若前端此前为了显示团期名而在列表页额外调用团期接口或按 groupBatchId 反查,可改用本接口的两个新字段;无此类逻辑则无需改动。
- 回滚:撤销 PR #8261 即可,无数据、无迁移、无配置残留。
- 未覆盖:本次只证明后端契约可用。页面上的筛选框与团期文案是否落位属前端实现侧;两个页面对同一输入的差异见「业务边界」末条。
七、不影响范围
- 仅影响:管理后台订单列表(筛选条件 + 团单行字段)。
- 零影响:
- 团期看板的搜索口径与命中结果(本次只新增解析口,未改看板既有语义)
- 订单详情的团期四字段(batchNo / batchName / groupBatchStatus / groupBatchId)
- 下单接口(订单创建响应)的同名字段
- 六个页签计数的计算口径(关键词无命中时同步归零属既定一致行为)
- 权限码与数据权限收缩逻辑
- 小程序端:本接口仅管理后台使用,未涉及
八、测试环境已验证
部署:hl-order-service-v3 dev-v3 @ b6e84bdd9(PR #8261 合并提交),2026-09-23 16:23~16:24 滚动部署完成,两实例健康。
验证入口:https://api.test.1814.love(经网关调用,非直连服务端口)。
自动化验收脚本 19 项全部 PASS,摘要如下:
| 用例 | 场景 | 结果 |
|---|---|---|
| AC-1 | 按团期名 10月8日出发团 筛 |
200,total=2,两行 groupBatchName 均为「10月8日出发团」 |
| AC-2 | 按期次 第3期 筛 |
200,total=2,命中期次集合 = ['3'](精确,不含 10 / 13 / 23 / 30) |
| AC-3 | 按期次 第1期 筛 |
200,total=13,命中期次集合 = ['1'](不含 10 / 11 / 21) |
| AC-4 | 裸数字 3 筛 |
200,total=406;第3期的 2 单是其中子集 |
| AC-5 | 复合输入 第3期 10月8日出发团 |
200,total=2,期次 = ['3'] |
| AC-6 | 无命中 不存在的团期名ZZZ9 |
200,空页,total=0 |
| AC-7 | 页签计数与列表同口径 | 命中时 ALL=2、其余页签 0;无命中时六个页签全 0 |
| AC-8 | 只填空格 vs 完全不传 | total 同为 708,首行订单号逐字一致 |
| AC-9 | 定制师身份(CUSTOMIZER) | 200 而非 589507;不带关键词时 total=19 且定制师列只含本人 |
| AC-10 | 65 字符关键词 | 100001「团期关键词长度不能超过 64」 |
| AC-11 | 只传 groupBatchId | 200,total=2 |
| AC-12 | 两参同传 | 与只传 ID 同结果,orderNo 序列一致 |
| AC-13 | 团期看板口径回归 | 三组关键词的命中团期集合与基线一致 |
| AC-14 | 团单行展示字段 | orderNo=HL20260922161158291,groupBatchName=10月8日出发团,groupBatchLabel=3 → 可渲染「第3期 10月8日出发团」 |
| AC-15 | 团单 300 行扫描 | 无空串残缺值;groupBatchLabel 为 null 的行数为 0 |
| AC-17 | 普通单 220 行 | 两个新字段全部为 null(非空串) |
| AC-18 | 同订单不同 pageSize 一致性 | pageSize=1 与 20 的 groupBatchName 一致;页级一次批量回填(单测 times(1),逐行查询 never) |
| AC-19 | 深翻页 | 第 2、3 页各 20 行均带团期名 |
| AC-20 | 订单详情回归 | 团期四字段与基线逐字一致 |
在此之上补一组经网关的真实请求取证,覆盖脚本未包含的软删场景:
| 用例 | 场景 | 结果 |
|---|---|---|
| AC-16 | 团期已软删(解散)的历史订单,groupBatchId=2097270759599616002 |
200,total=3;三行 groupOrder=true,groupBatchName 与 groupBatchLabel 均为 null |
十、相关文档
- 关联 Issue: wx/HL#8252
- 关联 PR: wx/HL#8261
- 团期看板关键词口径出处:#7942
- 订单列表 groupBatchId 冻结契约出处:#7635
关联 / 联系人
链接
联系人
- 后端负责人: @wx