当前位置: 首页 > news >正文

员工管理系统 (Python实现)

1.系统概述

          本研究开发了一套基于Python编程语言构建的控制台员工管理系统。该系统遵循面向对象编程(Object-Oriented Programming, OOP)的设计原则,实现了员工信息的全面管理功能。具体而言,系统支持员工信息的增删改查等操作。同时,该系统具备数据持久化能力,能够将员工信息长期存储于本地文件或数据库中,从而保障数据的安全性与稳定性,便于用户随时进行信息调用和管理。通过该系统,企业能够有效地实现员工信息的集中化管理与维护,进而提高人力资源管理的效率。

2.功能特点

1.员工信息管理(添加、删除、修改、查询)

2.多种查询方式(按ID、按姓名、按部门)

3.数据持久化(使用JSON文件存储)

4.简单的用户界面

import json
import osclass Employee:"""员工类"""def __init__(self, emp_id, name, department, position, salary):self.emp_id = emp_idself.name = nameself.department = departmentself.position = positionself.salary = salarydef __str__(self):return f"ID: {self.emp_id}, 姓名: {self.name}, 部门: {self.department}, 职位: {self.position}, 薪资: {self.salary}"class EmployeeManagementSystem:"""员工管理系统"""def __init__(self, data_file='employees.json'):self.data_file = data_fileself.employees = []self.load_data()def load_data(self):"""加载员工数据"""if os.path.exists(self.data_file):with open(self.data_file, 'r', encoding='utf-8') as f:data = json.load(f)self.employees = [Employee(**emp) for emp in data]def save_data(self):"""保存员工数据"""with open(self.data_file, 'w', encoding='utf-8') as f:json.dump([emp.__dict__ for emp in self.employees], f, ensure_ascii=False, indent=2)def add_employee(self):"""添加员工"""print("\n--- 添加员工 ---")emp_id = input("请输入员工ID: ")# 检查ID是否已存在if any(emp.emp_id == emp_id for emp in self.employees):print("错误: 该ID已存在!")returnname = input("请输入姓名: ")department = input("请输入部门: ")position = input("请输入职位: ")salary = input("请输入薪资: ")try:salary = float(salary)except ValueError:print("错误: 薪资必须是数字!")returnnew_emp = Employee(emp_id, name, department, position, salary)self.employees.append(new_emp)self.save_data()print(f"员工 {name} 添加成功!")def delete_employee(self):"""删除员工"""print("\n--- 删除员工 ---")emp_id = input("请输入要删除的员工ID: ")for i, emp in enumerate(self.employees):if emp.emp_id == emp_id:self.employees.pop(i)self.save_data()print(f"员工 {emp.name} 已删除!")returnprint("错误: 未找到该员工!")def update_employee(self):"""修改员工信息"""print("\n--- 修改员工信息 ---")emp_id = input("请输入要修改的员工ID: ")for emp in self.employees:if emp.emp_id == emp_id:print("当前信息:")print(emp)name = input(f"请输入新姓名 ({emp.name}): ") or emp.namedepartment = input(f"请输入新部门 ({emp.department}): ") or emp.departmentposition = input(f"请输入新职位 ({emp.position}): ") or emp.positionsalary = input(f"请输入新薪资 ({emp.salary}): ") or emp.salarytry:salary = float(salary)except ValueError:print("错误: 薪资必须是数字!")returnemp.name = nameemp.department = departmentemp.position = positionemp.salary = salaryself.save_data()print("员工信息更新成功!")returnprint("错误: 未找到该员工!")def query_employee(self):"""查询员工信息"""print("\n--- 查询员工 ---")print("1. 按ID查询")print("2. 按姓名查询")print("3. 按部门查询")print("4. 显示所有员工")choice = input("请选择查询方式: ")if choice == '1':emp_id = input("请输入员工ID: ")found = [emp for emp in self.employees if emp.emp_id == emp_id]elif choice == '2':name = input("请输入员工姓名: ")found = [emp for emp in self.employees if name.lower() in emp.name.lower()]elif choice == '3':department = input("请输入部门名称: ")found = [emp for emp in self.employees if department.lower() in emp.department.lower()]elif choice == '4':found = self.employeeselse:print("无效选择!")returnif not found:print("未找到匹配的员工!")else:print("\n查询结果:")for emp in found:print(emp)def show_menu(self):"""显示菜单"""while True:print("\n=== 员工管理系统 ===")print("1. 添加员工")print("2. 删除员工")print("3. 修改员工信息")print("4. 查询员工信息")print("5. 退出系统")choice = input("请选择操作: ")if choice == '1':self.add_employee()elif choice == '2':self.delete_employee()elif choice == '3':self.update_employee()elif choice == '4':self.query_employee()elif choice == '5':print("感谢使用员工管理系统!")breakelse:print("无效选择,请重新输入!")# 启动系统
if __name__ == "__main__":system = EmployeeManagementSystem()system.show_menu()

3.使用说明

1.将代码保存为employee_management.py

2.运行程序: python employee_management.py

3.按照菜单提示进行操作

 4.扩展建议

1.员工考勤管理功能扩展代码

    下面是为员工管理系统添加考勤管理功能的扩展代码,该扩展代码涵盖了多个关键功能模块,包括但不限于考勤记录的详细录入与更新、考勤数据的综合统计与分析,以及考勤信息的便捷查询与展示功能。通过这些功能模块的集成,系统能够更加全面地管理和监控员工的考勤情况,从而提升企业的人力资源管理效率和准确性。

 

