企业级软件研发团队绩效考核系统开发(持续更新 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. 实现任务明细得分汇总计算
相关推荐
天才测试猿8 小时前
2026软件测试面试八股文(含答案+文档)
自动化测试·软件测试·python·功能测试·测试工具·面试·职场和发展
张小凡vip9 小时前
python--爬虫--成熟的爬虫框架Scrapy
爬虫·python·scrapy
Pluchon9 小时前
Java个人综合项目——萌部落社区V2.0
java·python·spring·spring cloud·postman·idea
不瘦80斤不改名10 小时前
01-vibe-coding-起源与本质
人工智能·python
夜雪一千10 小时前
如何对新闻数据进行模糊去重
python
oyguyteggytrrwwwrt12 小时前
3dgs渲染部分详细注释
python
天天爱吃肉821814 小时前
【重磅发布:拿下新超仁达代理权 】
大数据·人工智能·python·功能测试·汽车
神王宝宝 王者小学14 小时前
面向领域驱动架构的查询实现方式
前端·python·架构
ningmengjing_15 小时前
Redis 从入门到实战:Python操作全攻略
数据库·redis·python
️学习的小王15 小时前
智能文档助手:基于RAG的本地化文档问答系统实战指南
人工智能·python·机器学习