376 行
14 KiB
Markdown
376 行
14 KiB
Markdown
---
|
||
schema: "hl-changelog/v2"
|
||
ticket: "8446"
|
||
title: "订单列表与状态计数新增查询参数 productType(核心 / 定制 / 团期页签)"
|
||
consumer: "admin"
|
||
author: "wx(GIT)"
|
||
change_type: "修改接口"
|
||
backend_status: "deployed"
|
||
gateway_status: "verified"
|
||
frontend_status: "verified"
|
||
frontend_owner: "mmg"
|
||
frontend_ref: "ab3b6be1268721e56ed809da9329b367d8b890e9"
|
||
target_release: "v2.1"
|
||
verified_at: "2026-09-28"
|
||
status_note: "PR #8454 已合入 dev-v3(22145977d),order-v3 已部署测试服,经网关实测三个端点。新增查询参数 productType,与其他条件取 AND;只传 productType、不传 orderKind 时不按团属性过滤。前端改动见同日前端 changelog。前端已交付(ab3b6be1):列表与状态计数透传 productType、不再传 orderKind;「订单类型」下拉改核心/定制/团期三页签,团期关键词框只在团期页签显示、切出团期清残留关键词;productTypeTabs/groupBatchKeyword 等 spec 全绿。"
|
||
updated_at: "2026-09-27"
|
||
base: "dev-v3"
|
||
---
|
||
|
||
# 订单服务(order-v3): 订单列表与状态计数新增查询参数 productType
|
||
|
||
> **服务**: hl-order-service-v3(端口 8086/8186)
|
||
> **PR**: #8454(合并提交 `22145977d`)
|
||
> **Issue**: #8446
|
||
> **日期**: 2026-09-27
|
||
> **影响范围**: 管理后台「订单管理v2 › 订单列表」的列表与状态计数接口
|
||
|
||
---
|
||
|
||
## ⚠️ 关键变化
|
||
|
||
1. 列表 `GET /v3/admin/order`(别名 `/v3/admin/order/list`)与状态计数 `GET /v3/admin/order/status-group-counts` 新增查询参数 **`productType`**:`CORE` / `ROUTE` / `CUSTOM` / `GROUP`,英文逗号多值,空串等同不传。
|
||
2. **只传 `productType`、不传(或传空串)`orderKind` 时,不再缺省 `orderKind=NORMAL`,不按「是否挂团期」过滤。** 页签「团期」因此能查到团期订单。
|
||
3. 其余组合行为不变:显式传 `orderKind` 与 `productType` 取 AND;传 `groupBatchId` / `groupBatchKeyword` 时仍强制按团期,再与 `productType` 取 AND。两个参数都不传时仍缺省 NORMAL。
|
||
4. 非法值(如 `productType=XYZ`)返回 HTTP 200 + `code=100001`,与 `orderKind` 非法值同码。
|
||
5. 响应结构不变。
|
||
|
||
---
|
||
|
||
## 一、背景
|
||
|
||
wx 2026-09-27 要求订单列表的「订单类型」下拉(散客 / 团单 / 全部)改成「核心 / 定制 / 团期」页签。页签按**产品类型**切分,而原 `orderKind` 按「订单有没有挂运营团期」切分,两者不是同一口径,所以新增 `productType`,`orderKind` 保留原语义不废弃。
|
||
|
||
---
|
||
|
||
## 二、变更接口清单
|
||
|
||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||
|---|------|------|------|----------|------|
|
||
| 1 | 订单列表 | GET | `/v3/admin/order` | 新增参数 | `productType`,别名路径 `/v3/admin/order/list` 同样生效 |
|
||
| 2 | 订单列表 Tab 分组计数 | GET | `/v3/admin/order/status-group-counts` | 新增参数 | `productType`,与列表同口径 |
|
||
|
||
---
|
||
|
||
## 三、接口详情
|
||
|
||
### 1. 订单列表 `GET /v3/admin/order`
|
||
|
||
**VO**: `OrderListReqVO` → `Result<PageResult<OrderListItemRespVO>>`
|
||
|
||
#### 使用场景
|
||
|
||
订单列表页签「核心 / 定制 / 团期」切换时,按当前页签传 `productType=CORE|CUSTOM|GROUP` 取列表。
|
||
|
||
#### 入参字段表
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| productType | query | String | 否 | `CORE`/`ROUTE`/`CUSTOM`/`GROUP`,多值用英文逗号分隔(如 `CORE,CUSTOM`),空串等同不传 | **新增**。按订单产品类型过滤,与其他条件取 AND |
|
||
| orderKind | query | String | 否 | `ALL`/`GROUP`/`NORMAL`,空串等同不传 | 原有。未传时缺省 NORMAL;**例外**:传了 productType 而本参数未传或为空串时不缺省、不按团属性过滤 |
|
||
|
||
其余参数(`keyword`、`orderStatus`、`statusGroup`、`groupBatchId`、`groupBatchKeyword`、`page`、`pageSize` 等)不变,`pageSize` 上限 100。
|
||
|
||
#### 出参字段表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| data.records[] | Array | 订单行(前端 `request.js` 拦截器会同步映射为 `list`) |
|
||
| data.records[].id | String | 订单 ID |
|
||
| data.records[].productType | String | 产品类型 CORE/ROUTE/CUSTOM/GROUP |
|
||
| data.total | Number | 符合条件的总条数 |
|
||
| data.page | Number | 当前页 |
|
||
| data.pageSize | Number | 每页条数 |
|
||
|
||
订单行其余字段不变。
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order?productType=CORE&page=1&pageSize=100
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
测试服 2026-09-27 实测,节选前 2 条、每条只保留关键字段:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"success": true,
|
||
"data": {
|
||
"total": 71,
|
||
"page": 1,
|
||
"pageSize": 100,
|
||
"records": [
|
||
{
|
||
"id": "2104192144560553985",
|
||
"orderNo": "HL20260927205115753",
|
||
"productType": "CORE",
|
||
"groupBatchId": null,
|
||
"orderStatus": "CUSTOMIZING"
|
||
},
|
||
{
|
||
"id": "2104161383220457474",
|
||
"orderNo": "HL20260927184901765",
|
||
"productType": "CORE",
|
||
"groupBatchId": null,
|
||
"orderStatus": "CUSTOMIZING"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
没有符合条件的订单时 `records` 为空数组、`total` 为 0,例如 `productType=CORE` 加一个只挂了团期订单的团期关键词。
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"success": true,
|
||
"data": {
|
||
"total": 0,
|
||
"page": 1,
|
||
"pageSize": 20,
|
||
"records": []
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 错误响应
|
||
|
||
非法值返回 HTTP 200,`code=100001`(测试服实测原文):
|
||
|
||
```json
|
||
{
|
||
"code": 100001,
|
||
"message": "productType 非法,可选值: CORE, ROUTE, CUSTOM, GROUP(多值用逗号分隔)",
|
||
"data": null,
|
||
"traceId": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 多值用英文逗号,命中任一即返回;空串等同不传。
|
||
- 只传 `productType` 时不按团属性过滤;默认仍排除已取消订单,传 `statusGroup=ALL` 才含已取消(与原口径一致)。
|
||
- 显式传 `orderKind` 时与 `productType` 取 AND,例如 `productType=GROUP&orderKind=NORMAL` 恒为空。
|
||
- 传 `groupBatchId` / `groupBatchKeyword` 时强制按团期,再与 `productType` 取 AND;在「核心 / 定制」页签下填团期关键词,只会查到挂了该团期、且产品类型是核心 / 定制的订单。
|
||
- `ROUTE`(自驾路书)后端接受,本次前端不设页签。
|
||
- 别名 `/v3/admin/order/list` 入参出参完全相同。
|
||
|
||
---
|
||
|
||
### 2. 订单列表 Tab 分组计数 `GET /v3/admin/order/status-group-counts`
|
||
|
||
**VO**: `OrderListReqVO` → `Result<List<StatusGroupCountVO>>`
|
||
|
||
#### 使用场景
|
||
|
||
页签切换时与列表一起请求,传同一个 `productType`,刷新顶部状态分组徽标。
|
||
|
||
#### 入参字段表
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| productType | query | String | 否 | `CORE`/`ROUTE`/`CUSTOM`/`GROUP`,多值用英文逗号分隔,空串等同不传 | **新增**。与列表同口径 |
|
||
| orderKind | query | String | 否 | `ALL`/`GROUP`/`NORMAL`,空串等同不传 | 原有。与列表同口径,含上面的例外 |
|
||
|
||
其余参数与列表相同(不传 `statusGroup` / `orderStatus` / `page` / `pageSize`)。
|
||
|
||
#### 出参字段表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| data[].group | String | 分组标识,固定 6 项,顺序 ALL、BEFORE_TRIP、ON_TRIP、SETTLEMENT、ABNORMAL、AFTERSALE |
|
||
| data[].label | String | 分组中文名:全部 / 出行前 / 出行中 / 核单 / 异常/取消 / 售后 |
|
||
| data[].orderCount | Number | 该分组订单数 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/status-group-counts?productType=GROUP
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
测试服 2026-09-27 实测原文:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": [
|
||
{ "group": "ALL", "label": "全部", "orderCount": 14 },
|
||
{ "group": "BEFORE_TRIP", "label": "出行前", "orderCount": 14 },
|
||
{ "group": "ON_TRIP", "label": "出行中", "orderCount": 0 },
|
||
{ "group": "SETTLEMENT", "label": "核单", "orderCount": 0 },
|
||
{ "group": "ABNORMAL", "label": "异常/取消", "orderCount": 8 },
|
||
{ "group": "AFTERSALE", "label": "售后", "orderCount": 0 }
|
||
],
|
||
"traceId": null,
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
没有符合条件的订单时 6 项仍全部返回,`orderCount` 均为 0。
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": [
|
||
{ "group": "ALL", "label": "全部", "orderCount": 0 },
|
||
{ "group": "BEFORE_TRIP", "label": "出行前", "orderCount": 0 },
|
||
{ "group": "ON_TRIP", "label": "出行中", "orderCount": 0 },
|
||
{ "group": "SETTLEMENT", "label": "核单", "orderCount": 0 },
|
||
{ "group": "ABNORMAL", "label": "异常/取消", "orderCount": 0 },
|
||
{ "group": "AFTERSALE", "label": "售后", "orderCount": 0 }
|
||
],
|
||
"traceId": null,
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 错误响应
|
||
|
||
与列表相同,非法值返回 HTTP 200 + `code=100001`(测试服实测原文):
|
||
|
||
```json
|
||
{
|
||
"code": 100001,
|
||
"message": "productType 非法,可选值: CORE, ROUTE, CUSTOM, GROUP(多值用逗号分隔)",
|
||
"data": null,
|
||
"traceId": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 与列表共用 `OrderListReqVO` 和同一套过滤,页签徽标与列表条数同口径。
|
||
- 「全部」= 出行前 + 出行中 + 核单,**不含**「异常/取消」,只有显式 `orderKind=ALL` 或 `cancelled=true` 时才计入。只传 `productType` 时不含,与两个参数都不传时一致。上例 14 = 14 + 0 + 0。
|
||
- 「售后」是横切计数,任何情况下都不计入「全部」。
|
||
|
||
---
|
||
|
||
## 四、契约约束与正确调用方式
|
||
|
||
- 页签「核心 / 定制 / 团期」→ 列表与计数都传 `productType=CORE|CUSTOM|GROUP`,**不传 `orderKind`**。
|
||
- 如果仍带着旧的 `orderKind=NORMAL`,会与 `productType` 取 AND,「团期」页签恒为空。
|
||
- 旧调用方(只传 `orderKind` 或都不传)行为不变。
|
||
|
||
| 组合 | 结果 |
|
||
|------|------|
|
||
| `productType=CORE` | 核心产品订单,不看是否挂团期 |
|
||
| `productType=CORE,CUSTOM` | 核心 + 定制 |
|
||
| `productType=GROUP&orderKind=NORMAL` | 恒为空 |
|
||
| 两个都不传 | 缺省 NORMAL(未挂团期的订单),与改动前一致 |
|
||
| `productType=XYZ` | HTTP 200,`code=100001` |
|
||
|
||
---
|
||
|
||
## 五、数据库行为
|
||
|
||
无数据库变更,只新增查询条件 `product_type IN (...)`。
|
||
|
||
---
|
||
|
||
## 六、边界行为
|
||
|
||
1. `productType` 是独立追加的 AND 条件,不进团属性判断链,所以不会和 `groupBatchId` / `groupBatchKeyword` 互相吞掉(`OrderListScopeFilter.java:44`、`:54-55`)。
|
||
2. 只传 `productType` 时 Service 把 `orderKind` 置 null 而不是 `ALL`:置 `ALL` 会让「全部」徽标计入已取消(`OrderService.java:529`)。
|
||
3. `ROUTE` 测试服当前产品与订单都是 0 条,后端已支持,将来加页签无需改后端。
|
||
|
||
---
|
||
|
||
## 六.5、枚举 / 数据字典
|
||
|
||
### productType(产品类型)
|
||
|
||
**所属字段**: 入参 `OrderListReqVO.productType`、出参 `records[].productType` | **类型**: `String`
|
||
|
||
| 值 | 中文 | 页签 |
|
||
|----|------|------|
|
||
| `CORE` | 核心 | 核心 |
|
||
| `CUSTOM` | 定制 | 定制 |
|
||
| `GROUP` | 团期 | 团期 |
|
||
| `ROUTE` | 自驾路书 | 本次不设 |
|
||
|
||
---
|
||
|
||
## 六.6、修改前后对比
|
||
|
||
| 场景 | 改前 | 改后 |
|
||
|------|------|------|
|
||
| 入参 `productType` | 无 | 新增,多值 |
|
||
| 只传 `productType`、不传 `orderKind` | —(参数不存在) | 不缺省 NORMAL,不按团属性过滤 |
|
||
| 只传 `orderKind` 或都不传 | 都不传时缺省 NORMAL | 不变 |
|
||
|
||
---
|
||
|
||
## 六.7、影响评估
|
||
|
||
- **向后兼容**:是。不传 `productType` 的调用方行为不变。
|
||
- **前端是否必须同步**:前端改页签时列表与计数都要改传 `productType`、删掉 `orderKind`;不改前端时现有下拉照常可用。
|
||
|
||
---
|
||
|
||
## 七、不影响范围
|
||
|
||
- 订单详情、创建、编辑等其他接口不变。
|
||
- 定制师待办列表(`DesignerOrderListService`)、财务订单查询(`FinanceOrderQueryApiImpl`)复用同一查询对象但不设 `productTypes`,行为不变。
|
||
- 小程序(`MpOrderListReqVO`)、H5 不涉及。
|
||
|
||
---
|
||
|
||
## 八、测试环境已验证
|
||
|
||
测试服 order-v3 `22145977d`,经网关、测试专用 ADMIN 账号,逐条与同条件 SQL(`hl_order_service_v3.order_main`,`deleted_at IS NULL`,默认排除已取消)比对,全部一致:
|
||
|
||
| 请求 | total / 计数 | SQL |
|
||
|------|------|------|
|
||
| `productType=CORE` / `CUSTOM` / `GROUP` | 71 / 2 / 14,逐条 productType 全匹配 | 71 / 2 / 14 |
|
||
| 同上 + `statusGroup=ALL` | 86 / 2 / 22 | 86 / 2 / 22 |
|
||
| `/v3/admin/order/list?productType=GROUP` | 14 | 与主路径相同 |
|
||
| `productType=CORE,CUSTOM` | 73 | 71 + 2 |
|
||
| `productType=`(空串)/ 都不传 | 73 / 73 | NORMAL 口径 73 |
|
||
| `orderKind=GROUP` / `orderKind=ALL` | 14 / 87 | 14 / 87 |
|
||
| 计数 `productType=GROUP` | 全部 14、出行前 14、出行中 0、核单 0、异常/取消 8、售后 0 | 逐组一致 |
|
||
| 计数不传 productType | 全部 73、出行前 43、出行中 0、核单 30、异常/取消 15、售后 0 | 与上一行不同,参数生效 |
|
||
| 团期关键词 / + `productType=GROUP` / + `productType=CORE` | 12 / 12 / 0 | 该团期 CORE 订单 0 条 |
|
||
| `productType=XYZ`(列表、计数) | HTTP 200,`code=100001` | — |
|
||
|
||
单测:OrderServiceTest 323、OrderListScopeFilterTest 18、OrderListReqVOValidationTest 16、OrderGlobalExceptionHandlerTest 9、OrderControllerTest 56、OrderInfoMapperIT 30(Testcontainers 真库),全绿。
|
||
|
||
---
|
||
|
||
## 十、相关文档
|
||
|
||
- 接口文档:`docs/order-v3/api/API-SPEC.html`(订单列表参数表、orderKind 例外、§1.11 计数口径)
|
||
- 入参:`hl-order-service-v3/src/main/java/com/hulalv/order/core/controller/admin/vo/OrderListReqVO.java:91-104`(productType)、`:59-63`(orderKind 例外说明)
|
||
- 过滤:`hl-order-service-v3/src/main/java/com/hulalv/order/core/mapper/OrderListScopeFilter.java:54-55`
|
||
- 错误码:`hl-order-service-v3/src/main/java/com/hulalv/shared/exception/OrderGlobalExceptionHandler.java:104-110`
|
||
|
||
---
|
||
|
||
## 关联 / 联系人
|
||
|
||
### 链接
|
||
|
||
- **Issue**: [#8446](https://git.1814.love/wx/HL/issues/8446)
|
||
- **PR**: [#8454](https://git.1814.love/wx/HL/pulls/8454)
|
||
- **前端 changelog**: `27_frontend_订单列表订单类型改页签-前端优化-管理后台.md`
|
||
|
||
### 联系人
|
||
|
||
- **后端负责人**: @wx
|
||
- **前端负责人**: @mmg
|