---
author: "yst(GIT)"
schema: "hl-changelog/v2"
ticket: "5356"
title: "车辆 Tab 三接口汇总"
consumer: "admin"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "partial"
frontend_status: "implemented"
frontend_owner: "Pi"
frontend_ref: "v2.1@21dccf38d1413b098cfd5a456d3fb76611581ebb"
target_release: ""
verified_at: "2026-08-02"
status_note: "汇总 #5356、#5360、#5380 已实现的车辆 Tab 现行契约；管理后台使用 Step3 GET/PUT 和 vehicle-options，并按 settlementReady/blockReasonCode 区分车辆两类空态。"
updated_at: "2026-08-05"
base: "dev-v3"
---

# 🔧【修改接口·管理后台】车辆 Tab 三接口汇总 (#5356 / #5360 / #5380)

> **服务**：`hl-order-service-v3` ｜ **更新时间**：2026-08-05 ｜ **消费端**：管理后台

## 1. 接口背景

车辆核单 Tab 需要一份可直接对接的完整契约：先用车辆下拉接口检索手工行候选，再读取车辆核单草稿，最后按草稿版本全量保存。本文汇总三个现行接口，并纳入车辆草稿查询的最新空状态语义；不替代或修改三份历史通知。

## 2. 变更清单

| # | 接口名 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 查询车辆核单草稿 | `GET` | `/v3/admin/order/{orderId}/settlement/step3/vehicles` | 修改 | 返回车辆核单全量草稿；空结果用 `settlementReady/blockReasonCode` 区分是否可继续核单 |
| 2 | 全量保存车辆核单草稿 | `PUT` | `/v3/admin/order/{orderId}/settlement/step3/vehicles` | 修改 | 携带 `version` 全量保存，保护 `FLEET` 权威行并返回保存后的完整草稿 |
| 3 | 查询核单车辆异步下拉 | `GET` | `/v3/admin/order/{orderId}/settlement/vehicle-options` | 新增 | 按车牌、品牌型号、车型大类或常驻司机姓名检索候选车辆 |

三个接口均要求管理后台登录态和订单查看权限，房务角色不可访问；无接口级特殊限流。两个 GET 为只读幂等，PUT 以当前 `version` 和全量 `items` 保存。

## 3. 接口详情

### 3.1 查询车辆核单草稿

- **接口说明**：查询车辆 Tab 当前全量明细、草稿版本、确认状态以及车辆费用是否具备完成核单条件。
- **方法与路径**：`GET /v3/admin/order/{orderId}/settlement/step3/vehicles`
- **认证**：管理后台登录态；需满足订单查看权限；房务角色不可访问。
- **幂等性**：是，只读查询。
- **限流**：未声明独立限流规则。

**路径参数**

| 字段 | 类型 | 必填 | 说明与校验 |
|---|---|---|---|
| `orderId` | String(Long) | 是 | 订单 ID，必须为正整数；按字符串传递 |

无 Query 参数、无请求体。

**统一响应外层**

| 字段 | 类型 | 可空 | 说明 |
|---|---|---|---|
| `code` | Integer | 否 | 成功为 `200` |
| `message` | String | 否 | 结果说明 |
| `data` | VehicleDraft/null | 失败时为空 | 成功时为车辆核单草稿 |
| `traceId` | String | 是 | 链路追踪 ID |
| `success` | Boolean | 否 | `code=200` 时为 `true` |

**成功响应 `data`**

| 字段 | 类型 | 可空 | 说明 |
|---|---|---|---|
| `orderId` | String(Long) | 否 | 订单 ID，按字符串返回 |
| `version` | Long | 否 | 当前草稿版本；首次空结果为 `0` |
| `totalAmount` | Decimal | 否 | 全部车辆明细金额合计；空结果为 `0.00` |
| `allConfirmed` | Boolean | 否 | 非空明细是否全部确认；空状态取值见判定表 |
| `settlementReady` | Boolean | 否 | 车辆费用是否具备完成核单条件 |
| `blockReasonCode` | String/null | 是 | 不具备条件时的机器可读原因；具备条件时为 `null` |
| `items` | VehicleItem[] | 否 | 当前全量明细；无明细时为 `[]` |

