# 订单列表 Tab 分组计数与分组过滤 — 新增接口 — 管理后台 > 变更类型:✨ 新增接口 + 修改接口(列表新增入参) > 端类型:管理后台 > 日期:2026-06-17 > 服务:hl-order-service-v3 > PR:https://git.1814.love:8443/wx/HL/pulls/3939 --- ## 1. 接口背景 **功能页面**:管理后台「订单列表」页的**顶部 Tab 栏**(出行前 / 出行中 / 核单 / 异常·取消 / 全部)。 **用在哪**: 1. **Tab 计数徽标**:页面加载 / 筛选条件变更时,调 `GET /v3/admin/order/status-group-counts` 取每个 Tab 上显示的订单数量角标(如"出行前 33"、"异常/取消 5")。 2. **点击 Tab 过滤列表**:用户点某个 Tab,前端只需把该 Tab 的 `group` 值作为 `statusGroup` 参数传给列表接口(`GET /v3/admin/order`),后端内部把 group 展开为对应状态集合过滤,前端无需自己维护"哪个 Tab 对应哪些状态"的映射。 **设计意图**:把 6 个粗状态按出行阶段折叠成 4 组+全部,让定制师快速聚焦当前阶段的订单,Tab 计数单独一个端点供徽标独立刷新,点击 Tab 与列表接口通过 `statusGroup` 解耦。 --- ## 2. 变更清单 | 变更类型 | 接口 | 说明 | |---|---|---| | ✨ 新增 | `GET /v3/admin/order/status-group-counts` | Tab 分组计数,返回 5 项(ALL + 4 组),每项含 group/label/orderCount | | ⚠️ 修改 | `GET /v3/admin/order`(列表) | 新增可选入参 `statusGroup`,前端传 group key 触发 Tab 过滤 | --- ## 3. 接口详情 ### 3.1 Tab 分组计数 - **方法 + 路径**:`GET /v3/admin/order/status-group-counts` - **接口名**:订单列表 Tab 分组计数 - **认证**:需要 JWT(管理后台登录 token) - **幂等性**:查询接口,天然幂等 - **限流**:无独立限流规则 - **语义**:计数值尊重其他筛选条件(keyword/出发日期/定制师名/来源/标签),但与当前选中 Tab 无关(faceted 计数,ALL 恒含已取消) ### 3.2 订单列表(新增 statusGroup 入参) - **方法 + 路径**:`GET /v3/admin/order`(别名 `GET /v3/admin/order/list`) - **接口名**:订单列表 - **认证**:需要 JWT - **幂等性**:查询接口,天然幂等 - **限流**:无独立限流规则 --- ## 4. 接口入参 ### 4.1 Tab 分组计数 Query 参数(复用列表筛选条件,不传 orderStatus / statusGroup) | 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | `keyword` | String | 否 | 关键字模糊搜索(团号/客户姓名/产品名/订单号) | | `departureDateFrom` | LocalDate | 否 | 出发日期起始(格式 `yyyy-MM-dd`) | | `departureDateTo` | LocalDate | 否 | 出发日期结束(格式 `yyyy-MM-dd`) | | `consultantName` | String | 否 | 定制师姓名 LIKE 匹配 | | `createSource` | String | 否 | 订单来源(`CONSULTANT` / `CUSTOMER`) | | `tagNames` | List\ | 否 | 标签名列表过滤(AND) | > 注:不传 `orderStatus`(按 group 内部统计)、不传 `statusGroup`(计数接口自己统计所有组)、不传 `page`/`pageSize`(计数接口无分页)。 ### 4.2 订单列表新增入参 | 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | `statusGroup` | String | 否 | Tab 分组 key,取值见下方枚举表;后端内部展开为 orderStatus 集合;与 `orderStatus` 下拉并存时取 AND;不传或传 `ALL` 时含已取消 | --- ## 5. 出参字段 ### 5.1 Tab 分组计数 StatusGroupCountVO 返回类型:`Result>`,共 5 项,ALL 在首位,后跟 4 组,按固定顺序。 | 字段 | 类型 | 说明 | 示例 | |---|---|---|---| | `group` | String | 分组标识 key,对应 `statusGroup` 入参 | `"BEFORE_TRIP"` | | `label` | String | 分组中文标签,用于 Tab 展示 | `"出行前"` | | `orderCount` | Long | 该分组订单数(满足其他筛选条件的计数) | `33` | ### 5.2 订单列表(本次只新增入参,出参字段不变,无需修改) 订单列表 `OrderListItemRespVO` 出参字段无变化(参考现有接口文档)。 --- ## 6. 枚举 / 数据字典 ### Tab 分组 group 值(statusGroup 参数取值 + 分组计数返回 group 值) | group 值 | 中文标签 | 含义(包含的 orderStatus) | |---|---|---| | `ALL` | 全部 | 全部状态(含已取消) | | `BEFORE_TRIP` | 出行前 | `PENDING_PAY`(待支付)+ `CUSTOMIZING`(定制中)+ `PENDING_DEPARTURE`(待出行) | | `ON_TRIP` | 出行中 | `TRAVELLING`(出行中) | | `SETTLEMENT` | 核单 | `COMPLETED`(已完成,横跨核单+结算两子阶段) | | `ABNORMAL` | 异常/取消 | `CANCELLED`(已取消) | > 前端只需感知 group 值,状态枚举的内部映射由后端维护,前端不用硬编码。 --- ## 7. 错误码 | code | 含义 | |---|---| | `200` | 成功 | | `401` | 未登录 / token 过期 | | `400` | `statusGroup` 传了非法值(后端宽松处理:未知 group 忽略,不抛 400;但建议传枚举定义值) | --- ## 8. 示例 ### 8.1 典型成功——获取 Tab 分组计数 ```http GET /v3/admin/order/status-group-counts Authorization: Bearer ``` ```json { "code": 200, "data": [ { "group": "ALL", "label": "全部", "orderCount": 38 }, { "group": "BEFORE_TRIP","label": "出行前", "orderCount": 33 }, { "group": "ON_TRIP", "label": "出行中", "orderCount": 0 }, { "group": "SETTLEMENT", "label": "核单", "orderCount": 0 }, { "group": "ABNORMAL", "label": "异常/取消", "orderCount": 5 } ] } ``` ### 8.2 边界——带筛选条件的计数(Faceted,计数随筛选条件变化) ```http GET /v3/admin/order/status-group-counts?departureDateFrom=2026-07-01&departureDateTo=2026-07-31 ``` 返回值中每组 `orderCount` 仅统计出发日期在 7 月的订单,即使当前 Tab 已选 BEFORE_TRIP,ALL 和其他组也只统计 7 月内的。 ```json { "code": 200, "data": [ { "group": "ALL", "label": "全部", "orderCount": 12 }, { "group": "BEFORE_TRIP","label": "出行前", "orderCount": 10 }, { "group": "ON_TRIP", "label": "出行中", "orderCount": 1 }, { "group": "SETTLEMENT", "label": "核单", "orderCount": 0 }, { "group": "ABNORMAL", "label": "异常/取消", "orderCount": 1 } ] } ``` ### 8.3 业务失败——点击 Tab 后列表 statusGroup 传了未知值 ```http GET /v3/admin/order?statusGroup=UNKNOWN_GROUP&page=1&pageSize=10 ``` ```json { "code": 200, "data": { "total": 38, "list": [ ... ] } } ``` > 后端宽松处理:未知 group 忽略,等同于不传 statusGroup(返回默认不含已取消的全部订单)。前端避免传枚举定义之外的值。 --- ## 9. 业务边界 **适用**: - 管理后台订单列表顶部 Tab 计数徽标渲染。 - 用户点击 Tab 触发列表按分组过滤。 **不适用**: - 分组计数不适用于精确状态统计(`SETTLEMENT` 组包含 `COMPLETED`,横跨核单和结算两个子阶段,不区分子状态)。 - 分组计数的 `ALL` 恒含已取消订单(不可排除);其他接口参数 `cancelled=false` 对分组计数无效。 **特殊边界**: - `statusGroup=ALL` 与不传 `statusGroup` 行为不同:传 `ALL` 时含已取消;不传时默认不含已取消(`cancelled` 默认 `false`)。 - `statusGroup` 与 `orderStatus` 下拉可同时传,取 AND 逻辑(例:`statusGroup=BEFORE_TRIP&orderStatus=CUSTOMIZING` 只返定制中的订单)。 - 分组计数与当前选中 Tab 的 `statusGroup` 无关(Faceted 设计),每次只要其他筛选条件变了就重新调计数接口。 --- ## 12. 注意事项 - **计数接口与列表接口分开调**:Tab 徽标数字调 `status-group-counts`,Tab 点击过滤调 `GET /v3/admin/order?statusGroup=...`,两者分开请求。 - **`statusGroup=ALL` 传参覆盖默认排除取消**:前端若需要"全部"含取消,用 `statusGroup=ALL` 而不是 `cancelled=true`(两者效果等同,但 `statusGroup=ALL` 更语义明确)。 - **分组映射由后端维护**:前端不要在代码里硬编码"BEFORE_TRIP = [PENDING_PAY, CUSTOMIZING, PENDING_DEPARTURE]"这样的映射表——这是后端内部逻辑,后端调整分组时前端自动跟随。 - 已实测(2026-06-17,测试服 dev-v3):`statusGroup=BEFORE_TRIP` 返 33 单、无越界;`ALL` 组计数 = 4 组之和。 --- ## 13. 关联 / 联系人 - Issue:https://git.1814.love:8443/wx/HL/issues/3938 - PR:https://git.1814.love:8443/wx/HL/pulls/3939 - Commit(refactor review 后):https://git.1814.love:8443/wx/HL/commit/5eca8d67b0432dfc19e2b6d2c67ef7e6eac6ec02 - 后端负责人:腰苏图