docs(changelog): 团期详情用车两份前端交接件(确认弹窗 onPositive 不发请求 / 用车汇总改逐条列出)
changelog-filename-gate / validate (push) Failing after 2s
changelog-filename-gate / validate (push) Failing after 2s
- 前端缺陷:VehicleHouseholdsSection.vue:387/:334、RequirementTab.vue:588 弹窗回调键名写成 onPositive, naive-ui 只认 onPositiveClick,点确认只关窗不发请求;spec mock 同步改 - 前端优化:用车·汇总的行程用车与接送机两块改由 vehicle-households 逐条列出(接送机现状同样是按车型聚合) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
这个提交包含在:
@@ -0,0 +1,165 @@
|
||||
---
|
||||
schema: hl-changelog/v2
|
||||
ticket: "frontend"
|
||||
title: "团期详情「用车汇总」块,行程用车与接送机从按车型聚合改逐条列出,调用既有 /requirement/vehicle-households 接口"
|
||||
consumer: admin
|
||||
author: "wx(GIT)"
|
||||
change_type: "前端优化"
|
||||
backend_status: "not_required"
|
||||
gateway_status: "not_required"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: "mmg"
|
||||
frontend_ref: ""
|
||||
target_release: "v2.1"
|
||||
verified_at: ""
|
||||
status_note: ""
|
||||
updated_at: "2026-09-29"
|
||||
base: dev-v3
|
||||
---
|
||||
|
||||
# 团期详情用车汇总改逐条列出
|
||||
|
||||
> **服务**: hl-order-service-v3(**后端无改动,复用既有接口**)
|
||||
> **页面**: 管理后台 → 团期订单 → 进入团期(团期详情)→「查看需求」Tab →「用车 · 汇总」块
|
||||
> **数据源接口**: `GET /v3/admin/order/group-batch/{groupBatchId}/requirement/vehicle-households`(既有,VehicleHouseholdsSection 已在调)
|
||||
> **日期**: 2026-09-29
|
||||
> **影响范围**: 前端页面展示逻辑。行程用车与接送机块从按车型聚合的 N 行改为逐户逐行的完整列表。
|
||||
|
||||
---
|
||||
|
||||
## 一、需求
|
||||
|
||||
改变「用车 · 汇总」块的行程用车与接送机两个板块展示形态——从当前按车型聚合(显示「车型 / 合计座位 / 台数」)改为**逐条列出**(显示「团号 / 客户 / 车型 / 单车座位 / 台数」),让信息粒度与「用车 · 子订单用车需求记录」块对齐。
|
||||
|
||||
---
|
||||
|
||||
## 二、前提订正
|
||||
|
||||
当前「接送机」块**其实也是按车型汇总的**,而非逐条列表——只是恰好本次测试团的两户选了不同车型(suv / mpv),所以看起来像列表。后端 `requirement-summary` 接口的 `vehicleSeatSummary`(行程)与 `transferSummary.vehicleSeatSummary`(接送机)都用同一个聚合方法(hl-order-service-v3 `GroupBatchRequirementService.java` 第 343、346 行都调 `aggregateVehicleSeats`)。
|
||||
|
||||
wx 的原话是「行程用车也不需要汇总,list 列出来就行,和接送机需求一样就行」。既然接送机现状也是汇总,按「逐条列出」的本意,**行程用车与接送机两块都改成逐条列表**。
|
||||
|
||||
---
|
||||
|
||||
## 三、数据源
|
||||
|
||||
使用既有接口 `GET /v3/admin/order/group-batch/{groupBatchId}/requirement/vehicle-households`,契约不变:
|
||||
|
||||
- 响应字段见同目录 `22_8152_团期用车需求补车辆规格与接送机汇总-修改接口-管理后台.md` 与 `22_8195_团期查看需求页五处缺口-修改接口-管理后台.md`。
|
||||
- query 参数 `kind` 可选,只收单个值 `TRAVEL` 或 `TRANSFER`;不传或传空时两类都返回。**不支持逗号多值**(`kind=TRAVEL,TRANSFER` 会被判为非法取值,返错误码 809000)。本需求建议不传 `kind`,一次拿两类。
|
||||
|
||||
**关键字段**:
|
||||
- `households[n].teamNo` —— 团号(可为 null,显示「—」,**禁用 orderNo 顶替**)
|
||||
- `households[n].customerName` —— 客户名
|
||||
- `households[n].requirements[m].kind` —— 类型(`TRAVEL` 或 `TRANSFER`)
|
||||
- `households[n].requirements[m].fleet[p]` —— 车型数组,其中:
|
||||
- `vehicleTypeName` —— 车型名称(为空时退回 `vehicleType`)
|
||||
- `seats` —— 单车座位数
|
||||
- `count` —— 台数
|
||||
|
||||
---
|
||||
|
||||
## 四、数据处理规则
|
||||
|
||||
### ① 按 kind 过滤
|
||||
|
||||
行程用车:取所有 `kind='TRAVEL'` 的行,不按 `countedInSummary` 过滤。
|
||||
|
||||
接送机:取所有 `kind='TRANSFER'` 的行,不按 `countedInSummary` 过滤。
|
||||
|
||||
**禁用 `countedInSummary` 作为过滤条件**。后端 `countedInSummary` 的定义是「该户有活跃 TRAVEL 行」(hl-order-service-v3 `GroupBatchVehicleHouseholdService.java` 第 233 行),用它筛接送机会漏掉只报了接送机的户。聚合数已经按 kind 隔离,前端只需按 kind 对应过滤。
|
||||
|
||||
### ② 按状态
|
||||
|
||||
**不按状态过滤**。汇总的车侧口径不看状态(待审核的也计入),列表要与汇总对得上就不能自行二次筛选。
|
||||
|
||||
### ③ 逐行展开
|
||||
|
||||
对每个 `households[n].requirements[m].fleet` 数组,**每个元素出一行**。行组成:
|
||||
|
||||
```
|
||||
[团号] | [客户名] | [车型] | [单车座位] | [台数] | [状态](可选)
|
||||
```
|
||||
|
||||
具体列如下:
|
||||
|
||||
| 列 | 来源字段 | 说明 |
|
||||
|---|---|---|
|
||||
| 团号 | `teamNo` | 为 null 显「—」;禁用 orderNo 顶替 |
|
||||
| 客户 | `customerName` | — |
|
||||
| 车型 | `vehicleTypeName` 或 `vehicleType` | 优先用 `vehicleTypeName`;空时退回 `vehicleType` |
|
||||
| 单车座位 | `seats` | — |
|
||||
| 台数 | `count` | — |
|
||||
| 状态 | `statusName`(可选) | 仅供展示,不作过滤依据。直接用后端给的 `statusName`,不要按 `status` 自己翻译:同为 `PENDING_REVIEW`,行程用车返「待提交车务」、接送机返「待审核」 |
|
||||
|
||||
---
|
||||
|
||||
## 五、页面形态
|
||||
|
||||
**VehicleSummarySection.vue** 修改位置(现约第 14-33 行行程用车块 + 第 35-61 行接送机块):
|
||||
|
||||
### 行程用车块
|
||||
- 小标题保持「行程用车」。
|
||||
- **替代当前汇总表**:用逐行列表替代按车型聚合的表。
|
||||
- **表头**:`团号 | 客户 | 车型 | 单车座位 | 台数`。
|
||||
- **合计行保留**(可选):表尾显「合计 X 座」「合计 Y 辆」,取 `requirement-summary.vehicleSeatSummary` 或由前端加总。
|
||||
- **空态**:列表为空时显「暂无行程用车需求」。
|
||||
|
||||
### 接送机块
|
||||
- 小标题保持「接送机」。
|
||||
- **分为两部分**:
|
||||
1. **逐行列表**(同行程用车的结构),但 `kind='TRANSFER'` 过滤。
|
||||
2. **既有统计摘要保留**(取 `requirement-summary.transferSummary`):接机 N 户、送机 N 户、合计 N 人、服务日期。
|
||||
- **空态**:接送机列表为空时显「暂无接送机需求」。
|
||||
|
||||
---
|
||||
|
||||
## 六、已实测对账
|
||||
|
||||
测试团期:`2100856430494973953`(王晓测试团期产品·第3期 10月8日出发团)。两户样本数据:
|
||||
|
||||
**行程用车(TRAVEL)**:
|
||||
- 户 1(王有亿,teamNo=`26-7060`):大巴系列(bus)19 座 ×1
|
||||
- 户 2(王二麻子,teamNo=`26-2355`):大巴系列(bus)19 座 ×1
|
||||
- **列表加总**:bus 合计 38 座,2 辆
|
||||
- **汇总返回**(`requirement-summary.vehicleSeatSummary`):bus 38 座,2 辆
|
||||
- **一致性**:✓ 一致
|
||||
|
||||
**接送机(TRANSFER)**:
|
||||
- 户 1(王有亿):SUV系列(suv)5 座 ×1
|
||||
- 户 2(王二麻子):商务车(mpv)7 座 ×1
|
||||
- **列表加总**:suv 5/1,mpv 7/1
|
||||
- **汇总返回**(`requirement-summary.transferSummary.vehicleSeatSummary`):suv 5 座 1 辆,mpv 7 座 1 辆
|
||||
- **一致性**:✓ 一致
|
||||
|
||||
列表逐条数据已与取数接口(`GET /v3/admin/order/group-batch/2100856430494973953/requirement/vehicle-households`)的返回原文核对。
|
||||
|
||||
**覆盖边界声明**:本次对账团两户都有 TRAVEL 行,所以「只报接送机、无 TRAVEL 行的户」分支未被实测覆盖;结论依据后端源码逻辑推出(`countedInSummary` 定义来自源码第 233 行)。
|
||||
|
||||
---
|
||||
|
||||
## 七、业务边界
|
||||
|
||||
- `vehicle-households` 单次最多返 500 户(超出截断并记后端日志);超限时列表加总会小于汇总数。
|
||||
- 户可能 `requirements` 为空数组(还未提交需求)——该户不出行。
|
||||
- 某行 `fleet` 若为空数组,该行不出列表行(汇总加总同样不计它)。
|
||||
- 列表为空时各块显示对应的「暂无」文案。
|
||||
- 与「用车 · 子订单用车需求记录」块共用同一接口,建议前端在父组件缓存一份响应以避免重复请求(非硬需求)。
|
||||
|
||||
---
|
||||
|
||||
## 八、后端接口(无改动)
|
||||
|
||||
- 接口:`GET /v3/admin/order/group-batch/{groupBatchId}/requirement/vehicle-households`
|
||||
- 路由、权限、响应字段、错误码均不变。
|
||||
- 测试服 2026-09-29 实调可用(HTTP 200 / code=200)。
|
||||
|
||||
---
|
||||
|
||||
## 九、验收
|
||||
|
||||
1. 在测试团期 `2100856430494973953` 打开团期详情「查看需求」Tab。
|
||||
2. 「用车 · 汇总」块的行程用车板显示 2 行(两户 bus 各一行),接送机板显示 2 行(一户 suv、一户 mpv)。
|
||||
3. 逐条列表核对字段完整性:每行都有团号、客户名、车型、座位、台数。
|
||||
4. 将列表按车型加总,与汇总摘要中的合计座位数、台数逐项核对,**完全相等**。
|
||||
5. 接送机块保留既有的「接机 N 户、送机 N 户」等统计行。
|
||||
@@ -0,0 +1,128 @@
|
||||
---
|
||||
schema: hl-changelog/v2
|
||||
ticket: "frontend"
|
||||
title: "团期详情「用车」块按户确认接送机弹窗,点「确认」关窗不发请求:弹窗键名写错(onPositive vs onPositiveClick)"
|
||||
consumer: admin
|
||||
author: "wx(GIT)"
|
||||
change_type: "前端缺陷"
|
||||
backend_status: "not_required"
|
||||
gateway_status: "not_required"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: "mmg"
|
||||
frontend_ref: ""
|
||||
target_release: "v2.1"
|
||||
verified_at: ""
|
||||
status_note: ""
|
||||
updated_at: "2026-09-29"
|
||||
base: dev-v3
|
||||
---
|
||||
|
||||
# 团期详情用车需求确认弹窗,点确认关窗不发请求
|
||||
|
||||
> **服务**: hl-order-service-v3(**后端无改动,接口正常**)
|
||||
> **页面**: 管理后台 → 团期订单 → 进入团期(团期详情)→「查看需求」Tab →「用车 · 子订单用车需求记录」块
|
||||
> **接口**: `POST /v3/admin/order/{orderId}/vehicle-requirement/dispatch?kind=TRANSFER`
|
||||
> **日期**: 2026-09-29
|
||||
> **影响范围**: 前端。同一写法共 3 处:单户确认接送机(wx 实测复现)、按户批量确认、整团确认(后两处为同一代码形态的静态推断,未实点)。
|
||||
|
||||
---
|
||||
|
||||
## 一、现象
|
||||
|
||||
1. 进入团期详情,切到「查看需求」Tab。
|
||||
2. 在「用车 · 子订单用车需求记录」块找某户的接送机行,点「确认」按钮。
|
||||
3. 弹出「确认接送机需求 / 确认放行「[客户名]」的接送机需求至车务处理?」。
|
||||
4. 点弹窗中的「确认」按钮。
|
||||
5. **弹窗关闭,但 Network 标签页无任何新请求**。
|
||||
|
||||
实测团期:`2100856430494973953`「王晓测试团期产品·第3期 10月8日出发团」,客户王有亿的接送机行(requirementId=`2102202475291549698`,状态待审核 PENDING_REVIEW)。
|
||||
|
||||
---
|
||||
|
||||
## 二、根因
|
||||
|
||||
hl-ui(`origin/v2.1` @ `4b800a29`)`src/views/order-v2/batch/detail/components/` 下两个组件的确认弹窗用了错误的回调键名 `onPositive`。
|
||||
|
||||
naive-ui(hl-ui 装的 2.44.1)`useDialog().warning({...})` 只认 `onPositiveClick` 作为"确认"按钮回调;写成 `onPositive` 时被静默忽略。来自 `node_modules/naive-ui/es/dialog/src/DialogEnvironment.mjs` 第 62-73 行:
|
||||
|
||||
```
|
||||
handlePositiveClick() 只调 props.onPositiveClick,若不存在直接 hide() 关窗
|
||||
```
|
||||
|
||||
**三处错误的键名**:
|
||||
|
||||
1. `VehicleHouseholdsSection.vue:387` —— 单户接送机确认 `confirmTransfer` 函数内弹窗(本次复现的那处;引入提交 `91d476c9`,2026-09-22)
|
||||
2. `VehicleHouseholdsSection.vue:334` —— 按户批量确认 `openBatchConfirm` 函数内弹窗(同一写法,静态推断同样不发请求,未实点)
|
||||
3. `RequirementTab.vue:588` —— 整团确认弹窗(`onPositive: () => doConfirm()`;引入提交 `96ef0c07`,2026-09-08;静态推断,未实点)
|
||||
|
||||
全 hl-ui 有 76 个文件用的是 `onPositiveClick`;写成 `onPositive:` 的只有上面 2 个文件 3 处。
|
||||
|
||||
---
|
||||
|
||||
## 三、后端验证(均正常)
|
||||
|
||||
测试服对后端接口直接探测(2026-09-29):
|
||||
|
||||
| 请求 | 结果 |
|
||||
|---|---|
|
||||
| `POST /v3/admin/order/1/vehicle-requirement/dispatch?kind=TRANSFER`(不存在订单) | HTTP 200,`code=581007`「订单不存在」,说明路由与端点都可用 |
|
||||
|
||||
探测用的是不存在的订单,对任何订单零写入。王有亿这行在 `GET /v3/admin/order/group-batch/2100856430494973953/requirement/vehicle-households` 里为 `orderId=2100856430239121409`、`requirementId=2102202475291549698`、`kind=TRANSFER`、`status=PENDING_REVIEW`,满足按钮显示与可确认的前置条件。
|
||||
|
||||
后端契约不变,无改动需求。
|
||||
|
||||
---
|
||||
|
||||
## 四、修复方案
|
||||
|
||||
**VehicleHouseholdsSection.vue**
|
||||
|
||||
第 334 行:
|
||||
```js
|
||||
// 当前(错):
|
||||
onPositive: () => doBatchConfirm(),
|
||||
// 改为(正):
|
||||
onPositiveClick: () => doBatchConfirm(),
|
||||
```
|
||||
|
||||
第 387 行:
|
||||
```js
|
||||
// 当前(错):
|
||||
onPositive: () => doConfirmTransfer(household, req),
|
||||
// 改为(正):
|
||||
onPositiveClick: () => doConfirmTransfer(household, req),
|
||||
```
|
||||
|
||||
**RequirementTab.vue**
|
||||
|
||||
第 588 行附近(整团确认弹窗)同样改键名为 `onPositiveClick:`。
|
||||
|
||||
---
|
||||
|
||||
## 五、单测同步修正
|
||||
|
||||
两个规格文件的 dialog.warning mock 中,当前直接调用 `opts.onPositive()`,验不出键名错误。需同步修正:
|
||||
|
||||
- `__tests__/VehicleHouseholdsSection.spec.js` —— 第 257、288、346、395、441 行的 mock implementation
|
||||
- `__tests__/RequirementTab.spec.js` —— 第 169、204、423、447 行直接调 `onPositive()`(第 144、167 行是用例名与注释里的字样,一并改)
|
||||
|
||||
修正方法:确保 mock 只调 `onPositiveClick`,不调 `onPositive`。这样键名一旦写错,用例会红。
|
||||
|
||||
---
|
||||
|
||||
## 六、业务边界
|
||||
|
||||
- 确认按钮调的是 `POST /v3/admin/order/{orderId}/vehicle-requirement/dispatch?kind=TRANSFER`。
|
||||
- 「确认」按钮只在 `kind=TRANSFER` 且 `status=PENDING_REVIEW` 的行上出现(`VehicleHouseholdsSection.vue:291` `canConfirmReq`)。
|
||||
- 修复后,按钮点击会正常发出请求,后端返回成功后列表刷新并同步父级预检状态。
|
||||
- 按户批量确认(同一块内)与整团确认(Tab 顶部)是同一写法,一并修;此修复只涉及弹窗回调键名,无新增端点或参数。
|
||||
|
||||
---
|
||||
|
||||
## 七、验收
|
||||
|
||||
1. 在测试团期 `2100856430494973953` 点王有亿接送机行的「确认」按钮。
|
||||
2. 弹窗确认后,Network 显示新请求 `POST /v3/admin/order/2100856430239121409/vehicle-requirement/dispatch?kind=TRANSFER`。
|
||||
3. 接口返回成功(HTTP 200),列表自动刷新,该行状态更新为接口返回值。
|
||||
4. 批量确认、整团确认各点一遍,同样看到请求发出。
|
||||
5. 两个 spec 文件改 mock 为 `onPositiveClick` 后全绿;临时把源码改回 `onPositive` 时相关用例变红。
|
||||
在新工单中引用
屏蔽一个用户