---
schema: "hl-changelog/v2"
ticket: "5820"
title: "主报账人报账表出参重构：顶层三维化 + 支出行统一扁平字段（破坏性变更）"
consumer: "admin"
change_type: "修改接口"
author: "yaosutu(GIT)"
backend_status: "deployed"
gateway_status: "pending"
frontend_status: "implemented"
frontend_owner: "mmg"
frontend_ref: "fd070dc2"
target_release: ""
verified_at: "2026-08-11"
status_note: "前端已实现(2026-08-11,mmg,fd070dc2),仅 driver/reimbursement 分支,group 单团核算未重构零改动:①adaptSettlementReport 的 reportStatus/confirmedAt 改优先读 baseInfo 回退顶层(不改则 confirmed 恒 false);②driver 汇总卡 6 字段改读 baseInfo,公共预支 publicPrepaidAmount→approvedAdvanceAmount,删 transferDirection 改 reporterNetAmount 正负推导(正=报账人应转回公司/负=公司应补报账人,金额取 transferAmount);③REPORT_DETAIL_CONFIG.driver 删 vehicleLines 项(车辆并入 expenseLines category=VEHICLE 逐天一行);④REPORT_FIELD_LABELS 补 date/reimburseAmount,expenseLines 12 扁平明细列数据驱动自适应。orderHeader 新增 returnDate/travelerCount 未接入(ReportModal 标题栏取 props.order 不读 orderHeader,按本次范围不接)。测试:ReportModal.spec 重构 fixture+1 baseInfo 方向推导用例,returnDetailAdapter.spec +4 baseInfo 兼容用例,settlement 91+4 全绿,checkpoint 精确文件集全过。"
updated_at: "2026-08-11"
base: "dev-v3"
---

# 【⚠️ 修改接口·管理后台】主报账人报账表出参重构：顶层三维化 + 支出行统一扁平字段（#5820 / #5859）

## 1. 接口背景

核单结算域的「主报账人报账表」接口，供管理后台在订单核单时查看主报账人（通常是司机）的代收、垫付支出、预支与净额结算情况。

本次重构解决两个历史问题：

1. **出参结构混乱**（#5820）：原出参把 30+ 个汇总字段平铺在顶层，支出行按费用类别拆成 7 族各自一套字段名（住宿用 hotelName/roomTypeName/stayDate、餐食用 mealName/mealTypeName/mealDate、门票用 scenicName/specName/dayDate、车辆用 vehiclePlate/driverName/serviceDate/dailyPrice……），前端需要为每类支出写一套渲染逻辑，且存在 4 对语义重复的镜像字段。
2. **订单抬头字段不全 + 方向字段冗余**（#5859）：baseInfo.transferDirection 与 transferAmount 正负 / reporterNetAmount 表达的信息重复；orderHeader 缺返回日期与出行人总数。

## 2. 变更清单

| # | 变更 | 类型 |
|---|------|------|
| 1 | 顶层 30+ 平铺汇总字段全部收拢进 baseInfo 子对象 | ⚠️ 破坏性 |
| 2 | expenseLines 支出行由 7 族稀疏字段统一为同一套 12 个扁平字段 | ⚠️ 破坏性 |
| 3 | 顶层 vehicleLines 字段删除（车辆支出行并入 expenseLines，签单/公司直付不再重复列出） | ⚠️ 破坏性 |
| 4 | baseInfo 删除 6 个冗余字段：reconNetAmount / driverCollectedTailAmount / publicPrepaidAmount / advanceOutstandingAmount / transferStatus / transferDirection | ⚠️ 破坏性 |
| 5 | 报账口径明确为口径 A：expenseLines 只含报账人垫付（CASH_PAID）支出 | 🔧 行为变化 |
| 6 | orderHeader 新增 returnDate（返回日期）、travelerCount（出行人总数） | ✨ 新增字段 |

## 3. 接口详情

