docs(changelog): 小程序用车详情 vehicleCount 由车·日数订正为车辆台数(#8143)
changelog-filename-gate / validate (push) Failing after 2s

同一个订单同一个字段,返回的数字会变小(3 天 2 辆车由 6 变成 2)。
字段名/类型/其余字段全不变,前端把它当「车辆数」展示则无需改动。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
这个提交包含在:
jw
2026-09-22 14:54:10 +08:00
共同撰写人 Claude Opus 5
父节点 553b870997
当前提交 7afd10b226
@@ -0,0 +1,275 @@
---
schema: "hl-changelog/v2"
ticket: "8143"
title: "用车详情 vehicleCount 由「车·日数」订正为「车辆台数」"
consumer: "mp"
author: "jw(GIT)"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "pending"
frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: "2026-09-22"
status_note: "路径/方法/入参/出参字段名全不变,唯一变化是 vehicleCount 的【值】——同一个订单同一个字段,数字会变小(3 天 2 辆车由 6 变成 2)。前端把它当「车辆数」展示则无需改动、显示自动变正确;若有基于该值的派生计算需复核。"
updated_at: "2026-09-22"
base: "dev-v3"
---
# 小程序用车详情: vehicleCount 由「车·日数」订正为「车辆台数」
> **服务**: hl-mp-service (端口 8085/8185)
> **PR**: #8172
> **Issue**: #8143
> **日期**: 2026-09-22
> **影响范围**: 小程序订单详情页「服务包含」→「用车详情」弹窗的车辆数字段
---
## ⚠️ 关键变化
`GET /mp/order/:orderId/vehicle` 的 `vehicleCount`,**契约一直声明是「车辆数」,实际下发的却是派车明细行数(车·日数)**。3 天 2 辆车的订单下发 `6`。本次订正为按车辆去重的台数,**同一个订单、同一个字段,返回的数字会变小**。
字段名、类型、其余所有字段均不变。
---
## 一、背景
v2 时代派车列表一车一行,行数即台数,两者恒等;v3 起派车明细的行粒度变成「一车一日」,取列表长度这个表达式的含义随之漂移成「车·日数」,而字段声明没跟着改。上游把这个数存在用车需求表的 `assignment_used_vehicle_day_count` 列里——**列名就是它真正的口径**。
该字段直接展示给客人,失败形态是静默的:无异常、无错误码,照常返回 200。
测试库实证(只读统计):
| 维度 | 读数 |
|------|------|
| (订单, 用车需求) 组合总数 | 165 |
| 行数 ≠ 去重台数的组合 | **123(74.5%)** |
| 最极端样本 | 订单 `2091418470443810817`:1 辆车连开 6 天,下发 `6` |
---
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 用车详情 | GET | `/mp/order/:orderId/vehicle` | 出参字段值语义订正 | `vehicleCount` 改为按车辆去重的台数;字段名/类型/其余字段全不变 |
---
## 三、接口详情
### 1. 用车详情 `GET /mp/order/:orderId/vehicle`
**VO**: `MpVehicleDetailVO`
#### 使用场景
小程序订单详情页「服务包含」列表中「用车」条目的点击弹窗。
#### 入参
**零变化**。
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| `orderId` | path | Long | 是 | 雪花 ID,**按字符串传** | 订单 ID |
无查询参数、无请求体。登录态由网关注入 `X-User-Id`,前端不传。
#### 出参 `Result<MpVehicleDetailVO>`
字段名、类型、字段个数**全部不变**。唯一变化是 `vehicleCount` 的取值口径:
| 字段 | 类型 | 说明 |
|------|------|------|
| `vehicleCount` | Integer | **本次改动**。改前=派车明细行数(车·日数);改后=按车辆去重的台数 |
| `vehicleType` / `plateNumber` / `driverName` / `driverPhone` / `seatCount` | String / Integer | 不变,仍取第一辆车 |
| `matched` | Boolean | 不变 |
| `coverUrl` / `vehicleCategory` / `driverYearsRequired` / `features` | - | 不变,自 #7306 B-7 起恒 null |
#### 请求示例
```http
GET /mp/order/2091418470443810817/vehicle
Authorization: Bearer <user token>
```
#### 响应示例
改前(测试环境实测):
```json
{"code":200,"message":"成功","data":{
"vehicleType":"suv","vehicleCount":6,"coverUrl":null,
"plateNumber":"蒙A-E2E01","driverName":"阿拉坦","driverPhone":"135****5019",
"matched":true,"seatCount":5,
"vehicleCategory":null,"driverYearsRequired":null,"features":null},
"success":true}
```
改后(**仅 `vehicleCount` 变化**):
```json
{"code":200,"message":"成功","data":{
"vehicleType":"suv","vehicleCount":1,"coverUrl":null,
"plateNumber":"蒙A-E2E01","driverName":"阿拉坦","driverPhone":"135****5019",
"matched":true,"seatCount":5,
"vehicleCategory":null,"driverYearsRequired":null,"features":null},
"success":true}
```
该订单实际就是 1 辆车(蒙A-E2E01)连开 6 天。
#### 空数据 / 降级响应
未配车时仍返回 `matched=false` 的成功响应,`vehicleCount` 不下发。**该路径零变化**(改前改后响应逐字段一致,已实测)。
#### 错误响应
**不新增、不改动**,既有行为逐字保持:
```json
{"code":581008,"message":"无权查看此订单","data":null,"success":false}
```
```json
{"code":581007,"message":"订单不存在","data":null,"success":false}
```
#### 业务边界
- **「当日无需用车」的日行不计入台数**。车务可把行程中某一天明确标记为不用车,这种日行没有车辆、车牌与司机,它不占一个台数。
- 因此「3 天全都不用车」算出的是 `0` 而不是 `1`——多条无车日行不会被折叠成一台。
- **多车订单仍只显示第一辆车**的车型/车牌/司机/座位数,本次未改展示形态。
- 该字段与用车天数无关,不能用它反推行程长度。
---
## 四、契约约束与正确调用方式
本次不改变任何请求约束,调用方式与改前完全一致。
| 场景 | 调用 |
|------|------|
| ✅ 查本人订单用车详情 | `GET /mp/order/2091418470443810817/vehicle` + 本人登录态 → 200 |
| ❌ 查他人订单 | 同上路径 + 他人登录态 → `581008`(既有行为,未改) |
| ❌ 订单不存在 | → `581007`(既有行为,未改) |
**读取 `vehicleCount` 的正确姿势**:把它当「这趟行程一共用了几辆车」。它**不是**用车天数,也不是「车辆数 × 天数」。若需要用车天数,当前接口不提供,请另提需求。
---
## 五、数据库行为
无。本接口是只读链路,无事务、无锁、无写入。本次改动不涉及表结构、不涉及 Flyway。
---
## 六、边界行为
- 未登录 → 401(网关拦截),不变
- 订单不存在 / 非本人订单 → `581007` / `581008`,不变
- 未配车 → `matched=false` 的 200 响应,`vehicleCount` 不下发,不变
- 行程中某天标记「无需用车」→ 该天不计入台数
- 整趟都没有实际车辆 → `vehicleCount=0`(不会折成 1)
- 上游派单包取不到 → 透传上游错误码,不变
---
## 六.6、修改前后对比
### 字段级对比
| 字段 | 改前 | 改后 |
|------|------|------|
| `vehicleCount` | 派车明细行数(车·日数) | 按 `vehicleId` 去重的车辆台数 |
| 其余 10 个字段 | — | 逐字段不变(实测前后对照唯一差异就是 `vehicleCount`) |
### 行为级对比
| 订单 | 服务天数 | 实际车辆台数 | 明细行数 | 改前下发 | 改后下发 |
|------|----------|--------------|----------|----------|----------|
| `2091418470443810817` | 6 | 1 | 6 | 6 | **1** |
| `2089611106451398658` | 3 | 1 | 3 | 3 | **1** |
| `2087156782022393857` | 3 | 2 | 6 | 6 | **2** |
| `2087156855368187906` | 3(含 1 天不用车) | 2 | 3 | 3 | **2** |
---
## 六.7、影响评估
- **是否破坏向后兼容**: 否。字段名、类型、字段个数均不变,仅值变小。
- **前端是否必须同步上线**: 否。前端把该值当「车辆数」展示(与字段声明一致)则无需任何改动,显示会自动变正确。
- **前端 workaround 清理点**: 若前端曾为绕开这个错误值做过除以天数之类的换算,可以撤掉。若有基于该值的派生计算(按数量估算车辆费用、用它反推行程天数),**需复核**——它此前拿到的是车·日数。
---
## 七、不影响范围
- **仅影响**: 小程序「用车详情」弹窗的 `vehicleCount` 一个字段的值。
- **零影响**:
- **多车订单的展示形态未改** —— 车型/车牌/司机/座位数仍只显示第一辆,第二辆车与后续日期的司机在客人端仍然看不到(本单只订正计数,展示形态需前端配合改弹窗,另行立单)
- 同一弹窗的其余 10 个字段(实测前后逐字段一致)
- 领队详情 `GET /mp/order/:orderId/guide`
- 行前看板 `team.driver`(该字段恒 null,原型暂不展示)
- `hl-order-service-v3`:**零改动**
- 数据库:无表变更、无 Flyway、无存量迁移
- 错误码:不新增
---
## 八、测试环境已验证
构建身份(取证时 `deploy-status.sh`):`hl-mp-service` = `86967e224` / 分支 `dev-v3` / BEHIND `0/N` / STATE `ok`;`hl-order-service-v3` = `c4a1f1fb6` / BEHIND `2/N`(落后提交未触及该服务)。
真实网关(`api.test.1814.love:9443`)实测:
```
GET /mp/order/2091418470443810817/vehicle 改前 → 200 vehicleCount=6 ✓
GET /mp/order/2091418470443810817/vehicle 改后 → 200 vehicleCount=1 ✓(库:6 行 / 1 台车 / 6 天)
GET /mp/order/2089611106451398658/vehicle 改前 → 200 vehicleCount=3 ✓
GET /mp/order/2089611106451398658/vehicle 改后 → 200 vehicleCount=1 ✓(库:3 行 / 1 台车 / 3 天)
GET /mp/order/2086637109266862081/vehicle 改前后 → 200 matched=false 逐字段一致 ✓(未配车路径零回归)
```
含「当日无需用车」日行的订单(另一条上游分支):
```
order 2087156782022393857 → vehicleCount=2 ✓(库:6 行 / 2 台车 / 3 天)
order 2087156855368187906 → vehicleCount=2 ✓(库:3 行 = 2 实车 + 1 天无需用车;null 行未计入)
```
单元测试:`hl-mp-service` 整模块 `Tests run: 1058, Failures: 0, Errors: 0, Skipped: 0`。
---
## 九、相关历史 PR
| PR | Issue | 说明 | 是否仍有效 |
|----|-------|------|------------|
| — | #7306 | B-7 规格 4 字段 v3 无源降级恒 null | ✅ 有效(本次未改) |
| — | #7067 | 派车明细行粒度改为「assignmentId + serviceDate」日行 | ✅ 有效(本缺陷的成因) |
| **本 PR #8172** | **#8143** | `vehicleCount` 订正为车辆台数 | ✅ 最新 |
---
## 十、相关文档
- 关联 Issue: [wx/HL#8143](https://git.1814.love:8443/wx/HL/issues/8143)
- 关联 PR: [wx/HL#8172](https://git.1814.love:8443/wx/HL/pulls/8172)
## 关联 / 联系人
### 链接
- **Issue**: [#8143](https://git.1814.love:8443/wx/HL/issues/8143)
- **PR**: [#8172](https://git.1814.love:8443/wx/HL/pulls/8172)
- **Merge commit**: [86967e224](https://git.1814.love:8443/wx/HL/commit/86967e224)
### 联系人
- **后端负责人**: @jw
- **前端消费方**: hl-mini(mmg)