import datetime
from collections import defaultdictclass Attendance:"""考勤记录类"""def __init__(self, emp_id, date, check_in=None, check_out=None, status="正常"):self.emp_id = emp_idself.date = date  # 格式: YYYY-MM-DDself.check_in = check_in  # 格式: HH:MMself.check_out = check_outself.status = status  # 正常/迟到/早退/缺勤def __str__(self):return f"员工ID: {self.emp_id}, 日期: {self.date}, 上班: {self.check_in}, 下班: {self.check_out}, 状态: {self.status}"class EmployeeManagementSystemWithAttendance(EmployeeManagementSystem):"""带考勤功能的员工管理系统"""def __init__(self, data_file='employees.json', attendance_file='attendance.json'):super().__init__(data_file)self.attendance_file = attendance_fileself.attendance_records = []self.load_attendance_data()def load_attendance_data(self):"""加载考勤数据"""if os.path.exists(self.attendance_file):with open(self.attendance_file, 'r', encoding='utf-8') as f:data = json.load(f)self.attendance_records = [Attendance(**record) for record in data]def save_attendance_data(self):"""保存考勤数据"""with open(self.attendance_file, 'w', encoding='utf-8') as f:json.dump([record.__dict__ for record in self.attendance_records], f, ensure_ascii=False, indent=2)def record_check_in(self):"""记录上班打卡"""emp_id = input("请输入员工ID: ")# 验证员工是否存在if not any(emp.emp_id == emp_id for emp in self.employees):print("错误: 员工不存在!")returntoday = datetime.date.today().strftime("%Y-%m-%d")current_time = datetime.datetime.now().strftime("%H:%M")# 检查是否已打卡for record in self.attendance_records:if record.emp_id == emp_id and record.date == today:if record.check_in:print("错误: 该员工今天已打卡!")returnrecord.check_in = current_time# 判断是否迟到(假设9:00前不算迟到)if current_time > "09:00":record.status = "迟到"self.save_attendance_data()print(f"员工 {emp_id} 上班打卡成功! 时间: {current_time}")return# 如果没有当天记录,创建新记录new_record = Attendance(emp_id, today, check_in=current_time)if current_time > "09:00":new_record.status = "迟到"self.attendance_records.append(new_record)self.save_attendance_data()print(f"员工 {emp_id} 上班打卡成功! 时间: {current_time}")def record_check_out(self):"""记录下班打卡"""emp_id = input("请输入员工ID: ")# 验证员工是否存在if not any(emp.emp_id == emp_id for emp in self.employees):print("错误: 员工不存在!")returntoday = datetime.date.today().strftime("%Y-%m-%d")current_time = datetime.datetime.now().strftime("%H:%M")# 查找当天记录for record in self.attendance_records:if record.emp_id == emp_id and record.date == today:if record.check_out:print("错误: 该员工今天已下班打卡!")returnrecord.check_out = current_time# 判断是否早退(假设18:00前下班算早退)if current_time < "18:00":if record.status == "迟到":record.status = "迟到+早退"else:record.status = "早退"self.save_attendance_data()print(f"员工 {emp_id} 下班打卡成功! 时间: {current_time}")return# 如果没有当天记录,创建新记录(视为缺勤上午)new_record = Attendance(emp_id, today, check_out=current_time, status="缺勤(上午)")if current_time < "18:00":new_record.status += "+早退"self.attendance_records.append(new_record)self.save_attendance_data()print(f"员工 {emp_id} 下班打卡成功! 时间: {current_time}")def query_attendance(self):"""查询考勤记录"""print("\n--- 考勤查询 ---")print("1. 按员工查询")print("2. 按日期查询")print("3. 按状态查询")print("4. 显示所有考勤记录")choice = input("请选择查询方式: ")if choice == '1':emp_id = input("请输入员工ID: ")found = [record for record in self.attendance_records if record.emp_id == emp_id]elif choice == '2':date = input("请输入日期(YYYY-MM-DD): ")found = [record for record in self.attendance_records if record.date == date]elif choice == '3':status = input("请输入状态(正常/迟到/早退/缺勤): ")found = [record for record in self.attendance_records if status in record.status]elif choice == '4':found = self.attendance_recordselse:print("无效选择!")returnif not found:print("未找到匹配的考勤记录!")else:print("\n考勤记录:")for record in found:print(record)def attendance_statistics(self):"""考勤统计"""print("\n--- 考勤统计 ---")print("1. 员工月度考勤统计")print("2. 部门考勤统计")print("3. 公司整体考勤统计")choice = input("请选择统计方式: ")if choice == '1':emp_id = input("请输入员工ID: ")month = input("请输入月份(YYYY-MM): ")records = [r for r in self.attendance_records if r.emp_id == emp_id and r.date.startswith(month)]if not records:print("该员工本月无考勤记录!")returnstats = defaultdict(int)for record in records:stats[record.status] += 1print(f"\n员工 {emp_id} {month} 考勤统计:")for status, count in stats.items():print(f"{status}: {count}次")print(f"总计: {len(records)}天")elif choice == '2':department = input("请输入部门名称: ")month = input("请输入月份(YYYY-MM): ")# 获取部门所有员工IDemp_ids = [emp.emp_id for emp in self.employees if emp.department == department]if not emp_ids:print("该部门无员工!")returnrecords = [r for r in self.attendance_records if r.emp_id in emp_ids and r.date.startswith(month)]if not records:print("该部门本月无考勤记录!")returnstats = defaultdict(int)for record in records:stats[record.status] += 1print(f"\n{department}部门 {month} 考勤统计:")for status, count in sorted(stats.items()):print(f"{status}: {count}次")print(f"总计: {len(records)}人次")elif choice == '3':month = input("请输入月份(YYYY-MM): ")records = [r for r in self.attendance_records if r.date.startswith(month)]if not records:print("本月无考勤记录!")returnstats = defaultdict(int)for record in records:stats[record.status] += 1print(f"\n公司整体 {month} 考勤统计:")for status, count in sorted(stats.items()):print(f"{status}: {count}次")print(f"总计: {len(records)}人次")else:print("无效选择!")def show_menu(self):"""显示扩展菜单"""while True:print("\n=== 员工管理系统(带考勤功能) ===")print("1. 员工信息管理")print("2. 考勤管理")print("3. 退出系统")main_choice = input("请选择主菜单: ")if main_choice == '1':super().show_menu()elif main_choice == '2':print("\n--- 考勤管理 ---")print("1. 上班打卡")print("2. 下班打卡")print("3. 考勤查询")print("4. 考勤统计")sub_choice = input("请选择操作: ")if sub_choice == '1':self.record_check_in()elif sub_choice == '2':self.record_check_out()elif sub_choice == '3':self.query_attendance()elif sub_choice == '4':self.attendance_statistics()else:print("无效选择!")elif main_choice == '3':print("感谢使用员工管理系统!")breakelse:print("无效选择,请重新输入!")# 启动带考勤功能的系统
if __name__ == "__main__":system = EmployeeManagementSystemWithAttendance()system.show_menu()

员工管理系统数据统计分析功能扩展

   下面是为员工管理系统精心添加的一系列数据统计分析功能,这些功能涵盖了多个关键领域,旨在全面提升管理效率和决策精准度。具体而言,包括了对员工结构进行深入细致的分析,以便更好地了解企业的人力资源配置情况;对薪资数据进行全面系统的分析,帮助管理层掌握薪酬分布和成本控制;以及对考勤数据进行综合多维的分析,从而准确评估员工的工作状态和出勤情况,为优化管理策略提供有力支持。

