作者:呱牛
发布日期:2026年3月30日
标签:FastAPI、绩效考核
🔥 今日亮点
2026年3月30日 - 任务明细文件上传功能开发
-
✅ 实现双文件上传功能:前端页面新增独立的任务明细上传按钮
-
✅ 创建*_pa_task_assignment_score模块:完整的Model、Schema、CRUD三层架构
-
✅ 实现Excel解析入库功能:解析《团队任务派单明细》并存入数据库
-
✅ 修复CRUD类初始化问题:正确使用泛型类型参数和关键字参数
-
✅ 修复模块导入路径错误 :统一使用
app.core.base_crud导入路径 -
✅ 实现动态CRUD类加载:使用importlib动态导入CRUD类
-
✅ 完善事务管理机制:确保数据正确提交到数据库
📋 文章目录
-
[🎯 任务明细文件上传功能开发](#🎯 任务明细文件上传功能开发)
-
[🐛 问题排查与修复](#🐛 问题排查与修复)
-
[🔧 代码实现](#🔧 代码实现)
-
[📊 完整流程](#📊 完整流程)
-
[🚀 技术要点](#🚀 技术要点)
-
[📈 待实现功能](#📈 待实现功能)
-
[📝 今日总结](#📝 今日总结)
🎯 任务明细文件上传功能开发
1.1 功能需求
在现有绩效考核指标明细上传功能的基础上,新增任务明细文件上传功能:
-
前端页面新增独立的文件上传按钮
-
后端单独开发解析方法,不影响现有功能
-
数据存入
*_pa_task_assignment_score表 -
关联考核期次和数据时点字段
1.2 实现步骤
步骤1:前端页面修改
在index.vue中新增任务明细上传按钮:
<!-- 绩效明细上传 -->
<el-col :span="12">
<el-form-item label="绩效明细:">
<SingleFileUpload
v-model="formData.file_path"
:file-type="['xlsx', 'xls']"
accept=".xlsx,.xls"
tip="选择Excel文件(《绩效考核指标明细》)"
/>
</el-form-item>
</el-col>
<!-- 任务明细上传(新增) -->
<el-col :span="12">
<el-form-item label="任务明细:">
<SingleFileUpload
v-model="formData.task_file_path"
:file-type="['xlsx', 'xls']"
accept=".xlsx,.xls"
tip="选择Excel文件(《团队任务派单明细》)"
/>
</el-form-item>
</el-col>
步骤2:后端Schema扩展
在schema.py中新增字段:
class *PaExcelUploadRecordCreateSchema(BaseModel):
"""绩效考核期次文件上传记录新增模型"""
assessment_period: str = Field(..., description='考核期次(格式:YYYYMM)')
data_date: date = Field(..., description='数据时点(格式:YYYY-MM-DD)')
file_path: str | None = Field(default=None, description='绩效考核指标明细文件路径')
task_file_path: str | None = Field(default=None, description='团队任务派单明细文件路径') # 新增
task_file_name: str | None = Field(default=None, description='团队任务派单明细文件名称') # 新增
步骤3:创建数据模型
创建*_pa_task_assignment_score/model.py:
# -*- coding: utf-8 -*-
from datetime import date
from sqlalchemy import Date, String, Float
from sqlalchemy.orm import Mapped, mapped_column
from app.core.base_model import ModelMixin, UserMixin
class *PaTaskAssignmentScoreModel(ModelMixin, UserMixin):
"""
团队任务派单得分表
"""
__tablename__: str = 'yurdmc_pa_task_assignment_score'
__table_args__: dict[str, str] = {'comment': '团队任务派单得分'}
__loader_options__: list[str] = ["created_by", "updated_by"]
staff_no: Mapped[str | None] = mapped_column(String(50), nullable=True, comment='员工工号')
...
assessment_period: Mapped[str | None] = mapped_column(String(6), nullable=True, comment='考核期次(格式:YYYYMM)')
data_date: Mapped[date | None] = mapped_column(Date, nullable=True, comment='数据时点(格式:YYYY-MM-DD)')
步骤4:创建CRUD类
创建*_pa_task_assignment_score/crud.py:
# -*- coding: utf-8 -*-
from typing import Sequence
class *PaTaskAssignmentScoreCRUD(CRUDBase[*PaTaskAssignmentScoreModel, *PaTaskAssignmentScoreCreateSchema, *PaTaskAssignmentScoreUpdateSchema]):
"""团队任务派单得分数据层"""
def __init__(self, auth: AuthSchema) -> None:
"""
初始化CRUD数据层
参数:
- auth (AuthSchema): 认证信息模型
"""
super().__init__(model=*PaTaskAssignmentScoreModel, auth=auth)
📊 完整流程
2.1 任务明细文件上传流程图
开始
↓
用户选择任务明细Excel文件
↓
前端上传文件到服务器
↓
后端接收文件并保存路径
↓
调用_parse_task_assignment_file方法
↓
读取Excel文件内容
↓
检查必要列是否存在
↓
动态导入CRUD类
↓
遍历Excel行数据
↓
↓ 构建数据字典
↓ 开启嵌套事务
↓ 调用CRUD.create方法
↓ 提交事务
↓
记录插入和跳过数量
↓
返回解析结果
↓
结束
2.2 数据流转图
┌─────────────────────────────────────────────────────────────┐
│ 前端:文件上传 │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ SingleFileUpload组件 │ │
│ │ - 选择Excel文件 │ │
│ │ - 上传到服务器 │ │
│ │ - 返回文件路径 │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 后端:文件解析 │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ _parse_task_assignment_file方法 │ │
│ │ - pandas读取Excel │ │
│ │ - 检查列名 │ │
│ │ - 构建数据字典 │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 数据库:数据入库 │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ *_pa_task_assignment_score表 │ │
│ │ - staff_no: 员工工号 │ │
│ │ - real_name: 员工姓名 │ │
│ │ - team_name: 归属团队 │ │
│ │ - task_name: 任务名称 │ │
│ │ - task_score: 明细得分 │ │
│ │ - assessment_period: 考核期次 │ │
│ │ - data_date: 数据时点 │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
🚀 技术要点
3.1 CRUD模式最佳实践
# 1. 正确的泛型类型参数
class MyCRUD(CRUDBase[MyModel, MyCreateSchema, MyUpdateSchema]):
# 2. 使用关键字参数初始化
def __init__(self, auth: AuthSchema) -> None:
super().__init__(model=MyModel, auth=auth)
# 3. 正确的导入路径
from app.core.base_crud import CRUDBase
3.2 动态模块导入
import importlib
# 动态导入模块
module_path = "app.plugin.module_gencode.table_name.crud"
module = importlib.import_module(module_path)
# 动态获取类
class_name = "TableNameCRUD"
crud_class = getattr(module, class_name)
# 实例化对象
crud_instance = crud_class(auth)
优势:
-
支持动态加载不同表的CRUD类
-
避免硬编码依赖
-
提高代码的灵活性和可扩展性
3.3 事务管理
# 嵌套事务(推荐)
async with auth.db.begin_nested():
await crud.create(data=data)
# 手动事务管理
try:
async with auth.db.begin():
await crud.create(data=data)
except Exception as e:
await auth.db.rollback()
raise
注意事项:
-
使用
begin_nested()创建嵌套事务 -
事务会在上下文管理器退出时自动提交或回滚
-
避免在循环中频繁创建事务
3.4 Excel解析
import pandas as pd
# 读取Excel文件
df = pd.read_excel(file_path)
# 检查必要列
required_columns = ['列1', '列2', '列3']
missing_columns = [col for col in required_columns if col not in df.columns]
if missing_columns:
raise ValueError(f"缺少必要列: {missing_columns}")
# 遍历行数据
for _, row in df.iterrows():
value = row['列名']
if pd.isna(value):
value = None
📈 待实现功能
4.1 任务明细功能扩展
-
任务明细得分汇总计算
-
任务明细与绩效考核结果关联
-
任务明细数据去重处理
4.2 功能完善
-
数据验证和异常处理
-
单元测试和集成测试
-
用户界面优化
-
导出报表功能
📝 今日总结
5.1 完成功能
-
任务明细文件上传功能完整实现
-
*_pa_task_assignment_score模块创建
-
CRUD类正确实现(泛型类型参数、关键字参数)
-
动态CRUD类加载功能实现
-
Excel解析入库功能实现
-
事务管理机制完善
-
多个技术问题修复
5.2 技术收获
-
掌握CRUD模式的正确实现方式
-
学会使用泛型类型参数
-
理解动态模块导入的原理和应用
-
掌握事务管理的最佳实践
-
提高Excel解析和数据处理能力
-
理解模块化开发的重要性
5.3 踩坑记录
| 问题 | 原因 | 解决方案 |
|---|---|---|
| TypeError: unexpected keyword argument | 参数顺序错误 | 使用关键字参数 |
| 'function' object is not subscriptable | 缺少泛型类型参数 | 添加类型参数 |
| ModuleNotFoundError | 导入路径错误 | 修正导入路径 |
| AttributeError: no attribute 'tablename' | 模型继承错误 | 继承正确的基类 |
| 缺少必要列 | 列名不匹配 | 修正列名 |
5.4 下一步计划
- 实现任务明细得分汇总计算