---
date: 2026-05-13
type: backend-improvement
service: hl-order-service-v2
priority: medium
notify: ["@mmg"]
status: verified
---

# 12301 合同补充约定字数上限 2000 → 5000 (已测试服验证)

> **PR**: [#2187](https://git.1814.love:8443/wx/HL/pulls/2187) — 已合并 dev + 部署测试服
> **Issue**: [#2186](https://git.1814.love:8443/wx/HL/issues/2186)
> **状态**: ✅ **测试服已验证** (api.test.1814.love:9443) — 3/3 case 端到端通过

---

## 一、背景

`hl-ui` 管理端「编辑补充约定模板」弹窗目前 `maxlength=2000`,实际旅行社业务里 12301 旅游合同补充约定动辄超过 2000 字符,卡用户。

调研结论:
- **12301 国家旅游局 API 公开/内部文档均未约束 supplementaryClause 字段长度**(项目内 `35_合同对接12301国家旅游局API需求规格.md` 通篇没列字段长度;搜索 tourage.cn / 12301 字段长度均无公开资料)
- 数据库 `contract.supplementary_clause` / `contract_scheme.supplementary_clause` 是 `TEXT`(~21000 中文字符),底层不卡
- 历史 12301 错误码 `errcode=301025` 是换行符问题(已 `replace("\n", " ")` 净化),没遇到过长度被拒
- **2000 是当初开发期保守值**,本次放宽到 5000,留安全垫给 12301 未知上限

---

## 二、变更接口清单

| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 创建合同方案 | POST | `/admin/contract/scheme` | 校验放宽 | `supplementaryClause` 字数上限 2000 → 5000 |
| 2 | 更新合同方案 | PUT | `/admin/contract/scheme/{schemeId}` | 校验放宽 | 同上 |
| 3 | 创建合同 | POST | `/admin/contract/create`(及其同族) | 校验放宽 | `supplementaryClause` 字数上限 2000 → 5000 |
| 4 | 报备合同(SYNC) | POST | `/admin/contract/report`(及其同族) | 校验放宽 | `supplementaryClause` 字数上限 2000 → 5000 |

**未变接口**(已有行为不变):
- `POST/PUT /admin/contract/clause-template`(补充约定模板 CRUD):后端 `ClauseTemplateRequest.content` 本来就没 `@Size` 限制,DB TEXT 兜底。前端弹窗当前 2000 字限制是**前端自己加的**,需前端同步改。

---

## 三、字段约束变化

| DTO 字段 | 原约束 | 新约束 |
|---|---|---|
| `ContractSchemeRequest.supplementaryClause` | `@Size(max=2000)` | `@Size(max=5000)` |
| `CreateContractRequest.supplementaryClause` | `@Size(max=2000)` | `@Size(max=5000)` |
| `ReportContractRequest.supplementaryClause` | `@Size(max=2000)` | `@Size(max=5000)` |

错误 message 同步从「补充约定/条款不能超过2000个字符」改为「...不能超过5000个字符」。

---

## 四、前端待办(@mmg)

请 hl-ui 同步把以下输入框 `maxlength=2000` → `maxlength=5000`:

1. **「编辑补充约定模板」弹窗**(模板内容输入框)— 截图见 Issue #2186
2. **合同方案管理页**——「补充条款」输入框(POST/PUT `/admin/contract/scheme` 调用方)
3. **创建合同 / 报备合同表单**——「补充约定内容」输入框

字数计数器 `2000/2000` 显示也要同步改 `5000/5000`。

> 不改前端的话:用户能勾选 ≤2000 字符的旧模板,但不能写超过 2000 字符的内容(前端仍卡);后端能接 5000,前端是瓶颈。

---

## 五、测试服已验证 (硬性凭证)

`POST /admin/contract/scheme`,Bearer admin token:

```
A. supplementaryClause = "夏" × 4500 字符
   → HTTP 200 code=200 success  schemeId=2054442503913779201  ✓ (原 max=2000 会拦)

B. supplementaryClause = "x" × 5001 字符
   → HTTP 200 code=400 message="补充条款不能超过5000个字符"  ✓ (@Size(max=5000) 生效)

C. supplementaryClause = "中" × 2001 字符
   → HTTP 200 code=200 success  schemeId=2054442506648465410  ✓ (原 max=2000 会拦)

[CLEANUP] DELETE /admin/contract/scheme/2054442503913779201 → HTTP 200
[CLEANUP] DELETE /admin/contract/scheme/2054442506648465410 → HTTP 200
```

---

## 六、风险与回滚

- **风险**:12301 远端实际可能有 supplementaryClause 上限(未知),5000 字以内若被 12301 拒绝,会在 12301 调用时报 4xx/errcode 错误(不会损坏本地数据,仅合同上报失败)。
- **回滚**:3 处 `@Size(max=5000)` 改回 `2000` 即可,无 schema 变更、无数据兼容性问题。
- 若线上出现 12301 实际拒绝长 supplementaryClause 的 errcode,据实再调小。