class EmployeeManagementSystemWithStats(EmployeeManagementSystemWithAttendance):"""带统计分析功能的员工管理系统"""def show_statistics_menu(self):"""显示统计分析菜单"""while True:print("\n=== 数据统计分析 ===")print("1. 员工结构分析")print("2. 薪资分析")print("3. 考勤综合分析")print("4. 返回主菜单")choice = input("请选择分析类型: ")if choice == '1':self.employee_structure_analysis()elif choice == '2':self.salary_analysis()elif choice == '3':self.attendance_comprehensive_analysis()elif choice == '4':breakelse:print("无效选择!")def employee_structure_analysis(self):"""员工结构分析"""print("\n--- 员工结构分析 ---")# 部门分布dept_dist = defaultdict(int)for emp in self.employees:dept_dist[emp.department] += 1print("\n按部门分布:")for dept, count in sorted(dept_dist.items()):print(f"{dept}: {count}人 ({count/len(self.employees):.1%})")# 职位分布position_dist = defaultdict(int)for emp in self.employees:position_dist[emp.position] += 1print("\n按职位分布:")for position, count in sorted(position_dist.items()):print(f"{position}: {count}人")# 年龄结构(假设从ID中提取年龄)age_groups = {"20-29":0, "30-39":0, "40-49":0, "50+":0}for emp in self.employees:birth_year = int(emp.emp_id[:2])  # 假设ID前两位是出生年份age = datetime.datetime.now().year - (1900 + birth_year)if 20 <= age < 30:age_groups["20-29"] += 1elif 30 <= age < 40:age_groups["30-39"] += 1elif 40 <= age < 50:age_groups["40-49"] += 1else:age_groups["50+"] += 1print("\n按年龄分布:")for group, count in age_groups.items():print(f"{group}岁: {count}人")def salary_analysis(self):"""薪资分析"""if not self.employees:print("没有员工数据!")returnprint("\n--- 薪资分析 ---")salaries = [emp.salary for emp in self.employees]avg_salary = sum(salaries) / len(salaries)max_salary = max(salaries)min_salary = min(salaries)print(f"\n整体薪资情况:")print(f"平均薪资: {avg_salary:.2f}元")print(f"最高薪资: {max_salary:.2f}元")print(f"最低薪资: {min_salary:.2f}元")# 部门薪资分析dept_salaries = defaultdict(list)for emp in self.employees:dept_salaries[emp.department].append(emp.salary)print("\n各部门薪资情况:")for dept, sal_list in sorted(dept_salaries.items()):avg = sum(sal_list) / len(sal_list)print(f"{dept}: 平均{avg:.2f}元 (人数:{len(sal_list)})")# 薪资区间分布ranges = [(0,5000), (5000,10000), (10000,15000), (15000,20000), (20000,30000), (30000,float('inf'))]range_names = ["5k以下", "5k-10k", "10k-15k", "15k-20k", "20k-30k", "30k以上"]salary_dist = [0] * len(ranges)for salary in salaries:for i, (low, high) in enumerate(ranges):if low <= salary < high:salary_dist[i] += 1breakprint("\n薪资区间分布:")for name, count in zip(range_names, salary_dist):print(f"{name}: {count}人")def attendance_comprehensive_analysis(self):"""考勤综合分析"""if not self.attendance_records:print("没有考勤数据!")returnprint("\n--- 考勤综合分析 ---")# 总体考勤情况status_dist = defaultdict(int)for record in self.attendance_records:status_dist[record.status] += 1total_records = len(self.attendance_records)print("\n整体考勤情况:")for status, count in sorted(status_dist.items()):print(f"{status}: {count}次 ({count/total_records:.1%})")# 月度趋势分析month_records = defaultdict(list)for record in self.attendance_records:month = record.date[:7]  # 提取年月month_records[month].append(record)print("\n月度考勤趋势:")for month, records in sorted(month_records.items()):late_count = sum(1 for r in records if "迟到" in r.status)leave_early = sum(1 for r in records if "早退" in r.status)absent = sum(1 for r in records if "缺勤" in r.status)print(f"{month}: 迟到{late_count}次, 早退{leave_early}次, 缺勤{absent}次")# 部门考勤对比dept_stats = defaultdict(lambda: defaultdict(int))emp_dept = {emp.emp_id: emp.department for emp in self.employees}for record in self.attendance_records:if record.emp_id in emp_dept:dept = emp_dept[record.emp_id]dept_stats[dept]["total"] += 1if "迟到" in record.status:dept_stats[dept]["late"] += 1if "早退" in record.status:dept_stats[dept]["leave_early"] += 1if "缺勤" in record.status:dept_stats[dept]["absent"] += 1print("\n各部门考勤对比:")for dept, stats in sorted(dept_stats.items()):total = stats["total"]print(f"{dept}部门:")print(f"  迟到率: {stats['late']/total:.1%}")print(f"  早退率: {stats['leave_early']/total:.1%}")print(f"  缺勤率: {stats['absent']/total:.1%}")def show_menu(self):"""显示完整菜单"""while True:print("\n=== 员工管理系统(完整版) ===")print("1. 员工信息管理")print("2. 考勤管理")print("3. 数据统计分析")print("4. 退出系统")main_choice = input("请选择主菜单: ")if main_choice == '1':super().show_menu()elif main_choice == '2':# 调用父类的考勤管理菜单super(EmployeeManagementSystemWithAttendance, self).show_menu()elif main_choice == '3':self.show_statistics_menu()elif main_choice == '4':print("感谢使用员工管理系统!")breakelse:print("无效选择,请重新输入!")# 启动带统计分析功能的系统
if __name__ == "__main__":system = EmployeeManagementSystemWithStats()system.show_menu()

 员工管理系统GUI版本 (基于Tkinter)

     下面是一个利用Python的标准库Tkinter所开发的图形用户界面(GUI)版本的员工管理系统。该系统不仅涵盖了全面的员工管理功能,还集成了详尽的考勤管理模块,能够高效地处理员工的各项信息及考勤记录,确保企业人力资源管理的规范化和便捷化。

