This commit is contained in:
zlwu committed 2026-05-23 14:49:50 +08:00
1 parent fb85230d25
commit 05684ba2a4
56 files changed
+26110 -13601

No files matched your search

+100
View File
@@ -0,0 +1,100 @@
# 字段一致性开发指南
## 问题背景
在前后端全链路开发中,一个字段需要同时出现在 **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"`