feat(order-v3): 新增打印行程单接口 changelog(Issue #4644,PR #4650)
GET /v3/admin/order/{id}/print-itinerary
11 区块全量聚合,含字段表/枚举/3组示例/注意事项/关联链接
这个提交包含在:
父节点
faca68852a
当前提交
c005372652
@ -0,0 +1,630 @@
|
||||
# 打印行程单接口(出团行程单·Driver Copy)
|
||||
|
||||
**接口路径**:`GET /v3/admin/order/{id}/print-itinerary`
|
||||
**服务**:hl-order-service-v3
|
||||
**PR**:[#4650](https://git.1814.love:8443/wx/HL/pulls/4650) | **Issue**:[#4644](https://git.1814.love:8443/wx/HL/issues/4644) | **合并至**:dev-v3
|
||||
**变更类型**:✨ 新增接口
|
||||
|
||||
---
|
||||
|
||||
## 1. 接口背景
|
||||
|
||||
出团前,管理后台定制师(或运营人员)需打印一份完整的出团行程单(俗称"Driver Copy")交给司机/导游/领队,供出行全程参考。本次在订单详情页新增该打印端点,后端聚合 **11 个功能区块**(大交通、客人信息、费用明细、全程住宿、应急联系人、每日行程、注意事项、退费规则、交接确认、代收款回执、备注)一次性返回,前端按 A4 纵向布局渲染并提供打印/PDF 下载入口。
|
||||
|
||||
同源先例:`GET /v3/admin/order/{id}/sign-voucher`(签单 PDF)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 变更清单
|
||||
|
||||
| 类型 | 接口 | 说明 |
|
||||
|------|------|------|
|
||||
| ✨ 新增 | `GET /v3/admin/order/{id}/print-itinerary` | 打印行程单 11 区块全量聚合接口 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 接口详情
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| **方法 + 路径** | `GET /v3/admin/order/{id}/print-itinerary` |
|
||||
| **接口名** | 打印行程单(出团行程单·Driver Copy) |
|
||||
| **功能描述** | 聚合订单 11 个打印区块,供前端渲染 A4 行程单并打印 / 导出 PDF |
|
||||
| **认证** | 需携带管理后台 JWT(`Authorization: Bearer <token>`) |
|
||||
| **权限** | 已登录的管理后台用户,无额外角色限制 |
|
||||
| **幂等性** | 只读查询,天然幂等 |
|
||||
| **限流** | 无特殊限流(走网关通用限流) |
|
||||
| **响应格式** | `application/json; charset=utf-8` |
|
||||
| **包装类型** | `Result<PrintItineraryRespVO>` |
|
||||
|
||||
---
|
||||
|
||||
## 4. 接口入参
|
||||
|
||||
### 4.1 路径参数
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| `id` | Long(JSON 序列化为 String,防 JS 精度丢失) | 是 | 订单 ID(雪花 ID,前端应作为字符串透传,不要转 number) |
|
||||
|
||||
### 4.2 请求体
|
||||
|
||||
本接口无请求体(GET 请求)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 出参字段
|
||||
|
||||
响应结构:`Result<PrintItineraryRespVO>`,`code=200` 时 `data` 为完整行程单对象。
|
||||
|
||||
### 5.1 根字段(header 区块 + 顶层区块引用)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `agencyName` | String | 本社名称,如「呼籁旅行有限公司」 |
|
||||
| `printTime` | String | 打印时间,ISO-8601 格式,如 `2026-06-29T10:30:00` |
|
||||
| `teamNo` | String | 团号,如 `HLA2026060001` |
|
||||
| `productName` | String | 产品名 |
|
||||
| `dateRange` | String | 出行日期范围,格式 `YYYY-MM-DD→YYYY-MM-DD` |
|
||||
| `paxSummary` | String | 人数摘要,如 `2大1小` |
|
||||
| `driverName` | String | 司机姓名;未配置则为空串 |
|
||||
| `driverPhone` | String | 司机电话(内部明文,仅内网打印场景);未配置则为空串 |
|
||||
| `guideName` | String | 导游姓名;未配置则为空串 |
|
||||
| `guidePhone` | String | 导游电话;未配置则为空串 |
|
||||
| `leaderName` | String | 领队姓名;未配置则为空串 |
|
||||
| `leaderPhone` | String | 领队电话;未配置则为空串 |
|
||||
| `consultantName` | String | 定制师 / 经办人姓名 |
|
||||
| `transports` | `TransportVO[]` | 01 区块:大交通批次列表,按方向升序(ARRIVAL 在前) |
|
||||
| `customerOverview` | `CustomerOverviewVO` | 02 区块:客人信息速览 |
|
||||
| `feeDetail` | `FeeDetailVO` 或 `null` | 03 区块:费用明细;product-v2 Feign 失败时为 `null`,前端应降级展示「暂无」 |
|
||||
| `hotels` | `HotelVO[]` | 04 区块:全程住宿逐晚列表 |
|
||||
| `emergencyContacts` | `EmergencyContactVO[]` | 05 区块:应急兜底联系人(配房房务 claimer) |
|
||||
| `days` | `DayVO[]` | 06 区块:每日行程(来自固化行程表) |
|
||||
| `notices` | `NoticesVO` | 07 区块:注意事项(固定文案,见 §8 示例) |
|
||||
| `refundNotes` | `RefundNoteGroup[]` | 08 区块:退费规则(来自产品快照);无退费说明时为空数组 |
|
||||
| `handoverChecklist` | `String[]` | 09 区块:师傅领队交接确认 checklist(固定条目,前端在每项右侧留签字栏) |
|
||||
| `collectReceipt` | `CollectReceiptVO` | 10 区块:代收款签收回执 |
|
||||
| `remark` | String 或 `null` | 11 区块:备注(来自订单内部备注字段 `consultantRemark`) |
|
||||
|
||||
---
|
||||
|
||||
### 5.2 TransportVO(01 大交通批次)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `direction` | String | 方向枚举值:`ARRIVAL`(到达)/ `DEPARTURE`(出发) |
|
||||
| `transportType` | String | 交通方式枚举值:`FLIGHT`(航班)/ `TRAIN`(火车)/ `SELF_DRIVE`(自驾) |
|
||||
| `transportNo` | String | 航班号 / 车次号;`SELF_DRIVE` 时为空串 |
|
||||
| `carrier` | String | 航司 / 铁路公司名称 |
|
||||
| `departStation` | String | 出发站 / 机场全称 |
|
||||
| `arriveStation` | String | 到达站 / 机场全称 |
|
||||
| `departTime` | String(LocalDateTime) | 出发时间,格式 `YYYY-MM-DDTHH:mm:ss` |
|
||||
| `arriveTime` | String(LocalDateTime) | 到达时间,格式 `YYYY-MM-DDTHH:mm:ss` |
|
||||
| `selfDrivePeriod` | String 或 `null` | 自驾时段,仅 `SELF_DRIVE` 时有值:`MORNING` / `AFTERNOON` / `EVENING` |
|
||||
| `selfDriveEta` | String(LocalDateTime)或 `null` | 自驾预计到达时间,仅 `SELF_DRIVE` 时有值 |
|
||||
| `pickupRequired` | Boolean | 是否需要平台接送 |
|
||||
| `pickupRemark` | String 或 `null` | 接送备注 |
|
||||
| `remark` | String 或 `null` | 本段交通备注 |
|
||||
|
||||
---
|
||||
|
||||
### 5.3 CustomerOverviewVO(02 客人信息速览)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `customerName` | String | 主联系人姓名 |
|
||||
| `customerPhone` | String | 主联系人手机(已脱敏,格式 `138****5678`) |
|
||||
| `adultCount` | Integer | 成人数 |
|
||||
| `childCount` | Integer | 儿童数(6–12 岁) |
|
||||
| `youngChildCount` | Integer | 幼童数(2–6 岁) |
|
||||
| `babyCount` | Integer | 婴儿数(0–2 岁) |
|
||||
| `tripDays` | Integer | 行程天数 |
|
||||
| `customerType` | String 或 `null` | 客人类型(运营字段,当前后端恒为 `null`,前端按空值处理) |
|
||||
| `createSource` | String | 客源枚举值(见 §6 枚举表) |
|
||||
| `customerRemark` | String 或 `null` | 客户备注(特殊需求 / 忌口 / 纪念日等) |
|
||||
|
||||
---
|
||||
|
||||
### 5.4 FeeDetailVO(03 费用明细)
|
||||
|
||||
**整体可为 `null`**(product-v2 Feign 失败时降级),前端应展示「暂无」而不报错。
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `items` | `FeeLineItemVO[]` | 费用行项列表(仅含数量 > 0 的人群类型) |
|
||||
| `singleRoomSurcharge` | String(BigDecimal)或 `null` | 单房差加价;无单间需求时为 `null` |
|
||||
| `grandTotal` | String(BigDecimal) | 合计金额 |
|
||||
| `onsiteBalance` | String(BigDecimal)或 `null` | 代收款(现场实收尾款);未录入时为 `null` |
|
||||
|
||||
**FeeLineItemVO(费用行项)**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `name` | String | 行项名称,如 `成人包价` / `儿童包价` / `幼童包价` / `婴儿包价` |
|
||||
| `unitPrice` | String(BigDecimal) | 单价 |
|
||||
| `qty` | Integer | 数量 |
|
||||
| `subtotal` | String(BigDecimal) | 小计(= 单价 × 数量) |
|
||||
|
||||
> 注意:BigDecimal 字段均序列化为 **JSON String**(防 JS 精度丢失),前端渲染时直接使用,**不需要** `parseFloat()` 转换。
|
||||
|
||||
---
|
||||
|
||||
### 5.5 HotelVO(04 全程住宿,逐晚)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `dayNumber` | Integer | 天序号(1-based,第一晚 = 1) |
|
||||
| `stayDate` | String(LocalDate) | 入住日期,格式 `YYYY-MM-DD` |
|
||||
| `hotelName` | String | 酒店名称 |
|
||||
| `city` | String | 所在城市(通过 resource-service Feign 取;Feign 失败时为空串) |
|
||||
| `roomCategory` | String | 房型(中文,查字典 `room_category`;未命中则回退 `其他房型`) |
|
||||
| `roomCount` | Integer | 房间数 |
|
||||
| `contactPerson` | String | 酒店联系人(Feign 取;失败时为空串) |
|
||||
| `contactPhone` | String | 联系电话(Feign 取;失败时为空串) |
|
||||
| `settleType` | String | 结算方式(中文,查字典 `settle_type`;失败时为空串) |
|
||||
| `paymentMode` | String | 付款方式(中文,查字典 `payment_mode`;失败时为空串) |
|
||||
| `checkInTime` | String 或 `null` | 入住时间,格式 `HH:mm` |
|
||||
| `checkOutTime` | String 或 `null` | 退房时间,格式 `HH:mm` |
|
||||
|
||||
---
|
||||
|
||||
### 5.6 EmergencyContactVO(05 应急兜底联系人)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `contactName` | String | 姓名(来自配房 claimer_name 快照) |
|
||||
| `contactPhone` | String | 电话(通过 user-service Feign 取 admin_user.mobile;失败或未维护时为空串) |
|
||||
| `role` | String | 角色说明,固定为 `房务` |
|
||||
|
||||
---
|
||||
|
||||
### 5.7 DayVO(06 每日行程)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `dayNumber` | Integer | 天序号(1-based) |
|
||||
| `dayDate` | String(LocalDate) | 实际日期,格式 `YYYY-MM-DD` |
|
||||
| `dayTitle` | String | 当日标题 |
|
||||
| `description` | String 或 `null` | 当日描述 |
|
||||
| `breakfast` | String 或 `null` | 早餐安排枚举值(见 §6) |
|
||||
| `lunch` | String 或 `null` | 午餐安排枚举值 |
|
||||
| `dinner` | String 或 `null` | 晚餐安排枚举值 |
|
||||
| `diningRemark` | String 或 `null` | 餐饮备注 |
|
||||
| `gatherPlace` | String 或 `null` | 集合地点(POI JSON 字符串,前端按需解析展示名称) |
|
||||
| `dismissalPlace` | String 或 `null` | 解散地点(POI JSON 字符串) |
|
||||
| `dailyMileage` | String(BigDecimal)或 `null` | 当日里程(km) |
|
||||
| `nodes` | `NodeVO[]` | 当日点位列表,按 sort_order 升序 |
|
||||
|
||||
**NodeVO(06 子项:行程点位)**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `nodeName` | String | 点位名称(优先取 node 自定义名,回退资源名) |
|
||||
| `nodeType` | String | 节点类型枚举值(见 §6) |
|
||||
| `startTime` | String 或 `null` | 开始时间,格式 `HH:mm` |
|
||||
| `timePeriod` | String 或 `null` | 时段(`上午` / `下午` / `全天`) |
|
||||
| `supplierPhone` | String 或 `null` | 供应商电话;无则空串 |
|
||||
| `remark` | String 或 `null` | 操作备注(作司机 / 导游话术) |
|
||||
|
||||
---
|
||||
|
||||
### 5.8 NoticesVO(07 注意事项)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `forbidden` | `String[]` | 严禁项目(固定文案,见 §8 典型示例) |
|
||||
| `warning` | `String[]` | 警示项目(固定文案) |
|
||||
| `standard` | `String[]` | 流程标准项目(固定文案) |
|
||||
|
||||
> 三组均为后端硬编码固定文案,每次响应内容相同,前端直接渲染即可。
|
||||
|
||||
---
|
||||
|
||||
### 5.9 RefundNoteGroup(08 退费规则)
|
||||
|
||||
`refundNotes` 为 `RefundNoteGroup[]`,每个元素对应一个行程节点的退费说明。
|
||||
|
||||
**RefundNoteGroup**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `sourceName` | String | 来源点位名称,如 `呼伦湖景区` |
|
||||
| `intro` | String 或 `null` | 退费说明总体备注 |
|
||||
| `items` | `RefundItem[]` | 退费明细列表 |
|
||||
|
||||
**RefundItem**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `title` | String | 展示标题,如 `成人未参加` |
|
||||
| `amount` | String(BigDecimal) | 退费金额(赠送项目为 `0`) |
|
||||
| `unitLabel` | String | 展示单位文案,如 `/人` / `/团` / `/辆` |
|
||||
| `settleScope` | String | 结算粒度枚举值(见 §6) |
|
||||
| `settleScopeLabel` | String | 结算粒度中文,如 `按人` |
|
||||
| `remark` | String 或 `null` | 备注 |
|
||||
| `effectiveFrom` | String(LocalDate)或 `null` | 规则生效起日;`null` 表示无限制 |
|
||||
| `effectiveTo` | String(LocalDate)或 `null` | 规则生效止日;`null` 表示无限制 |
|
||||
|
||||
---
|
||||
|
||||
### 5.10 handoverChecklist(09 师傅领队交接确认)
|
||||
|
||||
`String[]`,后端返回以下 5 条固定条目,前端在每项右侧留签字栏:
|
||||
|
||||
1. `出行群已建立并拉入全部出行人`
|
||||
2. `签单核对完毕(日期/人数/酒店/景点无误)`
|
||||
3. `车辆及座位安排已确认`
|
||||
4. `特殊需求已告知(忌口/纪念日/老幼残)`
|
||||
5. `代收款金额已当面清点确认`
|
||||
|
||||
---
|
||||
|
||||
### 5.11 CollectReceiptVO(10 代收款签收回执)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `collectAmount` | String(BigDecimal)或 `null` | 代收金额(来自 `order_main.onsiteBalance`);未录入时为 `null` |
|
||||
|
||||
---
|
||||
|
||||
## 6. 枚举 / 数据字典
|
||||
|
||||
### 6.1 direction(大交通方向)
|
||||
|
||||
| 枚举值 | 说明 |
|
||||
|--------|------|
|
||||
| `ARRIVAL` | 到达(进藏 / 进目的地) |
|
||||
| `DEPARTURE` | 出发(离开目的地返程) |
|
||||
|
||||
### 6.2 transportType(交通方式)
|
||||
|
||||
| 枚举值 | 说明 |
|
||||
|--------|------|
|
||||
| `FLIGHT` | 航班 |
|
||||
| `TRAIN` | 火车 |
|
||||
| `SELF_DRIVE` | 自驾 |
|
||||
|
||||
### 6.3 selfDrivePeriod(自驾时段,仅 SELF_DRIVE)
|
||||
|
||||
| 枚举值 | 说明 |
|
||||
|--------|------|
|
||||
| `MORNING` | 上午 |
|
||||
| `AFTERNOON` | 下午 |
|
||||
| `EVENING` | 晚上 |
|
||||
|
||||
### 6.4 createSource(客源渠道)
|
||||
|
||||
| 枚举值 | 常见含义(展示名由字典 order_create_source 翻译) |
|
||||
|--------|------------------------------------------------|
|
||||
| `OTA` | 马蜂窝 / 携程等平台 |
|
||||
| `CUSTOMER` | 老客户 / 回头客 |
|
||||
| `B2B` | 同业 |
|
||||
| `REFERRAL` | 转介绍 |
|
||||
| `MINI_PROGRAM` | 小程序直询 |
|
||||
|
||||
> 字典值以实际 order_create_source 字典表为准,可能随运营配置增减。
|
||||
|
||||
### 6.5 nodeType(行程点位类型)
|
||||
|
||||
| 枚举值 | 说明 |
|
||||
|--------|------|
|
||||
| `SCENIC` | 景区 |
|
||||
| `RESTAURANT` | 餐厅 |
|
||||
| `ACTIVITY` | 活动 |
|
||||
| `SERVICE` | 服务项 |
|
||||
| `CUSTOM` | 自定义 |
|
||||
|
||||
### 6.6 餐食安排(breakfast / lunch / dinner)
|
||||
|
||||
| 枚举值 | 说明 |
|
||||
|--------|------|
|
||||
| `HOTEL` | 酒店早餐 / 含在住宿中 |
|
||||
| `CAMP` | 营地餐 |
|
||||
| `SPECIAL` | 特色餐(安排饭店) |
|
||||
| `SELF` | 自理 |
|
||||
|
||||
### 6.7 settleScope(退费结算粒度)
|
||||
|
||||
| 枚举值 | 说明 |
|
||||
|--------|------|
|
||||
| `PER_PERSON` | 按人结算(`/人`) |
|
||||
| `PER_TEAM` | 按团结算(`/团`) |
|
||||
| `PER_VEHICLE` | 按车结算(`/辆`) |
|
||||
|
||||
### 6.8 字典翻译字段
|
||||
|
||||
以下字段值来自数据字典,前端**不需要**自己翻译枚举,后端已翻译为中文:
|
||||
|
||||
| 字段 | 字典表 key | 说明 |
|
||||
|------|-----------|------|
|
||||
| `hotels[].roomCategory` | `room_category` | 房型中文名;未命中回退「其他房型」 |
|
||||
| `hotels[].settleType` | `settle_type` | 结算方式中文 |
|
||||
| `hotels[].paymentMode` | `payment_mode` | 付款方式中文 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 错误码
|
||||
|
||||
| 错误码 | HTTP 状态 | message | 触发场景 |
|
||||
|--------|-----------|---------|----------|
|
||||
| `581007` | 200(Result 业务码) | 订单不存在 | 路径参数 `id` 对应订单不存在或已软删除 |
|
||||
| `401` | 401 | Unauthorized | JWT 未携带 / 已过期 |
|
||||
| `403` | 403 | Forbidden | 无访问权限 |
|
||||
|
||||
> 其余 Feign 软依赖(product-v2 费用 / resource 城市 / user 应急电话)失败时**不报错**,对应字段降级为 `null` / 空串,不影响接口正常返回。
|
||||
|
||||
---
|
||||
|
||||
## 8. 示例
|
||||
|
||||
### 8.1 典型成功(完整 2 大 1 小 7 日游订单)
|
||||
|
||||
**请求**:
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/1914050000000001/print-itinerary
|
||||
Authorization: Bearer eyJhbGci...
|
||||
```
|
||||
|
||||
**响应**(节选关键区块,实际字段更多):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"agencyName": "呼籁旅行有限公司",
|
||||
"printTime": "2026-06-30T09:15:00",
|
||||
"teamNo": "HLA2026070001",
|
||||
"productName": "呼伦贝尔7日私家定制游",
|
||||
"dateRange": "2026-07-01→2026-07-07",
|
||||
"paxSummary": "2大1小",
|
||||
"driverName": "全广存",
|
||||
"driverPhone": "18614805444",
|
||||
"guideName": "",
|
||||
"guidePhone": "",
|
||||
"leaderName": "扎西",
|
||||
"leaderPhone": "13812345678",
|
||||
"consultantName": "张定制",
|
||||
"transports": [
|
||||
{
|
||||
"direction": "ARRIVAL",
|
||||
"transportType": "FLIGHT",
|
||||
"transportNo": "CA4167",
|
||||
"carrier": "中国国航",
|
||||
"departStation": "北京首都国际机场T3",
|
||||
"arriveStation": "海拉尔东山机场",
|
||||
"departTime": "2026-07-01T08:00:00",
|
||||
"arriveTime": "2026-07-01T11:30:00",
|
||||
"selfDrivePeriod": null,
|
||||
"selfDriveEta": null,
|
||||
"pickupRequired": true,
|
||||
"pickupRemark": "到达T2出口等候",
|
||||
"remark": null
|
||||
}
|
||||
],
|
||||
"customerOverview": {
|
||||
"customerName": "张三",
|
||||
"customerPhone": "138****5678",
|
||||
"adultCount": 2,
|
||||
"childCount": 1,
|
||||
"youngChildCount": 0,
|
||||
"babyCount": 0,
|
||||
"tripDays": 7,
|
||||
"customerType": null,
|
||||
"createSource": "CUSTOMER",
|
||||
"customerRemark": "小孩对海鲜过敏,全程忌口"
|
||||
},
|
||||
"feeDetail": {
|
||||
"items": [
|
||||
{"name": "成人包价", "unitPrice": "4500.00", "qty": 2, "subtotal": "9000.00"},
|
||||
{"name": "儿童包价", "unitPrice": "3000.00", "qty": 1, "subtotal": "3000.00"}
|
||||
],
|
||||
"singleRoomSurcharge": null,
|
||||
"grandTotal": "12000.00",
|
||||
"onsiteBalance": "5000.00"
|
||||
},
|
||||
"hotels": [{
|
||||
"dayNumber": 1,
|
||||
"stayDate": "2026-07-01",
|
||||
"hotelName": "伯爵大酒店",
|
||||
"city": "海拉尔",
|
||||
"roomCategory": "标准双床间",
|
||||
"roomCount": 2,
|
||||
"contactPerson": "张经理",
|
||||
"contactPhone": "0470-12345678",
|
||||
"settleType": "签单",
|
||||
"paymentMode": "月结",
|
||||
"checkInTime": "14:00",
|
||||
"checkOutTime": "12:00"
|
||||
}],
|
||||
"emergencyContacts": [{"contactName": "李房务", "contactPhone": "13900000001", "role": "房务"}],
|
||||
"days": [{
|
||||
"dayNumber": 1,
|
||||
"dayDate": "2026-07-01",
|
||||
"dayTitle": "抵达海拉尔·入住休整",
|
||||
"description": "抵达海拉尔后接机,送至酒店休整",
|
||||
"breakfast": null,
|
||||
"lunch": "SELF",
|
||||
"dinner": "SPECIAL",
|
||||
"diningRemark": "晚餐安排烤全羊",
|
||||
"gatherPlace": null,
|
||||
"dismissalPlace": null,
|
||||
"dailyMileage": "45.00",
|
||||
"nodes": [{
|
||||
"nodeName": "海拉尔东山机场",
|
||||
"nodeType": "SERVICE",
|
||||
"startTime": "11:30",
|
||||
"timePeriod": "上午",
|
||||
"supplierPhone": "0470-88880001",
|
||||
"remark": "接机后直接送酒店,行李搬运到房间"
|
||||
}]
|
||||
}],
|
||||
"notices": {
|
||||
"forbidden": ["严禁向客人推荐自费项目、带客进购物店;违者扣除本行程全部车费,且永不录用"],
|
||||
"warning": ["送站时间不得早于出发时间前 2 小时", "景区半价票差价须由领队自行承担,不得转嫁客人", "行程如有任何变更须经书面确认后方可执行"],
|
||||
"standard": ["出发前须核实全程住宿安排(联系酒店确认房态)", "在出行群内发出行提示及完整大交通信息", "妥善保管签单,行程结束后当日归还公司", "每次入住后须检查房间设施并拍照留存", "司机出发前主动向客人自我介绍并说明全程安排"]
|
||||
},
|
||||
"refundNotes": [{
|
||||
"sourceName": "呼伦湖景区",
|
||||
"intro": "苔藓步道为赠送项目,不退费",
|
||||
"items": [{"title": "成人未参加", "amount": "44.00", "unitLabel": "/人", "settleScope": "PER_PERSON", "settleScopeLabel": "按人", "remark": null, "effectiveFrom": null, "effectiveTo": null}]
|
||||
}],
|
||||
"handoverChecklist": ["出行群已建立并拉入全部出行人", "签单核对完毕(日期/人数/酒店/景点无误)", "车辆及座位安排已确认", "特殊需求已告知(忌口/纪念日/老幼残)", "代收款金额已当面清点确认"],
|
||||
"collectReceipt": {"collectAmount": "5000.00"},
|
||||
"remark": "客人全程需要轮椅通道,联系景区提前安排"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 8.2 边界情况(人员未配置 + feeDetail 降级 + 无退费规则)
|
||||
|
||||
模拟 product-v2 Feign 失败时 `feeDetail` 返回 `null`,司机/导游/领队均未配置,`refundNotes` 为空数组:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"agencyName": "呼籁旅行有限公司",
|
||||
"printTime": "2026-06-30T09:16:00",
|
||||
"teamNo": "HLA2026070002",
|
||||
"productName": "张家界3日游",
|
||||
"dateRange": "2026-07-10→2026-07-12",
|
||||
"paxSummary": "1大",
|
||||
"driverName": "",
|
||||
"driverPhone": "",
|
||||
"guideName": "",
|
||||
"guidePhone": "",
|
||||
"leaderName": "",
|
||||
"leaderPhone": "",
|
||||
"consultantName": "李运营",
|
||||
"transports": [],
|
||||
"customerOverview": {
|
||||
"customerName": "王五",
|
||||
"customerPhone": "139****0000",
|
||||
"adultCount": 1,
|
||||
"childCount": 0,
|
||||
"youngChildCount": 0,
|
||||
"babyCount": 0,
|
||||
"tripDays": 3,
|
||||
"customerType": null,
|
||||
"createSource": "OTA",
|
||||
"customerRemark": null
|
||||
},
|
||||
"feeDetail": null,
|
||||
"hotels": [],
|
||||
"emergencyContacts": [],
|
||||
"days": [],
|
||||
"notices": {
|
||||
"forbidden": ["严禁向客人推荐自费项目、带客进购物店;违者扣除本行程全部车费,且永不录用"],
|
||||
"warning": ["送站时间不得早于出发时间前 2 小时", "景区半价票差价须由领队自行承担,不得转嫁客人", "行程如有任何变更须经书面确认后方可执行"],
|
||||
"standard": ["出发前须核实全程住宿安排(联系酒店确认房态)", "在出行群内发出行提示及完整大交通信息", "妥善保管签单,行程结束后当日归还公司", "每次入住后须检查房间设施并拍照留存", "司机出发前主动向客人自我介绍并说明全程安排"]
|
||||
},
|
||||
"refundNotes": [],
|
||||
"handoverChecklist": ["出行群已建立并拉入全部出行人", "签单核对完毕(日期/人数/酒店/景点无误)", "车辆及座位安排已确认", "特殊需求已告知(忌口/纪念日/老幼残)", "代收款金额已当面清点确认"],
|
||||
"collectReceipt": {"collectAmount": null},
|
||||
"remark": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **前端处理建议**:
|
||||
> - `feeDetail === null` 时,整个费用区块显示「暂无(系统获取失败)」
|
||||
> - 人员字段(`driverName` 等)为空串时,对应展示行可隐藏或显示「-」
|
||||
> - `collectReceipt.collectAmount === null` 时,代收款回执区块显示「代收款金额待确认」
|
||||
|
||||
---
|
||||
|
||||
### 8.3 业务失败(订单不存在)
|
||||
|
||||
**请求**:
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/9999999999999/print-itinerary
|
||||
Authorization: Bearer eyJhbGci...
|
||||
```
|
||||
|
||||
**响应**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 581007,
|
||||
"message": "订单不存在",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 业务边界
|
||||
|
||||
### 适用场景
|
||||
|
||||
- 订单状态为任意状态均可查询(只读,不限状态)
|
||||
- 出团前 1–3 天由定制师打印交出行人员
|
||||
- 支持 A4 纵向排版,前端按 A4 规格渲染后提供打印 / PDF 导出
|
||||
|
||||
### 不适用场景
|
||||
|
||||
- 本接口**不替代**签单 PDF(`GET /v3/admin/order/{id}/sign-voucher`)
|
||||
- 本接口**不是**小程序端行程查看接口,只给管理后台打印用
|
||||
|
||||
### 特殊边界
|
||||
|
||||
| 情况 | 行为 |
|
||||
|------|------|
|
||||
| 订单行程未固化(`days` 为空) | 正常返回,`days` 为空数组 |
|
||||
| product-v2 Feign 超时 / 熔断 | `feeDetail` 降级为 `null`,接口正常 200 返回 |
|
||||
| resource-service Feign 失败 | `hotels[].city` / `contactPerson` / `contactPhone` 降级为空串 |
|
||||
| user-service Feign 失败 | `emergencyContacts[].contactPhone` 降级为空串 |
|
||||
| 费用快照与订单当前金额不一致 | 以产品快照(`feeDetail`)为准,非实时联动;若前端需要实时金额,读订单金额字段 |
|
||||
|
||||
---
|
||||
|
||||
## 10. 修改前后对比
|
||||
|
||||
本次为**新增接口**,无历史版本,跳过此节。
|
||||
|
||||
---
|
||||
|
||||
## 11. 影响评估 / 回滚
|
||||
|
||||
本次为**新增接口**(纯加量),不影响任何已有接口。
|
||||
|
||||
- **前端是否需要同步上线**:是(仅新增打印入口,不强制)
|
||||
- **回滚方案**:后端可随时下架接口,前端调用报 404 时隐藏打印按钮即可
|
||||
- **破坏兼容性**:无
|
||||
|
||||
---
|
||||
|
||||
## 12. 注意事项
|
||||
|
||||
1. **BigDecimal 均为 String**:`grandTotal` / `unitPrice` / `subtotal` / `singleRoomSurcharge` / `onsiteBalance` / `dailyMileage` / `collectAmount` / `amount` 均序列化为 JSON String,前端**直接展示**即可,不需要 `parseFloat` 转换。
|
||||
|
||||
2. **feeDetail 可为 null**:费用区块来自 product-v2 Feign,不保证一定有值,前端**必须**做 null 判断,展示兜底文案「暂无」。
|
||||
|
||||
3. **电话号码三级降级**:
|
||||
- 司机/导游/领队电话:来自订单人员分配,未分配时为空串(不为 null)
|
||||
- 酒店联系人/电话:来自 resource-service Feign,失败时为空串
|
||||
- 应急联系人电话:来自 user-service Feign 取 admin_user.mobile,失败时为空串
|
||||
- 三种情况均不报错,前端按空串处理即可(显示「-」或隐藏)
|
||||
|
||||
4. **主联系人手机已脱敏**:`customerOverview.customerPhone` 格式为 `138****5678`,用于打印展示,安全无需二次处理。
|
||||
|
||||
5. **注意事项固定文案**:`notices` 三组内容为后端常量(`PrintItineraryConstants`),不走数据库,修改文案需后端发版。
|
||||
|
||||
6. **费用与实际金额可能不同步**:`feeDetail` 来自产品快照,当产品价格调整但订单快照未更新时,打印金额可能与最新报价不一致,属预期行为(以签单时快照为准)。
|
||||
|
||||
---
|
||||
|
||||
## 13. 关联 / 联系人
|
||||
|
||||
| 项 | 链接 / 信息 |
|
||||
|----|------------|
|
||||
| **Issue** | [#4644 打印行程单接口(出团行程单·Driver Copy)](https://git.1814.love:8443/wx/HL/issues/4644) |
|
||||
| **PR** | [#4650 feat(order-v3): 打印行程单 11 区块聚合接口](https://git.1814.love:8443/wx/HL/pulls/4650) |
|
||||
| **Merge Commit** | [8e2b02f56](https://git.1814.love:8443/wx/HL/commit/8e2b02f56) |
|
||||
| **Feature Commit** | [187169daf](https://git.1814.love:8443/wx/HL/commit/187169daf) |
|
||||
| **后端负责人** | yaosutu |
|
||||
| **影响服务** | hl-order-service-v3(端口 8086) |
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户