| 项 | 值 |
|---|---|
| 方法 + 路径 | GET /v3/admin/order/{orderId}/settlement/reports/reimbursement |
| 接口名 | 查询主报账人报账表 |
| 使用场景 | 管理后台订单核单页，查看主报账人代收/垫付/预支/净额结算报表 |
| 认证 | 管理后台 JWT（/v3/admin/* 走网关鉴权） |
| 角色限制 | 房务角色（HOUSE）不可访问，调了会被拦截 |
| 幂等性 | 只读查询，幂等 |
| 限流 | 走网关默认限流，无接口级特殊限流 |

## 4. 接口入参

### 4.1 路径参数

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| orderId | Long | 是 | 订单 ID，必须大于 0 |

### 4.2 请求体

无请求体，无 Query 参数。

## 5. 出参字段

统一响应 Result<SettlementReimbursementReportRespVO>，data 结构如下。

### 5.1 顶层结构

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| baseInfo | Object | 是 | 基础信息（汇总值 + 报账人 + 审计字段），恒下发对象 |
| orderHeader | Object | 否 | 订单头（订单号/团号/产品/客户/出团日期/定制师/出行人构成） |
| incomeLines | Array | 是 | 收入行（司机代收）；无数据固定返回空数组 [] |
| expenseLines | Array | 是 | 支出行（统一扁平字段，仅报账人垫付支出）；无数据固定返回空数组 [] |
| advanceLines | Array | 是 | 预支明细行（已审批预支逐条）；无数据固定返回空数组 [] |

> 顶层**不再有任何平铺的汇总金额字段**，也**不再有 vehicleLines**。

### 5.2 baseInfo 字段表

| 字段 | 类型 | 说明 |
|------|------|------|
| id | Long(String) | 核单记录 ID（settlement_recon.recon_id）；未生成时为空。Long 序列化为字符串防 JS 精度丢失 |
| orderId | Long(String) | 订单 ID，序列化为字符串 |
| reportStatus | String | 报表状态，枚举：GENERATED（已生成）/ CONFIRMED（已确认） |
| reportVersion | Integer | 报表版本号，固定从 1 开始 |
| primaryReporterId | Long(String) | 主报账人人员安排 ID |
| primaryReporterName | String | 主报账人姓名 |
| primaryReporterRole | String | 主报账人角色（如 DRIVER） |
| primaryReporterCollectedAmount | BigDecimal | 主报账人代收金额（收入行合计），保留两位小数 |
| approvedAdvanceAmount | BigDecimal | 已审批预支金额（预支行合计），保留两位小数 |
| reportablePaidCostAmount | BigDecimal | 可报账已付成本（支出行合计），保留两位小数 |
| reporterNetAmount | BigDecimal | 报账人净额（代收 + 预支 - 支出）；正 = 报账人应转回公司，负 = 公司应补报账人 |
| primaryReporterDueAmount | BigDecimal | 主报账人应收尾款（核单口径），保留两位小数 |
| transferAmount | BigDecimal | 转账金额（净额绝对值），保留两位小数 |
| generatedBy | Long(String) | 生成人 ID |
| generatedByName | String | 生成人姓名 |
| generatedAt | String | 生成时间，格式 yyyy-MM-dd HH:mm:ss |
| confirmedBy | Long(String) | 确认人 ID；未确认时为空 |
| confirmedByName | String | 确认人姓名；未确认时为空 |
| confirmedAt | String | 确认时间，格式 yyyy-MM-dd HH:mm:ss；未确认时为空 |

**转账方向判定**（替代被删的 transferDirection）：

- reporterNetAmount > 0 → 报账人应转回公司
- reporterNetAmount < 0 → 公司应补报账人
- transferAmount = |reporterNetAmount|

### 5.3 orderHeader 字段表

| 字段 | 类型 | 说明 |
|------|------|------|
| orderNo | String | 订单号 |
| teamNo | String | 团号（订金未支付为 null） |
| productName | String | 产品名 |
| productType | String | 产品类型枚举（如 CORE） |
| productTypeName | String | 产品类型中文名（字典 product_type 回填） |
| customerName | String | 客户姓名 |
| departDate | String | 出团日期，格式 yyyy-MM-dd |
| returnDate | String | **新增**：返回日期，格式 yyyy-MM-dd |
| consultantName | String | 定制师姓名 |
| travelerCount | Integer | **新增**：出行人总数（成人+儿童+幼童+婴儿，空档按 0 计） |
| travelerComposition | String | 出行人构成（数量为 0 的档不显示，全空为 null），如 "2大 1儿童 1幼童" |

### 5.4 expenseLines 支出行字段表（统一扁平 12 字段）

**所有分类共用同一套字段**，前端单 table 渲染即可，不用再按类别分叉。

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| category | String | 是 | 费用类别 code：HOTEL / TICKET / MEAL / VEHICLE / GUIDE / PHOTOGRAPHER / OTHER_EXPENSE / INSURANCE |
| categoryName | String | 是 | 费用类别中文名（字典 settlement_category） |
| itemName | String | 是 | 项目名（分类特有信息折叠，见下方折叠规则表） |
| unitPrice | BigDecimal | 否 | 单价，保留两位小数；**无单价概念的分类不输出该键** |
| quantity | BigDecimal | 否 | 数量（住宿=房间数，餐食=份数，门票=票数，车辆按天每行=1）；**无数量概念的分类不输出该键** |
| amount | BigDecimal | 是 | 实际金额，保留两位小数 |
| reimburseAmount | BigDecimal | 是 | 报账金额，保留两位小数；人员行应报销与金额不同时分别给出，其余分类与 amount 相同 |
| paymentMethod | String | 是 | 付款方式；报账支出行固定 CASH_PAID |
| paymentMethodName | String | 是 | 付款方式中文名（字典 settlement_payment_method，缺值回退硬编码），如 "现金已付" |
| date | String | 是 | 业务日期，格式 yyyy-MM-dd（住宿=入住日，门票=游玩日，餐食=用餐日，车辆=服务日，人员=结算日） |
| remark | String | 否 | 备注；**无备注时不输出该键** |
| voucherUrls | Array<String> | 否 | 凭证 URL 数组；**无凭证时不输出该键** |

**itemName 折叠规则**（按 category）：

| category | itemName 格式 | 示例 |
|----------|--------------|------|
| HOTEL | 酒店名-房型 | 呼伦贝尔香格里拉大酒店-大床房 |
| TICKET | 景区名-规格 | 套娃景区-成人票 |
| MEAL | 餐食名(餐类型) | 手把肉套餐(午餐) |
| VEHICLE | 车牌 车型/司机 | 蒙A-E2E01 丰田普拉多/巴雅尔 |
| GUIDE / PHOTOGRAPHER | 人员姓名 | 巴特尔 |
| OTHER_EXPENSE / INSURANCE | 项目名 | 旅游意外险 |

### 5.5 incomeLines 收入行字段表（本次未动）

| 字段 | 类型 | 说明 |
|------|------|------|
| type | String | 行类型 code |
| typeName | String | 行类型中文名（字典 settlement_report_line_type） |
| receiptId | Long(String) | 线下收款记录 ID |
| amount | BigDecimal | 收款金额，保留两位小数 |
| channel | String | 收款渠道 code |
| channelName | String | 收款渠道中文名（PaymentChannelEnum 枚举 label） |
| payType | String | 收款款项类型 code |
| payTypeName | String | 收款款项类型中文名（PayType 枚举 label） |
| collectorStaffId | Long(String) | 收款人人员安排 ID |
| collectorName | String | 收款人姓名 |
| collectorRole | String | 收款人角色 code |
| collectorRoleName | String | 收款人角色中文名（字典 staff_role） |
| receivedAt | String | 收款时间，格式 yyyy-MM-dd HH:mm:ss |
| remark | String | 备注；无备注时为空 |

### 5.6 advanceLines 预支明细行字段表（本次未动）

| 字段 | 类型 | 说明 |
|------|------|------|
| type | String | 行类型 code |
| typeName | String | 行类型中文名（字典 settlement_report_line_type），如 "已审批预支" |
| advanceId | Long(String) | 预支单 ID |
| payeeStaffId | Long(String) | 借款对象人员安排 ID |
| payeeName | String | 借款对象姓名 |
| payeeRole | String | 借款对象角色 code |
| payeeRoleName | String | 借款对象角色中文名（字典 staff_role） |
| advanceType | String | 预支类型 code |
| advanceTypeName | String | 预支类型中文名（字典 advance_type），如 "住宿押金" |
| amount | BigDecimal | 预支金额，保留两位小数 |
| purpose | String | 预支用途 |
| voucherUrl | String | 凭证 URL |
| status | String | 预支状态 code |
| statusText | String | 预支状态中文名（AdvanceStatus 枚举 label），如 "已通过" |
| submittedAt | String | 提交时间，格式 yyyy-MM-dd HH:mm:ss |
| approvedAt | String | 审批时间，格式 yyyy-MM-dd HH:mm:ss |
| approvedBy | String | 审批人姓名 |

## 6. 枚举 / 数据字典

| 字段 | 来源 | 取值 |
|------|------|------|
| baseInfo.reportStatus | 枚举 | GENERATED（已生成）/ CONFIRMED（已确认） |
| expenseLines.category | 字典 settlement_category | HOTEL（住宿）/ TICKET（门票/游玩项目）/ MEAL（餐食）/ VEHICLE（车辆）/ GUIDE（导游）/ PHOTOGRAPHER（摄影师）/ OTHER_EXPENSE（其他费用）/ INSURANCE（保险） |
| expenseLines.paymentMethod | 字典 settlement_payment_method | 报账支出行固定 CASH_PAID（现金已付） |
| incomeLines.channel | PaymentChannelEnum | 收款渠道枚举 |
| incomeLines.payType | PayType 枚举 | 收款款项类型枚举（如尾款） |
| advanceLines.status | AdvanceStatus 枚举 | 预支状态（如已通过） |
| orderHeader.productType | 字典 product_type | 产品类型 |

**已删除的枚举字段**：transferStatus（#5816 连带下线）、transferDirection（#5859 删除，方向由 transferAmount 正负 / reporterNetAmount 表达）。

## 7. 错误码

| code | message | 触发场景 |
|------|---------|----------|
| 581007 | 订单不存在 | orderId 查不到订单 |
| 584088 | 核单凭证数据损坏，请联系管理员处理 | 快照读回时凭证数据异常（脏行），不会抛 500 |
| 400 | 订单 ID 必须大于 0 | orderId 路径参数校验失败 |

## 8. 示例

### 8.1 典型成功

请求：

    GET /v3/admin/order/2087088947225038849/settlement/reports/reimbursement

响应（已核单 CONFIRMED 订单，含住宿/门票/餐食/车辆支出 + 一条已审批预支）：

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "baseInfo": {
      "id": "2087089146102255617",
      "orderId": "2087088947225038849",
      "reportStatus": "CONFIRMED",
      "reportVersion": 1,
      "primaryReporterId": "7001",
      "primaryReporterName": "巴雅尔",
      "primaryReporterRole": "DRIVER",
      "primaryReporterCollectedAmount": 0,
      "approvedAdvanceAmount": 3000.00,
      "reportablePaidCostAmount": 1799.00,
      "reporterNetAmount": -4799.00,
      "primaryReporterDueAmount": 0,
      "transferAmount": 4799.00,
      "generatedBy": "2037350531801993218",
      "generatedByName": "腰苏图",
      "generatedAt": "2026-08-11 16:10:03",
      "confirmedBy": "2037350531801993218",
      "confirmedByName": "腰苏图",
      "confirmedAt": "2026-08-11 16:10:03"
    },
    "orderHeader": {
      "orderNo": "HL20260811001",
      "teamNo": "T20260811001",
      "productName": "呼伦贝尔草原 5 日游",
      "productType": "CORE",
      "productTypeName": "核心产品",
      "customerName": "张三",
      "departDate": "2026-08-29",
      "returnDate": "2026-09-02",
      "consultantName": "李四",
      "travelerCount": 5,
      "travelerComposition": "2大 1儿童 1幼童"
    },
    "incomeLines": [],
    "expenseLines": [
      {
        "category": "HOTEL",
        "categoryName": "住宿",
        "itemName": "呼伦贝尔香格里拉大酒店-大床房",
        "unitPrice": 320.00,
        "quantity": 1,
        "amount": 320.00,
        "reimburseAmount": 320.00,
        "paymentMethod": "CASH_PAID",
        "paymentMethodName": "现金已付",
        "date": "2026-08-29",
        "remark": "含早",
        "voucherUrls": ["https://oss.example.com/voucher/hotel-1.jpg"]
      },
      {
        "category": "TICKET",
        "categoryName": "门票/游玩项目",
        "itemName": "套娃景区-成人票",
        "unitPrice": 99.00,
        "quantity": 1,
        "amount": 99.00,
        "reimburseAmount": 99.00,
        "paymentMethod": "CASH_PAID",
        "paymentMethodName": "现金已付",
        "date": "2026-08-30"
      },
      {
        "category": "MEAL",
        "categoryName": "餐食",
        "itemName": "手把肉套餐(午餐)",
        "unitPrice": 68.00,
        "quantity": 5,
        "amount": 340.00,
        "reimburseAmount": 340.00,
        "paymentMethod": "CASH_PAID",
        "paymentMethodName": "现金已付",
        "date": "2026-08-30"
      },
      {
        "category": "VEHICLE",
        "categoryName": "车辆",
        "itemName": "蒙A-E2E01 丰田普拉多/巴雅尔",
        "unitPrice": 1000.00,
        "quantity": 1,
        "amount": 1000.00,
        "reimburseAmount": 1000.00,
        "paymentMethod": "CASH_PAID",
        "paymentMethodName": "现金已付",
        "date": "2026-08-29"
      }
    ],
    "advanceLines": [
      {
        "type": "APPROVED_ADVANCE",
        "typeName": "已审批预支",
        "advanceId": "5001",
        "payeeStaffId": "7001",
        "payeeName": "巴雅尔",
        "payeeRole": "DRIVER",
        "payeeRoleName": "司机",
        "advanceType": "ACCOMMODATION_DEPOSIT",
        "advanceTypeName": "住宿押金",
        "amount": 3000.00,
        "purpose": "酒店押金",
        "voucherUrl": "https://oss.example.com/advance-v1.jpg",
        "status": "APPROVED",
        "statusText": "已通过",
        "submittedAt": "2026-08-28 10:00:00",
        "approvedAt": "2026-08-28 12:00:00",
        "approvedBy": "财务丙"
      }
    ]
  },
  "traceId": null,
  "success": true
}
```

### 8.2 边界情况

**边界 1：零收入零预支零支出**（刚生成报表、尚未录任何行）——三个数组固定返回空数组，不是 null：

```json
{
  "code": 200,
  "data": {
    "baseInfo": {
      "id": "2087089146102255617",
      "orderId": "2087088947225038849",
      "reportStatus": "GENERATED",
      "reportVersion": 1,
      "primaryReporterId": "7001",
      "primaryReporterName": "巴雅尔",
      "primaryReporterRole": "DRIVER",
      "primaryReporterCollectedAmount": 0,
      "approvedAdvanceAmount": 0,
      "reportablePaidCostAmount": 0,
      "reporterNetAmount": 0,
      "primaryReporterDueAmount": 0,
      "transferAmount": 0,
      "generatedBy": "2037350531801993218",
      "generatedByName": "腰苏图",
      "generatedAt": "2026-08-11 16:10:03",
      "confirmedBy": null,
      "confirmedByName": null,
      "confirmedAt": null
    },
    "orderHeader": {
      "orderNo": "HL20260811001",
      "teamNo": null,
      "productName": "呼伦贝尔草原 5 日游",
      "productType": "CORE",
      "productTypeName": "核心产品",
      "customerName": "张三",
      "departDate": "2026-08-29",
      "returnDate": "2026-09-02",
      "consultantName": "李四",
      "travelerCount": 0,
      "travelerComposition": null
    },
    "incomeLines": [],
    "expenseLines": [],
    "advanceLines": []
  },
  "success": true
}
```

**边界 2：人员行（GUIDE）+ 无凭证无备注 + 报销金额与金额不同**——unitPrice/quantity/remark/voucherUrls 键不输出：

```json
{
  "category": "GUIDE",
  "categoryName": "导游",
  "itemName": "巴特尔",
  "amount": 500.00,
  "reimburseAmount": 450.00,
  "paymentMethod": "CASH_PAID",
  "paymentMethodName": "现金已付",
  "date": "2026-08-31"
}
```

**边界 3：门票单价为 0**（免费票）——unitPrice: 0.0 正常输出，金额 0：

```json
{
  "category": "TICKET",
  "categoryName": "门票/游玩项目",
  "itemName": "蓝房子（乌苏浪子湖）-成人票",
  "unitPrice": 0.0,
  "quantity": 1,
  "amount": 0.0,
  "reimburseAmount": 0.0,
  "paymentMethod": "CASH_PAID",
  "paymentMethodName": "现金已付",
  "date": "2026-08-31"
}
```

### 8.3 业务失败

**订单不存在**：

    GET /v3/admin/order/999999999/settlement/reports/reimbursement

```json
{
  "code": 581007,
  "message": "订单不存在",
  "success": false
}
```

**参数校验失败**（orderId = 0）：

    GET /v3/admin/order/0/settlement/reports/reimbursement

```json
{
  "code": 400,
  "message": "订单 ID 必须大于 0",
  "success": false
}
```

**房务角色访问被拦**（House 角色 JWT 调用）：

```json
{
  "code": 403,
  "message": "无权限访问",
  "success": false
}
```

## 9. 业务边界

**适用**：
- 订单已进入核单流程（已生成核单记录），查看主报账人维度的结算报表
- 已核单（CONFIRMED）与核单中（GENERATED）订单均可调，报表实时计算

**不适用**：
- 未发起核单的订单：baseInfo.id 等审计字段为空，汇总金额为 0
- 需要看整团（含非报账人支付）口径时用单团核算表接口 GET /v3/admin/order/{orderId}/settlement/reports/group，本接口是报账人视角

**特殊边界**：
- **报账口径 A**：expenseLines 只含报账人垫付（CASH_PAID）的支出；签单 / 公司直接付的车务费**不进** expenseLines，前端不要期待在支出行里看到所有成本
- incomeLines 只含报账人代收，线上支付（微信等）不在此列
- 旧快照兼容：历史已确认报表的旧快照数据读回时，旧扁平键静默忽略、落默认空 baseInfo，不会抛 500

## 10. 修改前后对比

### 10.1 顶层结构对比

| 维度 | 修改前 | 修改后 |
|------|--------|--------|
| 汇总字段 | 30+ 个平铺在顶层（id/orderId/reportStatus/primaryReporterCollectedAmount/...） | 全部收拢进 baseInfo 子对象 |
| 车辆支出 | 顶层独立 vehicleLines 数组（车辆专属字段） | 删除；车辆支出行并入 expenseLines（category=VEHICLE） |
| 订单头 | orderHeader（9 字段） | orderHeader（11 字段，新增 returnDate/travelerCount） |

### 10.2 baseInfo 字段级对比（删除清单）

| 删除字段 | 原位置 | 替代取值 |
|----------|--------|----------|
| reconNetAmount | 顶层平铺 | baseInfo.reporterNetAmount（同值镜像） |
| driverCollectedTailAmount | 顶层平铺 | baseInfo.primaryReporterCollectedAmount（同值镜像） |
| publicPrepaidAmount | 顶层平铺 | baseInfo.approvedAdvanceAmount（同口径） |
| advanceOutstandingAmount | 顶层平铺 | 无替代（该口径废弃，预支看 approvedAdvanceAmount + advanceLines） |
| transferStatus | baseInfo（#5816 连带下线） | 无替代（转账状态跟踪能力下线） |
| transferDirection | baseInfo | 由 reporterNetAmount 正负判定：正=报账人应转回公司，负=公司应补报账人；金额取 transferAmount |

> 其余原顶层平铺字段（id/orderId/reportStatus/reportVersion/primaryReporter*/各金额/generated*/confirmed*）**字段名与语义不变**，仅位置从顶层移入 baseInfo。

