diff --git a/changelogs/2026-03/2026-03-19_order_room_vehicle_contract_insurance.md b/changelogs/2026-03/2026-03-19_order_room_vehicle_contract_insurance.md new file mode 100644 index 0000000..d8f68ff --- /dev/null +++ b/changelogs/2026-03/2026-03-19_order_room_vehicle_contract_insurance.md @@ -0,0 +1,1897 @@ +# 订单配房配车 + 合同管理 + 保险管理 - 前端对接指南 + +> **日期**: 2026-03-19 +> **后端状态**: ✅ 已完成,可直接对接 +> **涉及模块**: hl-order-service(配房配车+交通信息)、hl-contract-service(合同管理)、hl-insurance-service(保险管理) + +--- + +## 功能说明 + +本文档涵盖订单内部流程中 **配房 → 配车 → 合同签署 → 保险投保** 四大模块的完整前端对接方案。 + +### 订单内部流程状态机(8步) + +``` +PENDING_INFO(待补全信息) + → PROCESSING(待内部流程) + → PENDING_INSURANCE(待配保险) + → PENDING_CONTRACT(待签合同) + → PENDING_ROOM(待配房) + → PENDING_VEHICLE(待配车) + → PENDING_FINANCE(待核算) + → READY(就绪) +``` + +每一步通过调用 `PUT /admin/order/{orderId}/process-status` 推进到下一步,或通过具体的配房/配车/合同/保险操作自动推进。 + +--- + +# 第一部分:配房配车 + 交通信息 + +--- + +## 接口清单(配房配车) + +| # | 接口 | 方法 | 路径 | 说明 | +|---|------|------|------|------| +| 1 | 更新房间信息(文本) | PUT | `/admin/order/{orderId}/room-info` | 简单文本描述房间分配 | +| 2 | 分配酒店(结构化) | PUT | `/admin/order/{orderId}/hotel-assignment` | 按家庭分配酒店、房型、入住退房日期 | +| 3 | 检测房型一致性 | POST | `/admin/order/{orderId}/room-info/check-diff` | 检测当前配置与产品快照是否一致 | +| 4 | 更新车辆信息(文本) | PUT | `/admin/order/{orderId}/vehicle-info` | 简单文本描述车辆分配 | +| 5 | 分配车辆(结构化) | PUT | `/admin/order/{orderId}/vehicle-assignment` | 详细分配车型、品牌、司机 | +| 6 | 检测车型一致性 | POST | `/admin/order/{orderId}/vehicle-info/check-diff` | 检测当前配置与产品快照是否一致 | +| 7 | 保存交通信息 | PUT | `/admin/order/{orderId}/transport` | 批量保存航班/车次信息(全量替换) | +| 8 | 查询交通信息 | GET | `/admin/order/{orderId}/transport` | 查询订单的所有交通信息 | +| 9 | 推进内部流程 | PUT | `/admin/order/{orderId}/process-status` | 手动推进到下一步 | + +--- + +## 接口 1:更新房间信息(文本模式) + +**使用场景**:配房管理员填写房间分配的文字描述,适用于简单场景(如"标准双人间2间,大床房1间")。 + +``` +PUT /admin/order/{orderId}/room-info +``` + +### 请求参数 + +| 参数 | 类型 | 位置 | 必填 | 说明 | +|------|------|------|------|------| +| orderId | Long | 路径 | ✅ | 订单ID | + +### 请求体 + +```json +{ + "roomInfo": "标准双人间2间,大床房1间" +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| roomInfo | String | ✅ | 房间信息描述,最长2000字 | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": null +} +``` + +### 业务规则 +- 仅限 **房务管理员** 或 **超级管理员** 操作 +- 保存成功后自动完成订单中的 `ARRANGE_ROOM` 待办 +- 系统会发送"房间信息已更新"通知给用户 +- 记录操作时间线 + +--- + +## 接口 2:分配酒店(结构化模式) + +**使用场景**:按家庭维度详细分配酒店和房型,适用于复杂场景(多家庭、不同酒店、不同房型)。 + +``` +PUT /admin/order/{orderId}/hotel-assignment +``` + +### 请求参数 + +| 参数 | 类型 | 位置 | 必填 | 说明 | +|------|------|------|------|------| +| orderId | Long | 路径 | ✅ | 订单ID | + +### 请求体 + +```json +{ + "assignments": [ + { + "familyIndex": 1, + "hotelName": "呼和浩特香格里拉大酒店", + "roomType": "豪华大床房", + "checkInDate": "2026-07-01", + "checkOutDate": "2026-07-03" + }, + { + "familyIndex": 2, + "hotelName": "呼和浩特香格里拉大酒店", + "roomType": "标准双人间", + "checkInDate": "2026-07-01", + "checkOutDate": "2026-07-03" + } + ] +} +``` + +### 请求字段 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| assignments | Array | ✅ | 酒店分配列表,不能为空 | +| assignments[].familyIndex | Integer | ✅ | 家庭序号(从1开始) | +| assignments[].hotelName | String | ✅ | 酒店名称 | +| assignments[].roomType | String | ✅ | 房型名称 | +| assignments[].checkInDate | String | ✅ | 入住日期(yyyy-MM-dd) | +| assignments[].checkOutDate | String | ✅ | 退房日期(yyyy-MM-dd) | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": null +} +``` + +### 前端实现建议 +- 每个家庭一行,用 `el-form` 动态表单 + `el-button` 添加/删除行 +- 酒店名称可用 `el-select` 远程搜索(调用资源服务酒店列表接口) +- 房型可联动酒店选择后加载(调用酒店房型列表接口) +- 日期用 `el-date-picker` 的 `daterange` 模式 + +--- + +## 接口 3:检测房型一致性 + +**使用场景**:配房前或配房后,检测当前房间配置是否与产品快照(下单时锁定的房型)一致,如不一致前端弹窗提示。 + +``` +POST /admin/order/{orderId}/room-info/check-diff +``` + +### 请求参数 + +| 参数 | 类型 | 位置 | 必填 | 说明 | +|------|------|------|------|------| +| orderId | Long | 路径 | ✅ | 订单ID | + +### 请求体 + +无(自动读取当前 roomInfo 与产品快照对比) + +### 响应示例 + +一致时: +```json +{ + "code": 200, + "message": "成功", + "data": null +} +``` + +不一致时: +```json +{ + "code": 200, + "message": "成功", + "data": "产品快照为标准双人间×2,当前配置为大床房×2" +} +``` + +### 响应字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| data | String / null | null=一致;非null=不一致的描述文本 | + +### 前端实现建议 +- 配房保存后自动调用此接口 +- 如返回非null,用 `el-message-box` 弹窗显示差异,按钮:"已知晓,继续" / "返回修改" + +--- + +## 接口 4:更新车辆信息(文本模式) + +**使用场景**:配车管理员填写车辆分配的文字描述。 + +``` +PUT /admin/order/{orderId}/vehicle-info +``` + +### 请求体 + +```json +{ + "vehicleInfo": "7座商务车1辆,司机张师傅,电话13800138000" +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| vehicleInfo | String | ✅ | 车辆信息描述,最长2000字 | + +### 业务规则 +- 仅限 **车务管理员** 或 **超级管理员** 操作 +- 保存成功后自动完成 `ARRANGE_VEHICLE` 待办 +- 系统会发送"车辆信息已更新"通知给用户 + +--- + +## 接口 5:分配车辆(结构化模式) + +**使用场景**:详细分配车型、品牌、车牌号和司机信息。 + +``` +PUT /admin/order/{orderId}/vehicle-assignment +``` + +### 请求体 + +```json +{ + "vehicleModel": "考斯特19座", + "vehicleBrand": "丰田", + "plateNumber": "蒙A88888", + "driverName": "张师傅", + "driverPhone": "13800138000" +} +``` + +### 请求字段 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| vehicleModel | String | ✅ | 车型名称(如:考斯特19座、别克GL8) | +| vehicleBrand | String | ✅ | 品牌(如:丰田、别克、奔驰) | +| plateNumber | String | 否 | 车牌号 | +| driverName | String | 否 | 司机姓名 | +| driverPhone | String | 否 | 司机电话 | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": null +} +``` + +### 前端实现建议 +- 车型可用 `el-select` 加载资源服务车型列表(`GET /admin/vehicle/models/all`) +- 品牌联动车型选择后自动填充 +- 司机信息手工填写 + +--- + +## 接口 6:检测车型一致性 + +**使用场景**:检测当前车辆配置与产品快照是否一致。 + +``` +POST /admin/order/{orderId}/vehicle-info/check-diff +``` + +### 响应 + +同接口3,data 为 null 表示一致,非 null 为差异描述。 + +--- + +## 接口 7:保存交通信息 + +**使用场景**:为订单添加航班/火车等交通信息,支持多段行程。**全量替换**——每次保存会删除旧数据,以新提交的为准。 + +``` +PUT /admin/order/{orderId}/transport +``` + +### 请求体 + +```json +{ + "segments": [ + { + "transportType": "FLIGHT", + "transportNo": "CA1234", + "departStation": "北京首都T3", + "arriveStation": "呼和浩特白塔", + "departTime": "2026-07-01T08:30:00", + "arriveTime": "2026-07-01T10:15:00", + "remark": "请提前2小时到达机场" + }, + { + "transportType": "FLIGHT", + "transportNo": "CA4321", + "departStation": "呼和浩特白塔", + "arriveStation": "北京首都T3", + "departTime": "2026-07-07T18:00:00", + "arriveTime": "2026-07-07T19:45:00", + "remark": "" + } + ] +} +``` + +### 请求字段 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| segments | Array | ✅ | 交通分段列表,不能为空 | +| segments[].transportType | String | ✅ | 交通类型(字典 `transport_type`):`FLIGHT`-航班、`TRAIN`-火车 | +| segments[].transportNo | String | 否 | 航班号/车次号,如 CA1234、G1234 | +| segments[].departStation | String | 否 | 出发站/出发机场 | +| segments[].arriveStation | String | 否 | 到达站/到达机场 | +| segments[].departTime | String | 否 | 出发时间(ISO格式:`yyyy-MM-ddTHH:mm:ss`) | +| segments[].arriveTime | String | 否 | 到达时间(ISO格式) | +| segments[].remark | String | 否 | 备注 | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "segmentId": "2026279738275856400", + "orderId": "2026270000000000001", + "transportType": "FLIGHT", + "transportNo": "CA1234", + "departStation": "北京首都T3", + "arriveStation": "呼和浩特白塔", + "departTime": "2026-07-01T08:30:00", + "arriveTime": "2026-07-01T10:15:00", + "remark": "请提前2小时到达机场", + "sortOrder": 0 + } + ] +} +``` + +### 响应字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| segmentId | String | 交通分段ID(雪花ID) | +| orderId | String | 订单ID | +| transportType | String | 交通类型 | +| transportNo | String | 航班号/车次号 | +| departStation | String | 出发站 | +| arriveStation | String | 到达站 | +| departTime | String | 出发时间 | +| arriveTime | String | 到达时间 | +| remark | String | 备注 | +| sortOrder | Integer | 排序序号(按提交顺序自动编号) | + +### 前端实现建议 +- 动态表单,每段一行,支持添加/删除 +- `transportType` 用 `el-select` 绑定字典 `transport_type` +- 时间用 `el-date-picker` 的 `datetime` 模式 +- 保存时将所有段一次性提交 + +--- + +## 接口 8:查询交通信息 + +**使用场景**:打开订单详情时加载已有的交通信息。 + +``` +GET /admin/order/{orderId}/transport +``` + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "segmentId": "2026279738275856400", + "orderId": "2026270000000000001", + "transportType": "FLIGHT", + "transportNo": "CA1234", + "departStation": "北京首都T3", + "arriveStation": "呼和浩特白塔", + "departTime": "2026-07-01T08:30:00", + "arriveTime": "2026-07-01T10:15:00", + "remark": "请提前2小时到达机场", + "sortOrder": 0 + } + ] +} +``` + +--- + +## 接口 9:推进内部流程 + +**使用场景**:每个阶段完成后,手动点击"推进到下一步"按钮。 + +``` +PUT /admin/order/{orderId}/process-status +``` + +### 请求参数 + +| 参数 | 类型 | 位置 | 必填 | 说明 | +|------|------|------|------|------| +| orderId | Long | 路径 | ✅ | 订单ID | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": null +} +``` + +### 业务规则 +- 按固定顺序推进:`PENDING_INFO → PROCESSING → PENDING_INSURANCE → PENDING_CONTRACT → PENDING_ROOM → PENDING_VEHICLE → PENDING_FINANCE → READY` +- 每次推进一步,不能跳步 +- 自动完成对应阶段的待办 + +--- + +## 订单详情中的配房配车字段 + +订单详情接口 `GET /admin/order/{orderId}` 返回的 `OrderDetailVO` 包含以下相关字段: + +| 字段 | 类型 | 说明 | +|------|------|------| +| processStatus | String | 当前内部流程状态(见下方字典) | +| processStatusLabel | String | 流程状态中文标签 | +| roomInfo | String | 房间信息(JSON字符串或文本) | +| vehicleInfo | String | 车辆信息(JSON字符串或文本) | +| hotelAssignments | String | 酒店分配信息(JSON数组) | +| transportSegments | Array | 交通分段列表(结构化数据) | +| checklistConfirmed | Boolean | 清单是否已确认 | +| balancePayMethod | String | 尾款支付方式:`ONLINE`-线上微信支付,`OFFLINE`-线下转账 | + +--- + +# 第二部分:合同管理 + +--- + +## 接口清单(合同管理) + +| # | 接口 | 方法 | 路径 | 说明 | +|---|------|------|------|------| +| 10 | 获取合同平台列表 | GET | `/admin/contract/platforms` | 可用签约平台 | +| 11 | 获取旅行社列表 | GET | `/admin/contract/agencies` | 旅行社列表 | +| 12 | 获取合同模板列表 | GET | `/admin/contract/templates` | 合同模板列表 | +| 13 | 创建合同(电子签约) | POST | `/admin/contract/create` | 标准电子签约模式 | +| 14 | 报备合同(同步模式) | POST | `/admin/contract/report` | 线下签约后报备 | +| 15 | 合同列表 | GET | `/admin/contract/list` | 分页查询合同 | +| 16 | 合同详情 | GET | `/admin/contract/{id}` | 含出行人+状态日志 | +| 17 | 按订单查合同 | GET | `/admin/contract/by-order/{orderId}` | 查询订单所有合同 | +| 18 | 获取订单有效合同 | GET | `/admin/contract/active-by-order/{orderId}` | 获取最新非作废合同 | +| 19 | 刷新合同状态 | GET | `/admin/contract/{id}/status` | 从平台同步最新状态 | +| 20 | 作废合同 | POST | `/admin/contract/{id}/invalidate` | 作废合同 | +| 21 | 重发签署短信 | POST | `/admin/contract/{id}/resend-sms` | 重发签署链接短信 | +| 22 | 上传已签署PDF | POST | `/admin/contract/{id}/upload-pdf` | 同步模式上传PDF | +| 23 | 补充约定模板-列表(启用) | GET | `/admin/contract/clause-template/list` | 下拉选择用 | +| 24 | 补充约定模板-全部列表 | GET | `/admin/contract/clause-template/list-all` | 管理用 | +| 25 | 补充约定模板-创建 | POST | `/admin/contract/clause-template` | 创建模板 | +| 26 | 补充约定模板-更新 | PUT | `/admin/contract/clause-template/{id}` | 更新模板 | +| 27 | 补充约定模板-切换状态 | PUT | `/admin/contract/clause-template/{id}/toggle-status` | 启用/停用 | +| 28 | 补充约定模板-删除 | DELETE | `/admin/contract/clause-template/{id}` | 删除模板 | + +--- + +## 接口 10:获取合同平台列表 + +**使用场景**:创建合同时,选择签约平台下拉框的数据源。 + +``` +GET /admin/contract/platforms +``` + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "code": "12301", + "name": "全国旅游监管平台", + "enabled": true + }, + { + "code": "FADADA", + "name": "法大大", + "enabled": true + } + ] +} +``` + +--- + +## 接口 11:获取旅行社列表 + +**使用场景**:创建合同时选择旅行社。 + +``` +GET /admin/contract/agencies +``` + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "code": "L-FJ-100005", + "name": "内蒙古呼籁国际旅行社有限公司" + } + ] +} +``` + +--- + +## 接口 12:获取合同模板列表 + +**使用场景**:创建合同时选择模板。 + +``` +GET /admin/contract/templates +``` + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "templateId": "2026279738275856380", + "templateCode": "TOURAGE_STANDARD", + "templateName": "国内旅游标准合同", + "platform": "12301", + "mode": "STANDARD", + "status": "ACTIVE", + "description": "全国旅游监管平台标准旅游合同模板" + } + ] +} +``` + +### 响应字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| templateId | String | 模板ID | +| templateCode | String | 模板编码(创建合同时传此值) | +| templateName | String | 模板名称 | +| platform | String | 签约平台(字典 `contract_platform`) | +| mode | String | 签约模式:`STANDARD`-电子签约,`SYNC`-同步报备 | +| status | String | 模板状态:`ACTIVE`-启用,`INACTIVE`-停用 | +| description | String | 模板描述 | + +--- + +## 接口 13:创建合同(电子签约模式) + +**使用场景**:为订单创建电子合同,系统会调用第三方平台(如12301)生成签署链接,通过短信发送给签署人。 + +``` +POST /admin/contract/create +``` + +### 请求体 + +```json +{ + "orderId": "2026270000000000001", + "contractType": "TOUR", + "platform": "12301", + "templateCode": "TOURAGE_STANDARD", + "agencyCode": "L-FJ-100005", + "transactorName": "王经理", + "transactorPhone": "13900139001", + "destination": "呼伦贝尔", + "routeName": "呼伦贝尔草原7日深度游", + "days": 7, + "nights": 6, + "departureDate": "2026-07-01", + "returnDate": "2026-07-07", + "departureCity": "北京", + "groupId": "GRP20260701001", + "signatoryMode": 1, + "signatoryName": "张三", + "signatoryPhone": "13800138000", + "signatoryIdType": 1, + "signatoryIdNumber": "110101199001011234", + "signingPlace": "北京市朝阳区", + "adultCost": 5980.00, + "childCost": 2990.00, + "totalAmount": 14950.00, + "paymentMethod": 2, + "disputeResolution": 2, + "leastCustomerNumber": 1, + "contactName": "张三", + "contactPhone": "13800138000", + "supplementaryClause": "夏季草原行程补充约定...", + "vehicleModel": "考斯特19座", + "travelers": [ + { + "name": "张三", + "gender": "male", + "age": 35, + "idCardType": 1, + "idCardNo": "110101199001011234", + "phone": "13800138000", + "isSigner": true, + "isChild": false, + "health": "健康" + }, + { + "name": "张小明", + "gender": "male", + "age": 8, + "idCardType": 1, + "idCardNo": "110101201801011234", + "phone": "", + "isSigner": false, + "isChild": true, + "health": "健康" + } + ] +} +``` + +### 请求字段 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| orderId | Long | 否 | 关联订单ID | +| contractType | String | 否 | 合同类型:`TOUR`-旅游合同(默认)、`INSURANCE`-保险单 | +| platform | String | 否 | 签约平台,不传则根据模板自动确定。字典 `contract_platform` | +| templateCode | String | ✅ | 模板编码(从接口12获取) | +| agencyCode | String | 否 | 旅行社编号,不填使用默认配置 | +| transactorName | String | 否 | 经办人姓名 | +| transactorPhone | String | 否 | 经办人电话 | +| destination | String | ✅ | 目的地 | +| routeName | String | ✅ | 线路名称 | +| days | Integer | 否 | 行程天数 | +| nights | Integer | 否 | 住宿晚数 | +| departureDate | String | ✅ | 出发日期(yyyy-MM-dd) | +| returnDate | String | ✅ | 返回日期(yyyy-MM-dd) | +| departureCity | String | 否 | 出发城市 | +| groupId | String | 否 | 团号 | +| signatoryMode | Integer | 否 | 签署模式:`1`-短信(默认)、`2`-现场、`3`-线下 | +| signatoryName | String | ✅ | 签署人姓名 | +| signatoryPhone | String | ✅ | 签署人电话 | +| signatoryIdType | Integer | 否 | 签署人证件类型:`1`-身份证(默认) | +| signatoryIdNumber | String | ✅ | 签署人证件号码 | +| signingPlace | String | 否 | 签约地点 | +| adultCost | BigDecimal | ✅ | 成人费用 | +| childCost | BigDecimal | 否 | 儿童费用 | +| totalAmount | BigDecimal | ✅ | 合同总金额 | +| paymentMethod | Integer | 否 | 付款方式:`1`-现金、`2`-转账(默认)、`3`-在线 | +| disputeResolution | Integer | 否 | 争议解决:`1`-仲裁、`2`-诉讼(默认) | +| leastCustomerNumber | Integer | 否 | 最低成团人数(默认1) | +| contactName | String | ✅ | 联系人姓名 | +| contactPhone | String | ✅ | 联系人电话 | +| supplementaryClause | String | 否 | 补充约定内容 | +| vehicleModel | String | 否 | 车型名称(产品快照) | +| travelers | Array | ✅ | 出行人列表(至少1人) | + +### 出行人字段 (travelers[]) + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| name | String | ✅ | 姓名 | +| gender | String | 否 | 性别:`male`-男、`female`-女 | +| age | Integer | 否 | 年龄 | +| idCardType | Integer | 否 | 证件类型:`1`-身份证(默认)、`2`-护照 | +| idCardNo | String | ✅ | 证件号码 | +| phone | String | 否 | 手机号 | +| isSigner | Boolean | 否 | 是否为签署人(默认false) | +| isChild | Boolean | 否 | 是否儿童(默认false) | +| health | String | 否 | 健康信息 | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "contractId": "2026279738275856500", + "orderId": "2026270000000000001", + "templateCode": "TOURAGE_STANDARD", + "templateName": "国内旅游标准合同", + "contractNumber": "CN20260701001", + "platform": "12301", + "contractType": "TOUR", + "mode": "STANDARD", + "status": "GENERATED", + "statusLabel": "已生成", + "signUrl": "https://12301.cn/sign/xxxx", + "qrCodeUrl": "https://12301.cn/qr/xxxx", + "fileUrl": null, + "agencyCode": "L-FJ-100005", + "travelAgencyName": "内蒙古呼籁国际旅行社有限公司", + "destination": "呼伦贝尔", + "departureDate": "2026-07-01", + "returnDate": "2026-07-07", + "totalAmount": 14950.00, + "touristCount": 2, + "contactName": "张三", + "contactPhone": "13800138000", + "createTime": "2026-03-19T10:30:00", + "supplementaryClause": "夏季草原行程补充约定...", + "travelers": [ + { + "travelerId": "2026279738275856510", + "name": "张三", + "idCardType": "1", + "idCardNo": "110101****1234", + "phone": "138****8000", + "isSigner": true + } + ], + "statusLogs": [ + { + "logId": "2026279738275856520", + "oldStatus": "PENDING", + "newStatus": "GENERATED", + "source": "MANUAL", + "createTime": "2026-03-19T10:30:00" + } + ] + } +} +``` + +--- + +## 接口 14:报备合同(同步模式) + +**使用场景**:线下已签署的合同,上传后同步报备到12301平台。请求结构与接口13相同,`signatoryMode` 默认为 `2`(现场)。 + +``` +POST /admin/contract/report +``` + +请求字段同接口13。 + +--- + +## 接口 15:合同列表 + +**使用场景**:合同管理列表页分页查询。 + +``` +GET /admin/contract/list?page=1&pageSize=20&orderId=2026270000000000001&status=SIGNED +``` + +### 请求参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| orderId | Long | 否 | 按订单ID过滤 | +| status | String | 否 | 按合同状态过滤 | +| platform | String | 否 | 按签约平台过滤 | +| page | Integer | 否 | 页码(默认1) | +| pageSize | Integer | 否 | 每页条数(默认20) | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "total": 15, + "page": 1, + "pageSize": 20, + "records": [ + { + "contractId": "2026279738275856500", + "orderId": "2026270000000000001", + "templateCode": "TOURAGE_STANDARD", + "templateName": "国内旅游标准合同", + "contractNumber": "CN20260701001", + "platform": "12301", + "contractType": "TOUR", + "mode": "STANDARD", + "status": "SIGNED", + "statusLabel": "已签署", + "signUrl": "https://12301.cn/sign/xxxx", + "qrCodeUrl": null, + "fileUrl": "https://12301.cn/file/xxxx.pdf", + "destination": "呼伦贝尔", + "departureDate": "2026-07-01", + "returnDate": "2026-07-07", + "totalAmount": 14950.00, + "touristCount": 2, + "contactName": "张三", + "contactPhone": "13800138000", + "createTime": "2026-03-19T10:30:00" + } + ] + } +} +``` + +--- + +## 接口 16:合同详情 + +``` +GET /admin/contract/{id} +``` + +返回 `ContractDetailVO`,在 `ContractVO` 基础上增加: + +| 字段 | 类型 | 说明 | +|------|------|------| +| supplementaryClause | String | 补充约定内容 | +| travelers | Array | 出行人列表 | +| travelers[].travelerId | String | 出行人ID | +| travelers[].name | String | 姓名 | +| travelers[].idCardType | String | 证件类型 | +| travelers[].idCardNo | String | 证件号码(脱敏) | +| travelers[].phone | String | 手机号(脱敏) | +| travelers[].isSigner | Boolean | 是否签署人 | +| statusLogs | Array | 状态变更日志 | +| statusLogs[].logId | String | 日志ID | +| statusLogs[].oldStatus | String | 旧状态 | +| statusLogs[].newStatus | String | 新状态 | +| statusLogs[].source | String | 来源:`CALLBACK`-平台回调、`POLLING`-轮询、`MANUAL`-手动 | +| statusLogs[].createTime | String | 变更时间 | + +--- + +## 接口 17-18:按订单查合同 + +``` +GET /admin/contract/by-order/{orderId} # 所有合同 +GET /admin/contract/active-by-order/{orderId} # 最新有效合同 +``` + +--- + +## 接口 19:刷新合同状态 + +**使用场景**:等待签署中的合同,点击"刷新状态"从平台同步最新签署状态。 + +``` +GET /admin/contract/{id}/status +``` + +返回更新后的 `ContractVO`。 + +--- + +## 接口 20:作废合同 + +``` +POST /admin/contract/{id}/invalidate +``` + +### 业务规则 +- 仅 `GENERATED` / `SIGNING` 状态的合同可以作废 +- 作废后状态变为 `VOIDED`,不可恢复 + +--- + +## 接口 21:重发签署短信 + +``` +POST /admin/contract/{id}/resend-sms +``` + +返回 `Boolean`,true=发送成功。 + +--- + +## 接口 22:上传已签署PDF(同步模式) + +**使用场景**:同步模式的合同,上传线下签署的PDF文件。 + +``` +POST /admin/contract/{id}/upload-pdf +Content-Type: multipart/form-data +``` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| file | File | ✅ | PDF文件 | + +--- + +## 接口 23-28:补充约定模板管理 + +### 创建模板(接口25) + +``` +POST /admin/contract/clause-template +``` + +```json +{ + "name": "夏季小团补充约定", + "content": "1. 如遇恶劣天气,行程可能调整...\n2. 草原蚊虫较多,建议自备驱蚊用品...", + "sortOrder": 1 +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| name | String | ✅ | 模板名称 | +| content | String | ✅ | 模板内容(支持换行) | +| sortOrder | Integer | 否 | 排序(升序,越小越前) | + +### 模板VO响应 + +| 字段 | 类型 | 说明 | +|------|------|------| +| templateId | String | 模板ID | +| name | String | 模板名称 | +| content | String | 模板内容 | +| sortOrder | Integer | 排序 | +| status | String | 状态:`ACTIVE`-启用、`INACTIVE`-停用 | +| createTime | String | 创建时间 | + +--- + +# 第三部分:保险管理 + +--- + +## 接口清单(保险管理) + +| # | 接口 | 方法 | 路径 | 说明 | +|---|------|------|------|------| +| 29 | 保险产品列表 | GET | `/admin/insurance/products` | 已同步的保险产品分页列表 | +| 30 | 保险产品详情 | GET | `/admin/insurance/products/{id}` | 产品详情 | +| 31 | 保险计划及费率 | GET | `/admin/insurance/products/{id}/plans` | 获取产品下所有计划+费率表 | +| 32 | 同步保险产品 | POST | `/admin/insurance/sync-products` | 从保游网拉取最新产品 | +| 33 | 投保公司主体列表 | GET | `/admin/insurance/entities` | 投保公司列表 | +| 34 | 投保下单 | POST | `/admin/insurance/purchase` | 为出行人投保(每人独立保单) | +| 35 | 退保 | POST | `/admin/insurance/cancel/{id}` | 取消保险单 | +| 36 | 保险订单列表 | GET | `/admin/insurance/orders` | 分页查询保险订单 | +| 37 | 保险订单详情 | GET | `/admin/insurance/orders/{id}` | 含被保人列表 | +| 38 | 按订单查保险单 | GET | `/admin/insurance/orders/by-order/{orderId}` | 查询旅行订单的所有保险单 | +| 39 | 保险保障汇总 | GET | `/admin/insurance/coverage/{orderId}` | 订单保险覆盖情况 | +| 40 | 保费试算 | POST | `/admin/insurance/trial-price` | 本地费率试算保费 | +| 41 | 查询账户余额 | GET | `/admin/insurance/balance` | 保游网账户余额 | +| 42 | 下载保单PDF | GET | `/admin/insurance/policy/{id}/download` | Base64格式保单 | +| 43 | 在线充值 | POST | `/admin/insurance/recharge` | 保游网账户充值 | +| 44 | 分享保单 | POST | `/admin/insurance/share-policy` | 合并PDF上传OSS | +| 45 | 保险方案-活跃列表 | GET | `/admin/insurance/scheme/list` | 下拉选择用 | +| 46 | 保险方案-全部列表 | GET | `/admin/insurance/scheme/list-all` | 管理用 | +| 47 | 保险方案-详情 | GET | `/admin/insurance/scheme/{id}` | 方案详情含段 | +| 48 | 保险方案-创建 | POST | `/admin/insurance/scheme` | 创建方案模板 | +| 49 | 保险方案-更新 | PUT | `/admin/insurance/scheme/{id}` | 更新方案 | +| 50 | 保险方案-切换状态 | PUT | `/admin/insurance/scheme/{id}/toggle-status` | 启用/停用 | +| 51 | 保险方案-删除 | DELETE | `/admin/insurance/scheme/{id}` | 软删除 | +| 52 | 保险方案-预览应用 | POST | `/admin/insurance/scheme/preview-apply` | 预览方案应用到订单的效果 | + +--- + +## 接口 29:保险产品列表 + +``` +GET /admin/insurance/products?page=1&pageSize=20&isOverseas=false +``` + +### 请求参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| page | Integer | 否 | 页码(默认1) | +| pageSize | Integer | 否 | 每页条数(默认20) | +| isOverseas | Boolean | 否 | 是否境外产品:`false`-境内、`true`-境外 | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "total": 8, + "page": 1, + "pageSize": 20, + "records": [ + { + "productId": "2026279738275856385", + "extProductGuid": "ABC-123-DEF", + "productName": "畅游神州境内游(旅行社专享)", + "companyName": "中国太平洋保险", + "productType": "旅行险", + "isOverseas": false, + "minDays": 1, + "maxDays": 90, + "minAge": 0, + "maxAge": 85, + "status": "ACTIVE", + "createTime": "2026-03-01T10:00:00" + } + ] + } +} +``` + +### 响应字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| productId | String | 保险产品ID | +| extProductGuid | String | 保游网产品GUID | +| productName | String | 产品名称 | +| companyName | String | 保险公司名称 | +| productType | String | 产品类型 | +| isOverseas | Boolean | 是否境外产品 | +| minDays | Integer | 最短保障天数 | +| maxDays | Integer | 最长保障天数 | +| minAge | Integer | 最小投保年龄 | +| maxAge | Integer | 最大投保年龄 | +| status | String | 产品状态:`ACTIVE`-可用、`INACTIVE`-不可用 | +| createTime | String | 同步时间 | + +--- + +## 接口 31:保险计划及费率 + +**使用场景**:选定产品后,展示该产品下所有计划及费率表,供管理员选择具体计划。 + +``` +GET /admin/insurance/products/{id}/plans +``` + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "planId": "2026279738275856390", + "productId": "2026279738275856385", + "extPlanGuid": "PLAN-001", + "planName": "经济版", + "securityList": "
意外伤害:10万元
意外医疗:1万元
", + "rates": [ + { + "rateId": "2026279738275856395", + "extRateCode": "RATE-001", + "ageRange": "0-85", + "dayRange": "1-3", + "dayType": 10, + "premium": 5.00 + }, + { + "rateId": "2026279738275856396", + "extRateCode": "RATE-002", + "ageRange": "0-85", + "dayRange": "4-7", + "dayType": 10, + "premium": 10.00 + } + ] + } + ] +} +``` + +### 响应字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| planId | String | 计划ID(投保时需传) | +| productId | String | 所属产品ID | +| planName | String | 计划名称(如:经济版、豪华版) | +| securityList | String | 保障内容(HTML格式) | +| rates | Array | 费率列表 | +| rates[].rateId | String | 费率ID | +| rates[].ageRange | String | 适用年龄范围(如 `0-85`) | +| rates[].dayRange | String | 适用天数范围(如 `4-7`) | +| rates[].dayType | Integer | 天数类型:`10`-按天、`20`-按月、`30`-按年 | +| rates[].premium | BigDecimal | 单人保费(元) | + +### 前端实现建议 +- 用 `el-table` 展示费率表格 +- `securityList` 用 `v-html` 渲染 +- 用户选择计划后,根据行程天数和年龄自动匹配费率 + +--- + +## 接口 34:投保下单 + +**使用场景**:为订单的出行人投保。系统会为每个被保人创建独立保单,调用保游网API完成投保。 + +``` +POST /admin/insurance/purchase +``` + +### 请求体 + +```json +{ + "orderId": "2026270000000000001", + "planId": "2026279738275856390", + "startDate": "2026-07-01", + "endDate": "2026-07-07", + "entityCode": "hulai", + "remark": "草原7日游保险", + "insuredPersons": [ + { + "name": "张三", + "idCardType": "ID_CARD", + "idCardNo": "110101199001011234", + "birthday": "1990-01-01", + "gender": "MALE", + "phone": "13800138000", + "isBeneficiary": false + }, + { + "name": "李四", + "idCardType": "ID_CARD", + "idCardNo": "110101199201011234", + "birthday": "1992-01-01", + "gender": "FEMALE", + "phone": "13900139000", + "isBeneficiary": false + } + ] +} +``` + +### 请求字段 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| orderId | Long | 否 | 关联旅行订单ID | +| planId | Long | ✅ | 保险计划ID(从接口31获取) | +| startDate | String | ✅ | 保障开始日期(yyyy-MM-dd) | +| endDate | String | ✅ | 保障结束日期(yyyy-MM-dd) | +| entityCode | String | 否 | 投保公司主体编码(从接口33获取,不填使用默认) | +| remark | String | 否 | 备注 | +| insuredPersons | Array | ✅ | 被保人列表(至少1人) | + +### 被保人字段 (insuredPersons[]) + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| name | String | ✅ | 姓名 | +| idCardType | String | 否 | 证件类型(默认 `ID_CARD`):`ID_CARD`-身份证、`PASSPORT`-护照、`OTHER`-其他 | +| idCardNo | String | ✅ | 证件号码 | +| birthday | String | ✅ | 出生日期(yyyy-MM-dd) | +| gender | String | ✅ | 性别:`MALE`-男、`FEMALE`-女 | +| phone | String | 否 | 手机号 | +| isBeneficiary | Boolean | 否 | 是否为受益人(默认false) | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "insuranceOrderId": "2026279738275856400", + "orderId": "2026270000000000001", + "productId": "2026279738275856385", + "productName": "畅游神州境内游(旅行社专享)", + "planId": "2026279738275856390", + "planName": "经济版", + "extOrderNo": "BYW202607010001", + "extPolicyNo": "P202607010001", + "totalPremium": 10.00, + "insuredCount": 1, + "policyHolderName": "内蒙古呼籁国际旅行社有限公司", + "entityCode": "hulai", + "startDate": "2026-07-01", + "endDate": "2026-07-07", + "status": "INSURED", + "statusLabel": "已承保", + "remark": "草原7日游保险", + "createTime": "2026-03-19T10:30:00", + "insuredPersons": [ + { + "insuredId": "2026279738275856410", + "name": "张三", + "idCardType": "ID_CARD", + "idCardNo": "110101****1234", + "birthday": "1990-01-01", + "gender": "MALE", + "phone": "138****8000", + "isBeneficiary": false + } + ] + } + ] +} +``` + +**注意**:返回的是**数组**,因为每个被保人一张独立保单。 + +--- + +## 接口 35:退保 + +``` +POST /admin/insurance/cancel/{id} +``` + +| 参数 | 类型 | 位置 | 必填 | 说明 | +|------|------|------|------|------| +| id | Long | 路径 | ✅ | 保险订单ID | + +返回退保后的 `InsuranceOrderVO`,状态变为 `CANCELLED`。 + +--- + +## 接口 36:保险订单列表 + +``` +GET /admin/insurance/orders?page=1&pageSize=20&orderId=2026270000000000001&status=INSURED +``` + +### 请求参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| orderId | Long | 否 | 按旅行订单ID过滤 | +| status | String | 否 | 按状态过滤 | +| page | Integer | 否 | 页码(默认1) | +| pageSize | Integer | 否 | 每页条数(默认20,最大100) | + +--- + +## 接口 37:保险订单详情 + +``` +GET /admin/insurance/orders/{id} +``` + +返回 `InsuranceOrderDetailVO`,在 `InsuranceOrderVO` 基础上增加 `insuredPersons` 被保人列表。 + +--- + +## 接口 39:保险保障汇总 + +**使用场景**:在订单详情中展示保险覆盖情况。 + +``` +GET /admin/insurance/coverage/{orderId} +``` + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "orderId": "2026270000000000001", + "orderCount": 3, + "insuranceOrders": [ + { + "insuranceOrderId": "2026279738275856400", + "productName": "畅游神州境内游(旅行社专享)", + "planName": "经济版", + "status": "INSURED", + "statusLabel": "已承保", + "totalPremium": 10.00, + "startDate": "2026-07-01", + "endDate": "2026-07-07", + "insuredPersons": [ + { + "name": "张三", + "idCardType": "ID_CARD", + "idCardNo": "110101****1234" + } + ] + } + ] + } +} +``` + +--- + +## 接口 40:保费试算 + +**使用场景**:投保前预估保费。 + +``` +POST /admin/insurance/trial-price +``` + +### 请求体 + +```json +{ + "planId": "2026279738275856390", + "startDate": "2026-07-01", + "endDate": "2026-07-07", + "insuredCount": 4 +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| planId | Long | ✅ | 保险计划ID | +| startDate | String | ✅ | 保障开始日期 | +| endDate | String | ✅ | 保障结束日期 | +| insuredCount | Integer | ✅ | 被保人数量 | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "unitPremium": 10.00, + "totalPremium": 40.00, + "coverageDays": 7, + "insuredCount": 4 + } +} +``` + +--- + +## 接口 41:查询账户余额 + +``` +GET /admin/insurance/balance +``` + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "Data": "1256.50" + } +} +``` + +--- + +## 接口 43:在线充值 + +``` +POST /admin/insurance/recharge +``` + +### 请求体 + +```json +{ + "money": 500.00, + "payType": 33 +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| money | BigDecimal | ✅ | 充值金额(元),最小0.01 | +| payType | Integer | ✅ | 支付方式:`11`-支付宝扫码、`33`-微信扫码 | +| backUrl | String | 否 | 同步回调地址(支付宝用) | + +--- + +## 接口 44:分享保单 + +**使用场景**:合并指定被保人的所有保单PDF,上传OSS生成分享链接。 + +``` +POST /admin/insurance/share-policy +``` + +### 请求体 + +```json +{ + "orderId": "2026270000000000001", + "insuredName": "张三", + "insuredIdCardNo": "110101199001011234" +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| orderId | Long | ✅ | 旅游订单ID | +| insuredName | String | ✅ | 被保人姓名 | +| insuredIdCardNo | String | ✅ | 被保人证件号码(明文) | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "pdfBase64": "JVBERi0xLjQK...", + "personName": "张三", + "policyCount": 2, + "failedCount": 0 + } +} +``` + +--- + +## 接口 48:创建保险方案模板 + +**使用场景**:创建可复用的保险方案,适用于不同行程的保险配置模板。方案由多个"段"组成,每段对应一个保险产品+计划,覆盖行程中的某几天。 + +``` +POST /admin/insurance/scheme +``` + +### 请求体 + +```json +{ + "name": "草原7日标准方案", + "description": "适用于7日国内草原行程,前段境内险+后段高原险", + "isOverseas": false, + "sortOrder": 0, + "segments": [ + { + "segmentName": "前段-境内险", + "dayOffsetStart": 1, + "dayOffsetEnd": 4, + "productId": "2026279738275856385", + "planId": "2026279738275856390", + "sortOrder": 0 + }, + { + "segmentName": "后段-高原险", + "dayOffsetStart": 5, + "dayOffsetEnd": -1, + "productId": "2026279738275856386", + "planId": "2026279738275856391", + "sortOrder": 1 + } + ] +} +``` + +### 请求字段 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| name | String | ✅ | 方案名称(最长100字符) | +| description | String | 否 | 方案描述(最长500字符) | +| isOverseas | Boolean | ✅ | 是否境外:`false`-境内、`true`-境外 | +| sortOrder | Integer | 否 | 排序序号(越小越靠前) | +| segments | Array | ✅ | 保险段列表(至少1个) | + +### 方案段字段 (segments[]) + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| segmentName | String | 否 | 段名称(最长100字符) | +| dayOffsetStart | Integer | ✅ | 相对起始天(1-based,1=出发日) | +| dayOffsetEnd | Integer | ✅ | 相对结束天(1-based,**-1 表示行程最后一天**) | +| productId | Long | ✅ | 保险产品ID | +| planId | Long | ✅ | 保险计划ID | +| sortOrder | Integer | 否 | 段排序序号 | + +### 响应 InsuranceSchemeVO + +```json +{ + "code": 200, + "message": "成功", + "data": { + "schemeId": "2026279738275856500", + "name": "草原7日标准方案", + "description": "适用于7日国内草原行程", + "isOverseas": false, + "sortOrder": 0, + "status": "ACTIVE", + "adminId": "100", + "createTime": "2026-03-19T10:30:00", + "segmentCount": 2, + "segments": [ + { + "segmentId": "2026279738275856510", + "segmentName": "前段-境内险", + "dayOffsetStart": 1, + "dayOffsetEnd": 4, + "productId": "2026279738275856385", + "productName": "畅游神州境内游(旅行社专享)", + "planId": "2026279738275856390", + "planName": "经济版", + "sortOrder": 0 + } + ] + } +} +``` + +--- + +## 接口 52:预览应用方案 + +**使用场景**:选择方案后,预览应用到某个订单的效果。系统会将方案中的相对天数解析为实际日期,并计算预估保费。 + +``` +POST /admin/insurance/scheme/preview-apply +``` + +### 请求体 + +```json +{ + "schemeId": "2026279738275856500", + "orderId": "2026270000000000001", + "departureDate": "2026-07-01", + "returnDate": "2026-07-07", + "insuredCount": 4 +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| schemeId | Long | ✅ | 方案ID | +| orderId | Long | ✅ | 订单ID(获取出行信息) | +| departureDate | String | 否 | 出发日期(不传从订单获取) | +| returnDate | String | 否 | 返回日期(不传从订单获取) | +| insuredCount | Integer | 否 | 被保人数量(不传从订单获取,最小1) | + +### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "schemeId": "2026279738275856500", + "schemeName": "草原7日标准方案", + "departureDate": "2026-07-01", + "returnDate": "2026-07-07", + "tripDays": 7, + "insuredCount": 4, + "totalEstimatedPremium": 320.00, + "segments": [ + { + "segmentName": "前段-境内险", + "dayOffsetStart": 1, + "dayOffsetEnd": 4, + "resolvedStartDate": "2026-07-01", + "resolvedEndDate": "2026-07-04", + "coverageDays": 4, + "productId": "2026279738275856385", + "productName": "畅游神州境内游(旅行社专享)", + "planId": "2026279738275856390", + "planName": "经济版", + "unitPremium": 10.00, + "estimatedPremium": 40.00, + "skipped": false, + "skipReason": null + }, + { + "segmentName": "后段-高原险", + "dayOffsetStart": 5, + "dayOffsetEnd": -1, + "resolvedStartDate": "2026-07-05", + "resolvedEndDate": "2026-07-07", + "coverageDays": 3, + "productId": "2026279738275856386", + "productName": "高原专享旅行险", + "planId": "2026279738275856391", + "planName": "标准版", + "unitPremium": 40.00, + "estimatedPremium": 160.00, + "skipped": false, + "skipReason": null + } + ], + "warnings": [] + } +} +``` + +### 响应字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| schemeId | String | 方案ID | +| schemeName | String | 方案名称 | +| departureDate | String | 行程出发日期 | +| returnDate | String | 行程返回日期 | +| tripDays | Integer | 行程天数 | +| insuredCount | Integer | 被保人数量 | +| totalEstimatedPremium | BigDecimal | 预估总保费 | +| segments | Array | 解析后的保险段 | +| segments[].segmentName | String | 段名称 | +| segments[].resolvedStartDate | String | 实际开始日期 | +| segments[].resolvedEndDate | String | 实际结束日期 | +| segments[].coverageDays | Integer | 覆盖天数 | +| segments[].productName | String | 保险产品名称 | +| segments[].planName | String | 保险计划名称 | +| segments[].unitPremium | BigDecimal | 单人保费 | +| segments[].estimatedPremium | BigDecimal | 段预估总保费(单人×人数) | +| segments[].skipped | Boolean | 是否跳过(超出行程范围) | +| segments[].skipReason | String | 跳过原因 | +| warnings | Array | 警告列表(日期间隙、重叠等) | + +### 前端实现建议 +- 选择方案后自动调用此接口展示预览 +- 用 `el-table` 展示保险段,高亮被跳过的段 +- `warnings` 不为空时用 `el-alert` 展示警告 +- 预览确认后,再逐段调用投保接口(接口34)下单 + +--- + +# 关联字典 + +| 字典类型 | 字典值 | 中文标签 | 说明 | +|----------|--------|----------|------| +| **process_status** | PENDING_INFO | 待补全信息 | 订单内部流程 | +| | PROCESSING | 待内部流程 | | +| | PENDING_INSURANCE | 待配保险 | | +| | PENDING_CONTRACT | 待签合同 | | +| | PENDING_ROOM | 待配房 | | +| | PENDING_VEHICLE | 待配车 | | +| | PENDING_FINANCE | 待核算 | | +| | READY | 就绪 | | +| | INTERNAL_CONFIRMED | 内部已确认 | | +| **transport_type** | FLIGHT | 航班 | 交通类型 | +| | TRAIN | 火车 | | +| **contract_platform** | 12301 | 全国旅游监管平台 | 签约平台 | +| | FADADA | 法大大 | | +| | ESIGN | e签宝 | | +| | TENCENT_ESS | 腾讯电子签 | | +| **contract_type** | TOUR | 旅游合同 | 合同类型 | +| | INSURANCE | 保险单 | | +| **contract_mode** | STANDARD | 电子签约 | 签约模式 | +| | SYNC | 同步报备 | | +| **contract_status** | PENDING | 待生成 | 合同状态 | +| | GENERATED | 已生成 | 签署URL已生成 | +| | SIGNING | 签署中 | 出行人正在签署 | +| | SIGNED | 已签署 | 签署完成 | +| | VOIDING | 作废中 | 作废请求已发送 | +| | VOIDED | 已作废 | 不可恢复 | +| | REPORTED | 已上报 | 同步模式报备完成 | +| | UPLOADED | 已上传 | 同步模式PDF已上传 | +| **insurance_status** | PENDING | 待出单 | 保险订单状态 | +| | INSURED | 已承保 | | +| | CANCELLED | 已退保 | | +| | FAILED | 投保失败 | | +| **id_card_type** | ID_CARD | 身份证 | 证件类型(保险) | +| | PASSPORT | 护照 | | +| | OTHER | 其他 | | +| **gender** | MALE | 男 | 性别(保险) | +| | FEMALE | 女 | | +| **common_status** | ACTIVE | 启用 | 通用状态 | +| | INACTIVE | 停用 | | +| **balance_pay_method** | ONLINE | 线上微信支付 | 尾款支付方式 | +| | OFFLINE | 线下转账 | | + +--- + +# 页面布局建议 + +## 订单详情页 - 配房配车Tab + +``` +┌─────────────────────────────────────────────────────┐ +│ 订单详情 > 配房配车 │ +├─────────────────────────────────────────────────────┤ +│ 当前流程状态:[待配房] ──── [待配车] ──── [待核算] │ +│ ✅ ○ ○ │ +├─────────────────────────────────────────────────────┤ +│ 🏨 房间分配 [检测一致性] │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ 模式切换: ○ 文本模式 ○ 结构化模式 │ │ +│ │ │ │ +│ │ [文本模式] 房间信息: [__________________] │ │ +│ │ │ │ +│ │ [结构化模式] │ │ +│ │ 家庭1: 酒店[____] 房型[____] 入住[__] 退房[__]│ │ +│ │ 家庭2: 酒店[____] 房型[____] 入住[__] 退房[__]│ │ +│ │ [+ 添加家庭] │ │ +│ └───────────────────────────────────────────────┘ │ +│ [保存房间信息] │ +├─────────────────────────────────────────────────────┤ +│ 🚗 车辆分配 [检测一致性] │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ 车型: [____] 品牌: [____] 车牌: [____] │ │ +│ │ 司机: [____] 电话: [____] │ │ +│ └───────────────────────────────────────────────┘ │ +│ [保存车辆信息] │ +├─────────────────────────────────────────────────────┤ +│ ✈️ 交通信息 │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ #1 类型[航班▼] 班次[CA1234] 出发[北京T3] │ │ +│ │ 到达[呼和浩特] 出发时间[____] 到达时间[____] │ │ +│ │ #2 类型[火车▼] 班次[G1234] ... │ │ +│ │ [+ 添加交通段] │ │ +│ └───────────────────────────────────────────────┘ │ +│ [保存交通信息] │ +├─────────────────────────────────────────────────────┤ +│ [推进到下一步 →] │ +└─────────────────────────────────────────────────────┘ +``` + +## 合同管理页 + +``` +┌─────────────────────────────────────────────────────┐ +│ 合同管理 [+ 创建合同] │ +├─────────────────────────────────────────────────────┤ +│ 过滤: 订单号[____] 状态[全部▼] 平台[全部▼] │ +├─────────────────────────────────────────────────────┤ +│ 合同编号 | 平台 | 类型 | 状态 | 金额 | 操作 │ +│ CN2026... | 12301 | 旅游 | 已签署 | ¥14950 | 详情 │ +│ CN2026... | 12301 | 保险 | 签署中 | ¥5000 | 刷新 │ +│ │ +│ [< 1 2 3 >] │ +└─────────────────────────────────────────────────────┘ +``` + +## 保险管理页 + +``` +┌─────────────────────────────────────────────────────┐ +│ 保险管理 │ +│ Tab: [保险投保] [保险方案] [账户管理] │ +├─────────────────────────────────────────────────────┤ +│ [保险投保Tab] │ +│ ① 选择产品: [畅游神州境内游▼] │ +│ ② 选择计划: [经济版▼] 费率: 1-3天 ¥5/人 │ +│ ③ 保障日期: [2026-07-01] 至 [2026-07-07] │ +│ ④ 试算保费: [试算] → 单人¥10 × 4人 = 总计¥40 │ +│ ⑤ 被保人: │ +│ [√] 张三 110101...1234 1990-01-01 男 │ +│ [√] 李四 110101...5678 1992-01-01 女 │ +│ ⑥ [确认投保] │ +├─────────────────────────────────────────────────────┤ +│ [保险方案Tab] │ +│ 方案名称 | 境内/外 | 段数 | 状态 | 操作 │ +│ 草原7日 | 境内 | 2 | 启用 | 编辑 预览 停用 │ +│ 海岛5日 | 境外 | 1 | 启用 | 编辑 预览 停用 │ +│ [+ 创建方案] │ +├─────────────────────────────────────────────────────┤ +│ [账户管理Tab] │ +│ 当前余额: ¥1,256.50 [刷新] │ +│ 充值: 金额[____] 方式[微信▼] [充值] │ +└─────────────────────────────────────────────────────┘ +``` + +--- + +# 完整调用示例 + +## 示例1:配房流程 + +```javascript +// 1. 结构化分配酒店 +await request.put(`/admin/order/${orderId}/hotel-assignment`, { + assignments: [ + { familyIndex: 1, hotelName: '香格里拉', roomType: '豪华大床房', checkInDate: '2026-07-01', checkOutDate: '2026-07-03' }, + { familyIndex: 2, hotelName: '香格里拉', roomType: '标准双人间', checkInDate: '2026-07-01', checkOutDate: '2026-07-03' } + ] +}) + +// 2. 检测一致性 +const diff = await request.post(`/admin/order/${orderId}/room-info/check-diff`) +if (diff.data) { + ElMessageBox.confirm(diff.data, '房型不一致提醒', { confirmButtonText: '已知晓', cancelButtonText: '返回修改' }) +} + +// 3. 推进流程到"待配车" +await request.put(`/admin/order/${orderId}/process-status`) +``` + +## 示例2:创建合同 + +```javascript +// 1. 获取模板列表 +const templates = await request.get('/admin/contract/templates') + +// 2. 获取补充约定模板 +const clauses = await request.get('/admin/contract/clause-template/list') + +// 3. 创建合同 +const contract = await request.post('/admin/contract/create', { + orderId, + templateCode: 'TOURAGE_STANDARD', + destination: '呼伦贝尔', + routeName: '呼伦贝尔草原7日深度游', + departureDate: '2026-07-01', + returnDate: '2026-07-07', + signatoryName: '张三', + signatoryPhone: '13800138000', + signatoryIdNumber: '110101199001011234', + adultCost: 5980.00, + totalAmount: 14950.00, + contactName: '张三', + contactPhone: '13800138000', + supplementaryClause: clauses.data[0]?.content || '', + travelers: orderTravelers.map(t => ({ + name: t.name, + idCardNo: t.idCardNo, + phone: t.phone, + isSigner: t.name === '张三' + })) +}) + +// 4. 如状态为GENERATED,可展示签署链接或二维码 +if (contract.data.signUrl) { + // 展示签署链接或二维码 +} +``` + +## 示例3:方案化投保 + +```javascript +// 1. 选择方案 +const schemes = await request.get('/admin/insurance/scheme/list') + +// 2. 预览方案应用效果 +const preview = await request.post('/admin/insurance/scheme/preview-apply', { + schemeId: schemes.data[0].schemeId, + orderId +}) + +// 3. 展示预览:预估总保费、各段明细 +console.log(`预估总保费: ¥${preview.data.totalEstimatedPremium}`) + +// 4. 确认后,逐段投保 +for (const segment of preview.data.segments) { + if (segment.skipped) continue + await request.post('/admin/insurance/purchase', { + orderId, + planId: segment.planId, + startDate: segment.resolvedStartDate, + endDate: segment.resolvedEndDate, + insuredPersons: travelers.map(t => ({ + name: t.name, + idCardNo: t.idCardNo, + birthday: t.birthday, + gender: t.gender, + phone: t.phone + })) + }) +} +``` + +--- + +🤖 Generated with [Claude Code](https://claude.com/claude-code)