文件
hl-api-changelog/changelogs-v2/2026-10/05_8796_发票管理列表出参移除stats-修改接口-管理后台.md
T

13 KiB
原始文件 Blame 文件历史

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 8796 发票管理列表出参移除顶部 stats 统计块(records / tabCounts 不变) admin yst 修改接口 merged not_required pending 产品决定下线发票管理列表顶部 4 张统计卡片;出参根级 stats 字段已删,tabCounts 角标计数保留。已合 dev-v3。前端需删除顶部统计卡片渲染逻辑。 2026-10-05 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):

{
  "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):

{
  "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 头)

响应:

{
  "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. 关联 / 联系人