### 10.3 expenseLines 字段级对比

| 修改前（按类别稀疏字段） | 修改后（统一扁平字段） |
|--------------------------|------------------------|
| HOTEL: hotelName / roomTypeName / stayDate / roomCount / unitPrice | itemName=「酒店-房型」/ date / quantity / unitPrice |
| TICKET: scenicName / specName / dayDate / ticketCount / ticketUnitPrice | itemName=「景区-规格」/ date / quantity / unitPrice |
| MEAL: mealName / mealTypeName / mealDate / quantity / unitPrice | itemName=「餐食名(餐类型)」/ date / quantity / unitPrice |
| VEHICLE: vehiclePlate / driverName / serviceDate / dailyPrice | itemName=「车牌 车型/司机」/ date / unitPrice（quantity 恒 1） |
| GUIDE/PHOTOGRAPHER: staffName / settledDate / amount / reimburseAmount | itemName=姓名 / date / amount / reimburseAmount |
| 各类各自的付款方式/备注/凭证字段名 | 统一 paymentMethod/paymentMethodName/remark/voucherUrls |

### 10.4 行为级对比

| 场景 | 修改前 | 修改后 |
|------|--------|--------|
| 签单/公司直付车务费 | 出现在 vehicleLines | 不出现在本接口任何行（口径 A：只列报账人垫付） |
| 支出行渲染 | 前端按 7 族类别各写一套列 | 单 table 统一 12 字段渲染 |
| 调旧字段（如 data.reportStatus、data.vehicleLines、data.baseInfo.transferDirection） | 有值 | **undefined**（字段不存在，不报错静默丢失） |

