赞
踩
使用模块要求:
tkinter、numpy、openpyxl、matplotlib、pymysql、re、time;其中matplotlib用于绘制统计图
开发工具:pycharm专业版、python3.7、mysql8.0
运行效果:
主页面:
教师端主要功能:
教师端登录后的效果——个人资料页面:
教师端登录后的效果——学生查询页面:
教师端登录后的效果——成绩查询页面:
教师端登录后的效果——成绩分析页面:
成绩分析页面——课程成绩分析(统计图):
各班级创建分析页面——统计图:
班级综合成绩评定页面——扇形统计图:
修改密码页面:
课程管理页面——根据学院、考试方式进行添加或删除课程:
Teacherpage.py页面代码如下:
更多代码:看主页联系、或访问:
腾讯文档腾讯文档-在线文档https://docs.qq.com/doc/p/71239d69a76f56cf1521717ae6b22c27cf876f10
- from tkinter import *
- from tkinter import messagebox, filedialog
- from tkinter.ttk import *
-
- import openpyxl as openpyxl
-
- import AddCoursePage
- import AddScorePage
- import ClassGradeAnalysis
- import ComprehensivePerformanceEvaluation
- import CourseScoreAnalysis
- import Dao
- import DeleteCoursePage
- import DeleteScorePage
- import Login
- import UpdateCoursePage
-
- import AddStudentPage
- import DeleteStudentPage
- import UpdateScorePage
- import UpdateStudentPage
-
- import numpy as np
- import matplotlib.pyplot as plt
-
- class WinGUI(Tk):
- def __init__(self):
- super().__init__()
- self.__win()
- self.tk_label_title = self.__tk_label_title()
- self.tk_label_current_user = self.__tk_label_current_user()
- self.tk_tabs_content = Frame_content(self)
- self.tk_button_logout_user = self.__tk_button_logout_user()
-
- def __win(self):
- self.title("教师端")
- # 设置窗口大小、居中
- width = 1000
- height = 600
- screenwidth = self.winfo_screenwidth()
- screenheight = self.winfo_screenheight()
- geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
- self.geometry(geometry)
- self.resizable(width=False, height=False)
- self.iconbitmap('logo.ico')
-
- def __tk_label_title(self):
- label = Label(self, text="学生成绩管理系统", anchor="center")
- label.place(x=0, y=0, width=800, height=100)
- return label
-
- def __tk_label_current_user(self):
- label = Label(self, text="当前用户:admin", anchor="center")
- label.place(x=800, y=70, width=150, height=30)
- return label
-
- def __tk_button_logout_user(self):
- btn = Button(self, text="退出")
- btn.place(x=950, y=70, width=50, height=30)
- return btn
-
-
- class Frame_content(Notebook):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
-
- def __frame(self):
- self.tk_tabs_content_0 = Frame_content_0(self)
- self.add(self.tk_tabs_content_0, text="个人资料")
-
- self.tk_tabs_content_1 = Frame_content_1(self)
- self.add(self.tk_tabs_content_1, text="学生查询")
-
- self.tk_tabs_content_2 = Frame_content_2(self)
- self.add(self.tk_tabs_content_2, text="成绩查询")
-
- self.tk_tabs_content_3 = Frame_content_3(self)
- self.add(self.tk_tabs_content_3, text="成绩分析")
-
- self.tk_tabs_content_4 = Frame_content_4(self)
- self.add(self.tk_tabs_content_4, text="修改密码")
-
- self.tk_tabs_content_5 = Frame_content_5(self)
- self.add(self.tk_tabs_content_5, text="课程管理")
-
- self.place(x=0, y=100, width=1000, height=500)
-
-
- class Frame_content_0(Frame):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
- self.tk_label_tea_number = self.__tk_label_tea_number()
- self.tk_input_tea_number = self.__tk_input_tea_number()
- self.tk_label_tea_name = self.__tk_label_tea_name()
- self.tk_input_tea_name = self.__tk_input_tea_name()
- self.tk_label_tea_gender = self.__tk_label_tea_gender()
- self.tk_select_tea_gender = self.__tk_select_tea_gender()
- self.tk_label_tea_identity = self.__tk_label_tea_identity()
- self.tk_input_tea_identity = self.__tk_input_tea_identity()
- self.tk_label_tea_email = self.__tk_label_tea_email()
- self.tk_input_tea_email = self.__tk_input_tea_email()
- self.tk_button_tea_update = self.__tk_button_tea_update()
- self.tk_button_tea_reset = self.__tk_button_tea_reset()
-
- def __frame(self):
- self.place(x=0, y=100, width=1000, height=500)
-
- def __tk_label_tea_number(self):
- label = Label(self, text="工号", anchor="e")
- label.place(x=360, y=40, width=100, height=30)
- return label
-
- def __tk_input_tea_number(self):
- self.tea_number = StringVar(self)
- ipt = Entry(self, text=self.tea_number)
- ipt.place(x=490, y=40, width=150, height=30)
- ipt.config(stat='disable')
- return ipt
-
- def __tk_label_tea_name(self):
- label = Label(self, text="姓名", anchor="e")
- label.place(x=360, y=110, width=100, height=30)
- return label
-
- def __tk_input_tea_name(self):
- self.tea_name = StringVar(self)
- ipt = Entry(self, text=self.tea_name)
- ipt.place(x=490, y=110, width=150, height=30)
- return ipt
-
- def __tk_label_tea_gender(self):
- label = Label(self, text="性别", anchor="e")
- label.place(x=360, y=180, width=100, height=30)
- return label
-
- def __tk_select_tea_gender(self):
- cb = Combobox(self, state='readonly')
- cb['values'] = ("男", "女")
- cb.place(x=490, y=180, width=150, height=30)
- return cb
-
- def __tk_label_tea_identity(self):
- label = Label(self, text="身份证号", anchor="e")
- label.place(x=360, y=250, width=100, height=30)
- return label
-
- def __tk_input_tea_identity(self):
- self.tea_identify = StringVar(self)
- ipt = Entry(self, text=self.tea_identify)
- ipt.place(x=490, y=250, width=150, height=30)
- return ipt
-
- def __tk_label_tea_email(self):
- label = Label(self, text="电子邮箱", anchor="e")
- label.place(x=360, y=320, width=100, height=30)
- return label
-
- def __tk_input_tea_email(self):
- self.tea_email = StringVar(self)
- ipt = Entry(self, text=self.tea_email)
- ipt.place(x=490, y=320, width=150, height=30)
- return ipt
-
- def __tk_button_tea_update(self):
- btn = Button(self, text="修改")
- btn.place(x=400, y=390, width=80, height=30)
- return btn
-
- def __tk_button_tea_reset(self):
- btn = Button(self, text="重置")
- btn.place(x=520, y=390, width=80, height=30)
- return btn
-
-
- class Frame_content_1(Frame):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
- self.tk_table_student_query = self.__tk_table_student_query()
- self.tk_input_stu_name = self.__tk_input_stu_name()
- self.tk_select_box_stu_gender = self.__tk_select_box_stu_gender()
- self.tk_button_stu_search = self.__tk_button_stu_search()
- self.tk_button_addStudent = self.__tk_button_addStudent()
- self.tk_button_delete_student = self.__tk_button_delete_student()
- self.tk_button_stu_refresh = self.__tk_button_stu_refresh()
- self.tk_button_studentinfo_export = self.__tk_button_studentinfo_export()
-
- def __frame(self):
- self.place(x=0, y=100, width=1000, height=500)
-
- def __tk_table_student_query(self):
- # 表头字段 表头宽度
- self.tk_table_student_manage_columns = {"ID": 50, "学号": 100, "姓名": 150, '性别': 100, '身份证号': 300, '班级': 100, '邮箱': 200}
- # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。
- tk_table = Treeview(self, show="headings", columns=list(self.tk_table_student_manage_columns))
- for text, width in self.tk_table_student_manage_columns.items(): # 批量设置列属性
- tk_table.heading(text, text=text, anchor='center')
- tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
-
- # 插入数据示例
-
- #
- # # 导入初始数据
- self.tk_student_table_dataset = Dao.getAllStudents()
- if self.tk_student_table_dataset.get("code") == 0:
- if self.tk_student_table_dataset.get("data"):
- print(self.tk_student_table_dataset.get("data"))
- for values in self.tk_student_table_dataset.get("data"):
- tk_table.insert('', END, values=list(values.values()))
- else:
- print("未查询到数据!")
- else:
- print("数据查询异常!")
-
- tk_table.place(x=0, y=60, width=1000, height=415)
- return tk_table
-
- def __tk_input_stu_name(self):
- ipt = Entry(self)
- ipt.place(x=360, y=10, width=150, height=30)
- return ipt
-
- def __tk_select_box_stu_gender(self):
- cb = Combobox(self, state="readonly")
- cb['values'] = ("请选择性别", "男", "女")
- cb.place(x=540, y=10, width=150, height=30)
- cb.current(0)
- return cb
-
- def __tk_button_stu_search(self):
- btn = Button(self, text="搜索")
- btn.place(x=720, y=10, width=70, height=30)
- return btn
-
- def __tk_button_stu_refresh(self):
- btn = Button(self, text="刷新")
- btn.place(x=820, y=10, width=70, height=30)
- return btn
-
- def __tk_button_addStudent(self):
- btn = Button(self, text="添加学生")
- btn.place(x=50, y=10, width=100, height=30)
- return btn
-
- def __tk_button_delete_student(self):
- btn = Button(self, text="删除学生")
- btn.place(x=180, y=10, width=100, height=30)
- return btn
-
- def __tk_button_studentinfo_export(self):
- btn = Button(self, text="导出")
- btn.place(x=920, y=10, width=50, height=30)
- return btn
-
-
- class Frame_content_2(Frame):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
- self.tk_table_stu_score = self.__tk_table_stu_score()
- self.tk_button_add_score = self.__tk_button_add_score()
- self.tk_button_delete_score = self.__tk_button_delete_score()
- self.tk_select_box_score_course_name = self.__tk_select_box_score_course_name()
- self.tk_select_box_score_nature = self.__tk_select_box_score_nature()
- self.tk_select_box_score_department = self.__tk_select_box_score_department()
- self.tk_button_stu_score_search = self.__tk_button_stu_score_search()
- self.tk_button_stu_score_export = self.__tk_button_stu_score_export()
-
- def __frame(self):
- self.place(x=0, y=100, width=1000, height=500)
-
- def __tk_table_stu_score(self):
- # 表头字段 表头宽度
- self.tk_table_stu_score_columns = {"#": 50, "学号": 70, "姓名": 80, "课程名称": 200, "课程性质": 100, "开课学院": 270, "考试方式": 80, "学分": 50, "成绩": 100}
- # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。
- tk_table = Treeview(self, show="headings", columns=list(self.tk_table_stu_score_columns))
- for text, width in self.tk_table_stu_score_columns.items(): # 批量设置列属性
- tk_table.heading(text, text=text, anchor='center')
- tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
-
- # 插入数据示例
- self.tk_score_table_dataset = Dao.searchStudentScore()
- # 导入初始数据
- if self.tk_score_table_dataset.get("code") == 0 and self.tk_score_table_dataset.get("data"):
- for data in self.tk_score_table_dataset.get("data"):
- tk_table.insert('', END, values=list(data.values()))
-
- tk_table.place(x=0, y=60, width=1000, height=415)
- return tk_table
-
- def __tk_button_add_score(self):
- btn = Button(self, text="添加成绩")
- btn.place(x=50, y=10, width=100, height=30)
- return btn
-
- def __tk_button_delete_score(self):
- btn = Button(self, text="删除成绩")
- btn.place(x=170, y=10, width=100, height=30)
- return btn
-
- def __tk_select_box_score_course_name(self):
- cb = Combobox(self, state="readonly")
- values = ["请选择课程名称"]
- for i in Dao.getAllCourses().get("data"):
- values.append(i.get("cname"))
- cb['values'] = values
- cb.current(0)
- cb.place(x=290, y=10, width=150, height=30)
- return cb
-
- def __tk_select_box_score_nature(self):
- cb = Combobox(self, state="readonly")
- values = ["请选择课程性质"]
- for i in Dao.getDataDictByType("nature").get("data"):
- values.append(i.get("v"))
- cb['values'] = values
- cb.current(0)
- cb.place(x=460, y=10, width=150, height=30)
- return cb
-
- def __tk_select_box_score_department(self):
- cb = Combobox(self, state="readonly")
- values = ["请选择开课学院"]
- for i in Dao.getAllDepartments().get("data"):
- values.append(i.get("v"))
- cb['values'] = values
- cb.current(0)
- cb.place(x=630, y=10, width=150, height=30)
- return cb
-
- def __tk_button_stu_score_search(self):
- btn = Button(self, text="搜索")
- btn.place(x=800, y=10, width=70, height=30)
- return btn
-
- def __tk_button_stu_score_export(self):
- btn = Button(self, text="导出")
- btn.place(x=890, y=10, width=70, height=30)
- return btn
-
-
- class Frame_content_3(Frame):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
- self.tk_button_pieChart = self.__tk_button_pieChart()
- self.tk_button_columnChart = self.__tk_button_columnChart()
- self.tk_button_paratacticColumnChart = self.__tk_button_paratacticColumnChart()
-
- def __frame(self):
- self.place(x=0, y=100, width=1000, height=500)
-
- def __tk_button_columnChart(self):
- btn = Button(self, text="课程成绩分析")
- btn.place(x=80, y=50, width=150, height=70)
- return btn
-
- def __tk_button_paratacticColumnChart(self):
- btn = Button(self, text="班级成绩分析")
- btn.place(x=420, y=50, width=150, height=70)
- return btn
-
- def __tk_button_pieChart(self):
- btn = Button(self, text="综合成绩评定")
- btn.place(x=760, y=50, width=150, height=70)
- return btn
-
-
- class Frame_content_4(Frame):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
- self.tk_label_original_pwd = self.__tk_label_original_pwd()
- self.tk_input_original_pwd = self.__tk_input_original_pwd()
- self.tk_label_new_pwd = self.__tk_label_new_pwd()
- self.tk_input_new_pwd = self.__tk_input_new_pwd()
- self.tk_label_confirm_pwd = self.__tk_label_confirm_pwd()
- self.tk_input_confirm_pwd = self.__tk_input_confirm_pwd()
- self.tk_button_update_tea_pwd = self.__tk_button_update_tea_pwd()
-
- def __frame(self):
- self.place(x=0, y=100, width=1000, height=500)
-
- def __tk_label_original_pwd(self):
- label = Label(self, text="原密码", anchor="e")
- label.place(x=360, y=40, width=100, height=30)
- return label
-
- def __tk_input_original_pwd(self):
- ipt = Entry(self, show='*')
- ipt.place(x=490, y=40, width=150, height=30)
- return ipt
-
- def __tk_label_new_pwd(self):
- label = Label(self, text="新密码", anchor="e")
- label.place(x=360, y=110, width=100, height=30)
- return label
-
- def __tk_input_new_pwd(self):
- ipt = Entry(self, show='*')
- ipt.place(x=490, y=110, width=150, height=30)
- return ipt
-
- def __tk_label_confirm_pwd(self):
- label = Label(self, text="确认密码", anchor="e")
- label.place(x=360, y=180, width=100, height=30)
- return label
-
- def __tk_input_confirm_pwd(self):
- ipt = Entry(self, show='*')
- ipt.place(x=490, y=180, width=150, height=30)
- return ipt
-
- def __tk_button_update_tea_pwd(self):
- btn = Button(self, text="修改")
- btn.place(x=450, y=260, width=100, height=30)
- return btn
-
-
- class Frame_content_5(Frame):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
- self.tk_table_course_manage = self.__tk_table_course_manage()
- self.tk_button_add_course = self.__tk_button_add_course()
- self.tk_button_delete_course = self.__tk_button_delete_course()
- self.tk_select_box_course_department = self.__tk_select_box_course_department()
- self.tk_select_box_course_exam_method = self.__tk_select_box_course_exam_method()
- self.tk_button_course_search = self.__tk_button_course_search()
- self.tk_button_course_export = self.__tk_button_course_export()
-
- def __frame(self):
- self.place(x=0, y=100, width=1000, height=500)
-
- def __tk_table_course_manage(self):
- # 表头字段 表头宽度
- self.tk_table_course_manage_columns = {"课程号": 100, "课程名称": 200, "学分": 100, "课程性质": 200, "开课学院": 300, "考试方式": 100}
- # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。
- tk_table = Treeview(self, show="headings", columns=list(self.tk_table_course_manage_columns))
- for text, width in self.tk_table_course_manage_columns.items(): # 批量设置列属性
- tk_table.heading(text, text=text, anchor='center')
- tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
-
- # 插入数据示例
- self.tk_course_table_dataset = Dao.getAllCourses()
- # 导入初始数据
- if self.tk_course_table_dataset.get("code") == 0 and self.tk_course_table_dataset.get("data"):
- for data in self.tk_course_table_dataset.get("data"):
- tk_table.insert('', END, values=list(data.values()))
-
- tk_table.place(x=0, y=60, width=1000, height=415)
- return tk_table
-
- def __tk_button_add_course(self):
- btn = Button(self, text="添加课程")
- btn.place(x=50, y=10, width=100, height=30)
- return btn
-
- def __tk_button_delete_course(self):
- btn = Button(self, text="删除课程")
- btn.place(x=180, y=10, width=100, height=30)
- return btn
-
- def __tk_select_box_course_department(self):
- cb = Combobox(self, state="readonly")
- values = ["请选择开课学院"]
- for i in Dao.getAllDepartments().get("data"):
- values.append(i.get("v"))
- cb['values'] = values
- cb.current(0)
- cb.place(x=310, y=10, width=150, height=30)
- return cb
-
- def __tk_select_box_course_exam_method(self):
- cb = Combobox(self, state="readonly")
- values = ["请选择考试方式"]
- for i in Dao.getDataDictByType("exammethod").get("data"):
- values.append(i.get("v"))
- cb['values'] = values
- cb.current(0)
- cb.place(x=490, y=10, width=150, height=30)
- return cb
-
- def __tk_button_course_search(self):
- btn = Button(self, text="搜索")
- btn.place(x=670, y=10, width=100, height=30)
- return btn
-
- def __tk_button_course_export(self):
- btn = Button(self, text="导出")
- btn.place(x=800, y=10, width=100, height=30)
- return btn
-
-
- class Win(WinGUI):
- def __init__(self, current_user):
- super().__init__()
- self.__event_bind()
- self.current_user = current_user
- self.uid = current_user.get("uid")
- self.tk_label_current_user['text'] = "当前用户:" + current_user.get("uname")
- self.tk_tabs_content.tk_tabs_content_0.tea_number.set(current_user.get("uid"))
- self.tk_tabs_content.tk_tabs_content_0.tea_name.set(current_user.get("uname"))
- self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.current(0 if current_user.get("ugender") == '男' else 1)
- self.tk_tabs_content.tk_tabs_content_0.tea_identify.set(current_user.get("uidentify"))
- self.tk_tabs_content.tk_tabs_content_0.tea_email.set(current_user.get("uemail"))
-
- def logout(self):
- try:
- self.updateStudent.destroy()
- self.addInfo.destroy()
- self.delete.destroy()
- except Exception as e:
- print(e)
- messagebox.showwarning('提示', '欢迎下次使用!')
- self.destroy()
- login = Login.Win()
- login.mainloop()
-
- def updateStudentInfo(self, evt):
- current_focus = self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.focus()
- current_studentinfo = self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.set(current_focus)
- current_uid = current_studentinfo.get('学号')
- self.updateStudent = UpdateStudentPage.Win(current_uid)
- self.updateStudent.mainloop()
- print("<<TreeviewSelect>>事件未处理", evt)
-
- def updateTeacherInfo(self, evt):
- __tea_name = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_name.get()
- __tea_gender = self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.get()
- __tea_identify = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_identity.get()
- __tea_email = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_email.get()
- if not __tea_name or not __tea_gender or not __tea_identify or not __tea_email:
- messagebox.showinfo("提示", "必填项不能为空!")
- return
- if not re.match(r'^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$',
- __tea_identify):
- messagebox.showinfo("提示", "身份证格式不合法!")
- return
- if not re.match(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$', __tea_email):
- messagebox.showinfo("提示", "电子邮箱格式不合法!")
- return
- res = Dao.updateUser(self.uid, __tea_name, __tea_gender, __tea_identify, 0, __tea_email)
- messagebox.showinfo("提示", res.get("msg"))
- self.tk_label_current_user['text'] = "当前用户:" + __tea_name
- print("更新教师信息", evt)
-
- def resetTeacherInfo(self, evt):
- self.tk_tabs_content.tk_tabs_content_0.tea_name.set(self.current_user.get("uname"))
- self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.current(0 if self.current_user.get("ugender") == '男' else 1)
- self.tk_tabs_content.tk_tabs_content_0.tea_identify.set(self.current_user.get("uidentify"))
- self.tk_tabs_content.tk_tabs_content_0.tea_email.set(self.current_user.get("uemail"))
- print("重置教师信息", evt)
-
- def searchStudentInfo(self, evt):
- for _ in map(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.delete,
- self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.get_children("")):
- pass
- value = self.tk_tabs_content.tk_tabs_content_1.tk_input_stu_name.get()
- num = self.tk_tabs_content.tk_tabs_content_1.tk_select_box_stu_gender.get()
- print(num, value)
- if num == '请选择性别':
- result = Dao.searchStudents(value, '')
- else:
- result = Dao.searchStudents(value, num)
- if result.get("code") == 0:
- if result.get("data"):
- # print(result.get("data"))
- for values in result.get("data"):
- self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.insert('', END, values=list(values.values()))
- else:
- print("未查询到数据!")
- else:
- print("数据查询异常!")
- print("搜索学生信息", evt)
-
- def updateStudentScore(self, evt):
- current_item = self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score.set(self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score.focus())
- data = {
- "uid": current_item.get("学号"),
- "cname": current_item.get("课程名称"),
- "score": current_item.get("成绩")
- }
- updateScorePage = UpdateScorePage.Win(data)
- updateScorePage.mainloop()
- print("修改学生课程成绩", evt)
-
- def searchStuScore(self, evt):
- __score_manage = self.tk_tabs_content.tk_tabs_content_2
- __course_name = __score_manage.tk_select_box_score_course_name.get()
- __course_nature = __score_manage.tk_select_box_score_nature.get()
- __course_department = __score_manage.tk_select_box_score_department.get()
- if __score_manage.tk_select_box_score_course_name.current() == 0:
- __course_name = ''
- if __score_manage.tk_select_box_score_nature.current() == 0:
- __course_nature = ''
- if __score_manage.tk_select_box_score_department.current() == 0:
- __course_department = ''
- for _ in map(__score_manage.tk_table_stu_score.delete, __score_manage.tk_table_stu_score.get_children("")):
- pass
- __score_manage.tk_score_table_dataset = Dao.searchStudentScore(__course_name, __course_nature, __course_department)
- # 导入初始数据
- if __score_manage.tk_score_table_dataset.get("code") == 0 and __score_manage.tk_score_table_dataset.get("data"):
- for data in __score_manage.tk_score_table_dataset.get("data"):
- __score_manage.tk_table_stu_score.insert('', END, values=list(data.values()))
- __score_manage.tk_select_box_score_course_name.current(0)
- __score_manage.tk_select_box_score_nature.current(0)
- __score_manage.tk_select_box_score_department.current(0)
- print("搜索学生成绩!")
-
- def exportStuScore(self, evt):
- path = filedialog.askdirectory()
- try:
- book = openpyxl.Workbook()
- sheet = book.active
- fff = list(self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score_columns.keys()) # 获取表头信息
- sheet.append(fff)
- dataset = [list(data_item.values()) for data_item in
- self.tk_tabs_content.tk_tabs_content_2.tk_score_table_dataset.get("data")]
- print(dataset)
- for i in dataset:
- sheet.append(i)
- book.save(f"{path}/student_score.xlsx")
- messagebox.showinfo("提示", "导出成功!")
- except Exception as e:
- messagebox.showinfo("提示", "导出失败!")
- print(e)
- print("导出学生成绩!", evt)
-
- def addStudentInfo(self, evt):
- self.addInfo = AddStudentPage.Win()
- self.addInfo.mainloop()
- print("<Button-1>事件未处理", evt)
-
- def deleteStudentInfo(self, evt):
- self.delete = DeleteStudentPage.Win()
- self.delete.mainloop()
- print("<Button-1>事件未处理", evt)
-
- def addStudentScore(self, evt):
- addScorePage = AddScorePage.Win()
- addScorePage.mainloop()
-
- def deleteStudentScore(self, evt):
- deleteScorePage = DeleteScorePage.Win()
- deleteScorePage.mainloop()
- print("删除学生成绩", evt)
-
- def updateTeacherPassword(self, evt):
- __original_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_original_pwd.get()
- __new_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_new_pwd.get()
- __confirm_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_confirm_pwd.get()
- if __original_pwd == '' or __new_pwd == '' or __confirm_pwd == '':
- messagebox.showwarning("提示", "必填项未填写!")
- return
- if not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __original_pwd) \
- or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __new_pwd) \
- or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __confirm_pwd):
- messagebox.showwarning("提示", "密码格式应为6-18位数字、字母、特殊字符的组合!")
- return
- if __new_pwd != __confirm_pwd:
- messagebox.showwarning("提示", "两次密码输入不一致")
- return
- res = Dao.updatePassword(self.uid, __original_pwd, __new_pwd)
- messagebox.showinfo("提示", res.get("msg"))
- if res.get("code") == 0:
- self.destroy()
- login = Login.Win()
- login.mainloop()
- print("修改教师密码", evt)
-
- def addCourseInfo(self, evt):
- addCoursePage = AddCoursePage.Win()
- addCoursePage.mainloop()
- print("添加成绩!")
-
- def deleteCourseInfo(self, evt):
- deleteCoursePage = DeleteCoursePage.Win()
- deleteCoursePage.mainloop()
- print("删除课程!")
-
- def searchCourseInfo(self, evt):
- __course_manage = self.tk_tabs_content.tk_tabs_content_5
- __department = __course_manage.tk_select_box_course_department.get()
- __exammethod = __course_manage.tk_select_box_course_exam_method.get()
- if __course_manage.tk_select_box_course_department.current() == 0:
- __department = ''
- if __course_manage.tk_select_box_course_exam_method.current() == 0:
- __exammethod = ''
- for _ in map(__course_manage.tk_table_course_manage.delete, __course_manage.tk_table_course_manage.get_children("")):
- pass
- self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset = Dao.searchCourses(__department, __exammethod)
- # 导入初始数据
- if self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("code") == 0 and self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data"):
- for data in self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data"):
- __course_manage.tk_table_course_manage.insert('', END, values=list(data.values()))
- __course_manage.tk_select_box_course_department.current(0)
- __course_manage.tk_select_box_course_exam_method.current(0)
- print("查询课程!")
-
- def updateCourseInfo(self, evt):
- __focus = self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.focus()
- current_item = self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.set(__focus)
- __cid = current_item.get("课程号")
- self.updateCoursePage = UpdateCoursePage.Win(__cid)
- self.updateCoursePage.mainloop()
- print("更新课程信息!")
-
- def exportCourseInfo(self, evt):
- path = filedialog.askdirectory()
- try:
- book = openpyxl.Workbook()
- sheet = book.active
- fff = list(self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage_columns.keys()) # 获取表头信息
- sheet.append(fff)
- dataset = [list(data_item.values()) for data_item in self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data")]
- print(dataset)
- for i in dataset:
- sheet.append(i)
- book.save(path + "/course_info.xlsx")
- messagebox.showinfo("提示", "导出成功!")
- except Exception as e:
- messagebox.showinfo("提示", "导出失败!")
- print(e)
-
- def logout_user(self, evt):
- messagebox.showwarning('提示', '欢迎下次使用!')
- self.destroy()
- login = Login.Win()
- login.mainloop()
-
- def studentinfo_refresh(self, evt):
- # 删除原结点,加入新结点
- for _ in map(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.delete,
- self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.get_children("")):
- pass
- result = Dao.getAllStudents()
- if result.get("code") == 0:
- if result.get("data"):
- # print(result.get("data"))
- for values in result.get("data"):
- self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.insert('', END,
- values=list(values.values()))
- else:
- print("未查询到数据!")
- else:
- print("数据查询异常!")
-
- def studentinfo_export(self, evt):
- path = filedialog.askdirectory()
- try:
- book = openpyxl.Workbook()
- sheet = book.active
- fff = list(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_manage_columns.keys()) # 获取表头信息
- sheet.append(fff)
- dataset = [list(data_item.values()) for data_item in
- self.tk_tabs_content.tk_tabs_content_1.tk_student_table_dataset.get("data")]
- print(dataset)
- for i in dataset:
- sheet.append(i)
- book.save(path + "/student_info.xlsx")
- messagebox.showinfo("提示", "导出成功!")
- except Exception as e:
- messagebox.showinfo("提示", "导出失败!")
- print(e)
-
- def columnChart(self, evt):
- courseScoreAnalysis = CourseScoreAnalysis.Win()
- courseScoreAnalysis.mainloop()
-
- def paratacticColumnChart(self, evt):
- classGradeAnalysis = ClassGradeAnalysis.Win()
- classGradeAnalysis.mainloop()
-
- def pieChart(self, evt):
- comprehensivePerformanceEvaluation = ComprehensivePerformanceEvaluation.Win()
- comprehensivePerformanceEvaluation.mainloop()
-
-
- def __event_bind(self):
- self.protocol('WM_DELETE_WINDOW', self.logout)
- self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.bind('<<TreeviewSelect>>', self.updateStudentInfo)
- self.tk_tabs_content.tk_tabs_content_0.tk_button_tea_update.bind('<Button-1>', self.updateTeacherInfo)
- self.tk_tabs_content.tk_tabs_content_0.tk_button_tea_reset.bind('<Button-1>', self.resetTeacherInfo)
- self.tk_tabs_content.tk_tabs_content_1.tk_button_stu_search.bind('<Button-1>', self.searchStudentInfo)
- self.tk_tabs_content.tk_tabs_content_1.tk_button_addStudent.bind('<Button-1>', self.addStudentInfo)
- self.tk_tabs_content.tk_tabs_content_1.tk_button_delete_student.bind('<Button-1>', self.deleteStudentInfo)
- self.tk_tabs_content.tk_tabs_content_1.tk_button_stu_refresh.bind('<Button-1>', self.studentinfo_refresh)
- self.tk_tabs_content.tk_tabs_content_1.tk_button_studentinfo_export.bind('<Button-1>', self.studentinfo_export)
- self.tk_tabs_content.tk_tabs_content_2.tk_button_add_score.bind('<Button-1>', self.addStudentScore)
- self.tk_tabs_content.tk_tabs_content_2.tk_button_delete_score.bind('<Button-1>', self.deleteStudentScore)
- self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score.bind('<<TreeviewSelect>>', self.updateStudentScore)
- self.tk_tabs_content.tk_tabs_content_2.tk_button_stu_score_search.bind('<Button-1>', self.searchStuScore)
- self.tk_tabs_content.tk_tabs_content_2.tk_button_stu_score_export.bind('<Button-1>', self.exportStuScore)
- self.tk_tabs_content.tk_tabs_content_3.tk_button_columnChart.bind('<Button-1>', self.columnChart)
- self.tk_tabs_content.tk_tabs_content_3.tk_button_paratacticColumnChart.bind('<Button-1>', self.paratacticColumnChart)
- self.tk_tabs_content.tk_tabs_content_3.tk_button_pieChart.bind('<Button-1>', self.pieChart)
-
- self.tk_tabs_content.tk_tabs_content_4.tk_button_update_tea_pwd.bind('<Button-1>', self.updateTeacherPassword)
- self.tk_tabs_content.tk_tabs_content_5.tk_button_add_course.bind('<Button-1>', self.addCourseInfo)
- self.tk_tabs_content.tk_tabs_content_5.tk_button_delete_course.bind('<Button-1>', self.deleteCourseInfo)
- self.tk_tabs_content.tk_tabs_content_5.tk_button_course_search.bind('<Button-1>', self.searchCourseInfo)
- self.tk_tabs_content.tk_tabs_content_5.tk_button_course_export.bind('<Button-1>', self.exportCourseInfo)
- self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.bind('<<TreeviewSelect>>', self.updateCourseInfo)
- self.tk_button_logout_user.bind('<Button-1>', self.logout_user)
学生端登录页面效果:
学生端——成绩分析:
学生端——修改密码:
学生端代码如下:
student.py:
- from tkinter import *
- from tkinter import messagebox, filedialog
- from tkinter.ttk import *
-
- import numpy as np
- import openpyxl
- from matplotlib import pyplot as plt
-
- import Dao
- import Login
-
- global current_uid
-
- class WinGUI(Tk):
- def __init__(self):
- super().__init__()
- self.__win()
- self.tk_label_title = self.__tk_label_title()
- self.tk_label_current_user = self.__tk_label_current_user()
- self.tk_tabs_content = Frame_content(self)
- self.tk_button_logout = self.__tk_button_logout()
-
- def __win(self):
- self.title("成绩查询")
- # 设置窗口大小、居中
- width = 1000
- height = 600
- screenwidth = self.winfo_screenwidth()
- screenheight = self.winfo_screenheight()
- geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
- self.geometry(geometry)
- self.resizable(width=False, height=False)
- self.iconbitmap('logo.ico')
-
- def __tk_label_title(self):
- label = Label(self, text="学生成绩管理系统", anchor="center")
- label.place(x=0, y=0, width=800, height=100)
- return label
-
- def __tk_label_current_user(self):
- label = Label(self, text="当前用户:admin", anchor="center")
- label.place(x=800, y=70, width=150, height=30)
- return label
-
- def __tk_button_logout(self):
- btn = Button(self, text="退出")
- btn.place(x=950, y=70, width=50, height=30)
- return btn
-
-
- class Frame_content(Notebook):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
-
- def __frame(self):
- self.tk_tabs_content_0 = Frame_content_0(self)
- self.add(self.tk_tabs_content_0, text="个人资料")
-
- self.tk_tabs_content_1 = Frame_content_1(self)
- self.add(self.tk_tabs_content_1, text="成绩查询")
-
- self.tk_tabs_content_3 = Frame_content_3(self)
- self.add(self.tk_tabs_content_3, text="修改密码")
-
- self.place(x=0, y=100, width=1000, height=500)
-
-
- class Frame_content_0(Frame):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
- self.tk_label_stu_number = self.__tk_label_stu_number()
- self.tk_input_stu_number = self.__tk_input_stu_number()
- self.tk_label_stu_name = self.__tk_label_stu_name()
- self.tk_input_stu_name = self.__tk_input_stu_name()
- self.tk_label_stu_gender = self.__tk_label_stu_gender()
- self.tk_tk_select_stu_gender = self.__tk_select_stu_gender()
- self.tk_label_stu_identity = self.__tk_label_stu_identity()
- self.tk_input_stu_identity = self.__tk_input_stu_identity()
- self.tk_label_stu_email = self.__tk_label_stu_email()
- self.tk_input_stu_email = self.__tk_input_stu_email()
- self.tk_button_stu_update = self.__tk_button_stu_update()
- self.tk_button_stu_reset = self.__tk_button_stu_reset()
-
- def __frame(self):
- self.place(x=0, y=100, width=1000, height=500)
-
- def __tk_label_stu_number(self):
- label = Label(self, text="学号", anchor="e")
- label.place(x=360, y=40, width=100, height=30)
- return label
-
- def __tk_input_stu_number(self):
- self.student_number = StringVar(self)
- ipt = Entry(self, text=self.student_number)
- ipt.place(x=490, y=40, width=150, height=30)
- ipt.config(stat='disable')
- return ipt
-
- def __tk_label_stu_name(self):
- label = Label(self, text="姓名", anchor="e")
- label.place(x=360, y=110, width=100, height=30)
- return label
-
- def __tk_input_stu_name(self):
- self.student_name = StringVar(self)
- ipt = Entry(self, text=self.student_name)
- ipt.place(x=490, y=110, width=150, height=30)
- return ipt
-
- def __tk_label_stu_gender(self):
- label = Label(self, text="性别", anchor="e")
- label.place(x=360, y=180, width=100, height=30)
- return label
-
- def __tk_select_stu_gender(self):
- cb = Combobox(self, state='readonly')
- cb['values'] = ("男", "女")
- cb.place(x=490, y=180, width=150, height=30)
- return cb
-
- def __tk_label_stu_identity(self):
- label = Label(self, text="身份证号", anchor="e")
- label.place(x=360, y=250, width=100, height=30)
- return label
-
- def __tk_input_stu_identity(self):
- self.student_identify = StringVar(self)
- ipt = Entry(self, text=self.student_identify)
- ipt.place(x=490, y=250, width=150, height=30)
- return ipt
-
- def __tk_label_stu_email(self):
- label = Label(self, text="电子邮箱", anchor="e")
- label.place(x=360, y=320, width=100, height=30)
- return label
-
- def __tk_input_stu_email(self):
- self.student_email = StringVar(self)
- ipt = Entry(self, text=self.student_email)
- ipt.place(x=490, y=320, width=150, height=30)
- return ipt
-
- def __tk_button_stu_update(self):
- btn = Button(self, text="修改")
- btn.place(x=400, y=390, width=80, height=30)
- return btn
-
- def __tk_button_stu_reset(self):
- btn = Button(self, text="重置")
- btn.place(x=520, y=390, width=80, height=30)
- return btn
-
-
- class Frame_content_1(Frame):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
- self.tk_button_analysis = self.__tk_button_analysis()
- self.tk_table_stu_score = self.__tk_table_stu_score()
- self.tk_select_box_course_nature = self.__tk_select_box_course_nature()
- self.tk_select_box_course_department = self.__tk_select_box_course_department()
- self.tk_select_box_exam_method = self.__tk_select_box_exam_method()
- self.tk_button_search = self.__tk_button_search()
- self.tk_button_export = self.__tk_button_export()
-
- def __frame(self):
- self.place(x=0, y=100, width=1000, height=500)
-
- def __tk_table_stu_score(self):
- # 表头字段 表头宽度
- self.tk_table_stu_score_columns = {"#": 50, "课程名称": 200, "课程性质": 150, "开课学院": 300, "考试方式": 100, "学分": 100, "成绩": 100}
- # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。
- tk_table = Treeview(self, show="headings", columns=list(self.tk_table_stu_score_columns))
- for text, width in self.tk_table_stu_score_columns.items(): # 批量设置列属性
- tk_table.heading(text, text=text, anchor='center')
- tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
-
- # 插入数据示例
- # self.tk_score_table_dataset = Dao.getScoreByUid(8888)
- # # 导入初始数据
- # if self.tk_score_table_dataset.get("code") == 0 and self.tk_score_table_dataset.get("data"):
- # for data in self.tk_score_table_dataset.get("data"):
- # tk_table.insert('', END, values=list(data.values()))
-
- tk_table.place(x=0, y=55, width=1000, height=420)
- return tk_table
-
- def __tk_button_analysis(self):
- btn = Button(self, text="分析")
- btn.place(x=65, y=10, width=75, height=30)
- return btn
-
- def __tk_select_box_course_nature(self):
- cb = Combobox(self, state="readonly")
- values = ["请选择课程性质"]
- for i in Dao.getDataDictByType("nature").get("data"):
- values.append(i.get("v"))
- cb['values'] = values
- cb.current(0)
- cb.place(x=180, y=10, width=150, height=30)
- return cb
-
- def __tk_select_box_course_department(self):
- cb = Combobox(self, state="readonly")
- values = ["请选择开课学院"]
- for i in Dao.getAllDepartments().get("data"):
- values.append(i.get("v"))
- cb['values'] = values
- cb.current(0)
- cb.place(x=370, y=10, width=150, height=30)
- return cb
-
- def __tk_select_box_exam_method(self):
- cb = Combobox(self, state="readonly")
- values = ["请选择考试方式"]
- for i in Dao.getDataDictByType("exammethod").get("data"):
- values.append(i.get("v"))
- cb['values'] = values
- cb.current(0)
- cb.place(x=560, y=10, width=150, height=30)
- return cb
-
- def __tk_button_search(self):
- btn = Button(self, text="搜索")
- btn.place(x=750, y=10, width=75, height=30)
- return btn
-
- def __tk_button_export(self):
- btn = Button(self, text="导出")
- btn.place(x=840, y=10, width=75, height=30)
- return btn
-
-
- class Frame_content_3(Frame):
- def __init__(self, parent):
- super().__init__(parent)
- self.__frame()
- self.tk_label_original_password = self.__tk_label_original_password()
- self.tk_input_original_password = self.__tk_input_original_password()
- self.tk_label_new_password = self.__tk_label_new_password()
- self.tk_input_new_password = self.__tk_input_new_password()
- self.tk_label_confirm_password = self.__tk_label_confirm_password()
- self.tk_input_confirm_password = self.__tk_input_confirm_password()
- self.tk_button_update_stu_password = self.__tk_button_update_stu_password()
-
- def __frame(self):
- self.place(x=0, y=100, width=1000, height=500)
-
- def __tk_label_original_password(self):
- label = Label(self, text="原密码", anchor="e")
- label.place(x=360, y=40, width=100, height=30)
- return label
-
- def __tk_input_original_password(self):
- ipt = Entry(self, show='*')
- ipt.place(x=490, y=40, width=150, height=30)
- return ipt
-
- def __tk_label_new_password(self):
- label = Label(self, text="新密码", anchor="e")
- label.place(x=360, y=110, width=100, height=30)
- return label
-
- def __tk_input_new_password(self):
- ipt = Entry(self, show='*')
- ipt.place(x=490, y=110, width=150, height=30)
- return ipt
-
- def __tk_label_confirm_password(self):
- label = Label(self, text="确认密码", anchor="e")
- label.place(x=360, y=180, width=100, height=30)
- return label
-
- def __tk_input_confirm_password(self):
- ipt = Entry(self, show='*')
- ipt.place(x=490, y=180, width=150, height=30)
- return ipt
-
- def __tk_button_update_stu_password(self):
- btn = Button(self, text="修改")
- btn.place(x=460, y=250, width=100, height=30)
- return btn
-
-
- class Win(WinGUI):
- def __init__(self, current_user):
- super().__init__()
- self.__event_bind()
- self.uid = current_user.get("uid")
- self.uclid = current_user.get("uclid")
- self.tk_label_current_user['text'] = "当前用户:" + current_user.get("uname")
- self.tk_tabs_content.tk_tabs_content_0.student_number.set(current_user.get("uid"))
- self.tk_tabs_content.tk_tabs_content_0.student_name.set(current_user.get("uname"))
- self.tk_tabs_content.tk_tabs_content_0.tk_tk_select_stu_gender.current(0 if current_user.get("ugender") == '男' else 1)
- self.tk_tabs_content.tk_tabs_content_0.student_identify.set(current_user.get("uidentify"))
- self.tk_tabs_content.tk_tabs_content_0.student_email.set(current_user.get("uemail"))
-
- # 插入数据示例
- self.score_table_dataset = Dao.getScoreByUid(self.uid)
- # 导入初始数据
- if self.score_table_dataset.get("code") == 0 and self.score_table_dataset.get("data"):
- for data in self.score_table_dataset.get("data"):
- self.tk_tabs_content.tk_tabs_content_1.tk_table_stu_score.insert('', END, values=list(data.values()))
-
- def logout(self):
- messagebox.showwarning('提示', '欢迎下次使用!')
- self.destroy()
- login = Login.Win()
- login.mainloop()
-
- def updateStudentInfo(self, evt):
- __stu_name = self.tk_tabs_content.tk_tabs_content_0.tk_input_stu_name.get()
- __stu_gender = self.tk_tabs_content.tk_tabs_content_0.tk_tk_select_stu_gender.get()
- __stu_identify = self.tk_tabs_content.tk_tabs_content_0.tk_input_stu_identity.get()
- __stu_email = self.tk_tabs_content.tk_tabs_content_0.tk_input_stu_email.get()
- if not __stu_name or not __stu_gender or not __stu_identify or not __stu_email:
- messagebox.showinfo("提示", "必填项不能为空!")
- return
- if not re.match(r'^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$', __stu_identify):
- messagebox.showinfo("提示", "身份证格式不合法!")
- return
- if not re.match(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$', __stu_email):
- messagebox.showinfo("提示", "电子邮箱格式不合法!")
- return
- res = Dao.updateUser(self.uid, __stu_name, __stu_gender, __stu_identify, self.uclid, __stu_email)
- messagebox.showinfo("提示", res.get("msg"))
- self.tk_label_current_user['text'] = "当前用户:" + __stu_name
- print("更新学生信息", evt)
-
- def stu_reset(self, evt):
- self.tk_tabs_content.tk_tabs_content_0.student_number.set(self.userInfo[0])
- self.tk_tabs_content.tk_tabs_content_0.student_name.set(self.userInfo[1])
- self.tk_tabs_content.tk_tabs_content_0.tk_tk_select_stu_gender.current(0 if self.userInfo[2] else 1)
- self.tk_tabs_content.tk_tabs_content_0.student_identify.set(self.userInfo[3])
- self.tk_tabs_content.tk_tabs_content_0.student_email.set(self.userInfo[5])
-
- def analysisStudentScore(self, evt):
- result = Dao.getScoreByUid(self.uid).get("data")
- plt.title('成绩统计图')
- # 设置x轴数据
- x = [i.get("cname") for i in result]
- # 每组数据n有3个类型
- total_width, n = 0.6, 3
- width = total_width / n
- y1 = [i.get("score") for i in result]
- y2 = [i.get("avg_score") for i in Dao.getAllCourseAvgScore(self.uid).get("data")]
- plt.bar(x, y1, color="b", width=width, label='我的成绩')
- plt.plot(x, y2, color="g", label='科目平均成绩')
- # x和y轴标题
- plt.xlabel("课程")
- plt.ylabel("分数")
- plt.legend(loc="best")
- plt.ylim((0, 100))
- # 设置纵轴起始,终止和间距
- my_y_ticks = np.arange(0, 100, 10)
- plt.yticks(my_y_ticks)
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 支持中文显示
- plt.show()
- print("成绩分析图表绘制")
-
- def searchStudentScore(self, evt):
- __score_query = self.tk_tabs_content.tk_tabs_content_1
- __nature = __score_query.tk_select_box_course_nature.get()
- __department = __score_query.tk_select_box_course_department.get()
- __exammethod = __score_query.tk_select_box_exam_method.get()
- if __score_query.tk_select_box_course_nature.current() == 0:
- __nature = ''
- if __score_query.tk_select_box_course_department.current() == 0:
- __department = ''
- if __score_query.tk_select_box_exam_method.current() == 0:
- __exammethod = ''
- for _ in map(__score_query.tk_table_stu_score.delete, __score_query.tk_table_stu_score.get_children("")):
- pass
- self.score_table_dataset = Dao.getScoreByUid(self.uid, __nature, __department, __exammethod)
- # 导入初始数据
- if self.score_table_dataset.get("code") == 0 and self.score_table_dataset.get("data"):
- for data in self.score_table_dataset.get("data"):
- __score_query.tk_table_stu_score.insert('', END, values=list(data.values()))
- __score_query.tk_select_box_course_nature.current(0)
- __score_query.tk_select_box_course_department.current(0)
- __score_query.tk_select_box_exam_method.current(0)
- print(f"查询学生{self.uid}的成绩!")
-
- def exportStudentScore(self, evt):
- path = filedialog.askdirectory()
- try:
- book = openpyxl.Workbook()
- sheet = book.active
- fff = list(self.tk_tabs_content.tk_tabs_content_1.tk_table_stu_score_columns.keys()) # 获取表头信息
- sheet.append(fff)
- dataset = [list(data_item.values()) for data_item in
- self.score_table_dataset.get("data")]
- print(dataset)
- for i in dataset:
- sheet.append(i)
- book.save(f"{path}/{self.uid}.xlsx")
- messagebox.showinfo("提示", "导出成功!")
- except Exception as e:
- messagebox.showinfo("提示", "导出失败!")
- print(e)
- print("<Button-1>事件未处理", evt)
-
- def updateStudentPassword(self, evt):
- __original_pwd = self.tk_tabs_content.tk_tabs_content_3.tk_input_original_password.get()
- __new_pwd = self.tk_tabs_content.tk_tabs_content_3.tk_input_new_password.get()
- __confirm_pwd = self.tk_tabs_content.tk_tabs_content_3.tk_input_confirm_password.get()
- if __original_pwd == '' or __new_pwd == '' or __confirm_pwd == '':
- messagebox.showwarning("提示", "必填项未填写!")
- return
- if not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __original_pwd) \
- or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __new_pwd) \
- or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __confirm_pwd):
- messagebox.showwarning("提示", "密码格式应为6-18位数字、字母、特殊字符的组合!")
- return
- if __new_pwd != __confirm_pwd:
- messagebox.showwarning("提示", "两次密码输入不一致")
- return
- res = Dao.updatePassword(self.uid, __original_pwd, __new_pwd)
- messagebox.showinfo("提示", res.get("msg"))
- if res.get("code") == 0:
- self.destroy()
- login = Login.Win()
- login.mainloop()
- print("修改密码", evt)
-
- def logout_user(self, evt):
- messagebox.showwarning('提示', '欢迎下次使用!')
- self.destroy()
- login = Login.Win()
- login.mainloop()
-
- def __event_bind(self):
- self.protocol('WM_DELETE_WINDOW', self.logout)
- self.tk_tabs_content.tk_tabs_content_0.tk_button_stu_update.bind('<Button-1>', self.updateStudentInfo)
- self.tk_tabs_content.tk_tabs_content_0.tk_button_stu_reset.bind('<Button-1>', self.stu_reset)
- self.tk_tabs_content.tk_tabs_content_1.tk_button_analysis.bind('<Button-1>', self.analysisStudentScore)
- self.tk_tabs_content.tk_tabs_content_1.tk_button_search.bind('<Button-1>', self.searchStudentScore)
- self.tk_tabs_content.tk_tabs_content_1.tk_button_export.bind('<Button-1>', self.exportStudentScore)
- self.tk_tabs_content.tk_tabs_content_3.tk_button_update_stu_password.bind('<Button-1>',
- self.updateStudentPassword)
- self.tk_button_logout.bind('<Button-1>', self.logout_user)
-
数据库采用mysql 8.0,库名和表如下:
Dao层代码如下:用于访问数据库,向数据库发送sql语句,完成成绩与科目等增删改查任务
Dao.py:
- import pymysql
-
-
- def getConnect():
- """
- 获取数据库连接
- :return:
- """
- conn = pymysql.Connect(
- host='localhost',
- port=3306,
- user='#你的数据库用户名',
- password='#你的数据库密码',
- db='stu_sc_sys',
- charset='utf8',
- cursorclass=pymysql.cursors.DictCursor
- )
- cursor = conn.cursor()
- return conn, cursor
-
-
- def getUserByIdAndPwd(username, password):
- conn, cursor = getConnect()
- sql = f"select uid, uname, ugender, uidentify, uclid, uemail, urole from user where uid='{username}' " \
- f"and upwd='{password}'"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchone()
- }
- cursor.close()
- conn.close()
- return res
-
-
- def getUserInfoById(uid):
- conn, cursor = getConnect()
- sql = f"select uid, uname, ugender, uidentify, uclid, uemail, urole from user where uid='{uid}'"
- cursor.execute(sql)
- res = cursor.fetchone()
- cursor.close()
- conn.close()
- return res
-
-
- def updatePassword(uid, origin_pwd, new_pwd):
- conn, cursor = getConnect()
- res = {
- "code": 1,
- "msg": "修改密码失败!"
- }
- if not getUserByIdAndPwd(uid, origin_pwd).get("data"):
- res = {
- "code": 1,
- "msg": "原密码不正确!"
- }
- else:
- sql = f"update user set upwd = '{new_pwd}' where uid = '{uid}'"
- try:
- cursor.execute(sql)
- conn.commit()
- res = {
- "code": 0,
- "msg": "修改成功!"
- }
- except Exception as e:
- conn.rollback()
- print(e)
- return res
-
-
- def getScoreByUid(uid, nature='', department='', exam_method=''):
- """
- 通过学号获取成绩
- :param uid:
- :param nature:
- :param department:
- :param exam_method:
- :return:
- """
- conn, cursor = getConnect()
- sql = f"select ROW_NUMBER() over () as id, uc.cname, c.cnature, c.cdepartment, c.cexammethod, c.ccredit, score " \
- f"from user_course uc inner join user u on uc.uid = u.uid inner join course c on uc.cname = c.cname " \
- f"where u.uid = '{uid}' and c.cnature like '%{nature}%' and " \
- f"c.cdepartment like '%{department}%' and c.cexammethod like '%{exam_method}%'"
- print(sql)
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- conn.close()
- return res
-
-
- def getAllUsers():
- connection, cursor = getConnect()
- sql = 'select uid, uname, ugender, uidentify, uclid, uemail, upwd, urole from user'
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def getAllStudents():
- connection, cursor = getConnect()
- sql = "select row_number() over () as id, uid, uname, ugender, uidentify, uclid, uemail from user where urole = 1"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def searchStudents(uname, ugender):
- """
- 学生信息搜索
- :param uname:
- :param ugender:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select row_number() over () as id, uid, uname, ugender, uidentify, uclid, uemail, upwd, urole from user " \
- f"where urole = 1 and uname like '%{uname}%' and ugender like '%{ugender}%'"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def addStudent(uid, uname, ugender, uidentify, uclid, uemail):
- """
- 添加一个学生信息,密码默认为123456
- :param uid:
- :param uname:
- :param ugender:
- :param uidentify:
- :param uclid:
- :param uemail:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"insert into user(uid, uname, ugender, uidentify, uclid, uemail, upwd) values ('{uid}', '{uname}'" \
- f", '{ugender}', '{uidentify}', '{uclid}', '{uemail}', '123456') "
- res = {
- "code": 0,
- "msg": "添加成功!"
- }
- try:
- cursor.execute(sql)
- connection.commit()
- except Exception as e:
- res = {
- "code": 1,
- "msg": "添加失败!"
- }
- connection.rollback()
- print(e)
- cursor.close()
- connection.close()
- return res
-
-
- def deleteUser(uid):
- """
- 通过uid删除用户
- :param uid:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"delete from user where uid = '{uid}'"
- res = {
- "code": 0,
- "msg": "删除成功!"
- }
- try:
- cursor.execute(sql)
- connection.commit()
- except Exception as e:
- res = {
- "code": 1,
- "msg": "删除失败!"
- }
- connection.rollback()
- print(e)
- cursor.close()
- connection.close()
- return res
-
-
- def updateUser(uid, uname, ugender, uidentify, uclid, uemail):
- """
- 通过uid更新用户信息
- :param uid:
- :param uname:
- :param ugender:
- :param uidentify:
- :param uclid:
- :param uemail:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"update user set uname = '{uname}', ugender = '{ugender}', uidentify = '{uidentify}', uclid = '{uclid}'" \
- f", uemail ='{uemail}' where uid = '{uid}'"
- print(sql)
- res = {
- "code": 0,
- "msg": "修改成功!"
- }
- try:
- cursor.execute(sql)
- connection.commit()
- except Exception as e:
- res = {
- "code": 1,
- "msg": "修改失败!"
- }
- connection.rollback()
- print(e)
- cursor.close()
- connection.close()
- return res
-
-
- def getAllCourses():
- """
- 获取所有的课程信息
- :return:
- """
- connection, cursor = getConnect()
- sql = "select cid, cname, ccredit, cnature, cdepartment, cexammethod from course"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def getCourseByCid(cid):
- """
- 获取cid的课程
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select cid, cname, cnature, ccredit, cdepartment, cexammethod from course where cid = '{cid}'"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def getDataDictByType(dtype):
- """
- 获取dtype类型的数据字典
- :param:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select d.ddtkey as k, d.ddtvalue as v from dictionary d where d.ddtype = '{dtype}'"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def getAllDepartments():
- """
- 获取所有的学院
- :return:
- """
- connection, cursor = getConnect()
- sql = "select did as k, dname as v from department"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def getMaxStuNumber(s_num_prefix):
- """
- 获取以s_num_prefix开头的最大学号
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select MAX(uid) as max_id from user where uid like '{s_num_prefix}%'"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def addCourse(cname, nature, credit, department, exam_method):
- """
- 添加课程
- :return:
- """
- connection, cursor = getConnect()
- sql = f"insert into course(cname, cnature, ccredit, cdepartment, cexammethod) VALUES ('{cname}', '{nature}'" \
- f", '{credit}', '{department}', '{exam_method}')"
- res = {
- "code": 0,
- "msg": "添加课程成功!"
- }
- try:
- cursor.execute(sql)
- connection.commit()
- except Exception as e:
- res = {
- "code": 1,
- "msg": "添加课程失败!"
- }
- connection.rollback()
- print(e)
- cursor.close()
- connection.close()
- return res
-
-
- def deleteCourse(cid):
- """
- 删除课程
- :return:
- """
- connection, cursor = getConnect()
- sql = f"delete from course where cid = {cid}"
- res = {
- "code": 0,
- "msg": "删除课程成功!"
- }
- try:
- cursor.execute(sql)
- connection.commit()
- except Exception as e:
- res = {
- "code": 1,
- "msg": "删除课程失败!"
- }
- connection.rollback()
- print(e)
- cursor.close()
- connection.close()
- return res
-
-
- def searchCourses(department, exammethod):
- """
- 搜索课程信息
- :param department:
- :param exammethod:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select cid, cname, ccredit, cnature, cdepartment, cexammethod from course " \
- f"where cdepartment like '%{department}%' and cexammethod like '%{exammethod}%'"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def updateCourseInfo(cid, cname, nature, credit, department, exammethod):
- """
- 修改课程信息
- :param cid:
- :param cname:
- :param nature:
- :param credit:
- :param department:
- :param exammethod:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"update course set cname = '{cname}', cnature = '{nature}', ccredit = '{credit}'" \
- f", cdepartment = '{department}', cexammethod = '{exammethod}' where cid = '{cid}'"
- res = {
- "code": 0,
- "msg": "修改课程成功!"
- }
- try:
- cursor.execute(sql)
- connection.commit()
- except Exception as e:
- res = {
- "code": 1,
- "msg": "更新课程失败!"
- }
- connection.rollback()
- print(e)
- cursor.close()
- connection.close()
- return res
-
-
- def getScoreBandByCName(course_name):
- """
- 获取课程名为course_name的各个分段的学生人数
- :param course_name:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select SUM(IF(score <= 100 and score >= 90, 1, 0)) as A, SUM(IF(score < 90 and score >= 80, 1, 0)) as B, " \
- f"SUM(IF(score < 80 and score >= 70, 1, 0)) as C, SUM(IF(score < 70 and score >= 60, 1, 0)) as D, " \
- f"SUM(IF(score < 60, 1, 0)) as E from user_course where cname = '{course_name}'"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def getMaxAndMinAndAvgScoreByCLid(class_id):
- """
- 获取班级号为class_id的班级的各科最高分、最低分以及平均分
- :param class_id:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select uc.cname, MAX(score) as max_score, MIN(score) as min_score, AVG(score) as avg_score " \
- f"from user_course uc inner join user u on uc.uid = u.uid where u.uclid = '{class_id}' group by uc.cname"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def getOverallGradeLevelByCLid(class_id):
- """
- 获取班级号为class_id的班级综合成绩等级各分段人数
- :param class_id:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select SUM(IF(avg_score >= 85 and avg_score <= 100, 1, 0)) as A, " \
- f"SUM(IF(avg_score >= 70 and avg_score < 85, 1, 0)) as B, " \
- f"SUM(IF(avg_score >= 60 and avg_score < 70, 1, 0)) as C, " \
- f"SUM(IF(avg_score < 60, 1, 0)) as D from (" \
- f"select AVG(score) as avg_score from user_course uc " \
- f"inner join user u on uc.uid = u.uid where u.uclid = '{class_id}' group by u.uid" \
- f") s"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def getAllClasses():
- """
- 获取用户表中已存在的班级号
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select distinct uclid from user where urole = 1"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def getAllCourseAvgScore(uid):
- """
- 获取所有课程的平均分
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select cname, AVG(score) as avg_score from user_course where cname in " \
- f"(select cname from user_course where uid = '{uid}') group by cname"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def searchStudentScore(course_name='', course_nature='', course_department=''):
- """
- 搜索学生成绩
- :param course_name:
- :param course_nature:
- :param course_department:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select ROW_NUMBER() over () as id, u.uid, u.uname, uc.cname, c.cnature, c.cdepartment, c.cexammethod, " \
- f"c.ccredit, score from user_course uc inner join user u on uc.uid = u.uid inner join course c " \
- f"on uc.cname = c.cname where c.cname like '%{course_name}%' and " \
- f"c.cnature like '%{course_nature}%' and c.cdepartment like '%{course_department}%'"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def getScoreByUidAndCName(uid, course_name):
- """
- 查找学号为uid课程为course_name的学生成绩
- :param uid:
- :param course_name:
- :return:
- """
- connection, cursor = getConnect()
- sql = f"select uid, cname, score from user_course where uid = '{uid}' and cname = '{course_name}'"
- cursor.execute(sql)
- res = {
- "code": 0,
- "msg": "success",
- "data": cursor.fetchall()
- }
- cursor.close()
- connection.close()
- return res
-
-
- def addStudentScore(uid, course_name, score):
- connection, cursor = getConnect()
- if not cursor.execute(f"select uid from user where uid = '{uid}'"):
- return {
- "code": 1,
- "msg": "学号不存在!"
- }
- if cursor.execute(f"select 1 from user_course where uid = '{uid}' and cname = '{course_name}' limit 1"):
- return {
- "code": 1,
- "msg": f"该学生的{course_name}课程成绩已经存在!"
- }
- sql = f"insert into user_course(uid, cname, score) VALUES ('{uid}', '{course_name}', '{score}')"
- res = {
- "code": 0,
- "msg": "添加成绩成功!"
- }
- try:
- cursor.execute(sql)
- connection.commit()
- except Exception as e:
- res = {
- "code": 1,
- "msg": "添加成绩失败!"
- }
- connection.rollback()
- print(e)
- cursor.close()
- connection.close()
- return res
-
-
- def deleteStudentScore(uid, course_name):
- connection, cursor = getConnect()
- if not cursor.execute(f"select uid from user where uid = '{uid}'"):
- return {
- "code": 1,
- "msg": "学号不存在!"
- }
- sql = f"delete from user_course where uid = '{uid}' and cname = '{course_name}'"
- res = {
- "code": 0,
- "msg": "删除成绩成功!"
- }
- try:
- code = cursor.execute(sql)
- connection.commit()
- if code == 0:
- res = {
- "code": 0,
- "msg": f"该学生的{course_name}课程成绩不存在!"
- }
- except Exception as e:
- res = {
- "code": 1,
- "msg": "删除成绩失败!"
- }
- connection.rollback()
- print(e)
- cursor.close()
- connection.close()
- return res
-
-
- def updateStudentScore(uid, course_name, score):
- connection, cursor = getConnect()
- sql = f"update user_course set score = '{score}' where uid = '{uid}' and cname = '{course_name}'"
- res = {
- "code": 0,
- "msg": "修改成绩成功!"
- }
- try:
- cursor.execute(sql)
- connection.commit()
- except Exception as e:
- res = {
- "code": 1,
- "msg": "修改成绩失败!"
- }
- connection.rollback()
- print(e)
- cursor.close()
- connection.close()
- return res
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。