# 综合前端对接指南 — 产品自动化配置 + 保险 + 合同 + 配房 + 配车

> **日期**: 2026-03-20
> **后端状态**: ✅ 已完成，可直接对接
> **涉及服务**: hl-product-service、hl-order-service、hl-insurance-service、hl-contract-service、hl-resource-service

---

## 一、整体变更说明

### 核心改动

1. **产品新增10个保险+合同配置字段**（创建时必填）：产品绑定保险方案和合同配置
2. **订单支付后自动投保+自动签约**：出行人补全后系统自动完成，无需管理员手动操作
3. **去掉「确认订单」步骤**：原6步待办缩减为5步，`CONFIRM_ORDER` 已删除
4. **`PROCESSING` 流程状态已删除**：`PENDING_INFO` 直接跳到 `PENDING_INSURANCE`
5. **配房改为按天粒度**：每天每个家庭一条记录，新增房型升级差价自动计算
6. **配房升级差价预览**：提交配房前可预览差价明细

### 新的订单内部流程

```
支付成功 → 创建5个待办 → 出行人补全 → 系统自动确认订单
  → 自动投保（按产品绑定的保险方案）  ← INSURANCE待办自动完成
  → 自动签约（按产品绑定的合同配置）  ← CONTRACT待办等签署回调完成
  → 手动配房 (ARRANGE_ROOM)
  → 手动配车 (ARRANGE_VEHICLE)
  → 手动确认清单 (CONFIRM_CHECKLIST)
```

**容错**：自动投保/签约失败时，待办保持 PENDING，管理员可手动处理。

---

## 二、破坏性变更（前端必须适配）

### 1. 待办类型变更

| 原 todoType | 原序号 | 新 todoType | 新序号 | 说明 |
|-------------|--------|-------------|--------|------|
| CONFIRM_ORDER | 1 | **已删除** | - | 不再需要手动确认 |
| INSURANCE | 2 | INSURANCE | 1 | 可被系统自动完成 |
| CONTRACT | 3 | CONTRACT | 2 | 可被系统自动完成 |
| ARRANGE_ROOM | 4 | ARRANGE_ROOM | 3 | 手动 |
| ARRANGE_VEHICLE | 5 | ARRANGE_VEHICLE | 4 | 手动 |
| CONFIRM_CHECKLIST | 6 | CONFIRM_CHECKLIST | 5 | 手动 |

**前端注意**：
- 不要 hardcode `CONFIRM_ORDER` 的判断
- 待办序号已变化（INSURANCE 从 2 变为 1）
- INSURANCE/CONTRACT 待办可能被系统自动完成，展示时注意区分

### 2. processStatus 变更

| 原流程 | 新流程 |
|--------|--------|
| PENDING_INFO → **PROCESSING** → PENDING_INSURANCE → ... | PENDING_INFO → PENDING_INSURANCE → ... |

`PROCESSING` 状态已删除，相关状态标签/过滤条件需要去掉。

**有效的 processStatus 值**：
`PENDING_INFO` / `PENDING_INSURANCE` / `PENDING_CONTRACT` / `PENDING_ROOM` / `PENDING_VEHICLE` / `PENDING_FINANCE` / `READY` / `INTERNAL_CONFIRMED`

### 3. 配房接口破坏性变更

从「按日期区间」改为「按天粒度」，详见下方配房章节。

---

## 三、产品服务 — 新增保险与合同配置

### 页面布局建议

在产品编辑页基本信息之后增加「保险与合同配置」区域：

```
┌─────────────────────────────────────────┐
│ 保险与合同配置                            │
├─────────────────────────────────────────┤
│ 保险方案：[下拉选择] ← GET /admin/insurance/scheme/list │
│                                         │
│ 合同平台：[12301 ▼] / [法大大 ▼]          │
│ 合同模板：[下拉选择] ← GET /admin/contract/templates │
│ 签约模式：[电子签约 ▼] / [线下报备 ▼]     │
│ 签署模式：[短信 ▼] / [现场 ▼] / [线下 ▼]  │
│ 旅行社：  [下拉选择] ← GET /admin/insurance/entities │
│ 争议解决：[仲裁 ▼] / [诉讼 ▼]            │
│ 经办人姓名：[________]                    │
│ 经办人电话：[________]                    │
│ 补充条款：[________________] (可选)       │
└─────────────────────────────────────────┘
```

