企业级软件研发团队绩效考核系统开发(持续更新 Day 7)

作者:呱牛

发布日期: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 完成功能

  1. 任务明细文件上传功能完整实现

  2. *_pa_task_assignment_score模块创建

  3. CRUD类正确实现(泛型类型参数、关键字参数)

  4. 动态CRUD类加载功能实现

  5. Excel解析入库功能实现

  6. 事务管理机制完善

  7. 多个技术问题修复

5.2 技术收获

  1. 掌握CRUD模式的正确实现方式

  2. 学会使用泛型类型参数

  3. 理解动态模块导入的原理和应用

  4. 掌握事务管理的最佳实践

  5. 提高Excel解析和数据处理能力

  6. 理解模块化开发的重要性

5.3 踩坑记录

问题 原因 解决方案
TypeError: unexpected keyword argument 参数顺序错误 使用关键字参数
'function' object is not subscriptable 缺少泛型类型参数 添加类型参数
ModuleNotFoundError 导入路径错误 修正导入路径
AttributeError: no attribute 'tablename' 模型继承错误 继承正确的基类
缺少必要列 列名不匹配 修正列名

5.4 下一步计划

  1. 实现任务明细得分汇总计算
相关推荐
用户8356290780511 天前
Python 操作 PDF 附件:添加、查看与管理指南
后端·python
宇宙之一粟1 天前
乐企版式文件生成平台
java·后端·python
学测绘的小杨2 天前
CompassFusion:一个从 GNSS 到 GNSS/INS 组合导航的独立工程包
python
zzzzzz3102 天前
当产品经理说这个很简单:我用Python自动化处理奇葩需求的实战指南
python·pycharm·产品经理
雪隐2 天前
个人电脑玩AI-06让5060 Ti给你打工——不光能画画,Qwen3-TTS还能学人说话,连我老板都信了!
人工智能·后端·python
兵慌码乱3 天前
面向桌面端的资产管理系统分层架构设计与核心模块实现
python·系统架构·sqlite·pyqt5·数据库设计·桌面应用开发·mvc架构
hboot3 天前
AI工程师第三课 - 机器学习基础
python·scikit-learn·kaggle
顾林海3 天前
Agent入门阶段-编程基础-Python:流程控制
python·agent·ai编程
呱呱复呱呱3 天前
Django CBV 源码解读:一个请求是怎么找到你的 get() 方法的
python·django
曲幽3 天前
刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API
python·fastapi·web·translate·goldendict·libretranslate·stardict·pystardict