基于Python的毕业设计选题管理系统设计与实现
基于Python的毕业设计选题管理系统设计与实现
摘要
本论文详细阐述了一个基于Python的毕业设计选题管理系统的设计与实现过程。该系统采用了Python的Tkinter库构建图形用户界面,使用SQLite数据库存储数据,实现了高校毕业设计选题过程中的教师出题、学生选题、管理员协调等核心功能。系统通过角色权限管理确保数据安全性,采用模块化设计提高代码可维护性,最终通过测试验证了系统的稳定性和实用性。该系统能够有效提高选题管理效率,减少人工操作错误,为高校毕业设计管理提供了便捷的解决方案。
关键词 Python;毕业设计管理;选题系统;Tkinter;SQLite
引言
- 研究背景与意义
毕业设计是高等教育人才培养过程中的重要环节,选题管理作为毕业设计的首要步骤,其效率和公平性直接影响到整个毕业设计的质量。传统的选题管理方式主要依靠人工操作,存在流程繁琐、信息不透明、容易出错等问题。随着计算机技术的发展,开发一套高效、便捷的毕业设计选题管理系统具有重要的现实意义。
- 国内外研究现状
目前,国内外针对高校教学管理系统的研究已经取得了一定的成果,但专门针对毕业设计选题管理的系统还相对较少。国外一些高校管理系统功能较为全面,但往往价格昂贵且不符合国内高校的实际需求。国内相关系统在功能完整性、用户体验和系统扩展性方面仍存在不足。
- 研究目标与方法
本研究旨在开发一套适合国内高校使用的毕业设计选题管理系统,实现选题过程的自动化和信息化。研究方法采用需求分析、系统设计、编码实现和测试验证相结合的方式,确保系统满足实际需求且具有良好的性能和可维护性。
系统需求分析
2.1 功能需求
用户管理:支持管理员、教师和学生三种角色的注册、登录和权限管理。
选题管理:教师可以发布、修改和删除选题;学生可以查看选题并提交选题申请;管理员可以审核选题。
选题流程管理:实现选题申请、审核、分配等流程的自动化管理。
数据统计与分析:提供选题情况统计、师生匹配情况分析等功能。 系统设置:支持系统参数配置、用户权限管理等功能。
2.2 非功能需求
性能需求:系统响应时间应控制在合理范围内,确保用户操作的流畅性。
安全性需求:保证用户数据的安全性,防止未授权访问和数据泄露。
易用性需求:界面设计应简洁明了,操作方便快捷,降低用户学习成本。
可扩展性需求:系统应具有良好的扩展性,便于未来功能的升级和扩展。
系统设计
3.1 总体架构设计
系统采用三层架构设计,包括表示层、业务逻辑层和数据访问层: 表示层:负责与用户进行交互,展示系统界面。
业务逻辑层:负责处理系统的业务逻辑,实现各种功能。
数据访问层:负责与数据库进行交互,实现数据的存储和读取。
3.2 数据库设计
系统使用SQLite数据库,主要包含以下数据表:
用户表(users):存储用户基本信息,包括用户名、密码、角色等。
选题表(topics):存储选题信息,包括选题标题、描述、指导教师等。
选题记录表(topic_records):记录学生选题申请的历史和状态。 教师信息表(teachers):存储教师的详细信息。
学生信息表(students):存储学生的详细信息。
3.3 模块设计
系统分为以下几个主要模块:
用户管理模块:负责用户的注册、登录和权限管理。
选题管理模块:负责选题的发布、查询和维护。
选题流程模块:负责选题申请、审核和分配的流程管理。
数据统计模块:负责数据的统计和分析。
系统设置模块:负责系统参数的配置和管理。
系统实现
4.1 开发环境
编程语言:Python 3.9
开发工具:PyCharm
数据库:SQLite
界面库:Tkinter
版本控制:Git
4.2 核心功能实现 以下是系统的核心代码实现:
import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
import hashlib
import os
from datetime import datetimeclass ThesisManagementSystem:def __init__(self, root):self.root = rootself.root.title("毕业设计选题管理系统")self.root.geometry("1024x768")self.current_user = Noneself.current_role = None# 创建数据库self.create_database()# 创建主界面self.create_main_frame()# 添加示例数据self.add_sample_data()def create_database(self):"""创建数据库和表结构"""if not os.path.exists("thesis_management.db"):conn = sqlite3.connect("thesis_management.db")c = conn.cursor()# 创建用户表c.execute('''CREATE TABLE users(id INTEGER PRIMARY KEY AUTOINCREMENT,username TEXT NOT NULL UNIQUE,password TEXT NOT NULL,role TEXT NOT NULL,name TEXT,student_id TEXT,department TEXT,email TEXT,phone TEXT)''')# 创建选题表c.execute('''CREATE TABLE topics(id INTEGER PRIMARY KEY AUTOINCREMENT,title TEXT NOT NULL,description TEXT,teacher_id INTEGER NOT NULL,teacher_name TEXT NOT NULL,department TEXT,status TEXT NOT NULL DEFAULT '未选',student_id INTEGER,student_name TEXT,create_time TEXT,FOREIGN KEY (teacher_id) REFERENCES users (id))''')# 创建选题记录表c.execute('''CREATE TABLE topic_records(id INTEGER PRIMARY KEY AUTOINCREMENT,topic_id INTEGER NOT NULL,student_id INTEGER NOT NULL,student_name TEXT NOT NULL,status TEXT NOT NULL,apply_time TEXT,approve_time TEXT,teacher_feedback TEXT,FOREIGN KEY (topic_id) REFERENCES topics (id),FOREIGN KEY (student_id) REFERENCES users (id))''')conn.commit()conn.close()def add_sample_data(self):"""添加示例数据"""conn = sqlite3.connect("thesis_management.db")c = conn.cursor()# 检查是否已有数据c.execute("SELECT COUNT(*) FROM users")count = c.fetchone()[0]if count == 0:# 添加管理员admin_password = hashlib.sha256("admin123".encode()).hexdigest()c.execute("INSERT INTO users (username, password, role, name) VALUES (?, ?, ?, ?)",("admin", admin_password, "管理员", "系统管理员"))# 添加教师teacher_password = hashlib.sha256("teacher123".encode()).hexdigest()c.execute("INSERT INTO users (username, password, role, name, department, email, phone) VALUES (?, ?, ?, ?, ?, ?, ?)",("teacher1", teacher_password, "教师", "张三", "计算机科学与技术", "zhangsan@example.com", "13800138001"))c.execute("INSERT INTO users (username, password, role, name, department, email, phone) VALUES (?, ?, ?, ?, ?, ?, ?)",("teacher2", teacher_password, "教师", "李四", "软件工程", "lisi@example.com", "13800138002"))# 添加学生student_password = hashlib.sha256("student123".encode()).hexdigest()c.execute("INSERT INTO users (username, password, role, name, student_id, department, email, phone) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",("student1", student_password, "学生", "王五", "20210001", "计算机科学与技术", "wangwu@example.com", "13800138003"))c.execute("INSERT INTO users (username, password, role, name, student_id, department, email, phone) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",("student2", student_password, "学生", "赵六", "20210002", "软件工程", "zhaoliu@example.com", "13800138004"))# 添加选题now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")c.execute("SELECT id FROM users WHERE username = 'teacher1'")teacher1_id = c.fetchone()[0]c.execute("SELECT id FROM users WHERE username = 'teacher2'")teacher2_id = c.fetchone()[0]c.execute("INSERT INTO topics (title, description, teacher_id, teacher_name, department, create_time) VALUES (?, ?, ?, ?, ?, ?)",("基于深度学习的图像识别系统研究", "研究基于深度学习的图像识别技术,实现高效准确的图像分类。", teacher1_id, "张三", "计算机科学与技术", now))c.execute("INSERT INTO topics (title, description, teacher_id, teacher_name, department, create_time) VALUES (?, ?, ?, ?, ?, ?)",("大数据分析在电商推荐系统中的应用", "研究大数据分析技术在电商推荐系统中的应用,提高推荐准确率。", teacher2_id, "李四", "软件工程", now))conn.commit()conn.close()def create_main_frame(self):"""创建主界面"""# 清除现有界面for widget in self.root.winfo_children():widget.destroy()# 创建登录框架login_frame = ttk.Frame(self.root, padding="30 30 30 30")login_frame.pack(fill=tk.BOTH, expand=True)# 标题ttk.Label(login_frame, text="毕业设计选题管理系统", font=("Arial", 20, "bold")).grid(column=0, row=0, columnspan=2, pady=20)# 用户名ttk.Label(login_frame, text="用户名:").grid(column=0, row=1, sticky=tk.W, pady=5)username_entry = ttk.Entry(login_frame, width=30)username_entry.grid(column=1, row=1, sticky=tk.W, pady=5)# 密码ttk.Label(login_frame, text="密码:").grid(column=0, row=2, sticky=tk.W, pady=5)password_entry = ttk.Entry(login_frame, width=30, show="*")password_entry.grid(column=1, row=2, sticky=tk.W, pady=5)# 登录按钮login_button = ttk.Button(login_frame, text="登录", command=lambda: self.login(username_entry.get(), password_entry.get()))login_button.grid(column=1, row=3, sticky=tk.W, pady=20)# 调整布局for child in login_frame.winfo_children():child.grid_configure(padx=5, pady=5)# 设置焦点username_entry.focus()def login(self, username, password):"""用户登录验证"""if not username or not password:messagebox.showerror("错误", "用户名和密码不能为空")returnconn = sqlite3.connect("thesis_management.db")c = conn.cursor()# 验证用户hashed_password = hashlib.sha256(password.encode()).hexdigest()c.execute("SELECT id, role, name FROM users WHERE username = ? AND password = ?", (username, hashed_password))user = c.fetchone()conn.close()if user:self.current_user = user[0]self.current_role = user[1]self.current_name = user[2]messagebox.showinfo("成功", f"欢迎 {self.current_name} ({self.current_role}) 登录系统!")self.show_main_menu()else:messagebox.showerror("错误", "用户名或密码错误")def show_main_menu(self):"""显示主菜单"""# 清除现有界面for widget in self.root.winfo_children():widget.destroy()# 创建主菜单框架menu_frame = ttk.Frame(self.root, padding="10 10 10 10")menu_frame.pack(fill=tk.BOTH, expand=True)# 顶部信息栏info_frame = ttk.Frame(menu_frame)info_frame.pack(fill=tk.X, pady=5)ttk.Label(info_frame, text=f"当前用户: {self.current_name} ({self.current_role})").pack(side=tk.LEFT, padx=10)ttk.Button(info_frame, text="退出登录", command=self.create_main_frame).pack(side=tk.RIGHT, padx=10)# 功能按钮区域buttons_frame = ttk.Frame(menu_frame)buttons_frame.pack(fill=tk.BOTH, expand=True, pady=20)if self.current_role == "管理员":# 管理员功能ttk.Button(buttons_frame, text="用户管理", command=self.manage_users).pack(fill=tk.X, pady=10, padx=20)ttk.Button(buttons_frame, text="选题管理", command=self.manage_topics).pack(fill=tk.X, pady=10, padx=20)ttk.Button(buttons_frame, text="选题统计", command=self.statistics_topics).pack(fill=tk.X, pady=10, padx=20)elif self.current_role == "教师":# 教师功能ttk.Button(buttons_frame, text="添加选题", command=self.add_topic).pack(fill=tk.X, pady=10, padx=20)ttk.Button(buttons_frame, text="管理选题", command=lambda: self.manage_my_topics(self.current_user)).pack(fill=tk.X, pady=10, padx=20)ttk.Button(buttons_frame, text="选题申请审批", command=self.approve_topics).pack(fill=tk.X, pady=10, padx=20)ttk.Button(buttons_frame, text="查看我的学生", command=self.view_my_students).pack(fill=tk.X, pady=10, padx=20)elif self.current_role == "学生":# 学生功能ttk.Button(buttons_frame, text="查看选题", command=self.view_topics).pack(fill=tk.X, pady=10, padx=20)ttk.Button(buttons_frame, text="申请选题", command=self.apply_topic).pack(fill=tk.X, pady=10, padx=20)ttk.Button(buttons_frame, text="我的选题", command=lambda: self.view_my_topic(self.current_user)).pack(fill=tk.X, pady=10, padx=20)ttk.Button(buttons_frame, text="选题历史", command=lambda: self.view_topic_history(self.current_user)).pack(fill=tk.X, pady=10, padx=20)def manage_users(self):"""用户管理界面"""# 清除现有界面for widget in self.root.winfo_children():widget.destroy()# 创建用户管理框架user_frame = ttk.Frame(self.root, padding="10 10 10 10")user_frame.pack(fill=tk.BOTH, expand=True)# 顶部信息栏info_frame = ttk.Frame(user_frame)info_frame.pack(fill=tk.X, pady=5)ttk.Label(info_frame, text="用户管理").pack(side=tk.LEFT, padx=10)ttk.Button(info_frame, text="返回", command=self.show_main_menu).pack(side=tk.RIGHT, padx=10)ttk.Button(info_frame, text="添加用户", command=self.add_user).pack(side=tk.RIGHT, padx=10)# 搜索框search_frame = ttk.Frame(user_frame)search_frame.pack(fill=tk.X, pady=5)ttk.Label(search_frame, text="搜索:").pack(side=tk.LEFT, padx=10)search_entry = ttk.Entry(search_frame, width=30)search_entry.pack(side=tk.LEFT, padx=10)ttk.Label(search_frame, text="角色:").pack(side=tk.LEFT, padx=10)role_var = tk.StringVar()role_combobox = ttk.Combobox(search_frame, textvariable=role_var, values=["全部", "管理员", "教师", "学生"], width=10)role_combobox.pack(side=tk.LEFT, padx=10)role_combobox.current(0)ttk.Button(search_frame, text="搜索", command=lambda: self.search_users(search_entry.get(), role_var.get())).pack(side=tk.LEFT, padx=10)# 用户表格columns = ("id", "username", "role", "name", "student_id", "department", "email", "phone")user_tree = ttk.Treeview(user_frame, columns=columns, show="headings")# 设置列标题user_tree.heading("id", text="ID")user_tree.heading("username", text="用户名")user_tree.heading("role", text="角色")user_tree.heading("name", text="姓名")user_tree.heading("student_id", text="学号/工号")user_tree.heading("department", text="院系")user_tree.heading("email", text="邮箱")user_tree.heading("phone", text="电话")# 设置列宽user_tree.column("id", width=50)user_tree.column("username", width=100)user_tree.column("role", width=80)user_tree.column("name", width=100)user_tree.column("student_id", width=120)user_tree.column("department", width=150)user_tree.column("email", width=150)user_tree.column("phone", width=120)user_tree.pack(fill=tk.BOTH, expand=True, pady=10)# 添加滚动条scrollbar = ttk.Scrollbar(user_tree, orient="vertical", command=user_tree.yview)user_tree.configure(yscroll=scrollbar.set)scrollbar.pack(side=tk.RIGHT, fill=tk.Y)# 绑定双击事件user_tree.bind("<Double-1>", lambda event: self.edit_user(user_tree))# 加载用户数据self.load_users(user_tree)def load_users(self, tree):"""加载用户数据到表格"""# 清空表格for item in tree.get_children():tree.delete(item)conn = sqlite3.connect("thesis_management.db")c = conn.cursor()# 查询用户c.execute("SELECT id, username, role, name, student_id, department, email, phone FROM users ORDER BY id")users = c.fetchall()conn.close()# 添加到表格for user in users:tree.insert("", tk.END, values=user)def search_users(self, keyword, role):"""搜索用户"""# 清空表格user_tree = self.root.winfo_children()[1].winfo_children()[2]for item in user_tree.get_children():user_tree.delete(item)conn = sqlite3.connect("thesis_management.db")c = conn.cursor()# 构建查询条件query = "SELECT id, username, role, name, student_id, department, email, phone FROM users WHERE 1=1"params = []if keyword:query += " AND (username LIKE ? OR name LIKE ? OR student_id LIKE ?)"params.extend([f"%{keyword}%", f"%{keyword}%", f"%{keyword}%"])if role and role != "全部":query += " AND role = ?"params.append(role)query += " ORDER BY id"# 执行查询c.execute(query, params)users = c.fetchall()conn.close()# 添加到表格for user in users:user_tree.insert("", tk.END, values=user)def add_user(self):"""添加用户对话框"""add_window = tk.Toplevel(self.root)add_window.title("添加用户")add_window.geometry("400x350")add_window.resizable(False, False)# 创建表单form_frame = ttk.Frame(add_window, padding="20 20 20 20")form_frame.pack(fill=tk.BOTH, expand=True)# 用户名ttk.Label(form_frame, text="用户名:").grid(column=0, row=0, sticky=tk.W, pady=5)username_entry = ttk.Entry(form_frame, width=30)username_entry.grid(column=1, row=0, sticky=tk.W, pady=5)# 密码ttk.Label(form_frame, text="密码:").grid(column=0, row=1, sticky=tk.W, pady=5)password_entry = ttk.Entry(form_frame, width=30, show="*")password_entry.grid(column=1, row=1, sticky=tk.W, pady=5)# 确认密码ttk.Label(form_frame, text="确认密码:").grid(column=0, row=2, sticky=tk.W, pady=5)confirm_entry = ttk.Entry(form_frame, width=30, show="*")confirm_entry.grid(column=1, row=2, sticky=tk.W, pady=5)# 角色ttk.Label(form_frame, text="角色:").grid(column=0, row=3, sticky=tk.W, pady=5)role_var = tk.StringVar()role_combobox = ttk.Combobox(form_frame, textvariable=role_var, values=["管理员", "教师", "学生"], width=27)role_combobox.grid(column=1, row=3, sticky=tk.W, pady=5)role_combobox.current(0)# 姓名ttk.Label(form_frame, text="姓名:").grid(column=0, row=4, sticky=tk.W, pady=5)name_entry = ttk.Entry(form_frame, width=30)name_entry.grid(column=1, row=4, sticky=tk.W, pady=5)# 学号/工号ttk.Label(form_frame, text="学号/工号:").grid(column=0, row=5, sticky=tk.W, pady=5)id_entry = ttk.Entry(form_frame, width=30)id_entry.grid(column=1, row=5, sticky=tk.W, pady=5)# 院系ttk.Label(form_frame, text="院系:").grid(column=0, row=6, sticky=tk.W, pady=5)department_entry = ttk.Entry(form_frame, width=30)department_entry.grid(column=1, row=6, sticky=tk.W, pady=5)# 邮箱ttk.Label(form_frame, text="邮箱:").grid(column=0, row=7, sticky=tk.W, pady=5)email_entry = ttk.Entry(form_frame, width=30)email_entry.grid(column=1, row=7, sticky=tk.W, pady=5)# 电话ttk.Label(form_frame, text="电话:").grid(column=0, row=8, sticky=tk.W, pady=5)phone_entry = ttk.Entry(form_frame, width=30)phone_entry.grid(column=1, row=8, sticky=tk.W, pady=5)# 按钮button_frame = ttk.Frame(add_window)button_frame.pack(fill=tk.X, pady=10)ttk.Button(button_frame, text="保存", command=lambda: self.save_user(username_entry.get(), password_entry.get(), confirm_entry.get(), role_var.get(), name_entry.get(), id_entry.get(), department_entry.get(), email_entry.get(), phone_entry.get(), add_window)).pack(side=tk.RIGHT, padx=10)ttk.Button(button_frame, text="取消", command=add_window.destroy).pack(side=tk.RIGHT, padx=10)def save_user(self, username, password, confirm_password, role, name, student_id, department, email, phone, window):"""保存用户信息"""if not username or not password:messagebox.showerror("错误", "用户名和密码不能为空")returnif password != confirm_password:messagebox.showerror("错误", "两次输入的密码不一致")returnconn = sqlite3.connect("thesis_management.db")c = conn.cursor()try:# 检查用户名是否已存在c.execute("SELECT id FROM users WHERE username = ?", (username,))if c.fetchone():messagebox.showerror("错误", "用户名已存在")conn.close()return# 加密密码hashed_password = hashlib.sha256(password.encode()).hexdigest()# 插入用户if role == "学生":c.execute("INSERT INTO users (username, password, role, name, student_id, department, email, phone) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",(username, hashed_password, role, name, student_id, department, email, phone))else:c.execute("INSERT INTO users (username, password, role, name, department, email, phone) VALUES (?, ?, ?, ?, ?, ?, ?)",(username, hashed_password, role, name, department, email, phone))conn.commit()messagebox.showinfo("成功", "用户添加成功")window.destroy()# 刷新用户列表user_tree = self.root.winfo_children()[1].winfo_children()[2]self.load_users(user_tree)except Exception as e:messagebox.showerror("错误", f"添加用户失败: {str(e)}")finally:conn.close()def edit_user(self, tree):"""编辑用户信息"""selected_item = tree.selection()if not selected_item:messagebox.showinfo("提示", "请选择要编辑的用户")returnuser_id = tree.item(selected_item[0])['values'][0]conn = sqlite3.connect("thesis_management.db")c = conn.cursor()# 查询用户信息c.execute("SELECT username, role, name, student_id, department, email, phone FROM users WHERE id = ?", (user_id,))user = c.fetchone()conn.close()if not user:messagebox.showerror("错误", "用户不存在")return# 创建编辑窗口edit_window = tk.Toplevel(self.root)edit_window.title("编辑用户")edit_window.geometry("400x350")edit_window.resizable(False, False)# 创建表单form_frame = ttk.Frame(edit_window, padding="20 20 20 20")form_frame.pack(fill=tk.BOTH, expand=True)# 用户名ttk.Label(form_frame, text="用户名:").grid(column=0, row=0, sticky=tk.W, pady=5)username_var = tk.StringVar(value=user[0])username_entry = ttk.Entry(form_frame, textvariable=username_var, width=30)username_entry.grid(column=1, row=0, sticky=tk.W, pady=5)username_entry.config(state="readonly") # 用户名不可修改# 密码ttk.Label(form_frame, text="新密码:").grid(column=0, row=1, sticky=tk.W, pady=5)password_entry = ttk.Entry(form_frame, width=30, show="*")password_entry.grid(column=1, row=1, sticky=tk.W, pady=5)# 确认密码ttk.Label(form_frame, text="确认新密码:").grid(column=0, row=2, sticky=tk.W, pady=5)confirm_entry = ttk.Entry(form_frame, width=30, show="*")confirm_entry.grid(column=1, row=2, sticky=tk.W, pady=5)# 角色ttk.Label(form_frame, text="角色:").grid(column=0, row=3, sticky=tk.W, pady=5)role_var = tk.StringVar(value=user[1])role_combobox = ttk.Combobox(form_frame, textvariable=role_var, values=["管理员", "教师", "学生"], width=27)role_combobox.grid(column=1, row=3, sticky=tk.W, pady=5)# 姓名ttk.Label(form_frame, text="姓名:").grid(column=0, row=4, sticky=tk.W, pady=5)name_var = tk.StringVar(value=user[2])name_entry = ttk.Entry(form_frame, textvariable=name_var, width=30)name_entry.grid(column=1, row=4, sticky=tk.W, pady=5)# 学号/工号ttk.Label(form_frame, text="学号/工号:").grid(column=0, row=5, sticky=tk.W, pady=5)id_var = tk.StringVar(value=user[3] if user[3] else "")id_entry = ttk.Entry(form_frame, textvariable=id_var, width=30)id_entry.grid(column=1, row=5, sticky=tk.W, pady=5)# 院系ttk.Label(form_frame, text="院系:").grid(column=0, row=6, sticky=tk.W, pady=5)department_var = tk.StringVar(value=user[4] if user[4] else "")department_entry = ttk.Entry(form_frame, textvariable=department_var, width=30)department_entry.grid(column=1, row=6, sticky=tk.W, pady=5)# 邮箱ttk.Label(form_frame, text="邮箱:").grid(column=0, row=7, sticky=tk.W, pady=5)email_var = tk.StringVar(value=user[5] if user[5] else "")email_entry = ttk.Entry(form_frame, textvariable=email_var, width=30)email_entry.grid(column=1, row=7, sticky=tk.W, pady=5)# 电话ttk.Label(form_frame, text="电话:").grid(column=0, row=8, sticky=tk.W, pady=5)phone_var = tk.StringVar(value=user[6] if user[6] else "")phone_entry = ttk.Entry(form_frame, textvariable=phone_var, width=30)phone_entry.grid(column=1, row=8, sticky=tk.W, pady=5)# 按钮button_frame = ttk.Frame(edit_window)button_frame.pack(fill=tk.X, pady=10)ttk.Button(button_frame, text="保存", command=lambda: self.update_user(user_id, password_entry.get(), confirm_entry.get(), role_var.get(), name_var.get(), id_var.get(), department_var.get(), email_var.get(), phone_var.get(), edit_window, tree)).pack(side=tk.RIGHT, padx=10)ttk.Button(button_frame, text="取消", command=edit_window.destroy).pack(side=tk.RIGHT, padx=10)def update_user(self, user_id, password, confirm_password, role, name, student_id, department, email, phone, window, tree):"""更新用户信息"""if password and password != confirm_password:messagebox.showerror("错误", "两次输入的密码不一致")returnconn = sqlite3.connect("thesis_management.db")c = conn.cursor()try:# 更新用户信息if password:# 加密新密码hashed_password = hashlib.sha256(password.encode()).hexdigest()if role == "学生":c.execute("UPDATE users SET password = ?, role = ?, name = ?, student_id = ?, department = ?, email = ?, phone = ? WHERE id = ?",(hashed_password, role, name, student_id, department, email, phone, user_id))else:c.execute("UPDATE users SET password = ?, role = ?, name = ?, department = ?, email = ?, phone = ?, student_id = NULL WHERE id = ?",(hashed_password, role, name, department, email, phone, user_id))else:if role == "学生":c.execute("UPDATE users SET role = ?, name = ?, student_id = ?, department = ?, email = ?, phone = ? WHERE id = ?",(role, name, student_id, department, email, phone, user_id))else:c.execute("UPDATE users SET role = ?, name = ?, department = ?, email = ?, phone = ?, student_id = NULL WHERE id = ?",(role, name, department, email, phone, user_id))conn.commit()messagebox.showinfo("成功", "用户信息更新成功")window.destroy()# 刷新用户列表self.load_users(tree)except Exception as e:messagebox.showerror("错误", f"更新用户失败: {str(e)}")finally:conn.close()# 其他功能实现... (代码太长,此处省略其他方法的实现)if __name__ == "__main__":root = tk.Tk()app = ThesisManagementSystem(root)root.mainloop()
4.3 界面设计
系统采用Tkinter库实现图形用户界面,主要包括以下界面:
登录界面:用户登录系统的入口。
主菜单界面:根据用户角色显示不同的功能菜单。
选题管理界面:教师发布和管理选题的界面。
选题浏览界面:学生查看和申请选题的界面。
选题审批界面:教师审批学生选题申请的界面。
用户管理界面:管理员管理用户信息的界面。
系统测试
5.1 测试环境
操作系统:Windows 10
Python版本:3.9
数据库:SQLite 3
5.2 测试方法与用例
采用黑盒测试方法,设计了以下测试用例:
用户登录测试:验证不同角色用户能否成功登录系统。
选题管理测试:验证教师能否正常发布、修改和删除选题。
选题申请测试:验证学生能否正常查看和申请选题。
选题审批测试:验证教师能否正常审批学生的选题申请。
数据统计测试:验证系统能否正确统计选题情况和师生匹配情况。
5.3 测试结果
通过对系统的功能和性能进行测试,结果表明系统能够满足高校毕业设计选题管理的基本需求,各项功能运行正常,界面友好,操作简便。
总结与展望
6.1 研究成果总结
本论文成功设计并实现了一个基于Python的毕业设计选题管理系统,该系统具有以下特点:
采用模块化设计,提高了系统的可维护性和可扩展性。
使用SQLite数据库,简化了系统部署和维护。
实现了用户权限管理,确保了数据的安全性。
提供了友好的用户界面,降低了用户的使用难度。
6.2 不足与展望
尽管系统已经实现了预期的功能,但仍存在一些不足之处,例如:
缺乏移动端支持,用户体验有待提升。
统计分析功能还不够完善,需要进一步增强。
系统的安全性还需要进一步加强。
未来的工作将主要集中在以下几个方面:
开发移动端应用,实现多平台支持。
增强系统的统计分析功能,提供更多的数据可视化方式。
加强系统的安全防护,提高系统的安全性。