### 接口 1：创建产品（新增必填字段）

```
POST /admin/product
```

**新增请求字段**（所有字段必填，`supplementaryClause` 除外）：

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| insuranceSchemeId | Long | 是 | 保险方案ID，从 `GET /admin/insurance/scheme/list` 获取 |
| contractPlatform | String | 是 | 合同平台：`12301`（全国旅游监管平台）/ `FADADA`（法大大） |
| contractTemplateCode | String | 是 | 合同模板编码，从 `GET /admin/contract/templates` 获取 |
| contractMode | String | 是 | 签约模式：`STANDARD`（电子签约）/ `SYNC`（线下报备） |
| signatoryMode | Integer | 是 | 签署模式：`1`=短信签署 / `2`=现场签署 / `3`=线下签署 |
| agencyCode | String | 是 | 旅行社编码，从 `GET /admin/insurance/entities` 获取 |
| disputeResolution | Integer | 是 | 争议解决方式：`1`=仲裁 / `2`=诉讼 |
| supplementaryClause | String | 否 | 合同补充条款 |
| transactorName | String | 是 | 经办人姓名 |
| transactorPhone | String | 是 | 经办人电话 |

### 接口 2：编辑产品（新增可选字段）

```
PUT /admin/product/{productId}
```

同上 10 个字段，**全部可选**（不传则不更新）。

### 接口 3：统一保存产品（新增字段）

```
POST /admin/product/save
```

同上 10 个字段，创建时必填，更新时可选。

### 接口 4：产品详情响应（新增返回字段）

```
GET /admin/product/{productId}
```

**响应新增字段**（ProductVO 和 ProductListVO 均返回）：

| 字段 | 类型 | 说明 |
|------|------|------|
| insuranceSchemeId | String | 保险方案ID |
| contractPlatform | String | 合同平台：`12301` / `FADADA` |
| contractTemplateCode | String | 合同模板编码 |
| contractMode | String | 签约模式：`STANDARD` / `SYNC` |
| signatoryMode | Integer | 签署模式：1/2/3 |
| agencyCode | String | 旅行社编码 |
| disputeResolution | Integer | 争议解决方式：1/2 |
| supplementaryClause | String | 补充条款 |
| transactorName | String | 经办人姓名 |
| transactorPhone | String | 经办人电话 |

### 下拉数据源接口

#### 保险方案列表（产品编辑页下拉）

```
GET /admin/insurance/scheme/list
```

**使用场景**：产品编辑页「保险方案」下拉选择。

**响应示例**：
```json
{
  "code": 200,
  "data": [
    {
      "id": "1901234567890",
      "name": "国内5天标准保障",
      "description": "覆盖5天国内行程的基础保障方案",
      "isOverseas": false,
      "status": "ACTIVE",
      "segments": [
        {
          "segmentIndex": 1,
          "insuranceProductId": "100",
          "planId": "200",
          "startDayOffset": 0,
          "endDayOffset": 4
        }
      ]
    }
  ]
}
```

#### 合同模板列表（产品编辑页下拉）

```
GET /admin/contract/templates
```

**使用场景**：产品编辑页「合同模板」下拉选择。

**响应示例**：
```json
{
  "code": 200,
  "data": [
    {
      "templateCode": "TOURAGE_STANDARD",
      "templateName": "国内旅游标准合同",
      "platform": "12301",
      "mode": "STANDARD"
    }
  ]
}
```

#### 合同平台列表（产品编辑页下拉）

```
GET /admin/contract/platforms
```

**使用场景**：产品编辑页「合同平台」下拉选择。

