# 订单配房配车 + 合同管理 + 保险管理 - 前端对接指南 > **日期**: 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... | 法大大 | 旅游 | 签署中 | ¥5000 | 刷新 │ │ │ │ [< 1 2 3 >] │ └─────────────────────────────────────────────────────┘ ``` ## 创建合同弹窗(管理员自主选择平台) 管理员可以自主选择在哪个合同平台签署,前端页面需提供平台选择下拉框。 ``` ┌──────────────────── 创建合同 ────────────────────────┐ │ │ │ 签约平台: [全国旅游监管平台 ▼] │ │ ┌──────────────────────┐ │ │ │ ● 全国旅游监管平台 │ ← available=true │ │ │ ● 法大大 │ ← available=true │ │ │ ○ e签宝 (未开通) │ ← available=false│ │ │ ○ 腾讯电子签 (未开通) │ ← available=false│ │ └──────────────────────┘ │ │ 合同模板: [国内旅游标准合同 ▼] ← 根据选中平台过滤 │ │ 旅行社: [呼籁国际旅行社 ▼] │ │ 签署模式: ○ 短信签署 ○ 现场签署 ○ 线下签署 │ │ │ │ ─── 合同信息 ─── │ │ 目的地: [________] 线路名称: [________] │ │ 出发日期: [____-__-__] 返回日期: [____-__-__] │ │ 出发城市: [________] 行程天数: [__] │ │ │ │ ─── 签署人信息 ─── │ │ 签署人: [________] 电话: [________] │ │ 证件号: [________________] │ │ │ │ ─── 费用信息 ─── │ │ 成人费用: [________] 儿童费用: [________] │ │ 合同总额: [________] │ │ │ │ ─── 出行人列表 ─── │ │ 姓名 | 证件号 | 性别 | 年龄 | 签署人 │ │ 张三 | 110101...1234 | 男 | 36 | ✓ │ │ 李四 | 110101...5678 | 女 | 34 | │ │ [+ 添加出行人] │ │ │ │ [取消] [确认创建] │ └──────────────────────────────────────────────────────┘ ``` ### 平台选择交互逻辑 1. **数据源**: 调用 `GET /admin/contract/platforms`,返回每个平台的 `code`/`name`/`enabled` 2. **下拉显示**: `enabled=true` 的平台可选,`enabled=false` 的灰显并标注"未开通" 3. **模板联动**: 选择平台后,从 `GET /admin/contract/templates` 返回的模板列表中过滤出 `platform` 匹配的模板 4. **提交**: 创建合同请求中的 `platform` 字段传所选平台的 `code` 值。不传则后端根据所选模板自动确定 5. **默认值**: 可默认选中第一个 `enabled=true` 的平台 ## 保险管理页 ``` ┌─────────────────────────────────────────────────────┐ │ 保险管理 │ │ 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)