import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
from datetime import datetime
import json
import osclass EmployeeGUISystem:def __init__(self, root):self.root = rootself.root.title("员工管理系统 GUI版")self.root.geometry("1000x700")# 数据文件self.emp_file = "employees_gui.json"self.att_file = "attendance_gui.json"# 加载数据self.employees = self.load_data(self.emp_file)self.attendance = self.load_data(self.att_file)# 创建主界面self.create_main_interface()# 默认显示员工管理标签页self.show_employee_tab()def load_data(self, filename):"""加载JSON数据"""if os.path.exists(filename):with open(filename, 'r', encoding='utf-8') as f:return json.load(f)return []def save_data(self, data, filename):"""保存数据到JSON文件"""with open(filename, 'w', encoding='utf-8') as f:json.dump(data, f, ensure_ascii=False, indent=2)def create_main_interface(self):"""创建主界面"""# 顶部菜单栏menubar = tk.Menu(self.root)self.root.config(menu=menubar)# 文件菜单file_menu = tk.Menu(menubar, tearoff=0)file_menu.add_command(label="导出数据", command=self.export_data)file_menu.add_separator()file_menu.add_command(label="退出", command=self.root.quit)menubar.add_cascade(label="文件", menu=file_menu)# 标签页控件self.tab_control = ttk.Notebook(self.root)# 创建各个标签页self.employee_tab = ttk.Frame(self.tab_control)self.attendance_tab = ttk.Frame(self.tab_control)self.stats_tab = ttk.Frame(self.tab_control)self.tab_control.add(self.employee_tab, text='员工管理')self.tab_control.add(self.attendance_tab, text='考勤管理')self.tab_control.add(self.stats_tab, text='统计分析')self.tab_control.pack(expand=1, fill="both")# 绑定标签页切换事件self.tab_control.bind("<<NotebookTabChanged>>", self.on_tab_changed)def on_tab_changed(self, event):"""标签页切换事件处理"""selected_tab = event.widget.tab('current')['text']if selected_tab == "员工管理":self.show_employee_tab()elif selected_tab == "考勤管理":self.show_attendance_tab()elif selected_tab == "统计分析":self.show_stats_tab()def show_employee_tab(self):"""显示员工管理标签页"""# 清除旧内容for widget in self.employee_tab.winfo_children():widget.destroy()# 顶部按钮区域btn_frame = ttk.Frame(self.employee_tab)btn_frame.pack(pady=10)ttk.Button(btn_frame, text="添加员工", command=self.add_employee_dialog).grid(row=0, column=0, padx=5)ttk.Button(btn_frame, text="编辑员工", command=self.edit_employee_dialog).grid(row=0, column=1, padx=5)ttk.Button(btn_frame, text="删除员工", command=self.delete_employee).grid(row=0, column=2, padx=5)ttk.Button(btn_frame, text="刷新列表", command=self.show_employee_tab).grid(row=0, column=3, padx=5)# 搜索区域search_frame = ttk.Frame(self.employee_tab)search_frame.pack(pady=5)ttk.Label(search_frame, text="搜索:").grid(row=0, column=0)self.emp_search_var = tk.StringVar()ttk.Entry(search_frame, textvariable=self.emp_search_var, width=30).grid(row=0, column=1, padx=5)ttk.Button(search_frame, text="搜索", command=self.search_employees).grid(row=0, column=2)ttk.Button(search_frame, text="重置", command=self.reset_search).grid(row=0, column=3)# 员工表格columns = ("ID", "姓名", "部门", "职位", "薪资")self.employee_tree = ttk.Treeview(self.employee_tab, columns=columns, show="headings", height=20)# 设置列属性col_widths = [80, 120, 150, 150, 100]for col, width in zip(columns, col_widths):self.employee_tree.heading(col, text=col)self.employee_tree.column(col, width=width, anchor='center')self.employee_tree.pack(fill="both", expand=True)# 添加滚动条scrollbar = ttk.Scrollbar(self.employee_tree, orient="vertical", command=self.employee_tree.yview)self.employee_tree.configure(yscrollcommand=scrollbar.set)scrollbar.pack(side="right", fill="y")# 填充数据self.populate_employee_tree()def populate_employee_tree(self, employees=None):"""填充员工表格数据"""# 清空现有数据for item in self.employee_tree.get_children():self.employee_tree.delete(item)# 显示所有员工或过滤后的员工employees_to_show = employees if employees else self.employeesfor emp in employees_to_show:self.employee_tree.insert("", "end", values=(emp.get("emp_id", ""),emp.get("name", ""),emp.get("department", ""),emp.get("position", ""),f"{emp.get('salary', 0):.2f}"))def search_employees(self):"""搜索员工"""keyword = self.emp_search_var.get().lower()if not keyword:self.populate_employee_tree()returnfiltered = [emp for emp in self.employeesif (keyword in emp.get("name", "").lower() or keyword in emp.get("department", "").lower() orkeyword in emp.get("position", "").lower() orkeyword in emp.get("emp_id", "").lower())]self.populate_employee_tree(filtered)def reset_search(self):"""重置搜索"""self.emp_search_var.set("")self.populate_employee_tree()def add_employee_dialog(self):"""添加员工对话框"""dialog = tk.Toplevel(self.root)dialog.title("添加新员工")dialog.geometry("400x300")dialog.resizable(False, False)# 表单字段ttk.Label(dialog, text="员工ID:").grid(row=0, column=0, padx=10, pady=5, sticky="e")emp_id_entry = ttk.Entry(dialog)emp_id_entry.grid(row=0, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="姓名:").grid(row=1, column=0, padx=10, pady=5, sticky="e")name_entry = ttk.Entry(dialog)name_entry.grid(row=1, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="部门:").grid(row=2, column=0, padx=10, pady=5, sticky="e")dept_entry = ttk.Entry(dialog)dept_entry.grid(row=2, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="职位:").grid(row=3, column=0, padx=10, pady=5, sticky="e")position_entry = ttk.Entry(dialog)position_entry.grid(row=3, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="薪资:").grid(row=4, column=0, padx=10, pady=5, sticky="e")salary_entry = ttk.Entry(dialog)salary_entry.grid(row=4, column=1, padx=10, pady=5, sticky="w")def save_employee():"""保存员工信息"""emp_id = emp_id_entry.get()name = name_entry.get()department = dept_entry.get()position = position_entry.get()try:salary = float(salary_entry.get())except ValueError:messagebox.showerror("错误", "薪资必须是数字")return# 验证ID是否已存在if any(emp["emp_id"] == emp_id for emp in self.employees):messagebox.showerror("错误", "该员工ID已存在")return# 添加新员工new_emp = {"emp_id": emp_id,"name": name,"department": department,"position": position,"salary": salary}self.employees.append(new_emp)self.save_data(self.employees, self.emp_file)messagebox.showinfo("成功", "员工添加成功")dialog.destroy()self.show_employee_tab()# 按钮区域btn_frame = ttk.Frame(dialog)btn_frame.grid(row=5, column=0, columnspan=2, pady=10)ttk.Button(btn_frame, text="保存", command=save_employee).pack(side="left", padx=10)ttk.Button(btn_frame, text="取消", command=dialog.destroy).pack(side="left", padx=10)def edit_employee_dialog(self):"""编辑员工对话框"""selected = self.employee_tree.selection()if not selected:messagebox.showwarning("警告", "请先选择要编辑的员工")return# 获取选中员工的数据item = self.employee_tree.item(selected[0])emp_id = item['values'][0]# 查找员工完整信息employee = next((emp for emp in self.employees if emp["emp_id"] == emp_id), None)if not employee:messagebox.showerror("错误", "未找到该员工")returndialog = tk.Toplevel(self.root)dialog.title("编辑员工信息")dialog.geometry("400x300")dialog.resizable(False, False)# 表单字段(带原始数据)ttk.Label(dialog, text="员工ID:").grid(row=0, column=0, padx=10, pady=5, sticky="e")emp_id_label = ttk.Label(dialog, text=employee["emp_id"])emp_id_label.grid(row=0, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="姓名:").grid(row=1, column=0, padx=10, pady=5, sticky="e")name_entry = ttk.Entry(dialog)name_entry.insert(0, employee["name"])name_entry.grid(row=1, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="部门:").grid(row=2, column=0, padx=10, pady=5, sticky="e")dept_entry = ttk.Entry(dialog)dept_entry.insert(0, employee["department"])dept_entry.grid(row=2, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="职位:").grid(row=3, column=0, padx=10, pady=5, sticky="e")position_entry = ttk.Entry(dialog)position_entry.insert(0, employee["position"])position_entry.grid(row=3, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="薪资:").grid(row=4, column=0, padx=10, pady=5, sticky="e")salary_entry = ttk.Entry(dialog)salary_entry.insert(0, str(employee["salary"]))salary_entry.grid(row=4, column=1, padx=10, pady=5, sticky="w")def update_employee():"""更新员工信息"""employee["name"] = name_entry.get()employee["department"] = dept_entry.get()employee["position"] = position_entry.get()try:employee["salary"] = float(salary_entry.get())except ValueError:messagebox.showerror("错误", "薪资必须是数字")returnself.save_data(self.employees, self.emp_file)messagebox.showinfo("成功", "员工信息已更新")dialog.destroy()self.show_employee_tab()# 按钮区域btn_frame = ttk.Frame(dialog)btn_frame.grid(row=5, column=0, columnspan=2, pady=10)ttk.Button(btn_frame, text="更新", command=update_employee).pack(side="left", padx=10)ttk.Button(btn_frame, text="取消", command=dialog.destroy).pack(side="left", padx=10)def delete_employee(self):"""删除员工"""selected = self.employee_tree.selection()if not selected:messagebox.showwarning("警告", "请先选择要删除的员工")returnitem = self.employee_tree.item(selected[0])emp_id, name = item['values'][0], item['values'][1]if not messagebox.askyesno("确认", f"确定要删除员工 {name} (ID: {emp_id}) 吗?"):return# 删除员工self.employees = [emp for emp in self.employees if emp["emp_id"] != emp_id]self.save_data(self.employees, self.emp_file)# 删除相关考勤记录self.attendance = [rec for rec in self.attendance if rec.get("emp_id") != emp_id]self.save_data(self.attendance, self.att_file)messagebox.showinfo("成功", "员工已删除")self.show_employee_tab()def show_attendance_tab(self):"""显示考勤管理标签页"""# 清除旧内容for widget in self.attendance_tab.winfo_children():widget.destroy()# 顶部按钮区域btn_frame = ttk.Frame(self.attendance_tab)btn_frame.pack(pady=10)ttk.Button(btn_frame, text="上班打卡", command=self.record_check_in).grid(row=0, column=0, padx=5)ttk.Button(btn_frame, text="下班打卡", command=self.record_check_out).grid(row=0, column=1, padx=5)ttk.Button(btn_frame, text="添加记录", command=self.add_attendance_record).grid(row=0, column=2, padx=5)ttk.Button(btn_frame, text="刷新列表", command=self.show_attendance_tab).grid(row=0, column=3, padx=5)# 搜索和过滤区域filter_frame = ttk.Frame(self.attendance_tab)filter_frame.pack(pady=5)ttk.Label(filter_frame, text="员工ID:").grid(row=0, column=0)self.att_emp_id_var = tk.StringVar()ttk.Entry(filter_frame, textvariable=self.att_emp_id_var, width=15).grid(row=0, column=1, padx=5)ttk.Label(filter_frame, text="日期:").grid(row=0, column=2)self.att_date_var = tk.StringVar()ttk.Entry(filter_frame, textvariable=self.att_date_var, width=15).grid(row=0, column=3, padx=5)ttk.Button(filter_frame, text="筛选", command=self.filter_attendance).grid(row=0, column=4, padx=5)ttk.Button(filter_frame, text="重置", command=self.reset_attendance_filter).grid(row=0, column=5, padx=5)# 考勤表格columns = ("ID", "姓名", "日期", "上班时间", "下班时间", "状态")self.attendance_tree = ttk.Treeview(self.attendance_tab, columns=columns, show="headings", height=20)# 设置列属性col_widths = [80, 100, 100, 100, 100, 120]for col, width in zip(columns, col_widths):self.attendance_tree.heading(col, text=col)self.attendance_tree.column(col, width=width, anchor='center')self.attendance_tree.pack(fill="both", expand=True)# 添加滚动条scrollbar = ttk.Scrollbar(self.attendance_tree, orient="vertical", command=self.attendance_tree.yview)self.attendance_tree.configure(yscrollcommand=scrollbar.set)scrollbar.pack(side="right", fill="y")# 填充数据self.populate_attendance_tree()def populate_attendance_tree(self, records=None):"""填充考勤表格数据"""# 清空现有数据for item in self.attendance_tree.get_children():self.attendance_tree.delete(item)# 获取员工姓名映射emp_name_map = {emp["emp_id"]: emp["name"] for emp in self.employees}# 显示所有记录或过滤后的记录records_to_show = records if records else self.attendancefor rec in records_to_show:emp_id = rec.get("emp_id", "")self.attendance_tree.insert("", "end", values=(emp_id,emp_name_map.get(emp_id, "未知"),rec.get("date", ""),rec.get("check_in", "-"),rec.get("check_out", "-"),rec.get("status", "未知")))def filter_attendance(self):"""筛选考勤记录"""emp_id = self.att_emp_id_var.get()date = self.att_date_var.get()filtered = []for rec in self.attendance:match_emp = not emp_id or rec.get("emp_id", "") == emp_idmatch_date = not date or rec.get("date", "").startswith(date)if match_emp and match_date:filtered.append(rec)self.populate_attendance_tree(filtered)def reset_attendance_filter(self):"""重置考勤筛选"""self.att_emp_id_var.set("")self.att_date_var.set("")self.populate_attendance_tree()def record_check_in(self):"""上班打卡"""emp_id = simpledialog.askstring("上班打卡", "请输入员工ID:")if not emp_id:return# 验证员工是否存在if not any(emp["emp_id"] == emp_id for emp in self.employees):messagebox.showerror("错误", "员工不存在")returntoday = datetime.now().strftime("%Y-%m-%d")current_time = datetime.now().strftime("%H:%M")status = "正常" if current_time <= "09:00" else "迟到"# 检查是否已有当天记录for rec in self.attendance:if rec["emp_id"] == emp_id and rec["date"] == today:if "check_in" in rec:messagebox.showerror("错误", "该员工今天已上班打卡")returnrec["check_in"] = current_timerec["status"] = statusbreakelse:# 新记录new_rec = {"emp_id": emp_id,"date": today,"check_in": current_time,"status": status}self.attendance.append(new_rec)self.save_data(self.attendance, self.att_file)messagebox.showinfo("成功", f"员工 {emp_id} 上班打卡成功\n时间: {current_time}")self.show_attendance_tab()def record_check_out(self):"""下班打卡"""emp_id = simpledialog.askstring("下班打卡", "请输入员工ID:")if not emp_id:return# 验证员工是否存在if not any(emp["emp_id"] == emp_id for emp in self.employees):messagebox.showerror("错误", "员工不存在")returntoday = datetime.now().strftime("%Y-%m-%d")current_time = datetime.now().strftime("%H:%M")# 查找当天记录for rec in self.attendance:if rec["emp_id"] == emp_id and rec["date"] == today:if "check_out" in rec:messagebox.showerror("错误", "该员工今天已下班打卡")returnrec["check_out"] = current_time# 更新状态if current_time < "18:00":if rec["status"] == "迟到":rec["status"] = "迟到+早退"else:rec["status"] = "早退"breakelse:# 没有上班记录,只有下班记录new_rec = {"emp_id": emp_id,"date": today,"check_out": current_time,"status": "缺勤(上午)"}if current_time < "18:00":new_rec["status"] += "+早退"self.attendance.append(new_rec)self.save_data(self.attendance, self.att_file)messagebox.showinfo("成功", f"员工 {emp_id} 下班打卡成功\n时间: {current_time}")self.show_attendance_tab()def add_attendance_record(self):"""手动添加考勤记录"""dialog = tk.Toplevel(self.root)dialog.title("添加考勤记录")dialog.geometry("400x300")# 表单字段ttk.Label(dialog, text="员工ID:").grid(row=0, column=0, padx=10, pady=5, sticky="e")emp_id_entry = ttk.Entry(dialog)emp_id_entry.grid(row=0, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="日期(YYYY-MM-DD):").grid(row=1, column=0, padx=10, pady=5, sticky="e")date_entry = ttk.Entry(dialog)date_entry.grid(row=1, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="上班时间(HH:MM):").grid(row=2, column=0, padx=10, pady=5, sticky="e")check_in_entry = ttk.Entry(dialog)check_in_entry.grid(row=2, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="下班时间(HH:MM):").grid(row=3, column=0, padx=10, pady=5, sticky="e")check_out_entry = ttk.Entry(dialog)check_out_entry.grid(row=3, column=1, padx=10, pady=5, sticky="w")ttk.Label(dialog, text="状态:").grid(row=4, column=0, padx=10, pady=5, sticky="e")status_entry = ttk.Combobox(dialog, values=["正常", "迟到", "早退", "缺勤", "迟到+早退", "缺勤(上午)"])status_entry.grid(row=4, column=1, padx=10, pady=5, sticky="w")status_entry.set("正常")def save_record():"""保存考勤记录"""emp_id = emp_id_entry.get()date = date_entry.get()check_in = check_in_entry.get() or Nonecheck_out = check_out_entry.get() or Nonestatus = status_entry.get()# 验证员工是否存在if not any(emp["emp_id"] == emp_id for emp in self.employees):messagebox.showerror("错误", "员工不存在")return# 验证日期格式try:datetime.strptime(date, "%Y-%m-%d")except ValueError:messagebox.showerror("错误", "日期格式不正确,应为YYYY-MM-DD")return# 验证时间格式if check_in:try:datetime.strptime(check_in, "%H:%M")except ValueError:messagebox.showerror("错误", "上班时间格式不正确,应为HH:MM")returnif check_out:try:datetime.strptime(check_out, "%H:%M")except ValueError:messagebox.showerror("错误", "下班时间格式不正确,应为HH:MM")return# 检查是否已有当天记录for rec in self.attendance:if rec["emp_id"] == emp_id and rec["date"] == date:messagebox.showerror("错误", "该员工当天已有考勤记录")return# 添加新记录new_rec = {"emp_id": emp_id,"date": date,"check_in": check_in,"check_out": check_out,"status": status}self.attendance.append(new_rec)self.save_data(self.attendance, self.att_file)messagebox.showinfo("成功", "考勤记录已添加")dialog.destroy()self.show_attendance_tab()# 按钮区域btn_frame = ttk.Frame(dialog)btn_frame.grid(row=5, column=0, columnspan=2, pady=10)ttk.Button(btn_frame, text="保存", command=save_record).pack(side="left", padx=10)ttk.Button(btn_frame, text="取消", command=dialog.destroy).pack(side="left", padx=10)def show_stats_tab(self):"""显示统计分析标签页"""# 清除旧内容for widget in self.stats_tab.winfo_children():widget.destroy()# 创建标签页内的子标签stats_notebook = ttk.Notebook(self.stats_tab)# 创建各个子标签页emp_stats_tab = ttk.Frame(stats_notebook)salary_stats_tab = ttk.Frame(stats_notebook)att_stats_tab = ttk.Frame(stats_notebook)stats_notebook.add(emp_stats_tab, text='员工结构')stats_notebook.add(salary_stats_tab, text='薪资分析')stats_notebook.add(att_stats_tab, text='考勤统计')stats_notebook.pack(expand=1, fill="both")# 填充员工结构分析标签页self.populate_emp_stats_tab(emp_stats_tab)# 填充薪资分析标签页self.populate_salary_stats_tab(salary_stats_tab)# 填充考勤统计标签页self.populate_att_stats_tab(att_stats_tab)def populate_emp_stats_tab(self, tab):"""填充员工结构分析标签页"""# 部门分布dept_frame = ttk.LabelFrame(tab, text="部门分布")dept_frame.pack(fill="x", padx=10, pady=5)dept_dist = defaultdict(int)for emp in self.employees:dept_dist[emp["department"]] += 1for dept, count in sorted(dept_dist.items()):ttk.Label(dept_frame, text=f"{dept}: {count}人 ({count/len(self.employees):.1%})").pack(anchor="w")# 职位分布position_frame = ttk.LabelFrame(tab, text="职位分布")position_frame.pack(fill="x", padx=10, pady=5)position_dist = defaultdict(int)for emp in self.employees:position_dist[emp["position"]] += 1for position, count in sorted(position_dist.items()):ttk.Label(position_frame, text=f"{position}: {count}人").pack(anchor="w")def populate_salary_stats_tab(self, tab):"""填充薪资分析标签页"""if not self.employees:ttk.Label(tab, text="没有员工数据").pack()returnsalaries = [emp["salary"] for emp in self.employees]avg_salary = sum(salaries) / len(salaries)max_salary = max(salaries)min_salary = min(salaries)# 整体统计overall_frame = ttk.LabelFrame(tab, text="整体薪资统计")overall_frame.pack(fill="x", padx=10, pady=5)ttk.Label(overall_frame, text=f"平均薪资: {avg_salary:.2f}元").pack(anchor="w")ttk.Label(overall_frame, text=f"最高薪资: {max_salary:.2f}元").pack(anchor="w")ttk.Label(overall_frame, text=f"最低薪资: {min_salary:.2f}元").pack(anchor="w")# 部门统计dept_frame = ttk.LabelFrame(tab, text="部门薪资统计")dept_frame.pack(fill="x", padx=10, pady=5)dept_salaries = defaultdict(list)for emp in self.employees:dept_salaries[emp["department"]].append(emp["salary"])for dept, sal_list in sorted(dept_salaries.items()):avg = sum(sal_list) / len(sal_list)ttk.Label(dept_frame, text=f"{dept}: 平均{avg:.2f}元 (人数:{len(sal_list)})").pack(anchor="w")def populate_att_stats_tab(self, tab):"""填充考勤统计标签页"""if not self.attendance:ttk.Label(tab, text="没有考勤数据").pack()return# 总体统计overall_frame = ttk.LabelFrame(tab, text="整体考勤情况")overall_frame.pack(fill="x", padx=10, pady=5)status_dist = defaultdict(int)for rec in self.attendance:status_dist[rec["status"]] += 1total = len(self.attendance)for status, count in sorted(status_dist.items()):ttk.Label(overall_frame, text=f"{status}: {count}次 ({count/total:.1%})").pack(anchor="w")# 月度统计month_frame = ttk.LabelFrame(tab, text="月度考勤趋势")month_frame.pack(fill="x", padx=10, pady=5)month_stats = defaultdict(lambda: defaultdict(int))for rec in self.attendance:month = rec["date"][:7]  # 提取年月month_stats[month]["total"] += 1if "迟到" in rec["status"]:month_stats[month]["late"] += 1if "早退" in rec["status"]:month_stats[month]["leave_early"] += 1if "缺勤" in rec["status"]:month_stats[month]["absent"] += 1for month, stats in sorted(month_stats.items()):ttk.Label(month_frame, text=f"{month}: 迟到{stats['late']}次, 早退{stats['leave_early']}次, 缺勤{stats['absent']}次").pack(anchor="w")def export_data(self):"""导出数据"""# 这里可以实现导出Excel或其他格式的功能messagebox.showinfo("提示", "导出功能将在后续版本实现")# 启动GUI应用
if __name__ == "__main__":root = tk.Tk()app = EmployeeGUISystem(root)root.mainloop()

 员工管理系统 - 带用户登录和权限管理功能的GUI版本

