hl-api-changelog/changelogs-v2/2026-06/30_4644_打印行程单接口-新增接口-管理后台.md
yaosutu c005372652 feat(order-v3): 新增打印行程单接口 changelog(Issue #4644,PR #4650)
GET /v3/admin/order/{id}/print-itinerary
11 区块全量聚合,含字段表/枚举/3组示例/注意事项/关联链接
2026-06-30 18:37:05 +08:00

25 KiB

打印行程单接口出团行程单·Driver Copy

接口路径GET /v3/admin/order/{id}/print-itinerary 服务hl-order-service-v3 PR#4650 Issue#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
认证 需携带管理后台 JWTAuthorization: Bearer <token>
权限 已登录的管理后台用户,无额外角色限制
幂等性 只读查询,天然幂等
限流 无特殊限流(走网关通用限流)
响应格式 application/json; charset=utf-8
包装类型 Result<PrintItineraryRespVO>

4. 接口入参

4.1 路径参数

参数名 类型 必填 说明
id LongJSON 序列化为 String,防 JS 精度丢失) 订单 ID雪花 ID,前端应作为字符串透传,不要转 number

4.2 请求体

本接口无请求体GET 请求)。


5. 出参字段

响应结构:Result<PrintItineraryRespVO>code=200data 为完整行程单对象。

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 FeeDetailVOnull 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 TransportVO01 大交通批次)

字段名 类型 说明
direction String 方向枚举值:ARRIVAL(到达)/ DEPARTURE(出发)
transportType String 交通方式枚举值:FLIGHT(航班)/ TRAIN(火车)/ SELF_DRIVE(自驾)
transportNo String 航班号 / 车次号;SELF_DRIVE 时为空串
carrier String 航司 / 铁路公司名称
departStation String 出发站 / 机场全称
arriveStation String 到达站 / 机场全称
departTime StringLocalDateTime 出发时间,格式 YYYY-MM-DDTHH:mm:ss
arriveTime StringLocalDateTime 到达时间,格式 YYYY-MM-DDTHH:mm:ss
selfDrivePeriod String 或 null 自驾时段,仅 SELF_DRIVE 时有值:MORNING / AFTERNOON / EVENING
selfDriveEta StringLocalDateTimenull 自驾预计到达时间,仅 SELF_DRIVE 时有值
pickupRequired Boolean 是否需要平台接送
pickupRemark String 或 null 接送备注
remark String 或 null 本段交通备注

5.3 CustomerOverviewVO02 客人信息速览)

字段名 类型 说明
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 FeeDetailVO03 费用明细)

整体可为 nullproduct-v2 Feign 失败时降级),前端应展示「暂无」而不报错。

字段名 类型 说明
items FeeLineItemVO[] 费用行项列表(仅含数量 > 0 的人群类型)
singleRoomSurcharge StringBigDecimalnull 单房差加价;无单间需求时为 null
grandTotal StringBigDecimal 合计金额
onsiteBalance StringBigDecimalnull 代收款(现场实收尾款);未录入时为 null

FeeLineItemVO费用行项

字段名 类型 说明
name String 行项名称,如 成人包价 / 儿童包价 / 幼童包价 / 婴儿包价
unitPrice StringBigDecimal 单价
qty Integer 数量
subtotal StringBigDecimal 小计(= 单价 × 数量)

注意BigDecimal 字段均序列化为 JSON String(防 JS 精度丢失),前端渲染时直接使用,不需要 parseFloat() 转换。


5.5 HotelVO04 全程住宿,逐晚)

字段名 类型 说明
dayNumber Integer 天序号1-based,第一晚 = 1
stayDate StringLocalDate 入住日期,格式 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 EmergencyContactVO05 应急兜底联系人)

字段名 类型 说明
contactName String 姓名(来自配房 claimer_name 快照)
contactPhone String 电话(通过 user-service Feign 取 admin_user.mobile;失败或未维护时为空串
role String 角色说明,固定为 房务

5.7 DayVO06 每日行程)

