企业级软件研发团队绩效考核系统开发(持续更新 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. 实现任务明细得分汇总计算
相关推荐
maqr_11013 分钟前
HTML怎么生成订单预览_HTML只读订单信息结构【操作】
jvm·数据库·python
sg_knight31 分钟前
设计模式实战:责任链模式(Chain of Responsibility)
python·设计模式·责任链模式
2301_8038756138 分钟前
如何通过phpMyAdmin给WordPress所有用户发送全站通知_系统表插入
jvm·数据库·python
学弟1 小时前
【内涵】深度学习中的三种变量及pytorch中对应的三种tensor
人工智能·pytorch·python
2301_777599371 小时前
mysql如何进行数据库容量规划_评估磁盘空间增长趋势
jvm·数据库·python
aq55356001 小时前
PHP vs Python:30秒看懂核心区别
开发语言·python·php
m0_377618232 小时前
Redis怎样应对大规模集群的重启风暴_分批次重启节点并等待集群状态恢复绿灯后再继续操作
jvm·数据库·python
心态与习惯2 小时前
Julia 初探,及与 C++,Java,Python 的比较
java·c++·python·julia·比较
ZC跨境爬虫2 小时前
3D 地球卫星轨道可视化平台开发 Day8(分步渲染200颗卫星+ 前端分页控制)
前端·python·3d·重构·html
zopple3 小时前
ThinkPHP5.x与3.x核心差异解析
java·python·php