#### 旅行社列表（产品编辑页下拉）

```
GET /admin/insurance/entities
```

**使用场景**：产品编辑页「旅行社」下拉选择（agencyCode 使用此列表中的 code 值）。

**响应示例**：
```json
{
  "code": 200,
  "data": [
    {
      "code": "HLNMG",
      "companyName": "内蒙古呼籁国际旅行社有限公司"
    }
  ]
}
```

---

## 四、保险服务 — 手动配置保险

订单保险在正常流程中会自动完成（支付后系统自动投保），但管理员也可以手动操作。手动配保险有两种方式：

### 页面布局建议

```
┌─────────────────────────────────────────┐
│ 保险配置                                 │
├─────────────────────────────────────────┤
│ ● 选择保险方案（推荐）                    │
│   [方案下拉] → 预览 → 确认投保            │
│                                         │
│ ○ 按天手动配置                            │
│   保险产品：[下拉]                        │
│   保险计划：[下拉]                        │
│   开始日期：[____] 结束日期：[____]        │
│   [试算保费] [确认投保]                   │
└─────────────────────────────────────────┘
```

### 方式一：选择保险方案投保（推荐）

#### 步骤1：选择方案 → 预览

```
POST /admin/insurance/scheme/preview-apply
```

**使用场景**：管理员选择保险方案后，预览投保效果（各段日期、保费明细）。

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| schemeId | Long | 是 | 保险方案ID（从方案列表获取） |
| orderId | Long | 是 | 订单ID（自动获取出行日期和人数） |

**响应**：返回各段的日期范围、计划信息、单人保费、总保费、日期间隙警告。

#### 步骤2：确认后逐段投保

确认后前端按预览结果中的各段信息，逐段调用 purchase 接口（参考方式二）。

### 方式二：按天手动投保

#### 接口 1：查询保险产品列表

```
GET /admin/insurance/products?isOverseas=false
```

**使用场景**：按天手动投保时，选择保险产品。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| isOverseas | Boolean | 否 | 是否境外保险，默认 false |
| page | Integer | 否 | 页码 |
| pageSize | Integer | 否 | 每页条数 |

#### 接口 2：查询保险计划列表

```
GET /admin/insurance/products/{productId}/plans
```

**使用场景**：选择保险产品后，查看该产品下的保险计划及费率。

#### 接口 3：保费试算

```
POST /admin/insurance/trial-price
```

**使用场景**：选择计划和日期后，试算保费（不下单）。

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| planId | Long | 是 | 保险计划ID |
| startDate | String | 是 | 保障开始日期 yyyy-MM-dd |
| endDate | String | 是 | 保障结束日期 yyyy-MM-dd |
| insuredCount | Integer | 是 | 被保人数 |

#### 接口 4：确认投保

```
POST /admin/insurance/purchase
```

**使用场景**：确认投保，创建保险订单。

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| orderId | Long | 否 | 关联的旅行订单ID |
| planId | Long | 是 | 保险计划ID |
| startDate | String | 是 | 保障开始日期 yyyy-MM-dd |
| endDate | String | 是 | 保障结束日期 yyyy-MM-dd |
| insuredPersons | Array | 是 | 被保人列表（至少1人） |
| insuredPersons[].name | String | 是 | 姓名 |
| insuredPersons[].idCardType | String | 否 | 证件类型：`ID_CARD`/`PASSPORT`/`OTHER`，默认 ID_CARD |
| insuredPersons[].idCardNo | String | 是 | 证件号 |
| insuredPersons[].birthday | String | 是 | 出生日期 yyyy-MM-dd |
| insuredPersons[].gender | String | 是 | 性别：`MALE`/`FEMALE` |
| entityCode | String | 否 | 投保公司编码，默认使用系统默认主体 |

**响应**：`List<InsuranceOrderDetailVO>`，每条包含保险单号、状态、被保人信息等。

### 保险查询与管理接口