## 11. 影响评估 / 回滚

### 11.1 影响评估

- **破坏兼容性**：⚠️ 是。所有读顶层平铺汇总字段、读 vehicleLines、按类别分叉渲染支出行、读 transferStatus/transferDirection 的前端代码**全部失效**（取到 undefined）。
- **前端必须同步上线**：是。前端需要：
  1. 汇总字段读取路径从 data.xxx 改为 data.baseInfo.xxx
  2. 支出行渲染改为单 table 统一字段（category/categoryName/itemName/unitPrice/quantity/amount/reimburseAmount/paymentMethod/paymentMethodName/date/remark/voucherUrls）
  3. 删除 vehicleLines 相关渲染
  4. 转账方向展示改由 reporterNetAmount 正负 + transferAmount 推导
  5. 4 个镜像字段改读保留字段（见 §10.2 替代表）
- **后端兼容**：旧快照数据读回不报错（静默忽略旧键），无需数据迁移。

### 11.2 回滚方案

- 后端回滚 = revert PR #5839 + PR #5865 两个 merge commit，重启 hl-order-service-v3。出参即恢复旧结构。
- 前端回滚 = 切回旧版前端包。前后端必须同版本（新后端 + 旧前端 = 页面全空）。
- 无 DDL，无数据迁移，回滚无残留风险。

