- #7939 → 8360287a(总览条 scopeFilterHint 两口径文案,scope 已摘除只提示不切) - 月份分组缺陷 → c19923be(默认月组倒序改升序,显式排序仍跟随行序) - batchNo 缺陷 → c6174f2c(仅删显示,keyword 搜索数据链不动) 各自定向 spec 6/6、21/21、9/9 + scoped checkpoint 全绿,hl-admin v2.1 已推。
13 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 | 7939 | 团期看板统计条回带生效班期范围 effectiveScope 与被过滤条数 filteredOutCount | admin | jw(GIT) | 修改接口 | deployed | verified | verified | mmg | 8360287a44191921a5abd7110b1ecd4f2b8f98ae | 2026-09-18 | 团期看板统计条 GET /v3/admin/order/group-batch/summary 出参纯新增 effectiveScope(本次生效的班期范围 ONGOING/FINISHED/ALL)与 filteredOutCount(被范围过滤掉的班期数,与 total 同一套 productId/month/keyword 筛选,ALL 时恒 0);入参、既有 5 个字段、错误码、scope 缺省值均不变。解决「产品卡片 10 期、统计条共 8 期」同屏打架且无解释的问题。后端已合并 dev-v3(129de0292)并部署 TEST,网关实测 29/29 通过。前端待办:effectiveScope≠ALL 且 filteredOutCount>0 时,在统计条旁提示「仅显示未结束班期(另有 N 期已结束)」,见第四节。[mmg 2026-09-18 已实现并验证] batch/index.vue 总览条加 scopeFilterHint:ONGOING 且 filteredOutCount>0 显「仅显示未结束班期(另有 N 期已结束)」、FINISHED 显「仅显示已结束班期(另有 N 期未结束)」、ALL 或 0 不提示;scope 已随 9/16 前台条目摘除,经用户确认只提示不加「查看全部」切换;store 原样存响应新字段自动流入,零 API/store 改动;spec 加 #7939 专项 3 例,定向 9/9+scoped checkpoint 全绿。 | 2026-09-18 | dev-v3 |
order-v3: 团期看板统计条回带生效班期范围与被过滤条数
存放目录:
changelogs-v2/{YYYY-MM}/(管理后台,二期 order-v3)服务: hl-order-service-v3 (端口 8086) PR: #7941 Issue: #7939 日期: 2026-09-18 影响范围: 管理后台「团期订单」页面的统计条(班期总览 / 状态页签计数)
⚠️ 关键变化
- 统计条接口多返回两个字段:
effectiveScope(本次实际按哪个班期范围统计)和filteredOutCount(被这个范围过滤掉了几期)。 - 只加字段,不改原有字段,也不改
scope的缺省规则:带productId不传scope时仍只统计未结束班期。 - 前端待办:结果集被时间过滤时给出提示,避免运营把「共 8 期」当成「这个产品只有 8 期」,见第四节。
一、背景
「团期订单」页面同一屏出现两个互相矛盾的班期数:左侧产品卡片写「王骁测试团期产品 10 期」,右侧班期总览写「共 8 期」、状态页签「全部期 8」,界面上没有任何解释。
原因是统计条接口在 productId 有值且不传 scope 时,缺省只统计未结束班期(end_date >= 今天 或未填返团日),已结束的 2 期被排除;而响应里没有任何字段说明「结果被按时间过滤过」,前端无从提示。2026-09-18 测试环境造数时当事人第一反应是「数据丢了」。
本次只让过滤变得可见,缺省只看未结束班期是刻意设计,保持不变。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 团期看板统计条 | GET | /v3/admin/order/group-batch/summary |
修改 | 出参新增 effectiveScope、filteredOutCount |
三、接口详情
1. 团期看板统计条 GET /v3/admin/order/group-batch/summary
VO: Result<GroupBatchSummaryVO>(新增 effectiveScope、filteredOutCount)
使用场景
管理后台「团期订单」页面顶部统计条:班期总数、8 个运营阶段页签计数、子订单数、成团/满团门槛副标题。本次新增的两个字段用于在结果集被班期范围过滤时给出提示。
入参
本次入参不变,原样列出供核对。
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| productId | Query | Long | 否 | 产品 ID | 缺省不限。有值时 scope 缺省为 ONGOING |
| month | Query | String | 否 | yyyy-MM,非法值忽略 |
按出团日落月 |
| keyword | Query | String | 否 | trim 后包含匹配 | 团期编号 / 名称模糊 |
| scope | Query | String | 否 | ONGOING / FINISHED / ALL,非法值按缺省 |
缺省:productId 有值→ONGOING,否则→ALL |
出参
| 字段 | 类型 | 说明 |
|---|---|---|
| total | Integer | 不变。当前范围内的班期总数(= 8 桶之和) |
| buckets | Map<String,Integer> | 不变。8 桶固定全键 |
| subOrderCount | Integer | 不变。活跃子订单合计 |
| minToForm | Integer | 不变。成团门槛(唯一才给,否则 null) |
| maxRooms | Integer | 不变。满团门槛(唯一才给,否则 null) |
| effectiveScope | String | 新增。本次实际生效的班期范围:ONGOING / FINISHED / ALL。不传 scope 时由 productId 决定;传了非法值时是回落后的缺省值 |
| filteredOutCount | Integer | 新增。被本次范围过滤掉的班期数。与 total 使用同一套 productId / month / keyword 条件,所以恒有 total + filteredOutCount = 同条件 scope=ALL 的 total;effectiveScope=ALL 时恒为 0;永不为 null |
请求示例
GET /v3/admin/order/group-batch/summary?productId=2100839045562077186
Authorization: Bearer <token>
响应示例
(测试服真实响应,2026-09-18;该产品 10 个班期,其中 08-2008-22、09-0309-05 两期已结束)
{
"code": 200,
"message": "成功",
"data": {
"total": 8,
"buckets": {
"RECRUIT": 8,
"FORMED": 0,
"PENDING_TRIP": 0,
"TRAVELLING": 0,
"TRIP_FINISHED": 0,
"AUDITING": 0,
"CHECKED": 0,
"DISBANDED": 0
},
"subOrderCount": 0,
"minToForm": 0,
"maxRooms": 0,
"effectiveScope": "ONGOING",
"filteredOutCount": 2
},
"success": true
}
同一产品显式传 scope=ALL:
{
"code": 200,
"message": "成功",
"data": {
"total": 10,
"buckets": { "RECRUIT": 10, "FORMED": 0, "PENDING_TRIP": 0, "TRAVELLING": 0, "TRIP_FINISHED": 0, "AUDITING": 0, "CHECKED": 0, "DISBANDED": 0 },
"subOrderCount": 0,
"minToForm": 0,
"maxRooms": 0,
"effectiveScope": "ALL",
"filteredOutCount": 0
},
"success": true
}
空数据 / 降级响应
产品名下没有任何班期时,两个新字段照常返回,不为 null(测试服真实响应,产品 2045486260364996609):
{
"code": 200,
"message": "成功",
"data": {
"total": 0,
"buckets": { "RECRUIT": 0, "FORMED": 0, "PENDING_TRIP": 0, "TRAVELLING": 0, "TRIP_FINISHED": 0, "AUDITING": 0, "CHECKED": 0, "DISBANDED": 0 },
"subOrderCount": 0,
"minToForm": null,
"maxRooms": null,
"effectiveScope": "ONGOING",
"filteredOutCount": 0
},
"success": true
}
错误响应
{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null }
| code | 触发条件 |
|---|---|
| 589507 | 没有团期列表查看权限(group-batch:list) |
| 401 | 未登录(网关拦截) |
与改动前相同,没有新增错误码。
业务边界
- 只读接口,无事务、无写库;判权与改动前一致。
filteredOutCount只统计时间范围这一个维度过滤掉的条数;month/keyword过滤掉的不算在内。- 状态未知的脏数据行既不计入
total,也不计入filteredOutCount,两者可直接相加。 productId有值时第二次统计是纯内存计算(产品班期只拉一次);productId缺省且scope≠ALL时多一次数据库查询。- 同一请求内「今天」只取一次,两次统计的范围判定口径一致。
四、契约约束与正确调用方式
前端展示建议
| 条件 | 建议提示 |
|---|---|
effectiveScope === 'ONGOING' && filteredOutCount > 0 |
统计条旁:「仅显示未结束班期(另有 {filteredOutCount} 期已结束)」,可带「查看全部」切到 scope=ALL |
effectiveScope === 'FINISHED' && filteredOutCount > 0 |
「仅显示已结束班期(另有 {filteredOutCount} 期未结束)」 |
effectiveScope === 'ALL' 或 filteredOutCount === 0 |
不提示 |
✅ 正确 / ❌ 错误 用法
| 场景 | 做法 |
|---|---|
| ✅ 判断统计结果有没有被时间过滤 | 看 effectiveScope 与 filteredOutCount,不要自己按「是否传了 scope」推断 |
| ✅ 得到该产品在当前筛选下的全部期数 | total + filteredOutCount |
❌ 把 total 当成「这个产品一共有多少期」 |
缺省只统计未结束班期,要么提示,要么显式传 scope=ALL |
❌ 用 filteredOutCount 解释 month / keyword 的差额 |
它只含时间范围过滤掉的条数 |
六、边界行为
- 产品有已结束班期、不传
scope→effectiveScope=ONGOING,filteredOutCount= 已结束期数。 - 显式
scope=ALL→filteredOutCount=0。 - 显式
scope=FINISHED→filteredOutCount= 未结束期数。 - 产品无班期 →
total=0、filteredOutCount=0,均不为 null。 - 全部班期都已结束且不传
scope→total=0,filteredOutCount= 全部期数。 - 返团日是今天的班期算「未结束」;没填返团日的班期也算「未结束」。
scope传非法值 → 按缺省处理(原行为),effectiveScope返回回落后的值。- 无权限 → 589507;未登录 → 401(与改动前相同)。
六.6、修改前后对比
字段级对比
| 字段 | 改前 | 改后 |
|---|---|---|
effectiveScope |
无 | 新增,String |
filteredOutCount |
无 | 新增,Integer,永不为 null |
total / buckets / subOrderCount / minToForm / maxRooms |
— | 不变(TEST 18 组请求改前改后逐字比对一致) |
| 入参 4 个 | — | 不变 |
行为级对比
| 行为 | 改前 | 改后 |
|---|---|---|
| 结果被按时间过滤时 | 响应无任何标识,前端无法提示 | 响应声明生效范围与被过滤条数 |
scope 缺省规则 |
productId 有值→ONGOING,否则→ALL |
不变 |
| 查询次数 | 1 次 | scope=ALL 时仍 1 次;否则 productId 场景多一次内存筛选,productId 缺省场景多一次 DB 查询 |
六.7、影响评估
- 是否破坏向后兼容: 否,只新增字段。
- 前端是否必须同步上线: 否,不接入也不会报错;但需要前端接入后,页面才会出现提示,「10 期 / 8 期」的困惑才会消失。
- 回滚: 回滚 PR #7941 即可,无数据变更。
七、不影响范围
- 仅影响:
GET /v3/admin/order/group-batch/summary的响应(新增 2 个字段)。 - 零影响:
GET /v3/admin/order/group-batch/board(缺省仍为ALL,与 summary 缺省不一致的问题另行立项)GET /v3/admin/order/group-batch/export(与 summary 共用缺省规则,导出同样只含未结束班期且无说明,另行立项)- GB-ADM-001 团期分页列表
- 数据库:无表结构变更,只读
八、测试环境已验证
被测版本:hl-order-service-v3 = dev-v3 129de0292(2026-09-18 15:41 部署,双实例滚动完成)。取证前确认面板检出 dev-v3 @ 129de0292、hl-order-service-v3 与 hl-gateway 均 running,且新字段在线。网关 https://api.test.1814.love:9443 实测 29/29 通过。
AC-1 productId=2100839045562077186 不传 scope → effectiveScope=ONGOING total=8 filteredOutCount=2;8+2 = ALL 的 10 ✓
AC-2 同产品 scope=ALL → effectiveScope=ALL filteredOutCount=0 ✓;scope=FINISHED → total=2 filteredOutCount=8 ✓
AC-3 productId + month=2026-09 → 0+1 = ALL 的 1 ✓
productId + keyword=Q20260 → 0+2 = ALL 的 2 ✓
productId + month=2026-10 → 4+0 = ALL 的 4 ✓
productId + month=2026-08 + keyword → 0+1 = ALL 的 1 ✓
无 productId month=2026-09 ONGOING → 9+8 = ALL 的 17 ✓
无 productId keyword=GB ONGOING → 7+0 = ALL 的 7 ✓
无 productId month=2026-09 FINISHED → 8+9 = ALL 的 17 ✓
AC-4 0 班期产品 2045486260364996609 → total=0 filteredOutCount=0 effectiveScope=ONGOING ✓
AC-5 18 组请求(各 scope × 有无 productId × month/keyword)改前改后既有 5 字段逐字一致 ✓
本地:GroupBatchBoardStatsServiceTest 33/0/0(新增 9 例);order-v3 全量 Half A 7849/0/0、Half B 3964/F1(MapperBoundaryArchTest.non_refund_not_depend_on_refund_mapper,干净 dev-v3 846998c4b 上同样失败,既存,与本次无关)。
十、相关文档
- 关联 Issue: wx/HL#7939
- 关联 PR: wx/HL#7941
- 缺省范围单源:
GroupBatchScopeResolver.defaultFor(#7189)