| # | 接口 | 方法 | 路径 | 说明 |
|---|------|------|------|------|
| 1 | 按订单查保险 | GET | `/admin/insurance/orders/by-order/{orderId}` | 查询订单关联的保险单列表 |
| 2 | 保险保障详情 | GET | `/admin/insurance/coverage/{orderId}` | 查询订单保险保障（含被保人详情） |
| 3 | 保险订单详情 | GET | `/admin/insurance/orders/{id}` | 单条保险订单详情 |
| 4 | 退保 | POST | `/admin/insurance/cancel/{id}` | 退保（管理员手动退保） |
| 5 | 下载保单 | GET | `/admin/insurance/policy/{id}/download` | 下载保单PDF（Base64） |
| 6 | 分享保单 | POST | `/admin/insurance/share-policy` | 分享保单给用户 |
| 7 | 账户余额 | GET | `/admin/insurance/balance` | 查询保游网账户余额 |
| 8 | 在线充值 | POST | `/admin/insurance/recharge` | 保游网在线充值 |

---

## 五、合同服务 — 手动配置合同

订单合同在正常流程中会自动完成（支付后系统自动发起签约），但管理员也可以手动操作。

### 接口 1：创建合同（电子签约模式 STANDARD）

```
POST /admin/contract/create
```

**使用场景**：手动创建合同，发送签署短信给游客。合同签署完成后 CONTRACT 待办自动完成。

**请求体**：CreateContractRequest（字段较多，参见 Knife4j 文档）

### 接口 2：报备合同（线下报备模式 SYNC）

```
POST /admin/contract/report
```

**使用场景**：线下签约后报备合同，报备成功 CONTRACT 待办自动完成。

### 合同查询与管理接口

| # | 接口 | 方法 | 路径 | 说明 |
|---|------|------|------|------|
| 1 | 合同列表 | GET | `/admin/contract/list` | 分页查询，支持按订单/状态/旅行社筛选 |
| 2 | 合同详情 | GET | `/admin/contract/{id}` | 单条合同详情 |
| 3 | 按订单查合同 | GET | `/admin/contract/by-order/{orderId}` | 查询订单关联的所有合同（含已作废） |
| 4 | 订单有效合同 | GET | `/admin/contract/active-by-order/{orderId}` | 获取订单最新有效合同 |
| 5 | 刷新合同状态 | GET | `/admin/contract/{id}/status` | 从平台同步最新签署状态 |
| 6 | 作废合同 | POST | `/admin/contract/{id}/invalidate` | 作废合同（可重新签约） |
| 7 | 重发签署短信 | POST | `/admin/contract/{id}/resend-sms` | 重发签署短信（STANDARD模式） |
| 8 | 上传已签署PDF | POST | `/admin/contract/{id}/upload-pdf` | 上传线下签署的PDF（SYNC模式） |
| 9 | 合同模板列表 | GET | `/admin/contract/templates` | 可用合同模板（下拉选择） |
| 10 | 合同平台列表 | GET | `/admin/contract/platforms` | 可用合同平台 |
| 11 | 旅行社列表 | GET | `/admin/contract/agencies` | 可用旅行社 |

### 合同状态字典（contract_status）

| 值 | 中文 | 说明 |
|----|------|------|
| CREATED | 已创建 | 合同已创建，待发起签署 |
| SIGNING | 签署中 | 已发送签署短信，等待签署 |
| SIGNED | 已签署 | 合同已签署完成 |
| UPLOADED | 已上传 | 已上传签署PDF（SYNC模式） |
| REPORTED | 已报备 | 已向平台报备（SYNC模式） |
| INVALID | 已作废 | 合同已作废 |

---

## 六、配房 — 按天粒度 + 房型升级差价

### 破坏性变更

配房接口从「按家庭+日期区间」改为「按天按家庭」粒度。**`checkInDate` 和 `checkOutDate` 字段已删除**，改用 `date` 单天日期。

### 接口 1：配房升级差价预览（新增）

```
POST /admin/order/{orderId}/hotel-assignment/preview
```

