docs(changelog): 8796 发票管理列表出参移除 stats 统计块(顶部4张统计卡片下线,tabCounts 保留)
changelog-filename-gate / validate (push) Failing after 3s
changelog-filename-gate / validate (push) Failing after 3s
这个提交包含在:
@@ -0,0 +1,340 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "8796"
|
||||
title: "发票管理列表出参移除顶部 stats 统计块(records / tabCounts 不变)"
|
||||
consumer: "admin"
|
||||
author: "yst"
|
||||
change_type: "修改接口"
|
||||
backend_status: "merged"
|
||||
gateway_status: "not_required"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: ""
|
||||
frontend_ref: ""
|
||||
target_release: ""
|
||||
verified_at: ""
|
||||
status_note: "产品决定下线发票管理列表顶部 4 张统计卡片;出参根级 stats 字段已删,tabCounts 角标计数保留。已合 dev-v3。前端需删除顶部统计卡片渲染逻辑。"
|
||||
updated_at: "2026-10-05"
|
||||
base: "dev-v3"
|
||||
---
|
||||
|
||||
# order-v3 invoice:发票管理列表出参移除 stats 统计块(管理后台)
|
||||
|
||||
> 注意:**破坏性变更(删字段)**:`GET /v3/admin/order/invoice/page` 出参根级 `stats` 字段已删除。前端若仍引用 `stats` 渲染顶部统计卡片,取到的将是 `undefined`,卡片会空白或异常,**必须同步下线该卡片渲染**。
|
||||
|
||||
## 1. 接口背景
|
||||
|
||||
管理后台「财务 → 发票管理」列表页顶部原有 4 张统计卡片:待开票 / 已开票·待推送 / 已推送 / 本月已开票,数据来自列表接口出参根级的 `stats` 数组。
|
||||
|
||||
产品决定不要这 4 张卡片了(#8796)。后端随之把 `stats` 统计块从列表接口出参整体移除,并清掉后端只为它服务的统计查询逻辑。列表行数据、tab 角标计数均不受影响。
|
||||
|
||||
## 2. 变更清单
|
||||
|
||||
| # | 接口 | 变更点 | 类型 |
|
||||
|---|------|--------|------|
|
||||
| 1 | `GET /v3/admin/order/invoice/page` | 出参根级删除 `stats` 字段(原 InvoiceStatItemVO 数组:4 项统计卡片数据) | 出参字段删除 |
|
||||
|
||||
入参、路径、`records` 列表行结构、`tabCounts` 角标计数**全部不变**。
|
||||
|
||||
## 3. 接口详情
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| 服务 | hl-order-service-v3(端口 8086) |
|
||||
| 路径 | `GET /v3/admin/order/invoice/page` |
|
||||
| 使用场景 | 管理后台 → 财务 → 发票管理列表(分页 + tab 过滤 + 搜索) |
|
||||
| 认证 | 管理后台登录态(JWT);网关既有路由 `/v3/admin/**`,无新增网关配置 |
|
||||
| 幂等性 | 纯查询,天然幂等 |
|
||||
| 限流 | 无特殊限流 |
|
||||
|
||||
## 4. 接口入参
|
||||
|
||||
**入参零变化**(Query 参数):
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| pageNo | int | 否 | 页码,默认 1 |
|
||||
| pageSize | int | 否 | 每页条数,默认 10 |
|
||||
| tab | string | 否 | tab 过滤:REQUESTED(待开票)/ ISSUED(待推送)/ PUSHED(已推送)/ NONE(未申请)/ ALL(全部),默认 ALL |
|
||||
| orderNo | string | 否 | 订单号模糊搜索 |
|
||||
| contactName | string | 否 | 客户名(主联系人)模糊搜索 |
|
||||
| titleName | string | 否 | 开票抬头模糊搜索(NONE tab 传此参数结果置空) |
|
||||
| requestedBy | string | 否 | 申请人(定制师/用户姓名)模糊搜索 |
|
||||
|
||||
## 5. 出参字段
|
||||
|
||||
响应统一包装 `Result<InvoicePageRespVO>`,`data` 结构如下。
|
||||
|
||||
### 5.1 顶层结构(变更后现状)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| records | array | 发票列表行(结构见 5.2) |
|
||||
| total | long | 总条数 |
|
||||
| page | int | 当前页码 |
|
||||
| pageSize | int | 每页条数 |
|
||||
| tabCounts | array | 各 tab 计数(**保留不变**,见 5.3) |
|
||||
| ~~stats~~ | ~~array~~ | **已删除**,不再返回 |
|
||||
|
||||
部署后实测出参顶层 keys = `["records", "total", "page", "pageSize", "tabCounts"]`,已无 `stats`。
|
||||
|
||||
### 5.2 records 列表行(InvoicePageItemRespVO,本次未动)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | string | 发票 ID(字符串防 JS 精度丢失) |
|
||||
| orderId | string | 订单 ID(字符串) |
|
||||
| orderNo | string | 订单号 |
|
||||
| productName | string | 产品名 |
|
||||
| productCoverImg | string | 产品封面图 URL |
|
||||
| tierName | string | 档位名 |
|
||||
| contactName | string | 客户名(主联系人) |
|
||||
| customizerName | string | 定制师名 |
|
||||
| departureDate | string(yyyy-MM-dd) | 出发日期 |
|
||||
| adultCount | int | 成人数 |
|
||||
| childCount | int | 儿童数 |
|
||||
| youngChildCount | int | 婴儿/小童数 |
|
||||
| invoiceType | string | 发票类型(VAT_NORMAL / VAT_SPECIAL) |
|
||||
| invoiceTypeText | string | 发票类型文案 |
|
||||
| titleType | string | 抬头类型(COMPANY / PERSONAL) |
|
||||
| titleName | string | 开票抬头 |
|
||||
| taxNo | string | 税号 |
|
||||
| amount | number | 开票金额(元) |
|
||||
| email | string | 收件邮箱 |
|
||||
| status | string | 发票状态(REQUESTED / ISSUED / PUSHED / VOIDED) |
|
||||
| statusText | string | 状态文案(待开票 / 已开票 / 已推送 / 已作废) |
|
||||
| requestedBy | string | 申请人(定制师名或用户名) |
|
||||
| requestedAt | string | 申请时间 |
|
||||
| issuedAt | string | 开票时间(ISSUED 后有值) |
|
||||
| issuedBy | string | 开票人(财务员工名) |
|
||||
| invoiceNo | string | 发票号(财务登记) |
|
||||
| fileUrl | string | 发票文件 URL(ISSUED/PUSHED 后有值) |
|
||||
| pdfName | string | 发票 PDF 文件名 |
|
||||
| pdfSize | long | 文件大小(字节) |
|
||||
| teamNo | string | 团号 |
|
||||
| createTime | string | 订单创建时间 |
|
||||
| orderStatus | string | 订单状态 |
|
||||
| orderStatusText | string | 订单状态文案 |
|
||||
| flowStatus | string | 流程状态 |
|
||||
| flowStatusText | string | 流程状态文案 |
|
||||
| orderAmount | number | 订单应收总额(元) |
|
||||
| paidAmount | number | 累计已收(元) |
|
||||
| refundedAmount | number | 累计已退(元) |
|
||||
| settlementAmount | number | 核单金额(元) |
|
||||
|
||||
### 5.3 tabCounts 项(InvoiceTabCountVO,保留不变)
|
||||
|
||||
固定 5 项,顺序:REQUESTED / ISSUED / PUSHED / NONE / ALL:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| code | string | 状态编码(REQUESTED / ISSUED / PUSHED / NONE / ALL) |
|
||||
| name | string | 中文名(待开票 / 待推送 / 已推送 / 未申请 / 全部) |
|
||||
| count | int | 计数 |
|
||||
|
||||
tabCounts 为全局全量计数,**不受搜索条件影响**(此行为未变)。
|
||||
|
||||
## 6. 枚举 / 数据字典
|
||||
|
||||
本次无枚举变化。涉及枚举均为既有值:
|
||||
|
||||
| 枚举 | 取值 |
|
||||
|------|------|
|
||||
| tab | REQUESTED / ISSUED / PUSHED / NONE / ALL |
|
||||
| status(发票) | REQUESTED(待开票)/ ISSUED(已开票)/ PUSHED(已推送)/ VOIDED(已作废) |
|
||||
| invoiceType | VAT_NORMAL / VAT_SPECIAL |
|
||||
| titleType | COMPANY / PERSONAL |
|
||||
|
||||
原 `stats[].code` 的 4 个取值(REQUESTED / ISSUED / PUSHED / CURRENT_MONTH_ISSUED)随字段一并废弃,不再有消费方。
|
||||
|
||||
## 7. 错误码
|
||||
|
||||
本接口为查询接口,正常情况无业务错误码。公共错误(未登录 / 无权限)走网关与全局异常处理。发票域业务错误码(5815xx 段,如 581500 发票不存在等)本次无变化,且本列表接口不抛出。
|
||||
|
||||
## 8. 示例
|
||||
|
||||
### 8.1 典型成功(REQUESTED tab,第一页)
|
||||
|
||||
请求:
|
||||
|
||||
```
|
||||
GET /v3/admin/order/invoice/page?tab=REQUESTED&pageNo=1&pageSize=10
|
||||
```
|
||||
|
||||
响应(注意顶层已无 stats):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"records": [
|
||||
{
|
||||
"id": "1975812345678901234",
|
||||
"orderId": "1960123456789012345",
|
||||
"orderNo": "2026092800001",
|
||||
"productName": "呼伦贝尔草原 5 日定制游",
|
||||
"productCoverImg": "https://oss.example.com/cover/abc.jpg",
|
||||
"tierName": "舒适档",
|
||||
"contactName": "张三",
|
||||
"customizerName": "李定制",
|
||||
"departureDate": "2026-10-15",
|
||||
"adultCount": 2,
|
||||
"childCount": 1,
|
||||
"youngChildCount": 0,
|
||||
"invoiceType": "VAT_NORMAL",
|
||||
"invoiceTypeText": "增值税普通发票",
|
||||
"titleType": "COMPANY",
|
||||
"titleName": "北京某某科技有限公司",
|
||||
"taxNo": "91110108MA01C8XH3B",
|
||||
"amount": 12800.00,
|
||||
"email": "zhangsan@example.com",
|
||||
"status": "REQUESTED",
|
||||
"statusText": "待开票",
|
||||
"requestedBy": "李定制",
|
||||
"requestedAt": "2026-10-01 10:23:45",
|
||||
"issuedAt": null,
|
||||
"issuedBy": null,
|
||||
"invoiceNo": null,
|
||||
"fileUrl": null,
|
||||
"pdfName": null,
|
||||
"pdfSize": null,
|
||||
"teamNo": "T2026101501",
|
||||
"createTime": "2026-09-28 14:02:11",
|
||||
"orderStatus": "COMPLETED",
|
||||
"orderStatusText": "已完成",
|
||||
"flowStatus": "SETTLED",
|
||||
"flowStatusText": "已核单",
|
||||
"orderAmount": 12800.00,
|
||||
"paidAmount": 12800.00,
|
||||
"refundedAmount": 0.00,
|
||||
"settlementAmount": 12800.00
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"pageSize": 10,
|
||||
"tabCounts": [
|
||||
{ "code": "REQUESTED", "name": "待开票", "count": 1 },
|
||||
{ "code": "ISSUED", "name": "待推送", "count": 3 },
|
||||
{ "code": "PUSHED", "name": "已推送", "count": 12 },
|
||||
{ "code": "NONE", "name": "未申请", "count": 45 },
|
||||
{ "code": "ALL", "name": "全部", "count": 61 }
|
||||
]
|
||||
},
|
||||
"msg": ""
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 边界情况(搜索无命中,空列表)
|
||||
|
||||
请求:
|
||||
|
||||
```
|
||||
GET /v3/admin/order/invoice/page?tab=ALL&titleName=不存在的公司名&pageNo=1&pageSize=10
|
||||
```
|
||||
|
||||
响应(records 空数组、total=0,**tabCounts 仍为全局计数**,无 stats):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"records": [],
|
||||
"total": 0,
|
||||
"page": 1,
|
||||
"pageSize": 10,
|
||||
"tabCounts": [
|
||||
{ "code": "REQUESTED", "name": "待开票", "count": 1 },
|
||||
{ "code": "ISSUED", "name": "待推送", "count": 3 },
|
||||
{ "code": "PUSHED", "name": "已推送", "count": 12 },
|
||||
{ "code": "NONE", "name": "未申请", "count": 45 },
|
||||
{ "code": "ALL", "name": "全部", "count": 61 }
|
||||
]
|
||||
},
|
||||
"msg": ""
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 业务失败(未登录 / token 失效)
|
||||
|
||||
请求:
|
||||
|
||||
```
|
||||
GET /v3/admin/order/invoice/page?tab=ALL
|
||||
(不带 Authorization 头)
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 401,
|
||||
"data": null,
|
||||
"msg": "未登录或登录已过期"
|
||||
}
|
||||
```
|
||||
|
||||
## 9. 业务边界
|
||||
|
||||
- **适用**:财务在管理后台发票管理列表做分页浏览、tab 切换、按订单号/客户名/抬头/申请人搜索;tab 角标计数展示。
|
||||
- **不适用**:任何需要「待开票 / 已开票 / 已推送 / 本月已开票」汇总卡片数据的场景 —— 后端已不再提供该汇总,前端**不要**自行用 tabCounts 拼凑原 stats 语义(原 stats 含金额合计与「本月已开票」口径,tabCounts 只有张数且无金额维度,CURRENT_MONTH_ISSUED 当月维度无任何替代数据源)。
|
||||
- **特殊边界**:VOIDED(已作废)发票不进任何 tab,也不计入 tabCounts;NONE tab 传 titleName / requestedBy 搜索时结果强制为空(既有行为,未变)。
|
||||
|
||||
## 10. 修改前后对比
|
||||
|
||||
### 10.1 出参顶层结构对比
|
||||
|
||||
| 顶层字段 | 修改前 | 修改后 |
|
||||
|---------|--------|--------|
|
||||
| records | 有 | 有(不变) |
|
||||
| total | 有 | 有(不变) |
|
||||
| page | 有 | 有(不变) |
|
||||
| pageSize | 有 | 有(不变) |
|
||||
| tabCounts | 有 | 有(不变) |
|
||||
| stats | 有(4 项统计数组) | **已删除** |
|
||||
|
||||
### 10.2 被删除的 stats 项结构(原 InvoiceStatItemVO,仅作存档)
|
||||
|
||||
原 `stats` 为固定 4 项数组,顺序 REQUESTED / ISSUED / PUSHED / CURRENT_MONTH_ISSUED:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| code | string | 状态编码(REQUESTED / ISSUED / PUSHED / CURRENT_MONTH_ISSUED) |
|
||||
| name | string | 中文名(待开票 / 已开票·待推送 / 已推送 / 本月已开票) |
|
||||
| count | int | 张数 |
|
||||
| amount | number | 合计金额(元) |
|
||||
|
||||
### 10.3 行为级对比
|
||||
|
||||
| 场景 | 修改前 | 修改后 |
|
||||
|------|--------|--------|
|
||||
| 列表查询性能 | 每次查询额外执行统计聚合(按状态计数 + 金额合计、本月口径) | 不再执行统计聚合,查询更轻 |
|
||||
| tabCounts 值 | 全量计数不受搜索影响 | 同左(不变) |
|
||||
| 前端顶部卡片 | 可用 stats 渲染 4 张卡片 | 数据源消失,卡片必须下线 |
|
||||
|
||||
## 11. 影响评估 / 回滚
|
||||
|
||||
### 11.1 影响评估
|
||||
|
||||
- **破坏兼容**:是(删出参字段)。
|
||||
- 前端若仍引用 `data.stats` → 取到 `undefined`,顶部卡片空白或渲染异常(接口本身正常返回,不会报错)。
|
||||
- **需要前端同步上线**:是。发票管理页须删除顶部统计卡片渲染逻辑。上线顺序建议:前端先删卡片上线(安全,后端 stats 仍在但无人消费),后端版本随后生效;反向顺序则会出现卡片空白窗口。
|
||||
- tab 角标、列表行、搜索、分页逻辑零改动。
|
||||
|
||||
### 11.2 回滚方案
|
||||
|
||||
- 后端回滚 = revert PR #8797(恢复 stats 字段与统计查询)。
|
||||
- 前端如已删卡片渲染,回滚后端后卡片无数据渲染,需同步回滚前端或保持卡片下线(产品决定下线,原则上不回滚)。
|
||||
|
||||
## 12. 注意事项
|
||||
|
||||
1. **前端必做**:删除发票管理列表页顶部 4 张统计卡片(待开票 / 已开票·待推送 / 已推送 / 本月已开票)的全部渲染逻辑与相关样式,清理对 `data.stats` / `stats[]` 的所有引用与类型定义。
|
||||
2. 不要试图用 `tabCounts` 还原原统计卡片:原 stats 含金额合计(amount)与「本月已开票」(CURRENT_MONTH_ISSUED)口径,tabCounts 无此数据。
|
||||
3. 若产品后续需要恢复统计卡片,属新需求,需重新走 Issue 排期,不是回滚本变更。
|
||||
4. 本变更只影响 `GET /v3/admin/order/invoice/page` 一个接口;发票详情(`GET /v3/admin/order/invoice/{id}`)、开票 / 重传 / 推送等接口均未动。
|
||||
|
||||
## 13. 关联 / 联系人
|
||||
|
||||
- Issue:https://git.1814.love/wx/HL/issues/8796
|
||||
- PR:https://git.1814.love/wx/HL/pulls/8797
|
||||
- Commit:https://git.1814.love/wx/HL/commit/ba01a0719a
|
||||
- 后端负责人:@yst
|
||||
在新工单中引用
屏蔽一个用户