**`data.items[]`**

| 字段 | 类型 | 可空 | 说明 |
|---|---|---|---|
| `id` | String(Long) | 否 | 车辆核单明细 ID |
| `sourceType` | String | 否 | `FLEET` 或 `MANUAL` |
| `sourceTypeName` | String | 否 | 车务或手工 |
| `serviceDate` | String(date) | 否 | 服务日期，`YYYY-MM-DD` |
| `vehicleId` | String(Long) | 是 | 车辆 ID |
| `vehiclePlate` | String | 是 | 车牌号 |
| `vehicleModelId` | String(Long) | 是 | 车型 ID |
| `vehicleModelName` | String | 是 | 车型名称 |
| `driverId` | String(Long) | 是 | 司机 ID |
| `driverName` | String | 是 | 司机姓名 |
| `amount` | Decimal | 否 | 核单金额 |
| `paymentMethod` | String | 否 | 付款方式编码，见 §6.2 |
| `paymentMethodName` | String | 否 | 付款方式名称 |
| `settlementConfirmStatus` | String | 否 | 确认状态编码，见 §6.3 |
| `settlementConfirmStatusName` | String | 否 | 未确认或已确认 |
| `remark` | String | 是 | 备注 |
| `voucherUrls` | String[] | 否 | 凭证 URL；无凭证时为 `[]` |

**错误码**

| code | 含义 | 触发场景 |
|---|---|---|
| `400` | 请求参数错误 | `orderId` 不是正整数 |
| `403` | 无访问权限 | 登录态或角色无权访问 |
| `581007` | 订单不存在 | `orderId` 对应订单不存在 |
| `584071` | 无权访问该订单 | 当前账号不在订单可访问范围内 |
| `584100` | 车辆费用暂时不可用 | 车辆费用来源调用失败、响应身份不匹配或必要字段无效 |
| `584101` | 车辆费用尚未满足核单条件 | 已有非空车辆明细，但来源未完结或费用条件未满足 |

`584102` 不再表示“有需求但费用尚未生成”；该场景现在返回 `code=200` 的阻断空状态。

**业务边界与空状态判定**

| 场景 | `items` | `totalAmount` | `settlementReady` | `blockReasonCode` | `allConfirmed` | 结果 |
|---|---|---|---|---|---|---|
| 无当前用车需求 | `[]` | `0.00` | `true` | `null` | `true` | 成功，可继续完成核单 |
| 有当前用车需求，但费用尚未生成 | `[]` | `0.00` | `false` | `VEHICLE_FEE_NOT_READY` | `false` | 成功，但不能完成核单 |
| 有明细、来源就绪，仍有未确认行 | 非空 | 明细合计 | `true` | `null` | `false` | 成功，需先确认明细 |
| 有明细、来源就绪且全部确认 | 非空 | 明细合计 | `true` | `null` | `true` | 成功，可继续完成核单 |

- `items=[]` 不是失败判据，必须读取 `settlementReady`。
- `allConfirmed=true` 只说明没有未确认行，能否完成核单仍以 `settlementReady` 为准。
- 车辆来源失败或必要字段无效仍返回业务错误，不转换为空结果。

**典型成功请求**

```http
GET /v3/admin/order/900000000001/settlement/step3/vehicles
Authorization: Bearer <管理后台访问令牌>
```

无请求体。

**典型成功响应**

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "orderId": "900000000001",
    "version": 4,
    "totalAmount": 1200.00,
    "allConfirmed": true,
    "settlementReady": true,
    "blockReasonCode": null,
    "items": [
      {
        "id": "930000000001",
        "sourceType": "FLEET",
        "sourceTypeName": "车务",
        "serviceDate": "2026-08-01",
        "vehicleId": "880000000001",
        "vehiclePlate": "藏A12345",
        "vehicleModelId": "870000000001",
        "vehicleModelName": "七座商务车",
        "driverId": "860000000001",
        "driverName": "张师傅",
        "amount": 1200.00,
        "paymentMethod": "COMPANY_PAID",
        "paymentMethodName": "公司付款",
        "settlementConfirmStatus": "CONFIRMED",
        "settlementConfirmStatusName": "已确认",
        "remark": "金额已核对",
        "voucherUrls": []
      }
    ]
  },
  "traceId": null,
  "success": true
}
```

**边界请求：有需求但费用未就绪**

```http
GET /v3/admin/order/900000000003/settlement/step3/vehicles
Authorization: Bearer <管理后台访问令牌>
```

无请求体。

**边界响应**

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "orderId": "900000000003",
    "version": 0,
    "totalAmount": 0.00,
    "allConfirmed": false,
    "settlementReady": false,
    "blockReasonCode": "VEHICLE_FEE_NOT_READY",
    "items": []
  },
  "traceId": null,
  "success": true
}
```