## 12. 注意事项

1. **所有 Long ID 字段（id/orderId/primaryReporterId/receiptId/advanceId/各种 staffId/generatedBy/confirmedBy）序列化为 JSON 字符串**，前端按 string 处理，不要 Number() 转换（防 JS 精度丢失）。
2. expenseLines 中 unitPrice / quantity / remark / voucherUrls 是**条件输出键**：无值时整个键不出现（NON_NULL），前端取值前判空。
3. reimburseAmount 大多数分类与 amount 相同；只有人员行（GUIDE/PHOTOGRAPHER）应报销与金额可能不同，展示报账口径时以 reimburseAmount 为准。
4. 转账方向不要再找 transferDirection 字段：用 reporterNetAmount > 0 判「报账人转回公司」、< 0 判「公司补报账人」，transferAmount 恒为绝对值。
5. orderHeader.travelerComposition 全空档时为 null，teamNo 订金未支付时为 null，展示需兜底。
6. 本接口与单团核算表 reports/group 是两个口径：本接口 = 主报账人视角（只含报账人垫付），group = 整团视角（含全部成本）。前端不要把两个接口的行混在一起渲染。
7. 车辆支出行在 expenseLines 里按服务日**逐天一行**（quantity 恒 1），不是一车一行。

## 13. 关联 / 联系人

- Issue：
  - https://git.1814.love:8443/wx/HL/issues/5820 （主报账人报账表 RespVO 重构）
  - https://git.1814.love:8443/wx/HL/issues/5859 （删 transferDirection + orderHeader 补 returnDate/travelerCount）
- PR：
  - https://git.1814.love:8443/wx/HL/pulls/5839 （#5820 出参重构）
  - https://git.1814.love:8443/wx/HL/pulls/5865 （#5859 orderHeader 补字段 + 删 transferDirection）
- 服务：hl-order-service-v3（端口 8086）
- 后端负责人：腰苏图