**使用场景**：选择酒店和房型后，提交前预览房型升级差价。前端根据返回的差价信息展示给用户确认。

**请求体**：同分配酒店信息接口

**响应**：`RoomUpgradePreviewVO`

| 字段 | 类型 | 说明 |
|------|------|------|
| details | Array | 各天差价明细（仅有差价的天） |
| details[].familyIndex | Integer | 家庭序号 |
| details[].date | String | 日期 |
| details[].defaultRoomTypeId | Long | 产品默认房型ID |
| details[].defaultRoomTypeName | String | 产品默认房型名称 |
| details[].assignedRoomTypeId | Long | 实际分配房型ID |
| details[].assignedRoomTypeName | String | 实际分配房型名称 |
| details[].defaultPrice | BigDecimal | 默认房型当天单价 |
| details[].assignedPrice | BigDecimal | 实际房型当天单价 |
| details[].dayDiff | BigDecimal | 当天差价（正=补款，负=退款） |
| details[].direction | String | `UPGRADE` / `DOWNGRADE` / `SAME` |
| details[].remark | String | 备注 |
| totalDiff | BigDecimal | 差价合计 |
| direction | String | `UPGRADE` / `DOWNGRADE` / `SAME` / `MIXED` |
| description | String | 差价描述（如「共 2 天有差价，合计 +400.00」） |

**响应示例**：
```json
{
  "code": 200,
  "data": {
    "details": [
      {
        "familyIndex": 1,
        "date": "2026-04-01",
        "defaultRoomTypeId": 2002,
        "defaultRoomTypeName": "标间",
        "assignedRoomTypeId": 2001,
        "assignedRoomTypeName": "豪华大床房",
        "defaultPrice": 300.00,
        "assignedPrice": 500.00,
        "dayDiff": 200.00,
        "direction": "UPGRADE",
        "remark": "需要加床"
      }
    ],
    "totalDiff": 200.00,
    "direction": "UPGRADE",
    "description": "共 1 天有差价，合计 +200.00"
  }
}
```

### 接口 2：分配酒店信息（破坏性变更）

```
PUT /admin/order/{orderId}/hotel-assignment
```

**使用场景**：为订单按天按家庭分配具体酒店房间。每天每个家庭一条记录。

**请求体**：

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| assignments | Array | 是 | 酒店分配列表（按天按家庭，每天每个家庭一条） |
| assignments[].familyIndex | Integer | 是 | 家庭序号 |
| assignments[].hotelId | Long | 是 | 酒店ID |
| assignments[].hotelName | String | 是 | 酒店名称 |
| assignments[].roomTypeId | Long | 是 | 房型ID |
| assignments[].roomType | String | 是 | 房型名称 |
| assignments[].date | String | 是 | 单天日期 `yyyy-MM-dd`（**替代原 checkInDate/checkOutDate**） |
| assignments[].remark | String | 否 | 当天备注（新增） |
| assignments[].upgradePrice | BigDecimal | 否 | 手动覆盖升级差价（null=使用系统计算值） |

**删除的字段**：`checkInDate`、`checkOutDate`

**房型升级逻辑（自动触发）**：
- 分配的 roomTypeId 与产品默认房型不同 → 自动计算差价
- CORE产品（快照中 roomTypeId 为 null）→ 默认基准为该酒店的标间（STANDARD）
- 差价 = 新房型日价格 - 默认房型日价格（来自价格日历）
- `upgradePrice` 可手动覆盖系统计算的差价
- **定制师操作**：差价自动确认，直接调整订单总售价
- **其他角色操作**：差价设为「待确认」临时加到尾款，通知定制师确认

