hl-api-changelog/changelogs/2026-04/2026-04-23_supplement-save-valid-effective.md

136 行
4.1 KiB
Markdown

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

# 产品 Step1-5 保存接口 JSR-303 校验真实生效
**日期**: 2026-04-23
**PR**: #1270 (Closes #1269) — PR #1259 后续补丁
**服务**: hl-product-service-v2 / hl-order-service-v2
**类型**: fix修复校验漏补
---
## 背景
PR #1259(装备建议字段改条目列表)里 SaveReqVO 加了 JSR-303 校验注解(`@NotBlank` / `@Size(max=20)` / `@Size(min=1, max=50)`),但 `AdminProductController` 的 Controller 方法未加 `@Valid` 修饰符,**校验注解实际未触发**。非法数据仍能 200 入库。
本次补丁把 Step1-5 全部保存接口及一个订单接口补齐 `@Valid`,校验现在真实生效。
---
## 影响接口9 处)
| 接口 | Method |
|------|--------|
| `POST /admin/product/item/basic` | saveBasic |
| `POST /admin/product/item/{id}/itinerary` | saveItinerary |
| `POST /admin/product/item/{id}/route` | saveRoute |
| `POST /admin/product/item/{id}/price-calendar/batch` | savePriceCalendar |
| `POST /admin/product/item/{id}/schedule` | saveSchedule2 个)|
| `POST /admin/product/item/{id}/schedule/batch` | batchCreateSchedule |
| `PUT /admin/product/item/{id}/supplement` | saveSupplement |
| `PUT /admin/product/item/{id}/detail-blocks` | saveDetailBlocks |
| `DELETE /admin/order/{orderId}/itinerary/pending/{editId}` | withdrawPendingEdit |
---
## 行为变化(前端必读)
### 之前PR #1270 前)
```http
PUT /admin/product/item/{id}/supplement
{
"equipmentList": [
{"text": ""} // 非法:空 text
]
}
→ 200 OK错误地通过数据存入 DB
```
### 之后PR #1270 后)
```http
PUT /admin/product/item/{id}/supplement
{
"equipmentList": [
{"text": ""}
]
}
→ 400 {
"code": 400,
"success": false,
"message": "equipmentList[0].text: 装备文案不能为空"
}
```
---
## 装备建议校验规则(生效中)
| 规则 | 违反时错误消息 |
|------|---------------|
| `equipmentList` 条目数 ≤ 20 | `equipmentList: 装备建议条目数不能超过20条` |
| 单条 `text` 非空非空白 | `equipmentList[0].text: 装备文案不能为空` |
| 单条 `text` 长度 1-50 字 | `equipmentList[0].text: 装备文案长度需在 1-50 字符之间` |
**注意错误消息格式**`{字段路径}: {消息}`,含数组索引(`[0]``[1]` 等),前端可精确定位哪条条目出错。
---
## 前端建议
### 1. 前置校验(推荐)
admin 编辑器在提交前自行 validate 一次:
- 条目数 > 20 → 禁止提交 + toast
- 单条 text 空 → 禁止提交 + 红色高亮
- 单条 text 长度 > 50 → 禁止提交 + 高亮
避免走到后端才发现,体验更好。
### 2. 后端报错展示(兜底)
如果绕过了前置校验,后端 400 返回的 `message` 字段可直接 toast
```javascript
const resp = await api.saveSupplement(req);
if (resp.code !== 200) {
ElMessage.error(resp.message || '保存失败');
return;
}
```
**错误消息已中文化**,直接展示即可。
### 3. 数组索引提示
如果要做精细错误提示,可解析 `equipmentList[N].text` 中的 N,滚动聚焦到对应条目输入框。
---
## 其他接口的校验
`basic / itinerary / route / price-calendar / schedule` 等其他 Step 接口的 SaveReqVO 本来就有 JSR-303 注解,但同样因为缺 `@Valid` 没有生效。**本次补丁一起修复**。
常见校验约束(以 `ProductBasicSaveReqVO` 为例):
- `productType` 非空
- `name` 长度 ≤ 30 字
- `tripDays` ≥ 1
- 具体以 Knife4j `@ApiModelProperty` 中的 `required`/`allowableValues` 为准
如果前端之前传错数据能 200,现在可能 400,请以实际接口返回为准调整。
---
## 向后兼容
- **合法请求**:行为不变,仍 200
- **非法请求**:从"假成功200 入脏数据)"变为"正确失败400 + 可读消息)"
- 属于**修复性变化**,非破坏性
---
## 验证
测试服网关已 curl 4 场景全过:
```bash
# 合法 3 条 → 200
# 21 条 → 400 equipmentList: 装备建议条目数不能超过20条
# 空 text → 400 equipmentList[0].text: 装备文案不能为空
# 51 字 text → 400 equipmentList[0].text: 装备文案长度需在 1-50 字符之间
```