下面是在原有GUI系统基础上增加了用户登录和权限管理功能的完整代码实现下面是在原有GUI系统基础上增加了用户登录和权限管理功能的完整代码实现v下面是在原有GUI系统基础上增加了用户登录和权限管理功能的完整代码实现:

import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
from datetime import datetime
import json
import os
import hashlib
from collections import defaultdictclass User:"""用户类"""def __init__(self, username, password_hash, role="user"):self.username = usernameself.password_hash = password_hashself.role = role  # admin/userdef verify_password(self, password):"""验证密码"""return self.password_hash == self.hash_password(password)@staticmethoddef hash_password(password):"""密码哈希处理"""return hashlib.sha256(password.encode()).hexdigest()class AuthSystem:"""认证系统"""def __init__(self, users_file="users.json"):self.users_file = users_fileself.users = self.load_users()self.current_user = Nonedef load_users(self):"""加载用户数据"""if os.path.exists(self.users_file):with open(self.users_file, 'r', encoding='utf-8') as f:users_data = json.load(f)return {user['username']: User(user['username'], user['password_hash'], user.get('role', 'user')) for user in users_data}return {}def save_users(self):"""保存用户数据"""users_data = [{'username': user.username, 'password_hash': user.password_hash,'role': user.role} for user in self.users.values()]with open(self.users_file, 'w', encoding='utf-8') as f:json.dump(users_data, f, ensure_ascii=False, indent=2)def register(self, username, password, role="user"):"""注册新用户"""if username in self.users:return False, "用户名已存在"if len(password) < 6:return False, "密码长度至少6位"password_hash = User.hash_password(password)self.users[username] = User(username, password_hash, role)self.save_users()return True, "注册成功"def login(self, username, password):"""用户登录"""user = self.users.get(username)if not user:return False, "用户不存在"if not user.verify_password(password):return False, "密码错误"self.current_user = userreturn True, "登录成功"def logout(self):"""用户登出"""self.current_user = Nonedef is_admin(self):"""检查当前用户是否是管理员"""return self.current_user and self.current_user.role == "admin"class EmployeeGUISystemWithAuth:def __init__(self, root):self.root = rootself.root.title("员工管理系统 - 请登录")self.root.geometry("500x300")# 认证系统self.auth = AuthSystem()# 数据文件self.emp_file = "employees_gui.json"self.att_file = "attendance_gui.json"# 加载数据self.employees = self.load_data(self.emp_file)self.attendance = self.load_data(self.att_file)# 显示登录界面self.show_login_interface()def load_data(self, filename):"""加载JSON数据"""if os.path.exists(filename):with open(filename, 'r', encoding='utf-8') as f:return json.load(f)return []def save_data(self, data, filename):"""保存数据到JSON文件"""with open(filename, 'w', encoding='utf-8') as f:json.dump(data, f, ensure_ascii=False, indent=2)def show_login_interface(self):"""显示登录界面"""# 清除旧内容for widget in self.root.winfo_children():widget.destroy()self.root.geometry("500x300")# 登录表单login_frame = ttk.Frame(self.root, padding="20")login_frame.pack(expand=True)ttk.Label(login_frame, text="员工管理系统", font=('Arial', 16)).grid(row=0, column=0, columnspan=2, pady=10)ttk.Label(login_frame, text="用户名:").grid(row=1, column=0, pady=5, sticky="e")self.username_var = tk.StringVar()ttk.Entry(login_frame, textvariable=self.username_var).grid(row=1, column=1, pady=5)ttk.Label(login_frame, text="密码:").grid(row=2, column=0, pady=5, sticky="e")self.password_var = tk.StringVar()ttk.Entry(login_frame, textvariable=self.password_var, show="*").grid(row=2, column=1, pady=5)btn_frame = ttk.Frame(login_frame)btn_frame.grid(row=3, column=0, columnspan=2, pady=10)ttk.Button(btn_frame, text="登录", command=self.handle_login).pack(side="left", padx=10)ttk.Button(btn_frame, text="注册", command=self.show_register_dialog).pack(side="left", padx=10)# 如果是管理员,显示初始化按钮if not self.auth.users:ttk.Button(login_frame, text="初始化管理员账户", command=self.init_admin_account).grid(row=4, column=0, columnspan=2, pady=10)def init_admin_account(self):"""初始化管理员账户"""dialog = tk.Toplevel(self.root)dialog.title("初始化管理员账户")dialog.geometry("400x250")ttk.Label(dialog, text="设置管理员账户", font=('Arial', 12)).pack(pady=10)ttk.Label(dialog, text="用户名:").pack()admin_user_entry = ttk.Entry(dialog)admin_user_entry.pack(pady=5)ttk.Label(dialog, text="密码:").pack()admin_pass_entry = ttk.Entry(dialog, show="*")admin_pass_entry.pack(pady=5)ttk.Label(dialog, text="确认密码:").pack()admin_pass_confirm_entry = ttk.Entry(dialog, show="*")admin_pass_confirm_entry.pack(pady=5)def create_admin():username = admin_user_entry.get()password = admin_pass_entry.get()confirm = admin_pass_confirm_entry.get()if not username or not password:messagebox.showerror("错误", "用户名和密码不能为空")returnif password != confirm:messagebox.showerror("错误", "两次输入的密码不一致")returnsuccess, msg = self.auth.register(username, password, "admin")messagebox.showinfo("提示", msg)if success:dialog.destroy()ttk.Button(dialog, text="创建", command=create_admin).pack(pady=10)def show_register_dialog(self):"""显示注册对话框"""dialog = tk.Toplevel(self.root)dialog.title("注册新用户")dialog.geometry("400x250")ttk.Label(dialog, text="注册新账户", font=('Arial', 12)).pack(pady=10)ttk.Label(dialog, text="用户名:").pack()new_user_entry = ttk.Entry(dialog)new_user_entry.pack(pady=5)ttk.Label(dialog, text="密码(至少6位):").pack()new_pass_entry = ttk.Entry(dialog, show="*")new_pass_entry.pack(pady=5)ttk.Label(dialog, text="确认密码:").pack()new_pass_confirm_entry = ttk.Entry(dialog, show="*")new_pass_confirm_entry.pack(pady=5)def register_user():username = new_user_entry.get()password = new_pass_entry.get()confirm = new_pass_confirm_entry.get()if not username or not password:messagebox.showerror("错误", "用户名和密码不能为空")returnif password != confirm:messagebox.showerror("错误", "两次输入的密码不一致")returnsuccess, msg = self.auth.register(username, password)messagebox.showinfo("提示", msg)if success:dialog.destroy()ttk.Button(dialog, text="注册", command=register_user).pack(pady=10)def handle_login(self):"""处理登录"""username = self.username_var.get()password = self.password_var.get()if not username or not password:messagebox.showerror("错误", "用户名和密码不能为空")returnsuccess, msg = self.auth.login(username, password)messagebox.showinfo("提示", msg)if success:self.show_main_interface()def show_main_interface(self):"""显示主界面"""# 清除旧内容for widget in self.root.winfo_children():widget.destroy()self.root.title(f"员工管理系统 - 当前用户: {self.auth.current_user.username}")self.root.geometry("1000x700")# 顶部菜单栏menubar = tk.Menu(self.root)# 文件菜单file_menu = tk.Menu(menubar, tearoff=0)file_menu.add_command(label="导出数据", command=self.export_data)# 用户菜单user_menu = tk.Menu(menubar, tearoff=0)user_menu.add_command(label="修改密码", command=self.change_password)user_menu.add_separator()user_menu.add_command(label="退出登录", command=self.logout)# 管理员菜单if self.auth.is_admin():admin_menu = tk.Menu(menubar, tearoff=0)admin_menu.add_command(label="用户管理", command=self.manage_users)menubar.add_cascade(label="管理员", menu=admin_menu)menubar.add_cascade(label="文件", menu=file_menu)menubar.add_cascade(label="用户", menu=user_menu)self.root.config(menu=menubar)# 标签页控件self.tab_control = ttk.Notebook(self.root)# 创建各个标签页self.employee_tab = ttk.Frame(self.tab_control)self.attendance_tab = ttk.Frame(self.tab_control)self.stats_tab = ttk.Frame(self.tab_control)self.tab_control.add(self.employee_tab, text='员工管理')self.tab_control.add(self.attendance_tab, text='考勤管理')self.tab_control.add(self.stats_tab, text='统计分析')self.tab_control.pack(expand=1, fill="both")# 绑定标签页切换事件self.tab_control.bind("<<NotebookTabChanged>>", self.on_tab_changed)# 默认显示员工管理标签页self.show_employee_tab()def change_password(self):"""修改密码"""dialog = tk.Toplevel(self.root)dialog.title("修改密码")dialog.geometry("400x250")ttk.Label(dialog, text="修改密码", font=('Arial', 12)).pack(pady=10)ttk.Label(dialog, text="当前密码:").pack()current_pass_entry = ttk.Entry(dialog, show="*")current_pass_entry.pack(pady=5)ttk.Label(dialog, text="新密码:").pack()new_pass_entry = ttk.Entry(dialog, show="*")new_pass_entry.pack(pady=5)ttk.Label(dialog, text="确认新密码:").pack()confirm_pass_entry = ttk.Entry(dialog, show="*")confirm_pass_entry.pack(pady=5)def update_password():current_pass = current_pass_entry.get()new_pass = new_pass_entry.get()confirm_pass = confirm_pass_entry.get()if not self.auth.current_user.verify_password(current_pass):messagebox.showerror("错误", "当前密码不正确")returnif new_pass != confirm_pass:messagebox.showerror("错误", "两次输入的新密码不一致")returnif len(new_pass) < 6:messagebox.showerror("错误", "密码长度至少6位")return# 更新密码self.auth.current_user.password_hash = User.hash_password(new_pass)self.auth.save_users()messagebox.showinfo("成功", "密码修改成功")dialog.destroy()ttk.Button(dialog, text="确认修改", command=update_password).pack(pady=10)def manage_users(self):"""用户管理(仅管理员)"""if not self.auth.is_admin():returndialog = tk.Toplevel(self.root)dialog.title("用户管理")dialog.geometry("600x400")# 用户列表columns = ("用户名", "角色")user_tree = ttk.Treeview(dialog, columns=columns, show="headings", height=15)for col in columns:user_tree.heading(col, text=col)user_tree.column(col, width=200, anchor='center')user_tree.pack(fill="both", expand=True, padx=10, pady=10)# 填充用户数据for user in self.auth.users.values():user_tree.insert("", "end", values=(user.username, user.role))# 操作按钮btn_frame = ttk.Frame(dialog)btn_frame.pack(pady=10)ttk.Button(btn_frame, text="添加用户", command=lambda: self.add_user_dialog(dialog)).pack(side="left", padx=5)ttk.Button(btn_frame, text="删除用户", command=lambda: self.delete_user(user_tree, dialog)).pack(side="left", padx=5)ttk.Button(btn_frame, text="设为管理员", command=lambda: self.change_user_role(user_tree, "admin", dialog)).pack(side="left", padx=5)ttk.Button(btn_frame, text="设为普通用户", command=lambda: self.change_user_role(user_tree, "user", dialog)).pack(side="left", padx=5)ttk.Button(btn_frame, text="关闭", command=dialog.destroy).pack(side="left", padx=5)def add_user_dialog(self, parent):"""添加用户对话框"""dialog = tk.Toplevel(parent)dialog.title("添加用户")dialog.geometry("400x250")ttk.Label(dialog, text="添加新用户", font=('Arial', 12)).pack(pady=10)ttk.Label(dialog, text="用户名:").pack()new_user_entry = ttk.Entry(dialog)new_user_entry.pack(pady=5)ttk.Label(dialog, text="密码(至少6位):").pack()new_pass_entry = ttk.Entry(dialog, show="*")new_pass_entry.pack(pady=5)ttk.Label(dialog, text="确认密码:").pack()new_pass_confirm_entry = ttk.Entry(dialog, show="*")new_pass_confirm_entry.pack(pady=5)role_var = tk.StringVar(value="user")ttk.Checkbutton(dialog, text="设为管理员", variable=role_var, onvalue="admin", offvalue="user").pack(pady=5)def add_user():username = new_user_entry.get()password = new_pass_entry.get()confirm = new_pass_confirm_entry.get()role = role_var.get()if not username or not password:messagebox.showerror("错误", "用户名和密码不能为空")returnif password != confirm:messagebox.showerror("错误", "两次输入的密码不一致")returnsuccess, msg = self.auth.register(username, password, role)messagebox.showinfo("提示", msg)if success:dialog.destroy()self.manage_users()  # 刷新用户列表ttk.Button(dialog, text="添加", command=add_user).pack(pady=10)def delete_user(self, user_tree, parent):"""删除用户"""selected = user_tree.selection()if not selected:messagebox.showwarning("警告", "请先选择要删除的用户")returnitem = user_tree.item(selected[0])username = item['values'][0]if username == self.auth.current_user.username:messagebox.showerror("错误", "不能删除当前登录的用户")returnif not messagebox.askyesno("确认", f"确定要删除用户 {username} 吗?"):returndel self.auth.users[username]self.auth.save_users()messagebox.showinfo("成功", "用户已删除")self.manage_users()  # 刷新用户列表def change_user_role(self, user_tree, new_role, parent):"""修改用户角色"""selected = user_tree.selection()if not selected:messagebox.showwarning("警告", "请先选择用户")returnitem = user_tree.item(selected[0])username = item['values'][0]if username == self.auth.current_user.username:messagebox.showerror("错误", "不能修改当前登录用户的角色")returnuser = self.auth.users[username]user.role = new_roleself.auth.save_users()messagebox.showinfo("成功", f"用户 {username} 角色已更新为 {new_role}")self.manage_users()  # 刷新用户列表def logout(self):"""用户登出"""self.auth.logout()self.show_login_interface()# 以下是原有员工管理、考勤管理和统计分析功能的实现# 与之前版本相同,只是增加了权限检查# 例如:def on_tab_changed(self, event):"""标签页切换事件处理"""selected_tab = event.widget.tab('current')['text']if selected_tab == "员工管理":self.show_employee_tab()elif selected_tab == "考勤管理":self.show_attendance_tab()elif selected_tab == "统计分析":self.show_stats_tab()def show_employee_tab(self):"""显示员工管理标签页"""# 清除旧内容for widget in self.employee_tab.winfo_children():widget.destroy()# 顶部按钮区域btn_frame = ttk.Frame(self.employee_tab)btn_frame.pack(pady=10)# 根据权限显示不同按钮if self.auth.is_admin():ttk.Button(btn_frame, text="添加员工", command=self.add_employee_dialog).grid(row=0, column=0, padx=5)ttk.Button(btn_frame, text="编辑员工", command=self.edit_employee_dialog).grid(row=0, column=1, padx=5)ttk.Button(btn_frame, text="删除员工", command=self.delete_employee).grid(row=0, column=2, padx=5)ttk.Button(btn_frame, text="刷新列表", command=self.show_employee_tab).grid(row=0, column=3, padx=5)# 搜索区域search_frame = ttk.Frame(self.employee_tab)search_frame.pack(pady=5)ttk.Label(search_frame, text="搜索:").grid(row=0, column=0)self.emp_search_var = tk.StringVar()ttk.Entry(search_frame, textvariable=self.emp_search_var, width=30).grid(row=0, column=1, padx=5)ttk.Button(search_frame, text="搜索", command=self.search_employees).grid(row=0, column=2)ttk.Button(search_frame, text="重置", command=self.reset_search).grid(row=0, column=3)# 员工表格columns = ("ID", "姓名", "部门", "职位", "薪资")self.employee_tree = ttk.Treeview(self.employee_tab, columns=columns, show="headings", height=20)# 设置列属性col_widths = [80, 120, 150, 150, 100]for col, width in zip(columns, col_widths):self.employee_tree.heading(col, text=col)self.employee_tree.column(col, width=width, anchor='center')self.employee_tree.pack(fill="both", expand=True)# 添加滚动条scrollbar = ttk.Scrollbar(self.employee_tree, orient="vertical", command=self.employee_tree.yview)self.employee_tree.configure(yscrollcommand=scrollbar.set)scrollbar.pack(side="right", fill="y")# 填充数据self.populate_employee_tree()# 其他原有方法(add_employee_dialog, edit_employee_dialog等)保持不变# 只需在适当位置添加权限检查,例如:def delete_employee(self):"""删除员工"""if not self.auth.is_admin():messagebox.showerror("权限不足", "只有管理员可以删除员工")returnselected = self.employee_tree.selection()if not selected:messagebox.showwarning("警告", "请先选择要删除的员工")return# 其余删除逻辑与之前相同...# 考勤管理和统计分析功能的实现也类似# 可以根据需要限制某些功能只对管理员开放def export_data(self):"""导出数据"""if not self.auth.is_admin():messagebox.showerror("权限不足", "只有管理员可以导出数据")return# 导出数据的具体实现messagebox.showinfo("提示", "导出功能将在后续版本实现")# 启动GUI应用
if __name__ == "__main__":root = tk.Tk()app = EmployeeGUISystemWithAuth(root)root.mainloop()

