diff --git a/changelogs-v2/2026-07/79_车务派单详情补全产品行程节点与出行人-修改接口-前端待处理-管理后台.md b/changelogs-v2/2026-07/79_车务派单详情补全产品行程节点与出行人-修改接口-前端待处理-管理后台.md new file mode 100644 index 0000000..b8383b2 --- /dev/null +++ b/changelogs-v2/2026-07/79_车务派单详情补全产品行程节点与出行人-修改接口-前端待处理-管理后台.md @@ -0,0 +1,209 @@ +# 【修改接口·前端待处理·管理后台】车务派单详情补全产品、行程节点与出行人 + +> **服务**: hl-order-service-v3 + hl-fleet-service +> **日期**: 2026-07-22 +> **影响范围**: 管理后台车务管理 / 派车看板 / 派单弹窗 Step1「订单详情」 + +--- + +## 关键变化 + +派单弹窗 Step1 不能再只展示人数、日期和每日一句简介。`GET /admin/fleet/board/orders/{orderId}` 现一次返回: + +- `productName`:订单产品名(原字段,前端本次必须展示)。 +- `itinerary.days[].nodes[]`:每日真实行程节点,含开始时间、时段、时长、名称和简介。 +- `travelers[]`:出行人脱敏基本信息,不含生日和任何明文字段。 +- `transport`:抵达、返程及分批大交通信息(原字段,前端本次必须完整展示时间和班次,不能只显示站点)。 + +行程数据仍以订单当前 `order_itinerary_day` 和 `order_itinerary_node` 为权威源,禁止从产品模板反推。 + +--- + +## 变更接口 + +```http +GET /admin/fleet/board/orders/{orderId} +``` + +响应 VO:`BoardOrderDetailVO` + +### 新增字段 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `itinerary.days[].nodes` | Array | 当日节点,按 `sortOrder` 升序;无节点返回 `[]` | +| `itinerary.days[].nodes[].nodeId` | String | 节点雪花 ID,必须按字符串处理 | +| `itinerary.days[].nodes[].nodeType` | String/null | 节点类型,如 `SCENIC`、`RESTAURANT`、`ACTIVITY`、`SERVICE`、`CUSTOM` | +| `itinerary.days[].nodes[].nodeName` | String/null | 节点展示名;节点名为空时后端回退资源名 | +| `itinerary.days[].nodes[].startTime` | String/null | 开始时间,格式 `HH:mm` | +| `itinerary.days[].nodes[].timePeriod` | String/null | 时段,如上午、下午、全天 | +| `itinerary.days[].nodes[].durationMinutes` | Number/null | 时长,单位分钟 | +| `itinerary.days[].nodes[].description` | String/null | 节点简介 | +| `itinerary.days[].nodes[].sortOrder` | Number/null | 同天排序 | +| `travelers` | Array | 出行人脱敏基本信息;无出行人或下游降级时返回 `[]` | +| `travelers[].travelerId` | String | 出行人雪花 ID,必须按字符串处理 | +| `travelers[].travelerType` | String/null | `ADULT` / `CHILD` / `YOUNG_CHILD` / `BABY` | +| `travelers[].nameMasked` | String/null | 脱敏姓名 | +| `travelers[].gender` | String/null | 性别字典值 | +| `travelers[].ageAtDeparture` | Number/null | 按订单出发日计算的周岁 | +| `travelers[].idType` | String/null | 证件类型字典值 | +| `travelers[].idNoMasked` | String/null | 脱敏证件号 | +| `travelers[].phoneMasked` | String/null | 脱敏手机号 | +| `travelers[].nationality` | String/null | 国籍 | +| `travelers[].emergencyContactMasked` | String/null | 脱敏紧急联系人姓名 | +| `travelers[].emergencyPhoneMasked` | String/null | 脱敏紧急联系人电话 | +| `travelers[].profileStatus` | String/null | 资料状态:`PENDING` / `COMPLETED` | + +`productName` 是已有字段,结构不变;本次页面必须消费,不再只保存在 `normalizeBoardOrder().product` 而不展示。 + +### 已有但本次必须完整展示的大交通字段 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `transport.arrive` | Object/null | 抵达接团段 | +| `transport.arrive.transportNo` | String/null | 抵达航班号/车次号 | +| `transport.arrive.time` | String/null | 抵达时间,ISO `LocalDateTime` | +| `transport.arrive.station` | String/null | 抵达机场/车站 | +| `transport.arrive.remark` | String/null | 抵达备注 | +| `transport.depart` | Object/null | 返程送站段 | +| `transport.depart.transportNo` | String/null | 返程航班号/车次号 | +| `transport.depart.time` | String/null | 返程时间,ISO `LocalDateTime` | +| `transport.depart.station` | String/null | 返程机场/车站 | +| `transport.depart.remark` | String/null | 返程备注 | +| `transport.batches` | Array | 分批接送列表 | +| `transport.batches[].travelerNames` | String/null | 本批出行人姓名摘要 | +| `transport.batches[].transportNo` | String/null | 本批航班号/车次号 | +| `transport.batches[].time` | String/null | 本批抵达/返程时间 | +| `transport.batches[].station` | String/null | 本批机场/车站 | +| `transport.transferTimeHint` | String/null | 无任何大交通时间时的后端提示,当前为“暂无接送机时间” | +| `transport.pickupRequired` | Boolean/null | 是否需要平台派车接送 | + +### 响应示例 + +```json +{ + "code": 200, + "data": { + "orderNo": "HL20260721171011648", + "productName": "草原亲子三日游", + "itinerary": { + "theme": "草原亲子三日游", + "route": null, + "days": [ + { + "dayNumber": 1, + "date": "2026-07-29", + "title": "接机", + "detail": "抵达后入住酒店", + "nodes": [ + { + "nodeId": "2001", + "nodeType": "SERVICE", + "nodeName": "海拉尔机场接机", + "startTime": "10:30", + "timePeriod": "上午", + "durationMinutes": 60, + "description": "司机举牌接机", + "sortOrder": 1 + } + ] + } + ] + }, + "travelers": [ + { + "travelerId": "3001", + "travelerType": "ADULT", + "nameMasked": "孔**", + "gender": "2", + "ageAtDeparture": 35, + "idType": "ID_CARD", + "idNoMasked": "150***********1234", + "phoneMasked": "138****1234", + "nationality": "中国", + "emergencyContactMasked": "王*", + "emergencyPhoneMasked": "139****5678", + "profileStatus": "COMPLETED" + } + ], + "transport": { + "transferTimeHint": null, + "arrive": { + "transportNo": "CA1234", + "time": "2026-07-29T10:30:00", + "station": "海拉尔东山国际机场", + "remark": "T2 出口举牌接机" + }, + "depart": { + "transportNo": "CA5678", + "time": "2026-07-31T17:20:00", + "station": "海拉尔东山国际机场", + "remark": "提前 2 小时送达" + }, + "batches": [], + "pickupRequired": true + } + }, + "success": true +} +``` + +--- + +## 前端页面调整要求 + +目标文件:`src/views/fleet/board/components/Step1OrderDetail.vue`。 + +1. 顶部订单摘要展示产品名,读取 `order.productName || order.product`;产品名为空才显示 `—`。 +2. 在顶部订单摘要下增加“大交通”信息卡,抵达与返程分栏展示 `transportNo + time + station + remark`: + - 时间使用完整月日和时分,不只展示日期。 + - `arrive`、`depart` 独立判空,只有一段时仍正常展示该段。 + - `batches[]` 非空时增加“分批接送”,展示本批出行人、班次、时间和站点。 + - 无任何时间时展示 `transport.transferTimeHint`,不得伪造航班或时间。 + - 当前顶部“接送”统计可保留站点摘要,但不能替代大交通详情卡。 +3. 左侧“每日安排”保留日标题和 `detail`,并在每一天下面渲染 `nodes[]`: + - 时间优先显示 `startTime`,为空时显示 `timePeriod`,两者都有可组合展示。 + - 主文案显示 `nodeName`。 + - `durationMinutes` 有值时显示易读时长。 + - `description` 有值且与日简介不重复时显示节点简介。 +4. 右侧新增“出行人信息”区,默认展示脱敏姓名、人员类型、性别、出发时年龄、脱敏手机号和资料状态;证件/紧急联系人可在行内展开或次要信息区展示。 +5. 禁止为了展示此页面调用明文接口 `POST /admin/fleet/board/orders/{orderId}/travelers/plain`。Step1 只使用详情响应中的脱敏 `travelers[]`。 +6. 空态明确:无节点显示“暂无行程节点”,无出行人显示“暂未填写出行人信息”;不得生成模拟节点或模拟出行人。 +7. 雪花 ID 禁止 `Number()` / `parseInt()`,统一按字符串处理。 + +推荐布局:顶部摘要下放横向“大交通”卡;左栏继续承载逐日节点时间线;右栏顺序为“出行人信息 → 客人留言 → 特殊要求 → 操作记录”。 + +--- + +## 兼容与降级 + +- 仅新增响应字段,不修改请求参数,不影响旧调用方。 +- 历史行程没有节点时 `nodes=[]`,每日标题和简介仍照常返回。 +- order-v3 聚合上下文失败并回退 fleet 本地快照时,`relatedDetailReady=false`,`travelers=[]`,行程节点不可用;前端显示真实空态。 +- 原独立脱敏接口 `GET /admin/fleet/board/orders/{orderId}/travelers` 保留兼容,但此页面无需再发第二次请求。 +- 不返回 `birthday`、明文姓名、明文证件号、明文手机号或明文紧急联系人。 + +--- + +## 验收清单 + +- [ ] 顶部可看到订单产品名。 +- [ ] 大交通卡分别展示抵达/返程的班次、完整时间、站点和备注。 +- [ ] 有分批接送时展示每批出行人、班次、时间和站点;无大交通时间时展示真实空态。 +- [ ] 每日安排按节点顺序展示时间、节点名、时长和简介。 +- [ ] 节点无 `startTime` 时可回退显示 `timePeriod`,不会出现 `undefined`。 +- [ ] 右侧可看到全部出行人的脱敏基本信息。 +- [ ] 无节点/无出行人时展示真实空态,不生成模拟数据。 +- [ ] 页面 Network 只需现有详情请求,不调用出行人明文接口。 +- [ ] 现有留言、特殊要求、步骤条和操作记录不受影响。 + +--- + +## 后端验证记录 + +- `ItineraryServiceTest`:覆盖节点名称、开始时间、时段、时长、简介和排序装配。 +- `OrderFleetProviderServiceTest`:覆盖节点随当前订单日期对齐且出行人脱敏进入聚合上下文。 +- `BoardOrderServiceTest`:覆盖 shared DTO 到管理端 VO 的节点和出行人映射。 +- `BoardControllerTest`:覆盖 `productName`、节点时间、String ID 与脱敏出行人的 JSON 契约。 + +> 本文是前端接入通知,不代表已修改或发布 `mmg/hl-ui`。