Files
zkxw/docs/dev-field-consistency.md
T
2026-05-23 14:49:50 +08:00

101 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 字段一致性开发指南
## 问题背景
在前后端全链路开发中,一个字段需要同时出现在 **5 个位置** 才能完整打通:
```
前端 formData → API Schema (Pydantic) → API Handler 传参 → CRUD 函数签名 → ORM 赋值
```
任何一层遗漏都会导致字段**静默丢失**(Pydantic 默认忽略未定义字段,不报错),产生难以发现的 bug。
## 历史问题
| 时间 | 问题 | 根因 |
|------|------|------|
| 2026-05 | 耗材/试剂新增时 `warning_qty` 未保存 | Schema 缺字段 → Handler 没传 → CRUD 没接 |
| 2026-05 | 耗材/试剂新增时 `status` 未保存 | 同上 |
| 2026-05 | 变动记录筛选"出库"无效 | 前端 value 与后端期望值不匹配 |
## 开发纪律(MUST)
### 1. `_row_to_dict` 是单一真相源
CRUD 文件中的 `_row_to_dict` 函数定义了实体返回给前端的**所有可读字段**。它是字段一致性的基准。
### 2. 先写 `_row_to_dict`,再写 create/update
新增实体时:
1. 先定义 `_row_to_dict`,列出所有字段的读取逻辑
2. 根据 `_row_to_dict` 的字段列表,逐字段编写 CreateBody/UpdateBody
3. 根据 Schema 字段,逐字段编写 create/update 函数签名和 ORM 赋值
4. 根据后端字段列表,编写前端 formData
### 3. 排除只读字段
以下字段出现在 `_row_to_dict` 中但**不需要**出现在 CreateBody/UpdateBody 或 formData 中:
- `id` — 自动生成
- `createTime` / `updateTime` — 自动维护
- `stockQty` — 通过出入库操作维护,不可直接设置
- `tenantNo` — 从认证上下文获取
### 4. 每个字段必须检查的 5 个位置
以 `warningQty` 为例:
| 位置 | 代码 | 必须 |
|------|------|------|
| `_row_to_dict` | `"warningQty": _dec(c.warning_qty)` | ✅ 读取 |
| CreateBody | `warning_qty: Optional[float] = Field(0, alias="warningQty")` | ✅ 接收 |
| Handler | `warning_qty=body.warning_qty` | ✅ 传递 |
| create 函数签名 | `warning_qty: Optional[float] = None` | ✅ 接收 |
| create ORM 赋值 | `warning_qty=warning_qty if warning_qty is not None else 0` | ✅ 写入 |
### 5. 实现后验证
每个实体完成后运行:
```bash
python backend/scripts/check_field_consistency.py
```
检查项:
- `_row_to_dict` 中的可写字段是否都在 CreateBody/UpdateBody 中
- `_row_to_dict` 中的可写字段是否都在前端 formData 中
- 前后端字段值映射是否一致(如筛选条件 value 对应关系)
## 校验脚本
`backend/scripts/check_field_consistency.py` 自动扫描以下三层,输出 diff 报告:
1. **CRUD 层**:提取 `_row_to_dict` 的所有 camelCase key
2. **API 层**:提取 CreateBody/UpdateBody 的所有字段(含 alias)
3. **前端层**:提取 `formData` 的所有 key
### 使用方式
```bash
# 检查所有注册实体
python backend/scripts/check_field_consistency.py
# 检查单个实体
python backend/scripts/check_field_consistency.py --entity consumable
# JSON 格式输出
python backend/scripts/check_field_consistency.py --json
```
### 退出码
- `0`:所有检查通过
- `1`:发现字段不一致
## 常见陷阱
1. **alias 遗漏**:Schema 字段有 `alias="warningQty"` 但忘记写,Pydantic 只接受 snake_case 键名
2. **Handler 传参遗漏**:Schema 有字段但 Handler 没传给 CRUD,字段在 Schema 层就被丢弃
3. **CRUD 签名遗漏**:Handler 传了但 CRUD 函数签名没接收,Python 会报 unexpected keyword argument(运行时错误)
4. **前端 value 与后端不匹配**:如筛选条件下拉框的 value 是 `"use"` 但后端期望 `"out"`