**边界请求：无当前用车需求**

```http
GET /v3/admin/order/900000000002/settlement/step3/vehicles
Authorization: Bearer <管理后台访问令牌>
```

无请求体。

**边界响应**

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "orderId": "900000000002",
    "version": 0,
    "totalAmount": 0.00,
    "allConfirmed": true,
    "settlementReady": true,
    "blockReasonCode": null,
    "items": []
  },
  "traceId": null,
  "success": true
}
```

**业务失败请求：车辆来源暂时不可用**

```http
GET /v3/admin/order/900000000004/settlement/step3/vehicles
Authorization: Bearer <管理后台访问令牌>
```

无请求体。

**业务失败响应**

```json
{
  "code": 584100,
  "message": "车务车辆总车费暂时不可用，请稍后重试",
  "data": null,
  "traceId": null,
  "success": false
}
```

### 3.2 全量保存车辆核单草稿

- **接口说明**：携带查询所得版本，全量保存车辆核单行并返回保存后的完整草稿。
- **方法与路径**：`PUT /v3/admin/order/{orderId}/settlement/step3/vehicles`
- **认证**：管理后台登录态；需满足订单查看及核单写权限；房务角色不可访问。
- **幂等性**：业务语义为全量替换；成功后版本递增，原请求不可原样重放，使用旧版本重试会返回 `584108`。
- **限流**：未声明独立限流规则。

**路径参数**

| 字段 | 类型 | 必填 | 说明与校验 |
|---|---|---|---|
| `orderId` | String(Long) | 是 | 订单 ID，必须为正整数；按字符串传递 |

无 Query 参数。

**请求体**

| 字段 | 类型 | 必填 | 说明与校验 |
|---|---|---|---|
| `version` | Long | 是 | GET 返回的草稿版本，最小 `0` |
| `items` | VehicleItem[] | 是 | 全量明细；现存 `FLEET` 行必须全部原样带回 |
| `items[].id` | String(Long) | FLEET/更新时是 | 已保存行 ID；手工新行为空 |
| `items[].sourceType` | String | 是 | `FLEET` 或 `MANUAL` |
| `items[].serviceDate` | String(date) | 是 | 服务日期，`YYYY-MM-DD` |
| `items[].vehicleId` | String(Long) | 否 | 正整数车辆 ID |
| `items[].vehiclePlate` | String | 否 | 车牌，最长 64 字符 |
| `items[].vehicleModelId` | String(Long) | 否 | 正整数车型 ID |
| `items[].vehicleModelName` | String | 否 | 车型名，最长 128 字符 |
| `items[].driverId` | String(Long) | 否 | 正整数司机 ID |
| `items[].driverName` | String | 否 | 司机名，最长 64 字符 |
| `items[].amount` | Decimal | 是 | 大于等于 `0.00`；最多 10 位整数、2 位小数 |
| `items[].paymentMethod` | String | 是 | `CASH_PAID/SIGNED/COMPANY_PAID` |
| `items[].settlementConfirmStatus` | String | 是 | `UNCONFIRMED/CONFIRMED` |
| `items[].remark` | String | 否 | 最长 500 字符 |
| `items[].voucherUrls` | String[] | 否 | 最多 9 个 HTTP/HTTPS URL；单个最长 1024 字符 |

请求对象和明细对象均不接受未声明字段。

**成功响应**

响应类型同 §3.1 的 `VehicleDraft`，包含 `orderId/version/totalAmount/allConfirmed/settlementReady/blockReasonCode/items` 及完整明细字段；`version` 返回保存后的新版本。

**错误码**

| code | 含义 | 触发场景 |
|---|---|---|
| `400` | 参数校验失败 | 必填缺失、格式/长度/枚举错误或出现未知字段 |
| `403` | 无访问权限 | 登录态、角色或核单写权限不足 |
| `581007` | 订单不存在 | `orderId` 对应订单不存在 |
| `584071` | 无权访问该订单 | 当前账号不在订单可访问范围内 |
| `584089` | 核单或结算已完成 | 当前订单已不能修改资金明细 |
| `584106` | 确认状态非法 | 非 `UNCONFIRMED/CONFIRMED` |
| `584107` | 手工新增行必须先未确认 | `id=null` 的 `MANUAL` 新行直接传 `CONFIRMED` |
| `584108` | 车辆草稿版本冲突 | PUT 的 `version` 已过期 |
| `584109` | 车务来源字段不可改删 | 修改、删除或漏传现存 `FLEET` 行的权威字段 |

**业务边界**

- `FLEET` 行的服务日期、车辆、司机、金额和付款方式不可修改或删除；仅允许修改确认状态、备注和凭证。
- 全量保存必须带回所有现存 `FLEET` 行；`MANUAL` 行可新增、修改，或通过不再提交该行来删除。
- 手工新行首次只能提交 `UNCONFIRMED`；取得 `id` 后，下一次 PUT 才可改为 `CONFIRMED`。
- `version` 冲突后必须重新 GET，并基于最新全量草稿重新编辑和保存。

**典型成功请求**

```http
PUT /v3/admin/order/900000000001/settlement/step3/vehicles
Authorization: Bearer <管理后台访问令牌>
Content-Type: application/json
```

```json
{
  "version": 3,
  "items": [
    {
      "id": "930000000001",
      "sourceType": "FLEET",
      "serviceDate": "2026-08-01",
      "vehicleId": "880000000001",
      "vehiclePlate": "藏A12345",
      "vehicleModelId": "870000000001",
      "vehicleModelName": "七座商务车",
      "driverId": "860000000001",
      "driverName": "张师傅",
      "amount": 1200.00,
      "paymentMethod": "COMPANY_PAID",
      "settlementConfirmStatus": "CONFIRMED",
      "remark": "金额已核对",
      "voucherUrls": []
    }
  ]
}
```

**典型成功响应**

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "orderId": "900000000001",
    "version": 4,
    "totalAmount": 1200.00,
    "allConfirmed": true,
    "settlementReady": true,
    "blockReasonCode": null,
    "items": [
      {
        "id": "930000000001",
        "sourceType": "FLEET",
        "sourceTypeName": "车务",
        "serviceDate": "2026-08-01",
        "vehicleId": "880000000001",
        "vehiclePlate": "藏A12345",
        "vehicleModelId": "870000000001",
        "vehicleModelName": "七座商务车",
        "driverId": "860000000001",
        "driverName": "张师傅",
        "amount": 1200.00,
        "paymentMethod": "COMPANY_PAID",
        "paymentMethodName": "公司付款",
        "settlementConfirmStatus": "CONFIRMED",
        "settlementConfirmStatusName": "已确认",
        "remark": "金额已核对",
        "voucherUrls": []
      }
    ]
  },
  "traceId": null,
  "success": true
}
```

