提交文件

This commit is contained in:
2026-02-28 15:16:15 +08:00
parent 1a4e50e0a4
commit 44f250f58e
159 changed files with 61268 additions and 0 deletions

View File

@@ -0,0 +1,403 @@
# 模型验证规则
<cite>
**本文档引用的文件**
- [backend/app/models/models.py](file://backend/app/models/models.py)
- [backend/app/models/finance.py](file://backend/app/models/finance.py)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py)
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py)
- [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py)
- [backend/app/api/v1/assessments.py](file://backend/app/api/v1/assessments.py)
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py)
- [backend/app/services/indicator_service.py](file://backend/app/services/indicator_service.py)
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py)
- [backend/app/main.py](file://backend/app/main.py)
- [backend/requirements.txt](file://backend/requirements.txt)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概览](#架构概览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 简介
本文件系统性梳理了医院绩效系统中的模型验证规则,涵盖数据模型的验证机制,包括字段类型验证、范围限制、格式检查和业务规则验证。文档重点解释了以下三个层面的验证实现:
- Pydantic 模型验证:通过 Pydantic 的 Field 参数与类型注解实现请求体与响应体的数据校验。
- SQLAlchemy 约束验证:通过数据库层的列类型、索引与 CheckConstraint 实现数据完整性约束。
- 业务逻辑验证:通过服务层与 API 层的业务规则检查,确保数据在业务语义上的正确性。
同时,文档阐述了验证错误的处理方式与用户友好的错误信息设计,并提供验证规则的扩展方法与自定义验证器的实现建议。
## 项目结构
后端采用 FastAPI + SQLAlchemy 异步 ORM 的架构,数据模型位于 models 目录Pydantic 数据模式位于 schemas 目录API 路由位于 api/v1 目录,业务逻辑位于 services 目录,异常处理与全局配置位于 main.py。
```mermaid
graph TB
subgraph "API 层"
A1["staff.py"]
A2["indicators.py"]
A3["assessments.py"]
end
subgraph "服务层"
S1["staff_service.py"]
S2["indicator_service.py"]
S3["assessment_service.py"]
end
subgraph "模式层"
P1["schemas.py"]
end
subgraph "模型层"
M1["models.py"]
M2["finance.py"]
end
subgraph "核心"
C1["main.py"]
C2["requirements.txt"]
end
A1 --> S1
A2 --> S2
A3 --> S3
S1 --> M1
S2 --> M1
S3 --> M1
A1 --> P1
A2 --> P1
A3 --> P1
M1 --> C2
M2 --> C2
P1 --> C2
C1 --> A1
C1 --> A2
C1 --> A3
```
**图表来源**
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L1-L124)
- [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py#L1-L142)
- [backend/app/api/v1/assessments.py](file://backend/app/api/v1/assessments.py#L1-L166)
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L1-L112)
- [backend/app/services/indicator_service.py](file://backend/app/services/indicator_service.py#L1-L197)
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L114-L262)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L1-L743)
- [backend/app/models/models.py](file://backend/app/models/models.py#L1-L438)
- [backend/app/models/finance.py](file://backend/app/models/finance.py#L1-L79)
- [backend/app/main.py](file://backend/app/main.py#L50-L91)
- [backend/requirements.txt](file://backend/requirements.txt#L1-L16)
**章节来源**
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L1-L124)
- [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py#L1-L142)
- [backend/app/api/v1/assessments.py](file://backend/app/api/v1/assessments.py#L1-L166)
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L1-L112)
- [backend/app/services/indicator_service.py](file://backend/app/services/indicator_service.py#L1-L197)
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L114-L262)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L1-L743)
- [backend/app/models/models.py](file://backend/app/models/models.py#L1-L438)
- [backend/app/models/finance.py](file://backend/app/models/finance.py#L1-L79)
- [backend/app/main.py](file://backend/app/main.py#L50-L91)
- [backend/requirements.txt](file://backend/requirements.txt#L1-L16)
## 核心组件
- Pydantic 数据模式:通过 Field 的类型、长度、数值范围、正则表达式等参数实现字段级验证;通过枚举类型保证取值域的正确性;通过 model_config 的 from_attributes 控制 ORM 对象到 Pydantic 模式的转换。
- SQLAlchemy 模型通过列类型String、Integer、Numeric、Boolean、DateTime、Enum、索引与 CheckConstraint 实现数据库层约束;通过外键关系与级联策略保证参照完整性。
- API 层:在路由函数中接收 Pydantic 模式作为请求体,自动触发 Pydantic 验证;在业务逻辑允许范围内进行额外的业务规则检查,并抛出 HTTP 异常。
- 服务层:封装 CRUD 与业务逻辑,负责数据一致性与业务规则的执行;在必要时进行跨实体的约束检查。
- 异常处理:全局注册异常处理器,捕获并记录验证错误与业务异常,返回统一的错误信息。
**章节来源**
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L49-L60)
- [backend/app/models/models.py](file://backend/app/models/models.py#L62-L85)
- [backend/app/models/finance.py](file://backend/app/models/finance.py#L45-L74)
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L81)
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L69-L91)
- [backend/app/main.py](file://backend/app/main.py#L58-L74)
## 架构概览
下图展示了从 API 请求到数据库写入的完整验证链路,包括 Pydantic 验证、业务规则检查与数据库约束验证。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant API as "API 路由"
participant Pyd as "Pydantic 模式"
participant Svc as "服务层"
participant DB as "SQLAlchemy 模型"
participant SQL as "数据库"
Client->>API : "POST /staff"
API->>Pyd : "StaffCreate 验证"
Pyd-->>API : "验证通过/错误"
API->>Svc : "调用业务逻辑"
Svc->>DB : "构造模型实例"
DB->>SQL : "执行插入/更新"
SQL-->>DB : "约束检查结果"
DB-->>Svc : "返回持久化结果"
Svc-->>API : "返回业务结果"
API-->>Client : "统一响应"
```
**图表来源**
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L81)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L107-L124)
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L69-L76)
- [backend/app/models/models.py](file://backend/app/models/models.py#L88-L114)
## 详细组件分析
### Pydantic 模型验证
- 字段类型与长度验证:通过 Field 的类型注解与 max_length/min_length 限制字符串长度;例如员工工号、姓名、职位、电话、邮箱等字段均设置了长度限制。
- 数值范围验证:通过 ge大于等于、le小于等于、gt大于等参数限制数值范围例如基本工资、绩效系数、权重、最高分值、年份、月份等。
- 枚举验证:通过 str + Enum 的组合确保取值域的正确性;例如科室类型、员工状态、指标类型、考核状态等。
- 正则表达式验证:通过 pattern 参数对字符串格式进行约束;例如用户角色字段使用正则限制合法取值。
- 响应模式转换:通过 model_config(from_attributes=True) 将 ORM 对象直接转换为 Pydantic 模式,避免重复映射。
```mermaid
classDiagram
class StaffBase {
+employee_id : str
+name : str
+department_id : int
+position : str
+title : Optional[str]
+phone : Optional[str]
+email : Optional[str]
+base_salary : float
+performance_ratio : float
}
class StaffCreate {
+status : StaffStatus
+hire_date : Optional[datetime]
}
class StaffResponse {
+id : int
+status : StaffStatus
+hire_date : Optional[datetime]
+created_at : datetime
+updated_at : datetime
+department_name : Optional[str]
}
StaffCreate --|> StaffBase
StaffResponse --|> StaffBase
```
**图表来源**
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L107-L150)
**章节来源**
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L64-L98)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L107-L150)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L315-L345)
### SQLAlchemy 约束验证
- 列类型与默认值:通过 String、Integer、Numeric、Boolean、DateTime、Enum 等类型定义字段属性与默认值;例如 Numeric(10,2) 用于金额与分数的精确存储。
- 索引优化:为常用查询字段添加索引,提升查询性能;例如科室类型、状态、年月组合等。
- CheckConstraint通过 CheckConstraint 在数据库层强制业务约束;例如指标权重必须大于 0财务金额必须大于等于 0。
- 外键关系:通过 ForeignKey 建立实体间的参照关系,配合级联策略保证数据一致性。
```mermaid
erDiagram
STAFF {
int id PK
string employee_id UK
string name
int department_id FK
string position
string title
string phone
string email
numeric base_salary
numeric performance_ratio
enum status
date hire_date
}
DEPARTMENTS {
int id PK
string name
string code UK
enum dept_type
int parent_id FK
int level
int sort_order
boolean is_active
}
INDICATORS {
int id PK
string name
string code UK
enum indicator_type
enum bs_dimension
numeric weight
numeric max_score
numeric target_value
string target_unit
text calculation_method
text assessment_method
text deduction_standard
text data_source
string applicable_dept_types
boolean is_veto
boolean is_active
}
ASSESSMENTS {
int id PK
int staff_id FK
int period_year
int period_month
string period_type
numeric total_score
numeric weighted_score
enum status
int assessor_id FK
int reviewer_id FK
datetime submit_time
datetime review_time
text remark
}
ASSESSMENT_DETAILS {
int id PK
int assessment_id FK
int indicator_id FK
numeric actual_value
numeric score
text evidence
text remark
}
SALARY_RECORDS {
int id PK
int staff_id FK
int period_year
int period_month
numeric base_salary
numeric performance_score
numeric performance_bonus
numeric deduction
numeric allowance
numeric total_salary
string status
text remark
}
DEPARTMENTS ||--o{ STAFF : "拥有"
STAFF ||--o{ ASSESSMENTS : "被考核"
ASSESSMENTS ||--o{ ASSESSMENT_DETAILS : "包含"
INDICATORS ||--o{ ASSESSMENT_DETAILS : "被评分"
```
**图表来源**
- [backend/app/models/models.py](file://backend/app/models/models.py#L62-L114)
- [backend/app/models/models.py](file://backend/app/models/models.py#L117-L146)
- [backend/app/models/models.py](file://backend/app/models/models.py#L149-L178)
- [backend/app/models/models.py](file://backend/app/models/models.py#L181-L202)
- [backend/app/models/models.py](file://backend/app/models/models.py#L205-L230)
- [backend/app/models/finance.py](file://backend/app/models/finance.py#L45-L74)
**章节来源**
- [backend/app/models/models.py](file://backend/app/models/models.py#L143-L146)
- [backend/app/models/finance.py](file://backend/app/models/finance.py#L68-L74)
### 业务逻辑验证
- API 层业务规则:在创建与更新接口中,先进行 Pydantic 验证,再进行业务规则检查;例如创建员工前检查工号唯一性,创建指标前检查编码唯一性。
- 服务层业务规则:在服务层进行更复杂的业务一致性检查;例如更新考核记录时,仅允许在草稿或已驳回状态下进行修改,并重新计算总分与加权分。
- 统一错误处理:通过 HTTPException 抛出业务错误,结合全局异常处理器记录日志并返回统一的错误响应。
```mermaid
flowchart TD
Start(["开始"]) --> ValidatePyd["Pydantic 验证"]
ValidatePyd --> PydanticOK{"验证通过?"}
PydanticOK --> |否| ReturnError["返回验证错误"]
PydanticOK --> |是| BusinessCheck["业务规则检查"]
BusinessCheck --> BusinessOK{"业务规则通过?"}
BusinessOK --> |否| RaiseHTTP["抛出 HTTP 异常"]
BusinessOK --> |是| Persist["持久化到数据库"]
Persist --> Done(["结束"])
ReturnError --> Done
RaiseHTTP --> Done
```
**图表来源**
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L75-L78)
- [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py#L78-L81)
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L114-L151)
- [backend/app/main.py](file://backend/app/main.py#L58-L74)
**章节来源**
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L95)
- [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py#L71-L98)
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L114-L151)
- [backend/app/main.py](file://backend/app/main.py#L58-L74)
### 验证错误处理与用户友好信息
- HTTP 异常:在业务规则不满足时,使用 HTTPException 返回明确的状态码与错误信息,如“员工不存在”、“工号已存在”、“指标不存在”等。
- 统一响应结构API 返回统一的响应结构,包含状态码、消息、数据、分页信息等,便于前端展示与调试。
- 全局异常处理:注册 RequestValidationError 与 StarletteHTTPException 的处理器,记录错误日志并向上抛出,确保错误信息一致且可追踪。
**章节来源**
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L60-L61)
- [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py#L66-L67)
- [backend/app/api/v1/assessments.py](file://backend/app/api/v1/assessments.py#L99-L101)
- [backend/app/main.py](file://backend/app/main.py#L58-L74)
### 验证规则扩展与自定义验证器
- 扩展 Pydantic 验证:可在现有 Field 参数基础上增加更多约束,如自定义正则表达式、长度范围、数值边界等;对于复杂字段(如 JSON可使用 Json 类型与自定义解析器。
- 自定义验证器:可通过 Pydantic 的 field_validator 或 root_validator 实现跨字段验证与复杂业务规则;例如在创建考核时,验证明细中的指标权重与总分计算的一致性。
- 数据库约束增强:在模型层新增 CheckConstraint 或复合索引,以强化数据完整性;例如为“员工工号+部门”的唯一性约束添加复合索引。
- 业务规则扩展:在服务层增加新的业务规则检查点,如在创建考核时检查指标是否适用于当前科室类型、是否启用等。
**章节来源**
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L153-L192)
- [backend/app/models/models.py](file://backend/app/models/models.py#L143-L146)
- [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L114-L151)
## 依赖关系分析
- 版本要求:项目使用 FastAPI、SQLAlchemy、Pydantic 等核心依赖,版本在 requirements.txt 中声明,确保验证与 ORM 功能的稳定性。
- 模块间耦合API 层依赖 Pydantic 模式与服务层;服务层依赖 SQLAlchemy 模型;模型层依赖数据库驱动与 Alembic 迁移工具。
- 异常处理:全局异常处理器统一处理验证与业务异常,减少重复代码并提升用户体验。
```mermaid
graph LR
Req["requirements.txt"] --> FastAPI["FastAPI"]
Req --> SQLAlchemy["SQLAlchemy"]
Req --> Pydantic["Pydantic"]
API["API 路由"] --> PydanticSchema["Pydantic 模式"]
API --> Service["服务层"]
Service --> Model["SQLAlchemy 模型"]
Model --> DB["数据库"]
Main["main.py"] --> API
Main --> Service
Main --> Model
```
**图表来源**
- [backend/requirements.txt](file://backend/requirements.txt#L1-L16)
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L10-L15)
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L9-L10)
- [backend/app/models/models.py](file://backend/app/models/models.py#L13-L13)
- [backend/app/main.py](file://backend/app/main.py#L50-L77)
**章节来源**
- [backend/requirements.txt](file://backend/requirements.txt#L1-L16)
- [backend/app/main.py](file://backend/app/main.py#L50-L77)
## 性能考虑
- 索引优化:为高频查询字段(如科室类型、状态、年月组合)建立索引,降低查询成本。
- 数值精度:使用 Numeric 类型存储金额与分数,避免浮点误差;合理设置精度与小数位数。
- 查询优化:在服务层使用 selectinload 等策略预加载关联对象,减少 N+1 查询问题。
- 异步 I/O利用 SQLAlchemy 异步引擎与 FastAPI 的异步特性,提升并发处理能力。
## 故障排除指南
- Pydantic 验证失败:检查请求体字段类型、长度与范围是否符合模式定义;查看响应中的错误字段与原因。
- 业务规则失败:确认业务状态是否允许当前操作(如仅草稿或已驳回状态可更新);检查唯一性约束冲突(如工号、指标编码)。
- 数据库约束失败:检查 CheckConstraint 与索引是否满足;确认外键关系是否正确。
- 异常处理:查看全局异常处理器的日志输出,定位具体错误位置与堆栈信息。
**章节来源**
- [backend/app/main.py](file://backend/app/main.py#L58-L74)
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L75-L78)
- [backend/app/models/models.py](file://backend/app/models/models.py#L143-L146)
## 结论
本系统通过“Pydantic 模式验证 + SQLAlchemy 数据库约束 + 服务层业务规则”的三层验证机制确保了数据在进入业务流程前后的完整性与一致性。API 层负责输入验证与业务规则检查,服务层负责复杂业务逻辑与数据一致性,模型层负责数据结构与约束定义。配合统一的异常处理与日志记录,系统在保证功能正确的同时,也具备良好的可维护性与可扩展性。未来可在 Pydantic 中引入自定义验证器与复杂字段解析,在模型层增加更多数据库约束,并在服务层扩展业务规则检查点,进一步完善验证体系。