企业级软件研发团队绩效考核系统开发(持续更新 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. 实现任务明细得分汇总计算
相关推荐
全栈陈序员4 小时前
【Python】基础语法入门(二十九)—— 正则表达式实战:文本处理利器
开发语言·人工智能·python·正则表达式
得物技术4 小时前
Jev 实战:为AI工作流引入轻量决策层 x10倍提速|得物技术
python·llm·测试
reasonsummer4 小时前
【教学类-07-12】20261028大3班破译电话号码html(手机按钮版本)
python·html
摇滚侠4 小时前
《On Java 中文版 基础卷》阅读笔记 复用 13
java·笔记·python
用户298698530145 小时前
Python 将 Word 文档转换为 XML 的实践要点
后端·python·api
薛之谦_5 小时前
用 Java 实现阿里云式 IAM 子用户管理:架构设计与表结构详解
java·python·阿里云
2601_952047795 小时前
金蝶云星空销售订单附件查询接口权威教程(BOS_Attachment)
python·机器人·钉钉
神仙别闹5 小时前
基于Python Yolo实现绝缘子目标检测程序
python·yolo·目标检测
超级架构师5 小时前
让 COBOL 长出 AI 大脑:原生 Agent 核心框架 praxo-core 深度剖析
c语言·开发语言·c++·人工智能·python·架构·ai编程
甜到心里的蛋糕5 小时前
抖音评论自动回复机器人部署实践:无头 Chrome + DeepSeek + NapCat(2C2G 云主机)
java·jvm·chrome·python·抖音·deepseek