企业级软件研发团队绩效考核系统开发(持续更新 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. 实现任务明细得分汇总计算
相关推荐
钰衡大师2 小时前
邮件头信息修改工具开发技术文档
开发语言·python
源码之家2 小时前
计算机毕业设计:Python二手车交易价格预测分析平台 Django框架 随机森林 可视化 数据分析 汽车 车辆 大数据 hadoop(建议收藏)✅
大数据·爬虫·python·机器学习·django·汽车·课程设计
清水白石0082 小时前
Python 性能优化避坑指南:回归风险防控、基准压测与安全回滚实战
python·性能优化·回归
好家伙VCC2 小时前
# 发散创新:基于状态通道的以太坊智能合约高效交互实践在区块链应用开发中,**交易
java·python·区块链·智能合约
gc_22992 小时前
学习python使用Ultralytics的YOLO26进行分类的基本用法
python·分类·ultralytics·yolo26
书到用时方恨少!2 小时前
Python 零基础入门系列(终篇):综合实战项目
开发语言·python
小陈工2 小时前
Python Web开发入门(二):Flask vs Django,项目结构大比拼
前端·数据库·python·安全·web安全·django·flask
杜子不疼.2 小时前
2026 GitHub 热门 Python 项目:AI 代理与数据工具精选
人工智能·python·github
迷藏4942 小时前
# 发散创新:用Rust构建高性能分布式账本节点——从零实现共识算法与链上数据存储
java·python·rust·共识算法·分布式账本