diff --git a/changelogs-v2/2026-06/22_4222_订单列表售后Tab-修改接口-管理后台.md b/changelogs-v2/2026-06/22_4222_订单列表售后Tab-修改接口-管理后台.md new file mode 100644 index 0000000..dc65429 --- /dev/null +++ b/changelogs-v2/2026-06/22_4222_订单列表售后Tab-修改接口-管理后台.md @@ -0,0 +1,289 @@ +# 订单列表售后 Tab — 修改接口(管理后台) + +- **日期**:2026-06-22 +- **端类型**:管理后台 +- **Issue**:[#4222](https://git.1814.love:8443/wx/HL/issues/4222) +- **PR**:[#4225](https://git.1814.love:8443/wx/HL/pulls/4225) +- **Commit**:[82c669b2a](https://git.1814.love:8443/wx/HL/commit/82c669b2a) +- **后端负责人**:腰苏图 + +--- + +## 1. 接口背景 + +管理后台订单列表原有 5 个 Tab(全部 / 出行前 / 出行中 / 核单 / 异常取消),均以 `orderStatus`(订单状态)为过滤维度。 + +本次新增第 6 个「售后」Tab,以 `aftersale_status=IN_PROGRESS` 为过滤维度。售后是**横切(叠加)语义**,与出行阶段正交:一个订单可同时出现在某出行阶段 Tab 和售后 Tab,且售后计数**不计入**「全部」(全部仍 = 出行前 + 出行中 + 核单 + 异常取消四项之和)。 + +--- + +## 2. 变更清单 + +| # | 接口 | 变更类型 | 具体内容 | +|---|------|----------|----------| +| 1 | `GET /v3/admin/order/status-group-counts` | ⚠️ 出参新增 | 返回数组由 5 项变 6 项,末尾新增 `{ group: "AFTERSALE", label: "售后", orderCount: N }` | +| 2 | `GET /v3/admin/order` | ✨ 入参枚举新增 | `statusGroup` 新增可选值 `AFTERSALE` | + +--- + +## 3. 接口详情 + +### 接口一:订单列表 Tab 分组计数 + +| 项 | 内容 | +|----|------| +| 方法 + 路径 | `GET /v3/admin/order/status-group-counts` | +| 功能描述 | 返回各 Tab 的订单计数,供顶部 Tab 展示角标数字 | +| 认证 | Bearer Token(管理员 JWT,必填) | +| 幂等性 | 只读,天然幂等 | +| 限流 | 无独立限流策略 | + +### 接口二:订单列表 + +| 项 | 内容 | +|----|------| +| 方法 + 路径 | `GET /v3/admin/order` | +| 功能描述 | 管理后台订单列表,支持多维度过滤与分页 | +| 认证 | Bearer Token(管理员 JWT,必填) | +| 幂等性 | 只读,天然幂等 | +| 限流 | 无独立限流策略 | + +--- + +## 4. 接口入参 + +### 4.1 接口一入参(Query 参数,与 GET /v3/admin/order 共用过滤字段) + +> 计数接口忽略分页字段(page / pageSize),只消费过滤字段。 + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| keyword | String | 否 | 关键词(订单号 / 客户姓名 / 手机号) | +| departureDateFrom | String | 否 | 出发日期起(yyyy-MM-dd) | +| departureDateTo | String | 否 | 出发日期止(yyyy-MM-dd) | +| consultantName | String | 否 | 定制师姓名 | +| createSource | String | 否 | 订单来源(字典值) | +| tagNames | Array\ | 否 | 标签名列表,多值 AND | + +### 4.2 接口二入参(Query 参数) + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| page | Integer | 否 | 页码,默认 1 | +| pageSize | Integer | 否 | 每页数量,默认 20 | +| keyword | String | 否 | 关键词 | +| departureDateFrom | String | 否 | 出发日期起(yyyy-MM-dd) | +| departureDateTo | String | 否 | 出发日期止(yyyy-MM-dd) | +| consultantName | String | 否 | 定制师姓名 | +| createSource | String | 否 | 订单来源字典值 | +| tagNames | Array\ | 否 | 标签名列表 | +| orderStatus | String | 否 | 订单状态下拉(与 statusGroup 并存时为 AND) | +| statusGroup | String | 否 | Tab 分组标识,见枚举表,**本次新增 `AFTERSALE`** | + +--- + +## 5. 出参字段 + +### 接口一出参 + +`Result>`,数组共 **6 项**(固定顺序)。 + +**StatusGroupCountVO 字段:** + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| group | String | 分组标识,见枚举表 | +| label | String | 分组中文标签(直接展示) | +| orderCount | long | 该分组订单数 | + +**6 项固定顺序:** + +| 顺序 | group | label | 语义 | +|------|-------|-------|------| +| 1 | ALL | 全部 | 全部订单(= 出行前+出行中+核单+异常取消之和,**不含**售后独立计数) | +| 2 | BEFORE_TRIP | 出行前 | orderStatus IN (PENDING_PAY, CUSTOMIZING, PENDING_DEPARTURE) | +| 3 | ON_TRIP | 出行中 | orderStatus = TRAVELLING | +| 4 | SETTLEMENT | 核单 | orderStatus = COMPLETED | +| 5 | ABNORMAL | 异常/取消 | orderStatus = CANCELLED | +| 6 | AFTERSALE | 售后 | aftersale_status = IN_PROGRESS(横切,不限出行阶段) | + +### 接口二出参 + +`PageResult`,字段结构与本次无变化。 + +--- + +## 6. 枚举 / 数据字典 + +### statusGroup 枚举值(接口二入参 + 接口一出参 group 字段) + +| 枚举值 | 含义 | 过滤维度 | 是否横切 | +|--------|------|----------|----------| +| ALL | 全部 | 不过滤(含取消) | 否 | +| BEFORE_TRIP | 出行前 | orderStatus IN (PENDING_PAY, CUSTOMIZING, PENDING_DEPARTURE) | 否 | +| ON_TRIP | 出行中 | orderStatus = TRAVELLING | 否 | +| SETTLEMENT | 核单 | orderStatus = COMPLETED | 否 | +| ABNORMAL | 异常/取消 | orderStatus = CANCELLED | 否 | +| **AFTERSALE** | **售后(新增)** | **aftersale_status = IN_PROGRESS** | **是** | + +**横切说明**:`AFTERSALE` 不按 orderStatus 过滤,而是按 `aftersale_status=IN_PROGRESS` 过滤。一个出行中的订单如果同时有在途售后工单,该订单会出现在「出行中」Tab 和「售后」Tab 两处。 + +--- + +## 7. 错误码 + +| 错误码 | 含义 | 触发场景 | +|--------|------|----------| +| 401 | 未认证 | 未携带或 Token 失效 | +| 403 | 无权限 | 非管理员角色访问 | +| 422 | 参数校验失败 | statusGroup 传了无法识别的值(后端宽松处理:未知 group 忽略,不报 422;前端只传枚举表中的值即可) | + +--- + +## 8. 示例 + +### 8.1 典型成功——获取各 Tab 计数(含售后) + +**请求:** +``` +GET /v3/admin/order/status-group-counts +Authorization: Bearer +``` + +**响应:** +```json +{ + "code": 200, + "msg": "success", + "data": [ + { "group": "ALL", "label": "全部", "orderCount": 120 }, + { "group": "BEFORE_TRIP","label": "出行前", "orderCount": 50 }, + { "group": "ON_TRIP", "label": "出行中", "orderCount": 30 }, + { "group": "SETTLEMENT", "label": "核单", "orderCount": 35 }, + { "group": "ABNORMAL", "label": "异常/取消","orderCount": 5 }, + { "group": "AFTERSALE", "label": "售后", "orderCount": 8 } + ] +} +``` + +> 注意:ALL.orderCount(120) = 50+30+35+5 = 120,不含 AFTERSALE 的 8。 + +### 8.2 边界情况——无任何在途售后工单 + +**请求:** +``` +GET /v3/admin/order/status-group-counts +Authorization: Bearer +``` + +**响应(售后 orderCount = 0):** +```json +{ + "code": 200, + "data": [ + { "group": "ALL", "label": "全部", "orderCount": 30 }, + { "group": "BEFORE_TRIP","label": "出行前", "orderCount": 20 }, + { "group": "ON_TRIP", "label": "出行中", "orderCount": 8 }, + { "group": "SETTLEMENT","label": "核单", "orderCount": 2 }, + { "group": "ABNORMAL", "label": "异常/取消","orderCount": 0 }, + { "group": "AFTERSALE", "label": "售后", "orderCount": 0 } + ] +} +``` + +### 8.3 业务失败——筛售后 Tab + 订单状态 AND 组合 + +**请求(出行中且在售后的单):** +``` +GET /v3/admin/order?statusGroup=AFTERSALE&orderStatus=TRAVELLING&page=1&pageSize=20 +Authorization: Bearer +``` + +**响应(无出行中的在售后单时返回空列表):** +```json +{ + "code": 200, + "data": { + "total": 0, + "records": [] + } +} +``` + +--- + +## 9. 业务边界 + +**适用:** +- `GET /v3/admin/order/status-group-counts` 在任意过滤条件下均会返回 6 项(含 AFTERSALE) +- `GET /v3/admin/order` 传 `statusGroup=AFTERSALE` 返回所有 `aftersale_status=IN_PROGRESS` 的订单,不限出行阶段(含已取消订单,只要售后工单仍在途) + +**不适用:** +- 售后 Tab 不会从其他 Tab 移走订单:用户在「出行中」Tab 看到的订单不会因为开了售后工单而消失 +- 售后计数不纳入「全部」总数,前端角标与「全部」Tab 数字不加 AFTERSALE.orderCount + +**特殊边界:** +- `statusGroup=AFTERSALE` 与 `orderStatus=XXX` 同时传为 AND 关系(先按 aftersale_status=IN_PROGRESS 过滤,再按 orderStatus 收窄) +- `statusGroup=ALL` 时包含取消的单,即 `cancelled=true`,行为不变 + +--- + +## 10. 修改前后对比 + +### 出参对比(接口一 status-group-counts) + +**字段级:** + +| 字段/项 | 修改前 | 修改后 | +|---------|--------|--------| +| 返回数组长度 | 5 项(ALL + 4 阶段) | **6 项**(ALL + 4 阶段 + 售后) | +| 第 6 项 group | 无 | `AFTERSALE` | +| 第 6 项 label | 无 | `售后` | +| 第 6 项 orderCount | 无 | long,`aftersale_status=IN_PROGRESS` 的订单数 | +| ALL.orderCount 口径 | 四阶段之和 | **不变**,仍 = 四阶段之和,不含 AFTERSALE | + +**行为级:** + +| 行为 | 修改前 | 修改后 | +|------|--------|--------| +| 下拉菜单 statusGroup 可选值 | ALL / BEFORE_TRIP / ON_TRIP / SETTLEMENT / ABNORMAL | 同上 + **AFTERSALE** | +| 传 AFTERSALE 的过滤逻辑 | 传入忽略(未知 group) | 按 `aftersale_status=IN_PROGRESS` 过滤 | + +--- + +## 11. 影响评估 / 回滚 + +**前端同步上线:** +- 若前端对 status-group-counts 返回长度做了硬编码(如 `data.length === 5`)或索引访问,需更新为动态渲染 +- 需在 Tab 列表末尾渲染新的「售后」Tab,点击时传 `statusGroup=AFTERSALE` +- ALL.orderCount 口径不变,前端逻辑无需调整 + +**兼容性:** +- 不传 statusGroup 或传旧值的请求行为不变,向下兼容 +- status-group-counts 固定多返回 1 项,前端旧版不会报错(JSON 数组多一项无副作用),但售后 Tab 不会渲染,属预期降级 + +**回滚方案:** +- 后端回滚:恢复 `OrderStatusGroup` 枚举(删除 AFTERSALE),countByStatusGroup 重新返回 5 项 +- 前端回滚:无感知(旧前端代码仍正常,只是不展示售后 Tab) + +--- + +## 12. 注意事项 + +1. **横切语义,计数不累加到 ALL**:前端不要把 AFTERSALE.orderCount 加到 ALL 的角标里,否则显示总数虚高。 + +2. **AND 过滤**:`statusGroup=AFTERSALE` 与 `orderStatus` 下拉同时传是合法且有意义的用法(筛"出行中且在售后"),前端过滤 UI 无需屏蔽两者同时选择。 + +3. **硬编码 5 个 Tab 需更新**:若之前按固定 5 项渲染 Tab,须改为遍历 API 返回数组动态渲染,否则「售后」Tab 不出现。 + +4. **售后 Tab 包含已取消订单**:`aftersale_status=IN_PROGRESS` 的订单不论 orderStatus 是什么(含 CANCELLED)都会出现在售后 Tab。 + +--- + +## 13. 关联 / 联系人 + +- **Issue**:[#4222 管理后台订单列表加「售后」Tab](https://git.1814.love:8443/wx/HL/issues/4222) +- **PR**:[#4225 feat(order-v3): 管理后台订单列表加「售后」Tab](https://git.1814.love:8443/wx/HL/pulls/4225) +- **Commit**:[399288d4d](https://git.1814.love:8443/wx/HL/commit/399288d4d97b26238d292b7c7768b69b67f46300) +- **关联 PR**:[#4197 订单售后中展示 aftersale_status(售后状态激活)](https://git.1814.love:8443/wx/HL/pulls/4197) +- **后端负责人**:腰苏图(yaosutu)