简介:一份面向数据库课程设计的员工信息管理系统源码包,基于Python与MySQL实现,适合高校学生在课程设计、毕业设计或项目练手中参考。资源覆盖员工与部门数据的增删改查、SQL查询、事务处理等典型功能,可帮助理解Python后端与关系型数据库的交互方式。压缩包共9个文件,约6.71MB,包含2个Python脚本、2份Word课程设计报告、4张设计文档图片及1个README说明,兼顾代码实现与文档撰写参考。其中两个Python脚本分别处理员工信息与账号管理,配合员工表、部门表的建表逻辑,以及E-R图、数据流图,完整呈现从数据库设计到Python操作MySQL的实现路径;报告还包含功能模块说明,便于二次开发与答辩讲解。目前已有4343人学习下载,适合需要快速搭建同类管理系统或补充数据库课程设计文档的同学。
1. 为什么是员工信息管理系统:一套不改也能答辩、改了也能上线的 Python + MySQL 课设
A同学把课程设计题目从“图书管理系统”换成“员工信息管理系统”,理由是图书管理网上模板太多,答辩时老师一眼能认出来;员工管理字段更贴近真实企业组织,能自然拆出部门、员工、薪资三张主表,外键关系、聚合查询、统计报表这些课程硬指标全都能覆盖。这套源码基于 Python 3.8 与 MySQL 8.0,GUI 用 Python 自带标准库 tkinter,不依赖第三方界面框架,数据库访问只用一个 PyMySQL,环境安装成本极低。适合正在做数据库课设的学生、想快速搭一套增删改查后台的新手、准备把课设改成简历项目的开发者——它能直接跑,也能二次开发,关键的技术细节都有源码可查。
2. 系统设计与数据库建模:从目录结构到四张表的关系设计
员工信息管理系统这种课设题目,难点不在“能跑”,而在“表设计得是否合理”。很多同学拿到的参考代码只有两个文件,一个拼 SQL,一个画界面,表关系基本靠感觉。这套源码不是这样,它把代码按模块切分,数据库部分单独拿出来建表,连接层、业务层、界面层各管各的。这一章先把整体设计讲清楚,后面看代码才不会迷路。
2.1 技术栈:为什么是 Python + MySQL + tkinter
这个组合几乎是数据库课程设计的最优解。第一,Python 3 是很多高校数据库课程的教学语言,学生至少能读懂语法;第二,MySQL 是课设题目里出现频率最高的数据库,老师也最熟悉,用 PostgreSQL 或 SQLite 会多出不必要的解释成本;第三,tkinter 是 Python 自带的标准 GUI 库,Linux、Windows、macOS 都能跑,不需要额外安装 PyQt5 或 wxPython,机房环境也友好。
为什么不选 Flask 或 Django 写成 Web 版?课设要求通常是“基于 Python 和 MySQL 实现一个系统”,Web 框架会自动帮你处理数据库连接、请求分发、表单验证,看着高级,但答辩时老师问“查询条件是怎么拼进 SQL 的”这类问题时,框架把细节全包装掉了,容易露怯。tkinter 这种桌面形态反而要求你手动处理按钮事件、表格绑定、SQL 执行,知识点全暴露在外面,适合现场答辩演示。
数据库驱动我选了 PyMySQL 而不是 mysql-connector-python。两者在课设量级下性能差异不大,但 PyMySQL 的 API 和教材里常见的 MySQLdb 几乎一致,纯 Python 实现,pip 安装不需要本机编译环境。机房的机器经常缺编译器,装上 C 库版本容易翻车,PyMySQL 基本开箱即用。
| 组件 | 选型 | 说明 |
|---|---|---|
| 语言 | Python 3.8+ | 课程教学常用,语法门槛低 |
| 数据库 | MySQL 8.0 | 课设高频要求,支持外键与生成列 |
| GUI | tkinter | 标准库自带,免安装部署 |
| 数据库驱动 | PyMySQL 1.x | 纯 Python 实现,pip 安装即用 |
| 图表 | matplotlib | 统计报表模块的可视化依赖 |
2.2 项目目录:每个文件负责什么
拿到源码先别急着跑,把目录结构过一遍。这套代码刻意按“配置—工具—界面—业务”四层拆,不是一上来就堆一个千行 main.py。
employee_management/ ├── main.py # 程序入口:启动登录窗口,串起所有界面 ├── config.py # 数据库连接配置,改密码、改库名都在这 ├── db.py # 连接层:执行 SQL、返回结果,所有模块共用 ├── login.py # 登录界面与鉴权逻辑 ├── dashboard.py # 主窗口:菜单栏、左侧导航、内容区容器 ├── employee_mgr.py # 员工管理:增删改查、按条件查询 ├── dept_mgr.py # 部门管理:部门维护与列表展示 ├── salary_mgr.py # 薪资管理:月度薪资录入 ├── report.py # 统计报表:人数统计、薪资汇总、图表绘制 ├── utils.py # 公共函数:日期校验、非空校验、ID 转换 ├── sql/ │ ├── init_db.sql # 建库建表脚本,定义全部外键约束 │ └── seed_data.sql # 测试数据:部门、员工、工资、账号 └── requirements.txt # 依赖清单:pymysql、matplotlib按这个顺序读代码最顺:先读 config.py 知道连哪个库,再读 db.py 看所有 SQL 怎么执行和提交,然后看 login.py 怎么进主界面,最后才是 employee_mgr.py 里的具体业务。四个文件之间依赖是单向的,界面层调用业务层,业务层调 db.py,db.py 只认 config.py,改一层不会牵动其他层。
这套分层在课设里看起来有点“过度设计”,但答辩加分点也在这:老师问“以后要换数据库怎么办”,你可以直接答,db.py 里把 PyMySQL 换成 psycopg2,调整一下占位符格式,业务和界面代码完全不用动。这就是分层的实际价值。
2.3 数据库设计:四张表承载全部业务
数据库是这门课的核心,表设计必须能讲出理由。init_db.sql 建了部门、员工、薪资、用户四张表,外键约束和唯一键都写在脚本里,覆盖了课设里“外键约束”“完整性约束”的考核点。
-- init_db.sql 核心建表部分 CREATE DATABASE IF NOT EXISTS employee_db DEFAULT CHARSET utf8mb4; USE employee_db; -- 部门表:被员工表引用,作为父表 CREATE TABLE t_dept ( dept_id INT AUTO_INCREMENT PRIMARY KEY, dept_name VARCHAR(50) NOT NULL UNIQUE, manager VARCHAR(20) DEFAULT NULL, phone VARCHAR(20) DEFAULT NULL ); -- 员工表:核心业务表,外键指向部门表 CREATE TABLE t_emp ( emp_id INT AUTO_INCREMENT PRIMARY KEY, emp_no VARCHAR(20) NOT NULL UNIQUE, name VARCHAR(50) NOT NULL, gender CHAR(2) DEFAULT '男', dept_id INT NOT NULL, position VARCHAR(50) DEFAULT NULL, hire_date DATE DEFAULT NULL, status TINYINT DEFAULT 1 COMMENT '1在职 0离职', CONSTRAINT fk_emp_dept FOREIGN KEY (dept_id) REFERENCES t_dept(dept_id) ); -- 薪资表:按月记录员工工资,外键指向员工表 CREATE TABLE t_salary ( salary_id INT AUTO_INCREMENT PRIMARY KEY, emp_id INT NOT NULL, month VARCHAR(7) NOT NULL COMMENT '格式:2024-06', base_salary DECIMAL(10,2) NOT NULL, bonus DECIMAL(10,2) DEFAULT 0.00, deduction DECIMAL(10,2) DEFAULT 0.00, total DECIMAL(10,2) GENERATED ALWAYS AS (base_salary + bonus - deduction) STORED, CONSTRAINT fk_salary_emp FOREIGN KEY (emp_id) REFERENCES t_emp(emp_id), UNIQUE KEY uk_emp_month (emp_id, month) ); -- 用户表:登录鉴权,密码建议后续改成哈希存储 CREATE TABLE t_user ( user_id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(30) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, role VARCHAR(10) DEFAULT 'admin' );建表时有几个设计点可以写进答辩文档。第一,部门和员工是一对多关系,外键加在 t_emp 的 dept_id 上,这是最标准的画法;第二,t_salary 的 total 字段用 MySQL 5.7 以上的生成列语法,由 base_salary + bonus - deduction 自动算出,避免应用层手工计算造成的累计误差,算一个技术加分项;第三,uk_emp_month 唯一键保证同一个月同一个员工只能有一条薪资记录,防止重复录入。
员工、部门、薪资三张表的字段长度都刻意贴近真实业务。比如 emp_no 设计成 VARCHAR(20) 而不是 INT,因为企业工号常带部门前缀,像“D05-1008”,用整型会丢失这种信息。后面做“批量导入员工”功能时,emp_no 的唯一键还能用来去重。这就是为什么课设要把表结构先想清楚再写代码。
3. 核心模块拆解:登录、增删改查、统计报表的完整链路
这一章选四条最重要的代码链路逐步拆:连接层是所有模块的地基,登录是系统的入口,员工增删改查是核心操作,统计报表是数据库聚合能力的展示。每条链路都按“代码 → 逐段说明 → 参数解释”来读。
3.1 数据库连接层:get_connection 与游标模式
先看 config.py,这是整个系统唯一需要你根据本机环境改的地方:
# config.py - 数据库连接配置 DB_CONFIG = { "host": "localhost", "port": 3306, "user": "root", "password": "123456", "database": "employee_db", "charset": "utf8mb4" }再来看 db.py,所有模块的 SQL 都走这里执行:
# db.py - 数据库连接工具 import pymysql from config import DB_CONFIG def get_connection(): conn = pymysql.connect( host=DB_CONFIG["host"], port=DB_CONFIG["port"], user=DB_CONFIG["user"], password=DB_CONFIG["password"], database=DB_CONFIG["database"], charset=DB_CONFIG["charset"], cursorclass=pymysql.cursors.DictCursor ) return conn def execute_query(sql, args=None): """执行查询,返回字典列表""" conn = get_connection() try: with conn.cursor() as cursor: cursor.execute(sql, args) result = cursor.fetchall() return result finally: conn.close() def execute_update(sql, args=None): """执行增删改,返回受影响行数""" conn = get_connection() try: with conn.cursor() as cursor: rows = cursor.execute(sql, args) conn.commit() return rows except Exception: conn.rollback() raise finally: conn.close()这里几个参数值得说清楚。cursorclass 指定为 DictCursor,查询结果会变成 [{"emp_id": 1, "name": "张三"}] 这种字典结构,界面代码直接用 row["name"] 取值,比元组下标好读得多,这是课设里很实用的小技巧。charset 必须是 utf8mb4,它和建库用的字符集保持一致,缺了它中文大概率乱码。
execute_query 和 execute_update 分开是有原因的。查询只读,用 with 管理游标,最后关闭连接即可;增删改要写库,execute 之后必须 commit 才真正落盘,发生异常时 rollback 保证一致性。每次调用都现建连接、用完关闭,避免多窗口并发时共用一个连接出现事务冲突。课设并发量小,这种短连接模式够用且逻辑简单,比维护连接池更好向老师解释。
3.2 登录鉴权:参数化查询与角色校验
登录模块在 login.py,核心函数只有十几行:
# login.py - 登录鉴权核心逻辑 import tkinter as tk from tkinter import messagebox from db import execute_query def check_login(username, password): sql = "SELECT user_id, username, role FROM t_user WHERE username=%s AND password=%s" result = execute_query(sql, (username, password)) return result[0] if result else None def on_login_click(): username = entry_username.get() password = entry_password.get() if not username or not password: messagebox.showwarning("提示", "用户名和密码不能为空") return user = check_login(username, password) if user: # 打开主窗口,并传入当前登录用户角色 open_dashboard(user) else: messagebox.showerror("错误", "用户名或密码不正确")关键在 SQL 写法:WHERE username=%s AND password=%s,参数通过 execute_query 的 args 传入,而不是把用户输入直接拼进 SQL 字符串。这种参数化查询语法是 PyMySQL 的标准占位符写法,能避免经典的 SQL 注入问题,比如输入 ' OR '1'='1 蹭进登录逻辑。参数本身由驱动做转义,这是课设答辩时一定会被问到的安全点。
check_login 返回的是一个字典,拿 role 字段可以做角色控制。比如管理员进主界面能看到“部门管理”和“薪资录入”菜单,普通操作员只看到“员工查询”。界面按钮的启用状态在 open_dashboard 里根据 user["role"] 判断,登录函数本身只负责验身份,职责单一。
3.3 员工模块:增删改查与动态条件查询
employee_mgr.py 是业务量最大的模块,先看增删改四个方法:
# employee_mgr.py - 员工增删改查 from db import execute_update, execute_query def add_employee(emp_no, name, gender, dept_id, position): sql = "INSERT INTO t_emp (emp_no, name, gender, dept_id, position) VALUES (%s, %s, %s, %s, %s)" return execute_update(sql, (emp_no, name, gender, dept_id, position)) def update_employee(emp_id, position, dept_id): sql = "UPDATE t_emp SET position=%s, dept_id=%s WHERE emp_id=%s" return execute_update(sql, (position, dept_id, emp_id)) def delete_employee(emp_id): sql = "DELETE FROM t_emp WHERE emp_id=%s" return execute_update(sql, (emp_id,)) def query_employees(keyword=None, dept_id=None): sql = "SELECT e.*, d.dept_name FROM t_emp e LEFT JOIN t_dept d ON e.dept_id = d.dept_id WHERE 1=1" args = [] if keyword: sql += " AND (e.name LIKE %s OR e.emp_no LIKE %s)" args.extend([f"%{keyword}%", f"%{keyword}%"]) if dept_id: sql += " AND e.dept_id = %s" args.append(dept_id) sql += " ORDER BY e.emp_id" return execute_query(sql, tuple(args) if args else None)增删改三个方法都返回受影响行数,界面层拿返回值判断要不要弹“操作成功”。add_employee 的参数顺序和 INSERT 语句的列顺序一一对应,界面按钮收集输入后再封装成元组传进来,业务函数不关心输入从哪来,方便以后接 Excel 批量导入或 Web 接口。
query_employees 用了动态拼接,这是课设里“按条件查询”的标准写法。初始条件是 WHERE 1=1,后面按需追加 AND 条件,args 列表同步收集参数。LIKE 的模糊匹配要自己拼 %keyword%,注意通配符是放在参数里的,不是拼进 SQL 模板,仍然走参数化,不会引入注入风险。LEFT JOIN 保证即使部门被误删或员工未分配部门,员工记录仍能查到,只是 dept_name 显示为 NULL。
3.4 统计报表:JOIN + GROUP BY 计算部门薪资
report.py 里的统计函数是数据库课程里聚合查询的集中展示:
# report.py - 统计报表核心查询 from db import execute_query def count_by_dept(): sql = """ SELECT d.dept_name, COUNT(e.emp_id) AS emp_count FROM t_dept d LEFT JOIN t_emp e ON d.dept_id = e.dept_id GROUP BY d.dept_id, d.dept_name ORDER BY emp_count DESC """ return execute_query(sql) def sum_salary_by_month(month): sql = """ SELECT d.dept_name, COUNT(e.emp_id) AS emp_count, SUM(s.total) AS total_salary FROM t_salary s JOIN t_emp e ON s.emp_id = e.emp_id JOIN t_dept d ON e.dept_id = d.dept_id WHERE s.month = %s GROUP BY d.dept_id, d.dept_name ORDER BY total_salary DESC """ return execute_query(sql, (month,))count_by_dept 用 LEFT JOIN 是从部门出发统计每个部门的人数,重点是保留人数为零的部门。如果换成 INNER JOIN,新建立的空部门在统计图里直接消失,答辩时老师往部门表插一条“新业务部”,再点统计按钮,图里没这个部门,这就是逻辑缺陷。GROUP BY 后面同时写了 d.dept_id 和 d.dept_name,这是 MySQL 的一个常见坑:只按 dept_id 分组也行,但 select 里出现 dept_name 时,ONLY_FULL_GROUP_BY 模式下会直接报错,所以把两个字段一并分组。
sum_salary_by_month 带月份参数,输入格式是“2024-06”这种字符串,正好对应 t_salary.month 的 VARCHAR(7)。统计结果是每个部门的薪资总和,界面层会把结果塞给 matplotlib 画柱状图。这里再提醒一句:图表显示中文乱码时,去 matplotlib 配置里设置中文字体,推荐用 SimHei 或 Microsoft YaHei,后面避坑章节还会细说。
4. 项目部署与运行:从空环境到跑通全流程
这套源码的部署过程很简单,但顺序不能乱。很多同学卡在“代码没问题,就是连不上数据库”这类问题上,其实都是环境准备漏了某一步。这一章按实际执行顺序走一遍。
4.1 环境准备:Python 依赖与 MySQL 服务
先确认本机有 Python 3.8 以上版本和 MySQL 5.7 以上版本。在命令行分别执行:
python --version mysql --version版本没问题后,进入项目根目录,安装依赖:
pip install -r requirements.txtrequirements.txt 内容只有两行:
pymysql==1.0.2 matplotlib==3.5.3PyMySQL 是数据库驱动,matplotlib 只在统计报表模块绘图时用到。如果你不打算用图表,可以把 matplotlib 那一行去掉,系统其余功能不受影响。pip 命令会从镜像站下载纯 Python 包,不需要编译,基本几分钟内装完。
4.2 建库建表:两个 SQL 脚本的执行顺序
建库脚本要按顺序导入,先建表再填数据。打开命令行,进入项目 sql 目录,执行:
mysql -u root -p < init_db.sql mysql -u root -p < seed_data.sql第一个脚本创建 employee_db 库和四张表,第二个脚本插入测试数据。注意顺序不能反,seed_data.sql 里插入的部门数据依赖 t_dept 表已经存在,员工数据又依赖部门有 dept_id 可引用,反了会报外键错误。
导入完成后验证一下:
mysql -u root -p -e "USE employee_db; SHOW TABLES; SELECT COUNT(*) FROM t_emp;"正常会看到五张表:t_dept、t_emp、t_salary、t_user,外加系统自带的表结构信息。t_emp 表里应该有 seed 脚本写入的十几条测试员工记录。如果 SHOW TABLES 输出为空,多半是 mysql 命令没连上目标实例,检查 root 密码是否正确。
4.3 启动验证:登录默认账号与操作顺序
环境就绪后,在项目根目录运行:
python main.py看到登录窗口就说明 GUI 启动成功了。默认账号 admin,默认密码 admin123,这两个值写在 seed_data.sql 里,正式使用前记得改。登录后建议按“先加部门 → 再加员工 → 再录薪资”的顺序操作,因为员工表的 dept_id 必须引用已有部门,薪资表的 emp_id 必须引用已有员工,界面操作顺序也遵循这个依赖关系。
验证功能的快捷路径是:先在部门管理里新增一个“研发部”,再去员工管理里添加一名姓名为“测试员”的员工,部门选研发部,最后在薪资管理里给该员工录一笔 2025-01 的工资。回到统计报表点刷新,柱状图应能看到研发部的数据和薪资总额。这一套走通,系统核心功能就都验证过了。
4.4 配置文件修改与故障排查
唯一需要改的配置文件就是 config.py。本机 MySQL 密码如果不是 123456,把 DB_CONFIG["password"] 改成你自己的;连的不是 localhost,改 host;想换库名,改 database,但要让 init_db.sql 里的 CREATE DATABASE 也改成同名。
连不上数据库时按这个顺序查:第一,MySQL 服务是否启动,Windows 下看服务列表,Linux 下执行 systemctl status mysql;第二,端口对不对,默认 3306,被占用时可以换 3307;第三,账号权限,root 默认只允许 localhost 登录,如果你的 Python 跑了 docker 容器要用 127.0.0.1 连接,就要确认用户表里 localhost 的授权还在;第四,端口和密码都确认后仍然报错,检查有没有装 mysql-connector-python 和 pymysql 混用,两个驱动的报错格式不一样,容易误判。
注意:改完 config.py 后必须重启 python main.py,重新打开主程序才能加载新配置。如果改了密码没重启,界面看着没报错,但第一次点击“查询”时就会弹连接异常,这属于典型的“改配置不重启”踩坑。
5. 课程设计避坑指南:五条实操踩坑记录
课设提交前后最容易翻车的问题,我按真实排错顺序整理了五条,每一条都是“现象 → 原因 → 解决”的结构。知道怎么改,更要知道为什么。
5.1 中文乱码:连接字符集和表字符集两处都要管
现象:界面和数据库里中文显示正常,但从程序插入的中文在表里变成问号,或者报错 Incorrect string value '\xE5\xBC...'。
原因:建库时指定了 utf8mb4,但 PyMySQL 连接参数里的 charset 没设置,或者反过来建库用了默认 latin1,连接却用了 utf8mb4。字符集不一致时,MySQL 按连接字符集解释传入字符串,存不进目标列就直接丢字节。
解决:建库脚本写 DEFAULT CHARSET utf8mb4,config.py 的 DB_CONFIG 里同时写 "charset": "utf8mb4",两边对齐。如果表已经建错了,ALTER TABLE t_emp CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci 可以补救。从那以后我拿到任何 Python + MySQL 项目,第一件事就是检查这两处的字符集是否一致。
5.2 删除部门报外键错误:子表还有引用
现象:在部门管理里删除一个部门,弹窗报 “Cannot delete or update a parent row: a foreign key constraint fails”。
原因:t_emp 里还有员工的 dept_id 指向这个部门。外键约束保护了数据完整性,但不先处理子表记录,父表就删不掉。
解决:业务上先把这个部门的员工调整到其他部门,或者先删员工再删部门。界面层可以在删除前查一下 count_by_dept 里这个部门的人数,不为零就提示“该部门仍有员工,不能删除”。这是课设里展示你对数据完整性理解的好机会,同时也避免答辩现场手忙脚乱。
5.3 Decimal 变成字符串:tkinter 表格显示不对
现象:薪资表查出来的 total 字段,print 显示 Decimal('8500.00'),塞进 tkinter Treeview 后变成奇怪的对象字符串,或者排序错乱。
原因:PyMySQL 对 DECIMAL 字段默认返回 Python 的 Decimal 对象,不是 float 也不是 str。Treeview 对非字符串类型支持不友好。
解决:在界面层统一格式化,取值后做 str(row["total"]),或格式化成两位小数。顺手写个 utils.py 的 fmt_money 函数,把 str(Decimal) 转成 8,500.00 这种显示格式,这个函数在薪资列表和报表里复用,比每次手写强。
5.4 窗口卡死:耗时查询堵住 UI 主线程
现象:点击“统计报表”后,整个窗口变成空白,鼠标转圈,几秒钟后才恢复,期间拖动窗口没反应。
原因:报表查询和 matplotlib 绘图都在 tkinter 主线程里同步执行,数据库慢或数据量大时,事件循环被阻塞,窗口来不及刷新。
解决:课程设计量级下,最省事的方案是让统计查询和绘图放进子线程,查询完成后通过根窗口的 after() 方法把结果回填到界面。如果不想引入线程复杂度,至少保证报表查询的 SQL 走了索引,month、dept_id 这类查询字段都建了索引,一般表数据量几百行以内卡顿不明显。但答辩前建议还是处理一下,否则演示时窗口卡死会被批“稳定性不行”。
5.5 SQL 注入不是说着玩的:字符串拼接必翻车
现象:在登录框输入 ' OR '1'='1 -- ,居然能绕过密码直接进主窗口。
原因:早期版本登录 SQL 是这么写的:sql = "SELECT * FROM t_user WHERE username='" + username + "' AND password='" + password + "'"。这个拼接把输入当成了 SQL 代码,条件被注释符绕过。
解决:所有 SQL 统一走参数化查询,execute_query(sql, (username, password))。前端输入永远只作为参数传递,不让它进入 SQL 语句文本。这条不是加分项,是必须项。课设评审老师极可能在答辩时往你的登录框里输一个单引号,看看系统会不会崩。从那以后,我每写完一条 SQL 都会代码走查一遍:有没有出现 f-string 拼 SQL、有没有直接把变量塞进 sql 文本。
6. 二次开发方向:把课设改造成简历级项目
课设交完不是终点,很多同学会把它写进简历。这套系统的底子不错,但直接写上去有点单薄,我建议按下面这个顺序改三轮。
6.1 第一轮:补安全和基本功
密码不能明文存。在 t_user 表里加 salt 字段,注册时用 hashlib 做 sha256(salt + password),登录时比对哈希值。这部分代码改动小,但面试聊到安全问题时能拿出来说。接着给 t_salary 表加 create_time、update_time 两个时间字段,用 datetime.now() 写入,体现审计意识。界面层把 messagebox 的提示统一改成日志文件输出,记录谁在什么时间删了哪个员工,这是“操作日志”的最小实现。
6.2 第二轮:加导出和分页
用 openpyxl 给员工列表加“导出 Excel”按钮,把 Treeview 当前页数据写入 xlsx 文件。这是工作中最常用的需求,比在简历里写“熟悉增删改查”有说服力得多。同时把 query_employees 改成 LIMIT %s OFFSET %s 分页查询,界面做上一页/下一页按钮。分页涉及 SQL 和界面状态同步,改造量适中,值得做。
6.3 第三轮:Web 化与 ORM 化
如果时间允许,用 Flask 把 tkinter 界面换成 Web 页面,保留 db.py 的逻辑,只需新增路由和 Jinja2 模板。更进一步,把 db.py 里的原生 SQL 替换成 SQLAlchemy ORM,模型定义和 t_dept、t_emp 的表结构一一对应。这样一轮一轮改下来,项目从“课设”变成“带安全、带导出、带分页、前后端分离雏形”的完整作品,面试时可聊的深度就完全不一样了。
我每次接到这类改造需求,都会强制自己先写一份“改动清单”,把每条改动对应到具体文件和具体函数,改完一个功能立刻回归验证一次增删改查和统计报表,确认没有把原系统改崩。这次拆这套员工信息管理系统,我也是先读 init_db.sql 再读 db.py,把表间依赖画清楚才开始动代码。希望这套思路和源码能帮到正在为课设发愁的你。
本文还有配套的精品资源,点击获取