---
author: "wx(GIT)"
schema: "hl-changelog/v2"
ticket: "5558"
title: "司机保单新增 policyPdfUrl（在线查看保单 PDF）+ 投保 bindAnnual 缺省语义变更"
consumer: "admin"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "implemented"
frontend_owner: "pi-main-session"
frontend_ref: "hl-admin@3e535fe3ad6a406529eb95d7787cefe11b9584cd"
target_release: "v2.1"
verified_at: "2026-08-06"
status_note: "司机详情与车务保险列表/详情仅在 policyPdfUrl 非空时显示查看保单并安全新窗口预览；空值隐藏且不再回退旧下载接口，投保沿用 bindAnnual 缺省绑定全年保险语义。"
updated_at: "2026-08-05"
base: "dev-v3"
---

# 司机险：保单行在线查看保单 PDF + 投保缺省绑定全年保险

> **服务**：hl-fleet-service + hl-order-service-v3 + hl-common
> **PR**：#5563
> **Issue**：[wx/HL #5558](https://git.1814.love:8443/wx/HL/issues/5558)
> **日期**：2026-08-05
> **影响范围**：管理后台司机详情「我的保单」区域、车务保险保单 Tab

## 变更接口

| 接口 | 方法 | 路径 | 变更 |
|---|---|---|---|
| 司机我的保单列表 | GET | `/admin/fleet/drivers/<driverId>/insurance/policies` | 每条记录新增 `policyPdfUrl` |
| 司机险保单列表（车务保险） | GET | `/admin/fleet/insurance/policies` | 每条记录新增 `policyPdfUrl` |
| 司机险保单详情 | GET | `/admin/fleet/insurance/policies/<insuranceOrderId>` | 响应新增 `policyPdfUrl` |
| 司机险投保 | POST | `/admin/fleet/drivers/<driverId>/insurance/purchase` | `bindAnnual` 缺省语义变更 |

## 二、响应字段

| 字段 | 类型 | 必填性 | 值 | 说明 |
|---|---|---|---|---|
| `policyPdfUrl` | `String` | 条件返 | 保游生成后上传 OSS 的 PDF 直链 | 保单行「查看保单」按钮数据源；空值=保单 PDF 未生成/无电子保单（MOCK 单、MANUAL 年保单），前端应隐藏查看入口 |

响应示例（司机我的保单列表）：

```json
{
  "code": 200,
  "data": [
    {
      "insuranceOrderId": "2084941753793552386",
      "policyNo": "11209006600507254235",
      "status": "INSURED",
      "totalPremium": "7.00",
      "policyPdfUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/insurance/policy/2026/08/05/policy_2084941753793552386.pdf"
    }
  ],
  "success": true
}
```

> 投保出参（purchase 响应）也携带 `policyPdfUrl` 字段，但出单受理瞬间 PDF 尚未异步生成，恒为空。

## 三、入参语义变更（bindAnnual 缺省）

| 入参 | 旧语义 | 新语义 |
|---|---|---|
| `bindAnnual` 缺省（不传） | false：只出单不动档案 | **true：直接购买默认全年保险**，出单成功后自动绑定司机档案（insurance_type=annual + 保单号/保费/起止回填 + annualSource=baoyou） |
| `bindAnnual: false` | 只出单不动档案 | 不变：只出单不动档案 |
| `bindAnnual: true` | 出单后绑定档案 | 不变 |

**背景**：司机详情页投保不传 `bindAnnual`，旧语义下保单落库但档案保险状态不同步（有保单显示但档案 `insurance_type=none`）。

## 四、兼容性与前端事项

- 三处响应均为**向后兼容的字段扩展**，不修改既有字段与分页结构。
- `bindAnnual` 缺省语义变更：前端若存在"只出单不动档案"的调用场景，需显式传 `false`；司机详情页/保险订单页投保路径无需改动（缺省即绑定档案）。
- 前端事项：
  1. 司机详情「我的保单」列表与车务保险保单 Tab：保单行增加「查看保单」按钮，`policyPdfUrl` 非空时可点击；浏览器内嵌预览（`window.open(policyPdfUrl)` 或 iframe），**不触发下载**。
  2. `policyPdfUrl` 为空时隐藏查看入口。
- 后端未修改 `mmg/hl-ui`，前端消费状态保持 `pending`。

## 验证证据

- `DriverInsuranceServiceTest`：25 项通过（含 #5558 缺省绑定新语义用例）。
- order-v3 保险域全量：229 项通过（三链 `policyPdfUrl` 断言）。
- fleet verify：仅 2 个仓库基线失败（`Step2CanonicalSnapshotServiceTest`、`ReleaseEOccupancyMysql8033RecoveryTest`，dev-v3 干净工作区同失败，与本次改动无关）。
- 测试服部署：hl-fleet-service + hl-order-service-v3 滚动部署成功（20:13/20:14）。
- 网关验证：三个查询接口 `policyPdfUrl` 透传通过；真实保游单返回 OSS PDF 直链（Content-Type: application/pdf，浏览器内嵌预览），MOCK 单返回 null。
- MOCKPOL 残留清理（2026-08-05 21:40）：manifest `5558-70cdf37dc3be`（hl-data-cleanup/v1，test）批准执行，删除 mock 时段假保单全关联 4 行（`insurance_order`/`insured_person`/`insurance_status_log`/`fleet_insurance_task`），备份至 `manifests/5558-mock-policy-cleanup.backup.json`；网关复验司机46622 我的保单=空列表、车务保单列表=4 条真单（PDF 全直链）、档案 `insurance_type=none` 未变。
- 投保端到端（缺省绑定档案）验证：保游测试环境 20:15 起 `POST /Insurance/Insuran` 真实投保请求 Read timed out（第三方不可用，17:02~17:57 曾成功出单）。按 wx 指示**跳过保游端到端**（2026-08-05 22:20），以 DriverInsuranceServiceTest 缺省绑定单测 + 契约链路代码审查 + 无保单场景网关验证为验收依据；预期投保成功 → 档案 `insurance_type=annual` + 四件套回填（bindAnnual 缺省=true 已部署）。
- oasdiff：`not_configured`，一期项目没有稳定 OAS3 导出与已配置工具，使用源码和 JSON 序列化测试回退。
- Spring Cloud Contract：`not_configured`，使用生产者及消费者 reactor 测试回退。

## 关联/联系人

### 链接

- **后端工单**: [#5558](https://git.1814.love:8443/wx/HL/issues/5558)
- **后端 PR**: [#5563](https://git.1814.love:8443/wx/HL/pulls/5563)
- **Merge commit**: [`b0685cca8d`](https://git.1814.love:8443/wx/HL/commit/b0685cca8d)

### 联系人

- **后端负责人**: @wx