**边界请求：新增金额为 0 的手工未确认行**

```http
PUT /v3/admin/order/900000000001/settlement/step3/vehicles
Authorization: Bearer <管理后台访问令牌>
Content-Type: application/json
```

```json
{
  "version": 4,
  "items": [
    {
      "sourceType": "MANUAL",
      "serviceDate": "2026-08-02",
      "vehicleId": "880000000002",
      "vehiclePlate": "藏A54321",
      "vehicleModelId": "870000000001",
      "vehicleModelName": "七座商务车",
      "driverId": null,
      "driverName": null,
      "amount": 0.00,
      "paymentMethod": "CASH_PAID",
      "settlementConfirmStatus": "UNCONFIRMED",
      "remark": null,
      "voucherUrls": []
    }
  ]
}
```

**边界响应**

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "orderId": "900000000001",
    "version": 5,
    "totalAmount": 0.00,
    "allConfirmed": false,
    "settlementReady": true,
    "blockReasonCode": null,
    "items": [
      {
        "id": "930000000002",
        "sourceType": "MANUAL",
        "sourceTypeName": "手工",
        "serviceDate": "2026-08-02",
        "vehicleId": "880000000002",
        "vehiclePlate": "藏A54321",
        "vehicleModelId": "870000000001",
        "vehicleModelName": "七座商务车",
        "driverId": null,
        "driverName": null,
        "amount": 0.00,
        "paymentMethod": "CASH_PAID",
        "paymentMethodName": "现金已付",
        "settlementConfirmStatus": "UNCONFIRMED",
        "settlementConfirmStatusName": "未确认",
        "remark": null,
        "voucherUrls": []
      }
    ]
  },
  "traceId": null,
  "success": true
}
```

**业务失败请求：提交过期版本**

```http
PUT /v3/admin/order/900000000001/settlement/step3/vehicles
Authorization: Bearer <管理后台访问令牌>
Content-Type: application/json
```

```json
{
  "version": 3,
  "items": []
}
```

**业务失败响应**

```json
{
  "code": 584108,
  "message": "车辆核单明细已变化，请刷新后重试",
  "data": null,
  "traceId": null,
  "success": false
}
```

### 3.3 查询核单车辆异步下拉

- **接口说明**：`keyword` 可匹配车牌、品牌型号、车型大类和常驻司机姓名；返回轻量车辆候选。
- **方法与路径**：`GET /v3/admin/order/{orderId}/settlement/vehicle-options`
- **认证**：管理后台登录态；管理员、超级管理员可查看任意订单，其他允许角色仅可查看本人作为定制师的订单；房务角色不可访问。
- **幂等性**：是，只读查询。
- **限流**：未声明独立限流规则。

**路径与 Query 参数**

| 字段 | 位置 | 类型 | 必填 | 默认值 | 说明与校验 |
|---|---|---|---|---|---|
| `orderId` | path | String(Long) | 是 | — | 订单 ID，必须为正整数；按字符串传递 |
| `keyword` | query | String | 否 | 空 | 模糊匹配车牌、品牌型号、车型大类或常驻司机姓名；空白表示不过滤 |
| `limit` | query | Integer | 否 | `10` | 非正数按 10 处理；超过 20 按 20 处理 |

无请求体。

**统一响应外层**

| 字段 | 类型 | 可空 | 说明 |
|---|---|---|---|
| `code` | Integer | 否 | 成功为 `200` |
| `message` | String | 否 | 结果说明 |
| `data` | VehicleOption[] | 失败时为空 | 没有匹配项时为 `[]` |
| `traceId` | String | 是 | 链路追踪 ID |
| `success` | Boolean | 否 | `code=200` 时为 `true` |

**`data[]`**

| 字段 | 类型 | 可空 | 说明 |
|---|---|---|---|
| `vehicleId` | String(Long) | 否 | 车辆 ID，按字符串返回 |
| `plate` | String | 是 | 车牌 |
| `modelName` | String | 是 | 品牌型号 |
| `typeName` | String | 是 | 车型大类名称 |
| `primaryDriverId` | String(Long) | 是 | 常驻司机 ID；无常驻司机时为 `null` |
| `primaryDriverName` | String | 是 | 常驻司机姓名；无常驻司机时为 `null` |
| `label` | String | 否 | 展示文案，依次包含车牌、品牌型号、车型大类和常驻司机；无常驻司机时最后一段为“无常驻司机” |

`data[]` 只包含以上七个字段，不包含车辆费用、付款方式或核单确认状态。

**错误码**

| code | 含义 | 触发场景 |
|---|---|---|
| `400` | 订单 ID 必须大于 0 | `orderId <= 0` |
| `581007` | 订单不存在 | `orderId` 对应订单不存在 |
| `581008` | 无权查看此订单 | 非管理员访问其他定制师订单，或上下文缺少订单归属判断所需的管理员 ID |
| `581045` | 房务角色无权查看订单详情 | 房务管理员或房务组长调用 |
| `584072` | 车务司机车辆信息暂时不可用 | 车辆候选信息不可用 |

登录态无效或缺失时，请求在进入接口前由统一认证拦截。

**业务边界**

- 最多返回 20 条；没有匹配项返回 `[]`。
- `keyword` 为空或空白时不过滤；`limit <= 0` 按 10，`limit > 20` 按 20。
- 本接口只查询候选车辆；成功响应不表示已选择、保存或确认车辆。
- `vehicleId` 与非空 `primaryDriverId` 必须按字符串处理。

**典型成功请求**

```http
GET /v3/admin/order/2079454953641836546/settlement/vehicle-options?keyword=%E5%BC%A0%E5%B8%88%E5%82%85&limit=10
Authorization: Bearer <管理后台访问令牌>
```

无请求体。

**典型成功响应**

```json
{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "vehicleId": "9202101",
      "plate": "蒙A-88888",
      "modelName": "丰田汉兰达",
      "typeName": "SUV",
      "primaryDriverId": "9204101",
      "primaryDriverName": "张师傅",
      "label": "蒙A-88888***丰田汉兰达***SUV***张师傅"
    }
  ],
  "traceId": null,
  "success": true
}
```

**边界请求：最大条数且无匹配结果**

```http
GET /v3/admin/order/2079454953641836546/settlement/vehicle-options?keyword=%E4%B8%8D%E5%AD%98%E5%9C%A8&limit=20
Authorization: Bearer <管理后台访问令牌>
```

无请求体。

**边界响应**

```json
{
  "code": 200,
  "message": "成功",
  "data": [],
  "traceId": null,
  "success": true
}
```

**业务失败请求：订单 ID 非法**

```http
GET /v3/admin/order/0/settlement/vehicle-options
Authorization: Bearer <管理后台访问令牌>
```

无请求体。

**业务失败响应**

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

## 6. 枚举 / 数据字典

### 6.1 `sourceType`

**所属字段**：车辆草稿请求/响应 `items[].sourceType` ｜ **类型**：String ｜ **必填**：是

| 值 | 中文 | 说明 |
|---|---|---|
| `FLEET` | 车务 | 车务同步的权威行，业务字段不可修改或删除 |
| `MANUAL` | 手工 | 管理后台手工维护的车辆核单行 |

### 6.2 `paymentMethod`

**所属字段**：车辆草稿请求/响应 `items[].paymentMethod` ｜ **类型**：String ｜ **必填**：是

| 值 | 中文 | 说明 |
|---|---|---|
| `CASH_PAID` | 现金已付 | 现金支付 |
| `SIGNED` | 签单 | 按签单方式结算 |
| `COMPANY_PAID` | 公司付款 | 由公司支付 |

### 6.3 `settlementConfirmStatus`

**所属字段**：车辆草稿请求/响应 `items[].settlementConfirmStatus` ｜ **类型**：String ｜ **必填**：是

| 值 | 中文 | 说明 |
|---|---|---|
| `UNCONFIRMED` | 未确认 | 当前车辆费用行尚未完成核单确认 |
| `CONFIRMED` | 已确认 | 当前车辆费用行已完成核单确认 |

### 6.4 `blockReasonCode`

**所属字段**：车辆草稿响应 `data.blockReasonCode` ｜ **类型**：String/null

| 值 | 中文 | 说明 |
|---|---|---|
| `VEHICLE_FEE_NOT_READY` | 车辆费用尚未就绪 | 有当前用车需求，但尚无可返回的车辆费用明细；此时 `settlementReady=false` |
| `null` | 无阻断原因 | 此时 `settlementReady=true`；为 JSON 空值，不是字符串 `"null"` |

车辆下拉接口不包含枚举或数据字典字段。

## 10. 修改前后对比

### 10.1 字段级对比

| 字段 | 改前 | 改后 |
|---|---|---|
| GET 草稿 `data.settlementReady` | 不对管理后台输出 | 返回 Boolean，明确车辆费用是否具备完成核单条件 |
| GET 草稿 `data.blockReasonCode` | 不存在 | 返回 String/null；未就绪时为 `VEHICLE_FEE_NOT_READY` |
| 车辆下拉 `data[]` | 无独立候选接口 | 返回七字段轻量候选数组 |

### 10.2 行为级对比

| 行为 | 改前 | 改后 |
|---|---|---|
| 无当前用车需求 | 空明细但无公开就绪原因字段 | `items=[]`、`settlementReady=true`、`blockReasonCode=null` |
| 有需求但费用未生成 | 返回 `584102` | 成功空结果：`items=[]`、`settlementReady=false`、`blockReasonCode=VEHICLE_FEE_NOT_READY` |
| 保存车辆草稿 | 车辆入口与字段口径分散 | 使用 Step3 PUT，携带 `version` 和全量 `items` |
| 手工选择车辆 | 无专用异步候选契约 | 使用 `vehicle-options` 按关键词查询，最多 20 条 |

## 11. 影响评估 / 回滚

- **是否破坏向后兼容**：GET 空状态行为有兼容影响；依赖 `584102` 或仅看 `items.length` 的旧逻辑需调整。新增字段和车辆下拉接口本身向后兼容。
- **前端是否必须同步上线**：是。车辆 Tab 必须读取 `settlementReady`，并在 PUT 版本冲突后重新查询；需要手工车辆选择时使用 `vehicle-options`。
- **回滚边界**：前端不得回滚到捕获 `584102` 识别未就绪空态的版本，也不得恢复已下线的旧车辆费用入口。

## 12. 注意事项

- GET 返回 `code=200` 且 `items=[]` 时，必须读取 `settlementReady`，不能直接判失败或无条件放行。
- 完成核单前同时检查 `settlementReady` 与 `allConfirmed`。
- 清理对 GET `584102` 的空态兼容逻辑；未就绪现在由 `blockReasonCode=VEHICLE_FEE_NOT_READY` 表达。
- PUT 必须提交 GET 返回的当前 `version` 和全量明细；不要遗漏或改写 `FLEET` 权威字段。
- 订单、明细、车辆、车型和司机 ID 均按字符串处理；金额按 Decimal 处理。
- 车辆下拉只提供候选，不返回费用或确认状态；选中后仍需组装 `MANUAL` 行并通过 Step3 PUT 保存。

## 13. 关联 / 联系人

### 13.1 Issue、PR 与提交

| 范围 | Issue | PR | Feature commit | Merge commit |
|---|---|---|---|---|
| 车辆 Step3 GET/PUT | [#5356](https://git.1814.love:8443/wx/HL/issues/5356) | [#5362](https://git.1814.love:8443/wx/HL/pulls/5362) | [6e396f6fc4](https://git.1814.love:8443/wx/HL/commit/6e396f6fc48fbf6581e87224bb85f2c811759727) | [cfac945db2](https://git.1814.love:8443/wx/HL/commit/cfac945db268640b0b9e60b4d8c7ab55739a69e3) |
| 车辆异步下拉 | [#5360](https://git.1814.love:8443/wx/HL/issues/5360) | [#5361](https://git.1814.love:8443/wx/HL/pulls/5361) | [5be7985164](https://git.1814.love:8443/wx/HL/commit/5be7985164cdae5417cdeb2a2be7d104dc8fdae8) | [0ff4ef45](https://git.1814.love:8443/wx/HL/commit/0ff4ef45ccd0f4ebb1d3be00b27cde06f26bce0b) |
| GET 空状态语义 | [#5380](https://git.1814.love:8443/wx/HL/issues/5380) | [#5393](https://git.1814.love:8443/wx/HL/pulls/5393) | — | [e4c1720871](https://git.1814.love:8443/wx/HL/commit/e4c1720871f33db38936d709caa7696db199ad1f) |

### 13.2 联系人

- **后端负责人**：@yst / yaosutu
- **前端消费方**：管理后台车辆核单 Tab

## 关联/联系人

### 链接

- [后端工单 #5356](https://git.1814.love:8443/wx/HL/issues/5356)

### 联系人

- **后端负责人**: @yst