字段名 类型 说明
dayNumber Integer 天序号1-based
dayDate StringLocalDate 实际日期,格式 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 StringBigDecimalnull 当日里程km
nodes NodeVO[] 当日点位列表,按 sort_order 升序

NodeVO06 子项:行程点位)

字段名 类型 说明
nodeName String 点位名称(优先取 node 自定义名,回退资源名)
nodeType String 节点类型枚举值(见 §6
startTime String 或 null 开始时间,格式 HH:mm
timePeriod String 或 null 时段(上午 / 下午 / 全天
supplierPhone String 或 null 供应商电话;无则空串
remark String 或 null 操作备注(作司机 / 导游话术)

5.8 NoticesVO07 注意事项)

字段名 类型 说明
forbidden String[] 严禁项目(固定文案,见 §8 典型示例)
warning String[] 警示项目(固定文案)
standard String[] 流程标准项目(固定文案)

三组均为后端硬编码固定文案,每次响应内容相同,前端直接渲染即可。


5.9 RefundNoteGroup08 退费规则)

refundNotesRefundNoteGroup[],每个元素对应一个行程节点的退费说明。

RefundNoteGroup

字段名 类型 说明
sourceName String 来源点位名称,如 呼伦湖景区
intro String 或 null 退费说明总体备注
items RefundItem[] 退费明细列表

RefundItem

字段名 类型 说明
title String 展示标题,如 成人未参加
amount StringBigDecimal 退费金额(赠送项目为 0
unitLabel String 展示单位文案,如 /人 / /团 / /辆
settleScope String 结算粒度枚举值(见 §6
settleScopeLabel String 结算粒度中文,如 按人
remark String 或 null 备注
effectiveFrom StringLocalDatenull 规则生效起日;null 表示无限制
effectiveTo StringLocalDatenull 规则生效止日;null 表示无限制

5.10 handoverChecklist09 师傅领队交接确认)

String[],后端返回以下 5 条固定条目,前端在每项右侧留签字栏:

  1. 出行群已建立并拉入全部出行人
  2. 签单核对完毕(日期/人数/酒店/景点无误)
  3. 车辆及座位安排已确认
  4. 特殊需求已告知(忌口/纪念日/老幼残)
  5. 代收款金额已当面清点确认

5.11 CollectReceiptVO10 代收款签收回执)

字段名 类型 说明
collectAmount StringBigDecimalnull 代收金额(来自 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 200Result 业务码) 订单不存在 路径参数 id 对应订单不存在或已软删除
401 401 Unauthorized JWT 未携带 / 已过期
403 403 Forbidden 无访问权限

其余 Feign 软依赖product-v2 费用 / resource 城市 / user 应急电话)失败时不报错,对应字段降级为 null / 空串,不影响接口正常返回。


8. 示例

8.1 典型成功(完整 2 大 1 小 7 日游订单)

请求

GET /v3/admin/order/1914050000000001/print-itinerary
Authorization: Bearer eyJhbGci...

响应(节选关键区块,实际字段更多):

{
  "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 为空数组:

{
  "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 业务失败(订单不存在)

请求

GET /v3/admin/order/9999999999999/print-itinerary
Authorization: Bearer eyJhbGci...

响应

{
  "code": 581007,
  "message": "订单不存在",
  "data": null
}

9. 业务边界

适用场景

  • 订单状态为任意状态均可查询(只读,不限状态)
  • 出团前 1–3 天由定制师打印交出行人员
  • 支持 A4 纵向排版,前端按 A4 规格渲染后提供打印 / PDF 导出

不适用场景

  • 本接口不替代签单 PDFGET /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 均为 StringgrandTotal / 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
PR #4650 feat(order-v3): 打印行程单 11 区块聚合接口
Merge Commit 8e2b02f56
Feature Commit 187169daf
后端负责人 yaosutu
影响服务 hl-order-service-v3端口 8086