diff --git a/changelogs-v2/2026-09/29_frontend_团期详情用车汇总行程用车与接送机改逐条列出-前端优化-管理后台.md b/changelogs-v2/2026-09/29_frontend_团期详情用车汇总行程用车与接送机改逐条列出-前端优化-管理后台.md new file mode 100644 index 00000000..b5e62d16 --- /dev/null +++ b/changelogs-v2/2026-09/29_frontend_团期详情用车汇总行程用车与接送机改逐条列出-前端优化-管理后台.md @@ -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 户」等统计行。 diff --git a/changelogs-v2/2026-09/29_frontend_团期详情用车需求确认弹窗点确认不发请求-前端缺陷-管理后台.md b/changelogs-v2/2026-09/29_frontend_团期详情用车需求确认弹窗点确认不发请求-前端缺陷-管理后台.md new file mode 100644 index 00000000..f175c31f --- /dev/null +++ b/changelogs-v2/2026-09/29_frontend_团期详情用车需求确认弹窗点确认不发请求-前端缺陷-管理后台.md @@ -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` 时相关用例变红。