fix(product-v2,order-v2): Step1-5 保存 JSR-303 校验生效前端告知 (PR #1270)
这个提交包含在:
父节点
4eb8240e58
当前提交
beae2cd7fc
@ -0,0 +1,135 @@
|
|||||||
|
# 产品 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` | saveSchedule(2 个)|
|
||||||
|
| `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 字符之间
|
||||||
|
```
|
||||||
正在加载...
x
在新工单中引用
屏蔽一个用户