**请求示例**：
```json
{
  "assignments": [
    {
      "familyIndex": 1,
      "hotelId": 1001,
      "hotelName": "呼伦贝尔大酒店",
      "roomTypeId": 2001,
      "roomType": "豪华大床房",
      "date": "2026-04-01",
      "remark": "需要加床"
    },
    {
      "familyIndex": 1,
      "hotelId": 1001,
      "hotelName": "呼伦贝尔大酒店",
      "roomTypeId": 2001,
      "roomType": "豪华大床房",
      "date": "2026-04-02",
      "remark": ""
    },
    {
      "familyIndex": 2,
      "hotelId": 1001,
      "hotelName": "呼伦贝尔大酒店",
      "roomTypeId": 2002,
      "roomType": "标间",
      "date": "2026-04-01",
      "remark": ""
    }
  ]
}
```

**响应**：`Result<Void>`

### 接口 3：查询可用酒店列表

```
GET /admin/order/{orderId}/available-hotels?dayIndex=1
```

**使用场景**：配房时根据行程天数查询可选酒店（产品快照中的酒店优先排序）。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| dayIndex | Integer | 是 | 行程第几天（1开始） |

### 推荐交互流程

```
选择酒店+房型 → 填写每天备注 → 点击「预览差价」
  → 调用 POST preview 接口
  → 展示差价明细（可修改 upgradePrice）
  → 点击「确认配房」→ 调用 PUT hotel-assignment
```

---

## 七、配车

### 接口：分配车辆信息

```
PUT /admin/order/{orderId}/vehicle-assignment
```

**使用场景**：为订单分配具体车辆和司机信息。

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| vehicleModel | String | 是 | 车型（如「别克GL8」） |
| vehicleBrand | String | 是 | 品牌（如「别克」） |
| plateNumber | String | 否 | 车牌号 |
| driverName | String | 否 | 司机姓名 |
| driverPhone | String | 否 | 司机电话 |

**响应**：`Result<Void>`

---

## 八、尾款调整汇总（字段增强）

```
GET /admin/order/{orderId}/itinerary/balance-summary
```

**使用场景**：订单详情页展示尾款调整明细，包含行程编辑和房型升级产生的差价。

**响应新增字段**：

| 字段 | 类型 | 说明 |
|------|------|------|
| confirmedAdjustment | BigDecimal | 已确认的调整金额（已计入总售价） |
| pendingAdjustment | BigDecimal | 待确认的调整金额（临时，待定制师确认） |
| totalAdjustment | BigDecimal | 合计（已确认 + 待确认） |
| details[].confirmStatus | String | `CONFIRMED`（已确认）或 `PENDING_CONFIRM`（待确认） |

**页面展示**：
- 展示「已确认调整」和「待确认调整（临时）」两个金额
- 待确认项标记为临时状态，提示「待定制师确认」

---

## 九、枚举/字典值汇总

| 字段 | 可选值 | 说明 |
|------|--------|------|
| contractPlatform | `12301` / `FADADA` | 合同平台 |
| contractMode | `STANDARD` / `SYNC` | 签约模式：电子签约 / 线下报备 |
| signatoryMode | `1` / `2` / `3` | 签署模式：1=短信 / 2=现场 / 3=线下 |
| disputeResolution | `1` / `2` | 争议解决：1=仲裁 / 2=诉讼 |
| todoType | `INSURANCE` / `CONTRACT` / `ARRANGE_ROOM` / `ARRANGE_VEHICLE` / `CONFIRM_CHECKLIST` | 待办类型（CONFIRM_ORDER 已删除） |
| processStatus | `PENDING_INFO` / `PENDING_INSURANCE` / `PENDING_CONTRACT` / `PENDING_ROOM` / `PENDING_VEHICLE` / `PENDING_FINANCE` / `READY` / `INTERNAL_CONFIRMED` | 内部流程状态（PROCESSING 已删除） |
| contract_status | `CREATED` / `SIGNING` / `SIGNED` / `UPLOADED` / `REPORTED` / `INVALID` | 合同状态 |
| upgradeDirection | `UPGRADE` / `DOWNGRADE` / `SAME` / `MIXED` | 房型升级方向 |
| confirmStatus | `CONFIRMED` / `PENDING_CONFIRM` | 尾款调整确认状态 |