数据存储格式

系统使用JSON格式存储数据,示例数据如下:

[{"emp_id": "1001","name": "张三","department": "技术部","position": "工程师","salary": 15000.0},{"emp_id": "1002","name": "李四","department": "人事部","position": "经理","salary": 18000.0}
]

相关文章:

  • 【MySQL】C语言连接
  • SQL正则表达式总结
  • 如何使用 Redis 快速实现排行榜?
  • Unity 中 Update、FixedUpdate 和 LateUpdate 的区别及使用场景
  • MySQL字段为什么要求定义为not null ?
  • Vue项目打包常见问题
  • 怎么选择合适的高防IP
  • 服务器数据恢复—EMC存储raid5阵列故障导致上层应用崩了的数据恢复案例
  • 【Kubernetes】集群内部 Pod 与 Pod 如何通信,CNI是什么?Flannel vs Calico
  • 如何通过数据分析优化项目决策
  • T5和GPT哪个更强大
  • DexGarmentLab 论文翻译
  • DeepSeek R1开源模型的技术突破与AI产业格局的重构
  • 黑马程序员C++核心编程笔记--4 类和对象--封装
  • 纯前端实现图片伪3D视差效果
  • 第二章 1.7 数据采集安全风险防范之数据质量管理
  • 理解频域滤波
  • 【Doris基础】Apache Doris vs 传统数据仓库:架构与性能的全面对比
  • 视觉分析开发范例:Puppeteer截图+计算机视觉动态定位
  • 【golang】channel原理和机制
  • 网站建设ppt模板/武汉seo和网络推广
  • 深圳百度网站推广/网站收录大全
  • 网站建设工具品牌有哪些/谷歌推广一年多少钱
  • 做网站哪家专业/名优网站关键词优化
  • wordpress做公司网站/网络营销公司如何建立
  • 项目计划书ai生成/临沂seo顾问