docs(changelog): 查看需求页 5 项前端缺陷交接件(订单号改团号/接送机逐行确认/弹窗默认值与文案)
changelog-filename-gate / validate (push) Failing after 2s

2026-09-22 wx 在「团期详情 → 查看需求」页逐屏提了 8 个问题,对 origin/dev-v3(cf9dc85a4)
与 hl-ui origin/v2.1(590c1155) 逐项查证后拆两边:本件只收后端零改动、可立即动手的 5 项
(5 处团号渲染点、接送机逐户确认按钮、新建弹窗默认分组、两个日期默认值、按钮文案)。
后端有硬缺口的 3 项(另 5 处渲染点缺 teamNo、车侧未提交户不返回、无批量确认端点)
建了 wx/HL#8195,本件不含也不做前向引用。

所有「不存在/0 命中」结论均配同形状阳性对照,逐条写在对应小节。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
这个提交包含在:
API Changelog Bot
2026-09-22 18:26:03 +08:00
共同撰写人 Claude Opus 5
父节点 a7df8cdc5a
当前提交 12c9c6d3d6
@@ -0,0 +1,160 @@
---
schema: hl-changelog/v2
ticket: "frontend"
title: "查看需求页:订单号改显团号(5 处可立即改)+ 接送机逐行确认按钮 + 正式用车需求弹窗默认分组/默认日期/按钮文案"
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: ""
updated_at: "2026-09-22"
base: dev-v3
status_note: "2026-09-22 wx 在「团期详情 → 查看需求」页逐屏截图提了 8 个问题。对 origin/dev-v3(cf9dc85a4) 与 hl-ui origin/v2.1(590c1155) 逐项查证后拆成两边:本条只收录后端零改动、今天就能动手的 5 项;另 3 项(另 5 处团号渲染点需后端补 teamNo、车侧未提交户后端根本不返回、接送机批量确认端点不存在)后端有硬缺口,已建 wx/HL#8195 处理,本条不含。查证依据:①名单表/打回弹窗/乘车户下拉三处的数据源 GB-ADM-003 GET /v3/admin/order/group-batch/{groupBatchId}/orders 已返回 teamNo(GroupBatchOrderItemRespVO.java:34,格式 26-0001,未付订金为 null);②逐户接送机确认可直接调已上线端点 POST /v3/admin/order/{id}/vehicle-requirement/dispatch?kind=TRANSFER(VehicleRequirementAdminController.java:77,请求体 DispatchReqVO 只有 dispatchRemark);③GroupVehicleRequirementEditModal.vue:434 新建时 form.groups 恒为空数组、:407-408 两个日期恒为 null,blankGroup() :401-416 只被「添加分组」按钮调用;④GroupVehicleRequirementSection.vue:19 文案「新建正式需求」。UI 库是 Naive UI 不是 Element。"
---
# 查看需求页:订单号改显团号 + 接送机逐行确认 + 正式用车需求弹窗三处默认值与文案
> **服务**: hl-order-service-v3(**后端零改动**)
> **页面**: 管理后台 → 团期订单 → 团期详情 → 「查看需求」Tab
> **日期**: 2026-09-22
> **影响范围**: 仅前台渲染与既有端点调用;无新端点、无出入参变化、无路由、无 DDL
---
## ⚠️ 关键变化
- **本条 5 项全部后端零改动**,涉及的字段与端点今天都在测试服上返回真实值,逐条给了查证出处。
- **本条只覆盖这 5 项**。wx 当天提的另外几项后端有硬缺口(响应里压根没有那个字段、那个端点不存在),记在 `wx/HL#8195`,不在本条范围——下面第六节把「哪些不在本条」写清楚了,免得照着改时撞上空字段。
- **UI 库是 Naive UI**(`n-data-table` / `n-modal` / `n-date-picker`),不是 Element。
- **活跃分支是 `origin/v2.1`**,不是 `master`。在 `master` 上 grep 会得到可信但错误的 0 命中(阳性对照:`git grep '#8151' origin/master -- src` → 0,换 `origin/v2.1` → 19)。
---
## 一、订单号改显团号(本页 5 处可立即改)
wx 原话:**「这个页面所有显示订单号的地方都改为显示团号」**。
本页 `orderNo` 共 11 个可见渲染点,其中 **5 处的数据源已经返回 `teamNo`**,可以现在就改:
| # | 文件:行 | 现在渲染 | 数据源 |
|---|---|---|---|
| 1 | `RequirementTab.vue:442-452` + `_shared/renderCells.js:19,21` | 名单表「子订单 / 联系人」列上行 `r.orderNo`,以及 hover 的 `title: r.orderNo` | GB-ADM-003 `orders` |
| 2 | `RequirementRejectModal.vue:129` | 打回弹窗「已选 N 户」标签 `${o.contactName \|\| '未命名'} · ${o.orderNo \|\| '无订单号'}` | 同上(props 传入) |
| 3 | `GroupVehicleRequirementEditModal.vue:289` | 乘车户下拉 label `o.customerName \|\| o.contactName \|\| o.orderNo \|\| String(o.orderId)` | 同上(props 传入) |
`teamNo` 的契约(`GroupBatchOrderItemRespVO.java:34`,已在返回):
| 项 | 取值 |
|---|---|
| 字段名 | `teamNo` |
| 类型 | `String` |
| 格式 | `26-0001`(年份后两位 + `-` + 4 位)。生成算法 `GroupCodeService.java:30-37` 是 LCG 混淆 `(7123*seq+2731)%10000`,**刻意不连续、不可按大小排序** |
| 粒度 | **每个子订单一个**,同团期内各户不同 |
| 空值 | **未付订金的户为 `null`**(团号在订金支付成功那一刻才生成,`OrderStatusService.java:151` / `:356`) |
| 兜底 | `orderV2GroupBatch.js:152` 注释明写「勿兜底成 `orderNo`/空串」;本页家族已有写法 `RosterTable.vue:62-66` 用 `r.teamNo \|\| '—'` |
### ⚠️ 名单表上有一处需要你们自己定的取舍
`369ed5b4`(同日交付,见 `22_frontend_查看需求Tab子订单表补齐列并订正联系人与房型-前端缺陷-管理后台.md`)刚给这张名单表**新增了一个独立的「团号」列**。若再把「子订单 / 联系人」列的上行也换成团号,同一行会出现两个相同的团号。
这是这张表内部的版面取舍,归你们定。三种走法都说得通:把「子订单 / 联系人」上行换成团号并删掉独立团号列;保留独立团号列、把该列上行改成客户名;或按 wx 字面全换、接受重复。
## 二、接送机逐行「确认」按钮
wx 原话:**「这块需要确认接送机用车需求没有按钮」**。
`VehicleHouseholdsSection.vue` 目前模板里唯一的 `n-button` 是 `:12-19` 卡右上角的「刷新」,逐行/逐户**没有任何操作按钮**(`grep '确认'` 0 命中;阳性对照:同 grep 在 `RequirementTab.vue` 命中 `:53`「整团确认需求」)。
**逐户确认可以现在就接**,端点已上线:
### POST /v3/admin/order/{id}/vehicle-requirement/dispatch(复用不改)
| 项 | 内容 |
|---|---|
| 路径参数 | `id` — 子订单 ID(`Long`),取逐户卡的 `household.orderId` |
| Query 参数 | `kind` — `TRAVEL` \| `TRANSFER`。**`@RequestParam(defaultValue = "TRAVEL")`,不显式传 `TRANSFER` 就变成确认行程用车**,务必显式传 |
| 请求体 | `DispatchReqVO`,**只有一个字段**:`dispatchRemark`(`String`,选填,`@Size(max=500)`,"提供给房控/车队的审核意见") |
| 权限码 | `group-batch:demand:confirm` |
| 副作用 | 该户该类需求 `PENDING_REVIEW → PENDING`,`vehicle_control → PENDING`(即转交车务) |
| 出处 | `VehicleRequirementAdminController.java:77`,`DispatchReqVO.java:28` |
按钮的显示条件用逐户卡上已有的 `req.kind === 'TRANSFER'` 且 `req.status === 'PENDING_REVIEW'`(`RequirementItem.status` 取值 `PENDING_REVIEW / PENDING / PROCESSING / DONE`,`GroupVehicleHouseholdsRespVO.java:105`)。
### 行程用车(TRAVEL)不要加这个按钮
行程用车走的是**整团一条**的结构化正式需求(`PUT .../vehicle-requirement` 全量替换),按 wx 早先的定案它本来就没有逐行确认这个动作。这一节只针对 `kind === 'TRANSFER'` 的行。
## 三、正式用车需求弹窗:新建时默认带一个分组
wx 原话:**「应默认有一个分组」**。
`GroupVehicleRequirementEditModal.vue:434`(打开弹窗时的 `watch(() => props.show, ...)`,`:428-460`):
```js
form.groups = (Array.isArray(req?.groups) ? req.groups : []).map(...)
```
新建时 `props.requirement` 为 `null` ⇒ `req` 为 `null` ⇒ `form.groups = []`,弹窗开出来是空的。
空分组模板 `blankGroup()` 已经写好了(`:401-416`,返回 `{groupId:null, groupCode:'', vehicleType:'', serviceStartDate:null, serviceEndDate:null, seats:null, count:null, specialTags:[], remark:'', days:[]}`),当前只被「添加分组」按钮(`:209-215` → `addGroup()` `:418-420`)调用,watch 里没调。新建分支补一次 `blankGroup()` 即可。
## 四、正式用车需求弹窗:两个日期默认填团期日期
wx 原话:**「默认填入」**。
`GroupVehicleRequirementEditModal.vue:82-89` / `:96-103` 的两个 `n-date-picker`,初始值来自 `blankGroup()` `:407-408` 的 `serviceStartDate: null, serviceEndDate: null`,全文件没有任何默认值逻辑(`new Date(` 只出现在 `:375-380` 的 `expandDates` 区间展开里)。
**团期的出发日与结束日前端已经拿得到**,不需要后端补字段:
| 日期 | 来源接口 | 字段 | 类型 |
|---|---|---|---|
| 出发日 | `GET /v3/admin/order/group-batch/{groupBatchId}`(A2 团期详情,父页面已在调) | `departDate` | `LocalDate`,形如 `2026-10-08` |
| 结束日 | 同上 | `endDate` | `LocalDate`,形如 `2026-10-10` |
出处 `GroupBatchDetailRespVO.java:183-190`(另有 `enrollDeadline` 报名截止日)。
弹窗当前的 props 只有 `show / groupBatchId / requirement / orders`(`:259-267`),**拿不到日期**——父页面 `GroupVehicleRequirementSection.vue:169-175` 挂载处把团期详情里的这两个日期传下去即可。
补充:「查看需求」的两个 households 读口(`requirement/hotel-households`、`requirement/vehicle-households`)目前返回 `departDate` 但**不返回** `endDate`(`GroupVehicleHouseholdsRespVO.java:36` / `GroupHotelHouseholdsRespVO.java:39`,`git grep endDate` 在这两个文件 exit=1,阳性对照同 grep 换 `departDate` 两个都命中)。走 A2 团期详情能一次拿全三个日期,是当前最省事的路。
## 五、按钮文案改为「新增正式行程用车需求」
wx 原话:**「改为 新增正式行程用车需求」**。
`GroupVehicleRequirementSection.vue:19`:
```
{{ requirement ? '编辑正式需求' : '新建正式需求' }}
```
(按钮带 `v-if="canEdit"`,`canEdit` = `:421` `!requirement.value || status === 'DRAFT'`。)
改文案会连带红两条测试:`__tests__/GroupVehicleRequirementSection.spec.js:108` 与 `:115`。
同族文案是否一并对齐由你们定,wx 只点名了这一个按钮。现有的同族文案有:`GroupVehicleRequirementSection.vue:340` 头注释「data=null 显空态+「新建正式需求」」、弹窗标题 `GroupVehicleRequirementEditModal.vue:5` `title="正式用车需求编辑"`、提交按钮 `:226`「保存正式需求」、成功提示 `:495`「正式用车需求已保存」。
## 六、本条不覆盖的部分(照着改会撞上空字段,先看这里)
下面三项后端有硬缺口,记在 `wx/HL#8195`:
| 缺口 | 具体表现 | 撞上的位置 |
|---|---|---|
| 另 5 处团号渲染点 | `confirm-check` 与两个 households 读口的响应里**没有 `teamNo` 字段**(`git grep teamNo` 在 `Group*HouseholdsRespVO.java` exit=1;阳性对照同 grep 换 `orderNo` 命中 4 行) | `RequirementTab.vue:73,82-83,106`、`RoomHouseholdsSection.vue:44`、`VehicleHouseholdsSection.vue:40` |
| 车侧「未提交用车需求」的户 | 这些户**根本不在响应的 `households` 数组里**——`GroupBatchVehicleHouseholdService.java:118-122` 遍历的是「有活跃需求行的户」,不是子订单全集(房侧 `GroupBatchHotelHouseholdService.java:113-123`/`:196-201` 相反,未提交户保留空卡、`status=null`) | `VehicleHouseholdsSection.vue` 无法照 `RoomHouseholdsSection.vue:57,98` 的写法做提示 |
| 接送机**批量**确认 | 不存在任何批量确认端点(`git grep -nE '@(Post\|Put)Mapping\("[^"]*(batch-confirm\|confirm-batch\|batch/confirm)'` 无输出;阳性对照:房务侧有 `HouseAssignmentAdminController.java:97`「批量提交配房方案」) | 多选 + 批量按钮 |
⚠️ 如果前端想先用 `orderId` 回 `orders` 数组反查 `teamNo` 来绕开第一项:本页 `orders` 已在 props 里,`RequirementTab.vue:264` 已有按 `orderId` 建 Map 的先例。这条路今天就能走通,取舍归你们。
---
## 七、查证基线
- 后端:`HL` `origin/dev-v3` HEAD `cf9dc85a4`(2026-09-22 17:33 +0800)。
- 前端:`hl-ui` `origin/v2.1` HEAD `590c1155`(2026-09-22 18:03 读取)。
- 分支选对的阳性对照:`git grep '#8151' origin/master -- src` → 0 命中;同命令换 `origin/v2.1` → 19 命中。`git ls-tree origin/master -- .../RequirementTab.vue .../VehicleHouseholdsSection.vue` → 空;`origin/v2.1` 两文件都在。
- 本条所有「不存在 / 0 命中」结论都配了同形状的阳性对照,逐条写在对应小节里。