当前位置:   article > 正文

Python+mysql+tkinter+matplotlib的可视化学生成绩管理系统课程设计_图形化实现班级成绩管理

图形化实现班级成绩管理

使用模块要求:

tkinter、numpy、openpyxl、matplotlib、pymysql、re、time;其中matplotlib用于绘制统计图

开发工具:pycharm专业版、python3.7、mysql8.0

运行效果:

主页面:

​​​​​​​

 

 教师端主要功能:

f38336fd4e1a4a01b7798fd09219b608.png

 教师端登录后的效果——个人资料页面:bd9003a086e3430387991eddc3c52a7a.png

  教师端登录后的效果——学生查询页面:a8c4d1ba3f114f2eb8cdb91e24ba8189.png

 教师端登录后的效果——成绩查询页面:5ee8fc3c23df400c8411af0c0bbc0c1a.png

 教师端登录后的效果——成绩分析页面:

d72520d0351c4607999a4304aa7c34dd.png

成绩分析页面——课程成绩分析(统计图):

619e5830475f4877bcd2e05a664d5647.png

各班级创建分析页面——统计图:

78748ba0041c41a2bbf6fa4576c3d557.png

 班级综合成绩评定页面——扇形统计图:

13780bc7892743ab900f6cf4fe4da0db.png

 修改密码页面:

c93d84ea9f1e4908803333332b50f43d.png

课程管理页面——根据学院、考试方式进行添加或删除课程:

3a703763bee04907a16c6ed6c2d95789.png

 Teacherpage.py页面代码如下:

更多代码:看主页联系、或访问:

腾讯文档腾讯文档-在线文档https://docs.qq.com/doc/p/71239d69a76f56cf1521717ae6b22c27cf876f10

  1. from tkinter import *
  2. from tkinter import messagebox, filedialog
  3. from tkinter.ttk import *
  4. import openpyxl as openpyxl
  5. import AddCoursePage
  6. import AddScorePage
  7. import ClassGradeAnalysis
  8. import ComprehensivePerformanceEvaluation
  9. import CourseScoreAnalysis
  10. import Dao
  11. import DeleteCoursePage
  12. import DeleteScorePage
  13. import Login
  14. import UpdateCoursePage
  15. import AddStudentPage
  16. import DeleteStudentPage
  17. import UpdateScorePage
  18. import UpdateStudentPage
  19. import numpy as np
  20. import matplotlib.pyplot as plt
  21. class WinGUI(Tk):
  22. def __init__(self):
  23. super().__init__()
  24. self.__win()
  25. self.tk_label_title = self.__tk_label_title()
  26. self.tk_label_current_user = self.__tk_label_current_user()
  27. self.tk_tabs_content = Frame_content(self)
  28. self.tk_button_logout_user = self.__tk_button_logout_user()
  29. def __win(self):
  30. self.title("教师端")
  31. # 设置窗口大小、居中
  32. width = 1000
  33. height = 600
  34. screenwidth = self.winfo_screenwidth()
  35. screenheight = self.winfo_screenheight()
  36. geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
  37. self.geometry(geometry)
  38. self.resizable(width=False, height=False)
  39. self.iconbitmap('logo.ico')
  40. def __tk_label_title(self):
  41. label = Label(self, text="学生成绩管理系统", anchor="center")
  42. label.place(x=0, y=0, width=800, height=100)
  43. return label
  44. def __tk_label_current_user(self):
  45. label = Label(self, text="当前用户:admin", anchor="center")
  46. label.place(x=800, y=70, width=150, height=30)
  47. return label
  48. def __tk_button_logout_user(self):
  49. btn = Button(self, text="退出")
  50. btn.place(x=950, y=70, width=50, height=30)
  51. return btn
  52. class Frame_content(Notebook):
  53. def __init__(self, parent):
  54. super().__init__(parent)
  55. self.__frame()
  56. def __frame(self):
  57. self.tk_tabs_content_0 = Frame_content_0(self)
  58. self.add(self.tk_tabs_content_0, text="个人资料")
  59. self.tk_tabs_content_1 = Frame_content_1(self)
  60. self.add(self.tk_tabs_content_1, text="学生查询")
  61. self.tk_tabs_content_2 = Frame_content_2(self)
  62. self.add(self.tk_tabs_content_2, text="成绩查询")
  63. self.tk_tabs_content_3 = Frame_content_3(self)
  64. self.add(self.tk_tabs_content_3, text="成绩分析")
  65. self.tk_tabs_content_4 = Frame_content_4(self)
  66. self.add(self.tk_tabs_content_4, text="修改密码")
  67. self.tk_tabs_content_5 = Frame_content_5(self)
  68. self.add(self.tk_tabs_content_5, text="课程管理")
  69. self.place(x=0, y=100, width=1000, height=500)
  70. class Frame_content_0(Frame):
  71. def __init__(self, parent):
  72. super().__init__(parent)
  73. self.__frame()
  74. self.tk_label_tea_number = self.__tk_label_tea_number()
  75. self.tk_input_tea_number = self.__tk_input_tea_number()
  76. self.tk_label_tea_name = self.__tk_label_tea_name()
  77. self.tk_input_tea_name = self.__tk_input_tea_name()
  78. self.tk_label_tea_gender = self.__tk_label_tea_gender()
  79. self.tk_select_tea_gender = self.__tk_select_tea_gender()
  80. self.tk_label_tea_identity = self.__tk_label_tea_identity()
  81. self.tk_input_tea_identity = self.__tk_input_tea_identity()
  82. self.tk_label_tea_email = self.__tk_label_tea_email()
  83. self.tk_input_tea_email = self.__tk_input_tea_email()
  84. self.tk_button_tea_update = self.__tk_button_tea_update()
  85. self.tk_button_tea_reset = self.__tk_button_tea_reset()
  86. def __frame(self):
  87. self.place(x=0, y=100, width=1000, height=500)
  88. def __tk_label_tea_number(self):
  89. label = Label(self, text="工号", anchor="e")
  90. label.place(x=360, y=40, width=100, height=30)
  91. return label
  92. def __tk_input_tea_number(self):
  93. self.tea_number = StringVar(self)
  94. ipt = Entry(self, text=self.tea_number)
  95. ipt.place(x=490, y=40, width=150, height=30)
  96. ipt.config(stat='disable')
  97. return ipt
  98. def __tk_label_tea_name(self):
  99. label = Label(self, text="姓名", anchor="e")
  100. label.place(x=360, y=110, width=100, height=30)
  101. return label
  102. def __tk_input_tea_name(self):
  103. self.tea_name = StringVar(self)
  104. ipt = Entry(self, text=self.tea_name)
  105. ipt.place(x=490, y=110, width=150, height=30)
  106. return ipt
  107. def __tk_label_tea_gender(self):
  108. label = Label(self, text="性别", anchor="e")
  109. label.place(x=360, y=180, width=100, height=30)
  110. return label
  111. def __tk_select_tea_gender(self):
  112. cb = Combobox(self, state='readonly')
  113. cb['values'] = ("男", "女")
  114. cb.place(x=490, y=180, width=150, height=30)
  115. return cb
  116. def __tk_label_tea_identity(self):
  117. label = Label(self, text="身份证号", anchor="e")
  118. label.place(x=360, y=250, width=100, height=30)
  119. return label
  120. def __tk_input_tea_identity(self):
  121. self.tea_identify = StringVar(self)
  122. ipt = Entry(self, text=self.tea_identify)
  123. ipt.place(x=490, y=250, width=150, height=30)
  124. return ipt
  125. def __tk_label_tea_email(self):
  126. label = Label(self, text="电子邮箱", anchor="e")
  127. label.place(x=360, y=320, width=100, height=30)
  128. return label
  129. def __tk_input_tea_email(self):
  130. self.tea_email = StringVar(self)
  131. ipt = Entry(self, text=self.tea_email)
  132. ipt.place(x=490, y=320, width=150, height=30)
  133. return ipt
  134. def __tk_button_tea_update(self):
  135. btn = Button(self, text="修改")
  136. btn.place(x=400, y=390, width=80, height=30)
  137. return btn
  138. def __tk_button_tea_reset(self):
  139. btn = Button(self, text="重置")
  140. btn.place(x=520, y=390, width=80, height=30)
  141. return btn
  142. class Frame_content_1(Frame):
  143. def __init__(self, parent):
  144. super().__init__(parent)
  145. self.__frame()
  146. self.tk_table_student_query = self.__tk_table_student_query()
  147. self.tk_input_stu_name = self.__tk_input_stu_name()
  148. self.tk_select_box_stu_gender = self.__tk_select_box_stu_gender()
  149. self.tk_button_stu_search = self.__tk_button_stu_search()
  150. self.tk_button_addStudent = self.__tk_button_addStudent()
  151. self.tk_button_delete_student = self.__tk_button_delete_student()
  152. self.tk_button_stu_refresh = self.__tk_button_stu_refresh()
  153. self.tk_button_studentinfo_export = self.__tk_button_studentinfo_export()
  154. def __frame(self):
  155. self.place(x=0, y=100, width=1000, height=500)
  156. def __tk_table_student_query(self):
  157. # 表头字段 表头宽度
  158. self.tk_table_student_manage_columns = {"ID": 50, "学号": 100, "姓名": 150, '性别': 100, '身份证号': 300, '班级': 100, '邮箱': 200}
  159. # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。
  160. tk_table = Treeview(self, show="headings", columns=list(self.tk_table_student_manage_columns))
  161. for text, width in self.tk_table_student_manage_columns.items(): # 批量设置列属性
  162. tk_table.heading(text, text=text, anchor='center')
  163. tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
  164. # 插入数据示例
  165. #
  166. # # 导入初始数据
  167. self.tk_student_table_dataset = Dao.getAllStudents()
  168. if self.tk_student_table_dataset.get("code") == 0:
  169. if self.tk_student_table_dataset.get("data"):
  170. print(self.tk_student_table_dataset.get("data"))
  171. for values in self.tk_student_table_dataset.get("data"):
  172. tk_table.insert('', END, values=list(values.values()))
  173. else:
  174. print("未查询到数据!")
  175. else:
  176. print("数据查询异常!")
  177. tk_table.place(x=0, y=60, width=1000, height=415)
  178. return tk_table
  179. def __tk_input_stu_name(self):
  180. ipt = Entry(self)
  181. ipt.place(x=360, y=10, width=150, height=30)
  182. return ipt
  183. def __tk_select_box_stu_gender(self):
  184. cb = Combobox(self, state="readonly")
  185. cb['values'] = ("请选择性别", "男", "女")
  186. cb.place(x=540, y=10, width=150, height=30)
  187. cb.current(0)
  188. return cb
  189. def __tk_button_stu_search(self):
  190. btn = Button(self, text="搜索")
  191. btn.place(x=720, y=10, width=70, height=30)
  192. return btn
  193. def __tk_button_stu_refresh(self):
  194. btn = Button(self, text="刷新")
  195. btn.place(x=820, y=10, width=70, height=30)
  196. return btn
  197. def __tk_button_addStudent(self):
  198. btn = Button(self, text="添加学生")
  199. btn.place(x=50, y=10, width=100, height=30)
  200. return btn
  201. def __tk_button_delete_student(self):
  202. btn = Button(self, text="删除学生")
  203. btn.place(x=180, y=10, width=100, height=30)
  204. return btn
  205. def __tk_button_studentinfo_export(self):
  206. btn = Button(self, text="导出")
  207. btn.place(x=920, y=10, width=50, height=30)
  208. return btn
  209. class Frame_content_2(Frame):
  210. def __init__(self, parent):
  211. super().__init__(parent)
  212. self.__frame()
  213. self.tk_table_stu_score = self.__tk_table_stu_score()
  214. self.tk_button_add_score = self.__tk_button_add_score()
  215. self.tk_button_delete_score = self.__tk_button_delete_score()
  216. self.tk_select_box_score_course_name = self.__tk_select_box_score_course_name()
  217. self.tk_select_box_score_nature = self.__tk_select_box_score_nature()
  218. self.tk_select_box_score_department = self.__tk_select_box_score_department()
  219. self.tk_button_stu_score_search = self.__tk_button_stu_score_search()
  220. self.tk_button_stu_score_export = self.__tk_button_stu_score_export()
  221. def __frame(self):
  222. self.place(x=0, y=100, width=1000, height=500)
  223. def __tk_table_stu_score(self):
  224. # 表头字段 表头宽度
  225. self.tk_table_stu_score_columns = {"#": 50, "学号": 70, "姓名": 80, "课程名称": 200, "课程性质": 100, "开课学院": 270, "考试方式": 80, "学分": 50, "成绩": 100}
  226. # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。
  227. tk_table = Treeview(self, show="headings", columns=list(self.tk_table_stu_score_columns))
  228. for text, width in self.tk_table_stu_score_columns.items(): # 批量设置列属性
  229. tk_table.heading(text, text=text, anchor='center')
  230. tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
  231. # 插入数据示例
  232. self.tk_score_table_dataset = Dao.searchStudentScore()
  233. # 导入初始数据
  234. if self.tk_score_table_dataset.get("code") == 0 and self.tk_score_table_dataset.get("data"):
  235. for data in self.tk_score_table_dataset.get("data"):
  236. tk_table.insert('', END, values=list(data.values()))
  237. tk_table.place(x=0, y=60, width=1000, height=415)
  238. return tk_table
  239. def __tk_button_add_score(self):
  240. btn = Button(self, text="添加成绩")
  241. btn.place(x=50, y=10, width=100, height=30)
  242. return btn
  243. def __tk_button_delete_score(self):
  244. btn = Button(self, text="删除成绩")
  245. btn.place(x=170, y=10, width=100, height=30)
  246. return btn
  247. def __tk_select_box_score_course_name(self):
  248. cb = Combobox(self, state="readonly")
  249. values = ["请选择课程名称"]
  250. for i in Dao.getAllCourses().get("data"):
  251. values.append(i.get("cname"))
  252. cb['values'] = values
  253. cb.current(0)
  254. cb.place(x=290, y=10, width=150, height=30)
  255. return cb
  256. def __tk_select_box_score_nature(self):
  257. cb = Combobox(self, state="readonly")
  258. values = ["请选择课程性质"]
  259. for i in Dao.getDataDictByType("nature").get("data"):
  260. values.append(i.get("v"))
  261. cb['values'] = values
  262. cb.current(0)
  263. cb.place(x=460, y=10, width=150, height=30)
  264. return cb
  265. def __tk_select_box_score_department(self):
  266. cb = Combobox(self, state="readonly")
  267. values = ["请选择开课学院"]
  268. for i in Dao.getAllDepartments().get("data"):
  269. values.append(i.get("v"))
  270. cb['values'] = values
  271. cb.current(0)
  272. cb.place(x=630, y=10, width=150, height=30)
  273. return cb
  274. def __tk_button_stu_score_search(self):
  275. btn = Button(self, text="搜索")
  276. btn.place(x=800, y=10, width=70, height=30)
  277. return btn
  278. def __tk_button_stu_score_export(self):
  279. btn = Button(self, text="导出")
  280. btn.place(x=890, y=10, width=70, height=30)
  281. return btn
  282. class Frame_content_3(Frame):
  283. def __init__(self, parent):
  284. super().__init__(parent)
  285. self.__frame()
  286. self.tk_button_pieChart = self.__tk_button_pieChart()
  287. self.tk_button_columnChart = self.__tk_button_columnChart()
  288. self.tk_button_paratacticColumnChart = self.__tk_button_paratacticColumnChart()
  289. def __frame(self):
  290. self.place(x=0, y=100, width=1000, height=500)
  291. def __tk_button_columnChart(self):
  292. btn = Button(self, text="课程成绩分析")
  293. btn.place(x=80, y=50, width=150, height=70)
  294. return btn
  295. def __tk_button_paratacticColumnChart(self):
  296. btn = Button(self, text="班级成绩分析")
  297. btn.place(x=420, y=50, width=150, height=70)
  298. return btn
  299. def __tk_button_pieChart(self):
  300. btn = Button(self, text="综合成绩评定")
  301. btn.place(x=760, y=50, width=150, height=70)
  302. return btn
  303. class Frame_content_4(Frame):
  304. def __init__(self, parent):
  305. super().__init__(parent)
  306. self.__frame()
  307. self.tk_label_original_pwd = self.__tk_label_original_pwd()
  308. self.tk_input_original_pwd = self.__tk_input_original_pwd()
  309. self.tk_label_new_pwd = self.__tk_label_new_pwd()
  310. self.tk_input_new_pwd = self.__tk_input_new_pwd()
  311. self.tk_label_confirm_pwd = self.__tk_label_confirm_pwd()
  312. self.tk_input_confirm_pwd = self.__tk_input_confirm_pwd()
  313. self.tk_button_update_tea_pwd = self.__tk_button_update_tea_pwd()
  314. def __frame(self):
  315. self.place(x=0, y=100, width=1000, height=500)
  316. def __tk_label_original_pwd(self):
  317. label = Label(self, text="原密码", anchor="e")
  318. label.place(x=360, y=40, width=100, height=30)
  319. return label
  320. def __tk_input_original_pwd(self):
  321. ipt = Entry(self, show='*')
  322. ipt.place(x=490, y=40, width=150, height=30)
  323. return ipt
  324. def __tk_label_new_pwd(self):
  325. label = Label(self, text="新密码", anchor="e")
  326. label.place(x=360, y=110, width=100, height=30)
  327. return label
  328. def __tk_input_new_pwd(self):
  329. ipt = Entry(self, show='*')
  330. ipt.place(x=490, y=110, width=150, height=30)
  331. return ipt
  332. def __tk_label_confirm_pwd(self):
  333. label = Label(self, text="确认密码", anchor="e")
  334. label.place(x=360, y=180, width=100, height=30)
  335. return label
  336. def __tk_input_confirm_pwd(self):
  337. ipt = Entry(self, show='*')
  338. ipt.place(x=490, y=180, width=150, height=30)
  339. return ipt
  340. def __tk_button_update_tea_pwd(self):
  341. btn = Button(self, text="修改")
  342. btn.place(x=450, y=260, width=100, height=30)
  343. return btn
  344. class Frame_content_5(Frame):
  345. def __init__(self, parent):
  346. super().__init__(parent)
  347. self.__frame()
  348. self.tk_table_course_manage = self.__tk_table_course_manage()
  349. self.tk_button_add_course = self.__tk_button_add_course()
  350. self.tk_button_delete_course = self.__tk_button_delete_course()
  351. self.tk_select_box_course_department = self.__tk_select_box_course_department()
  352. self.tk_select_box_course_exam_method = self.__tk_select_box_course_exam_method()
  353. self.tk_button_course_search = self.__tk_button_course_search()
  354. self.tk_button_course_export = self.__tk_button_course_export()
  355. def __frame(self):
  356. self.place(x=0, y=100, width=1000, height=500)
  357. def __tk_table_course_manage(self):
  358. # 表头字段 表头宽度
  359. self.tk_table_course_manage_columns = {"课程号": 100, "课程名称": 200, "学分": 100, "课程性质": 200, "开课学院": 300, "考试方式": 100}
  360. # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。
  361. tk_table = Treeview(self, show="headings", columns=list(self.tk_table_course_manage_columns))
  362. for text, width in self.tk_table_course_manage_columns.items(): # 批量设置列属性
  363. tk_table.heading(text, text=text, anchor='center')
  364. tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
  365. # 插入数据示例
  366. self.tk_course_table_dataset = Dao.getAllCourses()
  367. # 导入初始数据
  368. if self.tk_course_table_dataset.get("code") == 0 and self.tk_course_table_dataset.get("data"):
  369. for data in self.tk_course_table_dataset.get("data"):
  370. tk_table.insert('', END, values=list(data.values()))
  371. tk_table.place(x=0, y=60, width=1000, height=415)
  372. return tk_table
  373. def __tk_button_add_course(self):
  374. btn = Button(self, text="添加课程")
  375. btn.place(x=50, y=10, width=100, height=30)
  376. return btn
  377. def __tk_button_delete_course(self):
  378. btn = Button(self, text="删除课程")
  379. btn.place(x=180, y=10, width=100, height=30)
  380. return btn
  381. def __tk_select_box_course_department(self):
  382. cb = Combobox(self, state="readonly")
  383. values = ["请选择开课学院"]
  384. for i in Dao.getAllDepartments().get("data"):
  385. values.append(i.get("v"))
  386. cb['values'] = values
  387. cb.current(0)
  388. cb.place(x=310, y=10, width=150, height=30)
  389. return cb
  390. def __tk_select_box_course_exam_method(self):
  391. cb = Combobox(self, state="readonly")
  392. values = ["请选择考试方式"]
  393. for i in Dao.getDataDictByType("exammethod").get("data"):
  394. values.append(i.get("v"))
  395. cb['values'] = values
  396. cb.current(0)
  397. cb.place(x=490, y=10, width=150, height=30)
  398. return cb
  399. def __tk_button_course_search(self):
  400. btn = Button(self, text="搜索")
  401. btn.place(x=670, y=10, width=100, height=30)
  402. return btn
  403. def __tk_button_course_export(self):
  404. btn = Button(self, text="导出")
  405. btn.place(x=800, y=10, width=100, height=30)
  406. return btn
  407. class Win(WinGUI):
  408. def __init__(self, current_user):
  409. super().__init__()
  410. self.__event_bind()
  411. self.current_user = current_user
  412. self.uid = current_user.get("uid")
  413. self.tk_label_current_user['text'] = "当前用户:" + current_user.get("uname")
  414. self.tk_tabs_content.tk_tabs_content_0.tea_number.set(current_user.get("uid"))
  415. self.tk_tabs_content.tk_tabs_content_0.tea_name.set(current_user.get("uname"))
  416. self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.current(0 if current_user.get("ugender") == '男' else 1)
  417. self.tk_tabs_content.tk_tabs_content_0.tea_identify.set(current_user.get("uidentify"))
  418. self.tk_tabs_content.tk_tabs_content_0.tea_email.set(current_user.get("uemail"))
  419. def logout(self):
  420. try:
  421. self.updateStudent.destroy()
  422. self.addInfo.destroy()
  423. self.delete.destroy()
  424. except Exception as e:
  425. print(e)
  426. messagebox.showwarning('提示', '欢迎下次使用!')
  427. self.destroy()
  428. login = Login.Win()
  429. login.mainloop()
  430. def updateStudentInfo(self, evt):
  431. current_focus = self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.focus()
  432. current_studentinfo = self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.set(current_focus)
  433. current_uid = current_studentinfo.get('学号')
  434. self.updateStudent = UpdateStudentPage.Win(current_uid)
  435. self.updateStudent.mainloop()
  436. print("<<TreeviewSelect>>事件未处理", evt)
  437. def updateTeacherInfo(self, evt):
  438. __tea_name = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_name.get()
  439. __tea_gender = self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.get()
  440. __tea_identify = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_identity.get()
  441. __tea_email = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_email.get()
  442. if not __tea_name or not __tea_gender or not __tea_identify or not __tea_email:
  443. messagebox.showinfo("提示", "必填项不能为空!")
  444. return
  445. 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]$',
  446. __tea_identify):
  447. messagebox.showinfo("提示", "身份证格式不合法!")
  448. return
  449. if not re.match(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$', __tea_email):
  450. messagebox.showinfo("提示", "电子邮箱格式不合法!")
  451. return
  452. res = Dao.updateUser(self.uid, __tea_name, __tea_gender, __tea_identify, 0, __tea_email)
  453. messagebox.showinfo("提示", res.get("msg"))
  454. self.tk_label_current_user['text'] = "当前用户:" + __tea_name
  455. print("更新教师信息", evt)
  456. def resetTeacherInfo(self, evt):
  457. self.tk_tabs_content.tk_tabs_content_0.tea_name.set(self.current_user.get("uname"))
  458. self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.current(0 if self.current_user.get("ugender") == '男' else 1)
  459. self.tk_tabs_content.tk_tabs_content_0.tea_identify.set(self.current_user.get("uidentify"))
  460. self.tk_tabs_content.tk_tabs_content_0.tea_email.set(self.current_user.get("uemail"))
  461. print("重置教师信息", evt)
  462. def searchStudentInfo(self, evt):
  463. for _ in map(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.delete,
  464. self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.get_children("")):
  465. pass
  466. value = self.tk_tabs_content.tk_tabs_content_1.tk_input_stu_name.get()
  467. num = self.tk_tabs_content.tk_tabs_content_1.tk_select_box_stu_gender.get()
  468. print(num, value)
  469. if num == '请选择性别':
  470. result = Dao.searchStudents(value, '')
  471. else:
  472. result = Dao.searchStudents(value, num)
  473. if result.get("code") == 0:
  474. if result.get("data"):
  475. # print(result.get("data"))
  476. for values in result.get("data"):
  477. self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.insert('', END, values=list(values.values()))
  478. else:
  479. print("未查询到数据!")
  480. else:
  481. print("数据查询异常!")
  482. print("搜索学生信息", evt)
  483. def updateStudentScore(self, evt):
  484. 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())
  485. data = {
  486. "uid": current_item.get("学号"),
  487. "cname": current_item.get("课程名称"),
  488. "score": current_item.get("成绩")
  489. }
  490. updateScorePage = UpdateScorePage.Win(data)
  491. updateScorePage.mainloop()
  492. print("修改学生课程成绩", evt)
  493. def searchStuScore(self, evt):
  494. __score_manage = self.tk_tabs_content.tk_tabs_content_2
  495. __course_name = __score_manage.tk_select_box_score_course_name.get()
  496. __course_nature = __score_manage.tk_select_box_score_nature.get()
  497. __course_department = __score_manage.tk_select_box_score_department.get()
  498. if __score_manage.tk_select_box_score_course_name.current() == 0:
  499. __course_name = ''
  500. if __score_manage.tk_select_box_score_nature.current() == 0:
  501. __course_nature = ''
  502. if __score_manage.tk_select_box_score_department.current() == 0:
  503. __course_department = ''
  504. for _ in map(__score_manage.tk_table_stu_score.delete, __score_manage.tk_table_stu_score.get_children("")):
  505. pass
  506. __score_manage.tk_score_table_dataset = Dao.searchStudentScore(__course_name, __course_nature, __course_department)
  507. # 导入初始数据
  508. if __score_manage.tk_score_table_dataset.get("code") == 0 and __score_manage.tk_score_table_dataset.get("data"):
  509. for data in __score_manage.tk_score_table_dataset.get("data"):
  510. __score_manage.tk_table_stu_score.insert('', END, values=list(data.values()))
  511. __score_manage.tk_select_box_score_course_name.current(0)
  512. __score_manage.tk_select_box_score_nature.current(0)
  513. __score_manage.tk_select_box_score_department.current(0)
  514. print("搜索学生成绩!")
  515. def exportStuScore(self, evt):
  516. path = filedialog.askdirectory()
  517. try:
  518. book = openpyxl.Workbook()
  519. sheet = book.active
  520. fff = list(self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score_columns.keys()) # 获取表头信息
  521. sheet.append(fff)
  522. dataset = [list(data_item.values()) for data_item in
  523. self.tk_tabs_content.tk_tabs_content_2.tk_score_table_dataset.get("data")]
  524. print(dataset)
  525. for i in dataset:
  526. sheet.append(i)
  527. book.save(f"{path}/student_score.xlsx")
  528. messagebox.showinfo("提示", "导出成功!")
  529. except Exception as e:
  530. messagebox.showinfo("提示", "导出失败!")
  531. print(e)
  532. print("导出学生成绩!", evt)
  533. def addStudentInfo(self, evt):
  534. self.addInfo = AddStudentPage.Win()
  535. self.addInfo.mainloop()
  536. print("<Button-1>事件未处理", evt)
  537. def deleteStudentInfo(self, evt):
  538. self.delete = DeleteStudentPage.Win()
  539. self.delete.mainloop()
  540. print("<Button-1>事件未处理", evt)
  541. def addStudentScore(self, evt):
  542. addScorePage = AddScorePage.Win()
  543. addScorePage.mainloop()
  544. def deleteStudentScore(self, evt):
  545. deleteScorePage = DeleteScorePage.Win()
  546. deleteScorePage.mainloop()
  547. print("删除学生成绩", evt)
  548. def updateTeacherPassword(self, evt):
  549. __original_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_original_pwd.get()
  550. __new_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_new_pwd.get()
  551. __confirm_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_confirm_pwd.get()
  552. if __original_pwd == '' or __new_pwd == '' or __confirm_pwd == '':
  553. messagebox.showwarning("提示", "必填项未填写!")
  554. return
  555. if not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __original_pwd) \
  556. or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __new_pwd) \
  557. or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __confirm_pwd):
  558. messagebox.showwarning("提示", "密码格式应为6-18位数字、字母、特殊字符的组合!")
  559. return
  560. if __new_pwd != __confirm_pwd:
  561. messagebox.showwarning("提示", "两次密码输入不一致")
  562. return
  563. res = Dao.updatePassword(self.uid, __original_pwd, __new_pwd)
  564. messagebox.showinfo("提示", res.get("msg"))
  565. if res.get("code") == 0:
  566. self.destroy()
  567. login = Login.Win()
  568. login.mainloop()
  569. print("修改教师密码", evt)
  570. def addCourseInfo(self, evt):
  571. addCoursePage = AddCoursePage.Win()
  572. addCoursePage.mainloop()
  573. print("添加成绩!")
  574. def deleteCourseInfo(self, evt):
  575. deleteCoursePage = DeleteCoursePage.Win()
  576. deleteCoursePage.mainloop()
  577. print("删除课程!")
  578. def searchCourseInfo(self, evt):
  579. __course_manage = self.tk_tabs_content.tk_tabs_content_5
  580. __department = __course_manage.tk_select_box_course_department.get()
  581. __exammethod = __course_manage.tk_select_box_course_exam_method.get()
  582. if __course_manage.tk_select_box_course_department.current() == 0:
  583. __department = ''
  584. if __course_manage.tk_select_box_course_exam_method.current() == 0:
  585. __exammethod = ''
  586. for _ in map(__course_manage.tk_table_course_manage.delete, __course_manage.tk_table_course_manage.get_children("")):
  587. pass
  588. self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset = Dao.searchCourses(__department, __exammethod)
  589. # 导入初始数据
  590. 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"):
  591. for data in self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data"):
  592. __course_manage.tk_table_course_manage.insert('', END, values=list(data.values()))
  593. __course_manage.tk_select_box_course_department.current(0)
  594. __course_manage.tk_select_box_course_exam_method.current(0)
  595. print("查询课程!")
  596. def updateCourseInfo(self, evt):
  597. __focus = self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.focus()
  598. current_item = self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.set(__focus)
  599. __cid = current_item.get("课程号")
  600. self.updateCoursePage = UpdateCoursePage.Win(__cid)
  601. self.updateCoursePage.mainloop()
  602. print("更新课程信息!")
  603. def exportCourseInfo(self, evt):
  604. path = filedialog.askdirectory()
  605. try:
  606. book = openpyxl.Workbook()
  607. sheet = book.active
  608. fff = list(self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage_columns.keys()) # 获取表头信息
  609. sheet.append(fff)
  610. dataset = [list(data_item.values()) for data_item in self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data")]
  611. print(dataset)
  612. for i in dataset:
  613. sheet.append(i)
  614. book.save(path + "/course_info.xlsx")
  615. messagebox.showinfo("提示", "导出成功!")
  616. except Exception as e:
  617. messagebox.showinfo("提示", "导出失败!")
  618. print(e)
  619. def logout_user(self, evt):
  620. messagebox.showwarning('提示', '欢迎下次使用!')
  621. self.destroy()
  622. login = Login.Win()
  623. login.mainloop()
  624. def studentinfo_refresh(self, evt):
  625. # 删除原结点,加入新结点
  626. for _ in map(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.delete,
  627. self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.get_children("")):
  628. pass
  629. result = Dao.getAllStudents()
  630. if result.get("code") == 0:
  631. if result.get("data"):
  632. # print(result.get("data"))
  633. for values in result.get("data"):
  634. self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.insert('', END,
  635. values=list(values.values()))
  636. else:
  637. print("未查询到数据!")
  638. else:
  639. print("数据查询异常!")
  640. def studentinfo_export(self, evt):
  641. path = filedialog.askdirectory()
  642. try:
  643. book = openpyxl.Workbook()
  644. sheet = book.active
  645. fff = list(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_manage_columns.keys()) # 获取表头信息
  646. sheet.append(fff)
  647. dataset = [list(data_item.values()) for data_item in
  648. self.tk_tabs_content.tk_tabs_content_1.tk_student_table_dataset.get("data")]
  649. print(dataset)
  650. for i in dataset:
  651. sheet.append(i)
  652. book.save(path + "/student_info.xlsx")
  653. messagebox.showinfo("提示", "导出成功!")
  654. except Exception as e:
  655. messagebox.showinfo("提示", "导出失败!")
  656. print(e)
  657. def columnChart(self, evt):
  658. courseScoreAnalysis = CourseScoreAnalysis.Win()
  659. courseScoreAnalysis.mainloop()
  660. def paratacticColumnChart(self, evt):
  661. classGradeAnalysis = ClassGradeAnalysis.Win()
  662. classGradeAnalysis.mainloop()
  663. def pieChart(self, evt):
  664. comprehensivePerformanceEvaluation = ComprehensivePerformanceEvaluation.Win()
  665. comprehensivePerformanceEvaluation.mainloop()
  666. def __event_bind(self):
  667. self.protocol('WM_DELETE_WINDOW', self.logout)
  668. self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.bind('<<TreeviewSelect>>', self.updateStudentInfo)
  669. self.tk_tabs_content.tk_tabs_content_0.tk_button_tea_update.bind('<Button-1>', self.updateTeacherInfo)
  670. self.tk_tabs_content.tk_tabs_content_0.tk_button_tea_reset.bind('<Button-1>', self.resetTeacherInfo)
  671. self.tk_tabs_content.tk_tabs_content_1.tk_button_stu_search.bind('<Button-1>', self.searchStudentInfo)
  672. self.tk_tabs_content.tk_tabs_content_1.tk_button_addStudent.bind('<Button-1>', self.addStudentInfo)
  673. self.tk_tabs_content.tk_tabs_content_1.tk_button_delete_student.bind('<Button-1>', self.deleteStudentInfo)
  674. self.tk_tabs_content.tk_tabs_content_1.tk_button_stu_refresh.bind('<Button-1>', self.studentinfo_refresh)
  675. self.tk_tabs_content.tk_tabs_content_1.tk_button_studentinfo_export.bind('<Button-1>', self.studentinfo_export)
  676. self.tk_tabs_content.tk_tabs_content_2.tk_button_add_score.bind('<Button-1>', self.addStudentScore)
  677. self.tk_tabs_content.tk_tabs_content_2.tk_button_delete_score.bind('<Button-1>', self.deleteStudentScore)
  678. self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score.bind('<<TreeviewSelect>>', self.updateStudentScore)
  679. self.tk_tabs_content.tk_tabs_content_2.tk_button_stu_score_search.bind('<Button-1>', self.searchStuScore)
  680. self.tk_tabs_content.tk_tabs_content_2.tk_button_stu_score_export.bind('<Button-1>', self.exportStuScore)
  681. self.tk_tabs_content.tk_tabs_content_3.tk_button_columnChart.bind('<Button-1>', self.columnChart)
  682. self.tk_tabs_content.tk_tabs_content_3.tk_button_paratacticColumnChart.bind('<Button-1>', self.paratacticColumnChart)
  683. self.tk_tabs_content.tk_tabs_content_3.tk_button_pieChart.bind('<Button-1>', self.pieChart)
  684. self.tk_tabs_content.tk_tabs_content_4.tk_button_update_tea_pwd.bind('<Button-1>', self.updateTeacherPassword)
  685. self.tk_tabs_content.tk_tabs_content_5.tk_button_add_course.bind('<Button-1>', self.addCourseInfo)
  686. self.tk_tabs_content.tk_tabs_content_5.tk_button_delete_course.bind('<Button-1>', self.deleteCourseInfo)
  687. self.tk_tabs_content.tk_tabs_content_5.tk_button_course_search.bind('<Button-1>', self.searchCourseInfo)
  688. self.tk_tabs_content.tk_tabs_content_5.tk_button_course_export.bind('<Button-1>', self.exportCourseInfo)
  689. self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.bind('<<TreeviewSelect>>', self.updateCourseInfo)
  690. self.tk_button_logout_user.bind('<Button-1>', self.logout_user)

学生端登录页面效果:

4372cd6b99704ec4bc6aa215ec45f9da.png

学生端——成绩分析:

学生端——修改密码:

bc4900e878ee4e9c83d00a8bcb6cfc95.png

 学生端代码如下:

student.py:

  1. from tkinter import *
  2. from tkinter import messagebox, filedialog
  3. from tkinter.ttk import *
  4. import numpy as np
  5. import openpyxl
  6. from matplotlib import pyplot as plt
  7. import Dao
  8. import Login
  9. global current_uid
  10. class WinGUI(Tk):
  11. def __init__(self):
  12. super().__init__()
  13. self.__win()
  14. self.tk_label_title = self.__tk_label_title()
  15. self.tk_label_current_user = self.__tk_label_current_user()
  16. self.tk_tabs_content = Frame_content(self)
  17. self.tk_button_logout = self.__tk_button_logout()
  18. def __win(self):
  19. self.title("成绩查询")
  20. # 设置窗口大小、居中
  21. width = 1000
  22. height = 600
  23. screenwidth = self.winfo_screenwidth()
  24. screenheight = self.winfo_screenheight()
  25. geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
  26. self.geometry(geometry)
  27. self.resizable(width=False, height=False)
  28. self.iconbitmap('logo.ico')
  29. def __tk_label_title(self):
  30. label = Label(self, text="学生成绩管理系统", anchor="center")
  31. label.place(x=0, y=0, width=800, height=100)
  32. return label
  33. def __tk_label_current_user(self):
  34. label = Label(self, text="当前用户:admin", anchor="center")
  35. label.place(x=800, y=70, width=150, height=30)
  36. return label
  37. def __tk_button_logout(self):
  38. btn = Button(self, text="退出")
  39. btn.place(x=950, y=70, width=50, height=30)
  40. return btn
  41. class Frame_content(Notebook):
  42. def __init__(self, parent):
  43. super().__init__(parent)
  44. self.__frame()
  45. def __frame(self):
  46. self.tk_tabs_content_0 = Frame_content_0(self)
  47. self.add(self.tk_tabs_content_0, text="个人资料")
  48. self.tk_tabs_content_1 = Frame_content_1(self)
  49. self.add(self.tk_tabs_content_1, text="成绩查询")
  50. self.tk_tabs_content_3 = Frame_content_3(self)
  51. self.add(self.tk_tabs_content_3, text="修改密码")
  52. self.place(x=0, y=100, width=1000, height=500)
  53. class Frame_content_0(Frame):
  54. def __init__(self, parent):
  55. super().__init__(parent)
  56. self.__frame()
  57. self.tk_label_stu_number = self.__tk_label_stu_number()
  58. self.tk_input_stu_number = self.__tk_input_stu_number()
  59. self.tk_label_stu_name = self.__tk_label_stu_name()
  60. self.tk_input_stu_name = self.__tk_input_stu_name()
  61. self.tk_label_stu_gender = self.__tk_label_stu_gender()
  62. self.tk_tk_select_stu_gender = self.__tk_select_stu_gender()
  63. self.tk_label_stu_identity = self.__tk_label_stu_identity()
  64. self.tk_input_stu_identity = self.__tk_input_stu_identity()
  65. self.tk_label_stu_email = self.__tk_label_stu_email()
  66. self.tk_input_stu_email = self.__tk_input_stu_email()
  67. self.tk_button_stu_update = self.__tk_button_stu_update()
  68. self.tk_button_stu_reset = self.__tk_button_stu_reset()
  69. def __frame(self):
  70. self.place(x=0, y=100, width=1000, height=500)
  71. def __tk_label_stu_number(self):
  72. label = Label(self, text="学号", anchor="e")
  73. label.place(x=360, y=40, width=100, height=30)
  74. return label
  75. def __tk_input_stu_number(self):
  76. self.student_number = StringVar(self)
  77. ipt = Entry(self, text=self.student_number)
  78. ipt.place(x=490, y=40, width=150, height=30)
  79. ipt.config(stat='disable')
  80. return ipt
  81. def __tk_label_stu_name(self):
  82. label = Label(self, text="姓名", anchor="e")
  83. label.place(x=360, y=110, width=100, height=30)
  84. return label
  85. def __tk_input_stu_name(self):
  86. self.student_name = StringVar(self)
  87. ipt = Entry(self, text=self.student_name)
  88. ipt.place(x=490, y=110, width=150, height=30)
  89. return ipt
  90. def __tk_label_stu_gender(self):
  91. label = Label(self, text="性别", anchor="e")
  92. label.place(x=360, y=180, width=100, height=30)
  93. return label
  94. def __tk_select_stu_gender(self):
  95. cb = Combobox(self, state='readonly')
  96. cb['values'] = ("男", "女")
  97. cb.place(x=490, y=180, width=150, height=30)
  98. return cb
  99. def __tk_label_stu_identity(self):
  100. label = Label(self, text="身份证号", anchor="e")
  101. label.place(x=360, y=250, width=100, height=30)
  102. return label
  103. def __tk_input_stu_identity(self):
  104. self.student_identify = StringVar(self)
  105. ipt = Entry(self, text=self.student_identify)
  106. ipt.place(x=490, y=250, width=150, height=30)
  107. return ipt
  108. def __tk_label_stu_email(self):
  109. label = Label(self, text="电子邮箱", anchor="e")
  110. label.place(x=360, y=320, width=100, height=30)
  111. return label
  112. def __tk_input_stu_email(self):
  113. self.student_email = StringVar(self)
  114. ipt = Entry(self, text=self.student_email)
  115. ipt.place(x=490, y=320, width=150, height=30)
  116. return ipt
  117. def __tk_button_stu_update(self):
  118. btn = Button(self, text="修改")
  119. btn.place(x=400, y=390, width=80, height=30)
  120. return btn
  121. def __tk_button_stu_reset(self):
  122. btn = Button(self, text="重置")
  123. btn.place(x=520, y=390, width=80, height=30)
  124. return btn
  125. class Frame_content_1(Frame):
  126. def __init__(self, parent):
  127. super().__init__(parent)
  128. self.__frame()
  129. self.tk_button_analysis = self.__tk_button_analysis()
  130. self.tk_table_stu_score = self.__tk_table_stu_score()
  131. self.tk_select_box_course_nature = self.__tk_select_box_course_nature()
  132. self.tk_select_box_course_department = self.__tk_select_box_course_department()
  133. self.tk_select_box_exam_method = self.__tk_select_box_exam_method()
  134. self.tk_button_search = self.__tk_button_search()
  135. self.tk_button_export = self.__tk_button_export()
  136. def __frame(self):
  137. self.place(x=0, y=100, width=1000, height=500)
  138. def __tk_table_stu_score(self):
  139. # 表头字段 表头宽度
  140. self.tk_table_stu_score_columns = {"#": 50, "课程名称": 200, "课程性质": 150, "开课学院": 300, "考试方式": 100, "学分": 100, "成绩": 100}
  141. # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。
  142. tk_table = Treeview(self, show="headings", columns=list(self.tk_table_stu_score_columns))
  143. for text, width in self.tk_table_stu_score_columns.items(): # 批量设置列属性
  144. tk_table.heading(text, text=text, anchor='center')
  145. tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
  146. # 插入数据示例
  147. # self.tk_score_table_dataset = Dao.getScoreByUid(8888)
  148. # # 导入初始数据
  149. # if self.tk_score_table_dataset.get("code") == 0 and self.tk_score_table_dataset.get("data"):
  150. # for data in self.tk_score_table_dataset.get("data"):
  151. # tk_table.insert('', END, values=list(data.values()))
  152. tk_table.place(x=0, y=55, width=1000, height=420)
  153. return tk_table
  154. def __tk_button_analysis(self):
  155. btn = Button(self, text="分析")
  156. btn.place(x=65, y=10, width=75, height=30)
  157. return btn
  158. def __tk_select_box_course_nature(self):
  159. cb = Combobox(self, state="readonly")
  160. values = ["请选择课程性质"]
  161. for i in Dao.getDataDictByType("nature").get("data"):
  162. values.append(i.get("v"))
  163. cb['values'] = values
  164. cb.current(0)
  165. cb.place(x=180, y=10, width=150, height=30)
  166. return cb
  167. def __tk_select_box_course_department(self):
  168. cb = Combobox(self, state="readonly")
  169. values = ["请选择开课学院"]
  170. for i in Dao.getAllDepartments().get("data"):
  171. values.append(i.get("v"))
  172. cb['values'] = values
  173. cb.current(0)
  174. cb.place(x=370, y=10, width=150, height=30)
  175. return cb
  176. def __tk_select_box_exam_method(self):
  177. cb = Combobox(self, state="readonly")
  178. values = ["请选择考试方式"]
  179. for i in Dao.getDataDictByType("exammethod").get("data"):
  180. values.append(i.get("v"))
  181. cb['values'] = values
  182. cb.current(0)
  183. cb.place(x=560, y=10, width=150, height=30)
  184. return cb
  185. def __tk_button_search(self):
  186. btn = Button(self, text="搜索")
  187. btn.place(x=750, y=10, width=75, height=30)
  188. return btn
  189. def __tk_button_export(self):
  190. btn = Button(self, text="导出")
  191. btn.place(x=840, y=10, width=75, height=30)
  192. return btn
  193. class Frame_content_3(Frame):
  194. def __init__(self, parent):
  195. super().__init__(parent)
  196. self.__frame()
  197. self.tk_label_original_password = self.__tk_label_original_password()
  198. self.tk_input_original_password = self.__tk_input_original_password()
  199. self.tk_label_new_password = self.__tk_label_new_password()
  200. self.tk_input_new_password = self.__tk_input_new_password()
  201. self.tk_label_confirm_password = self.__tk_label_confirm_password()
  202. self.tk_input_confirm_password = self.__tk_input_confirm_password()
  203. self.tk_button_update_stu_password = self.__tk_button_update_stu_password()
  204. def __frame(self):
  205. self.place(x=0, y=100, width=1000, height=500)
  206. def __tk_label_original_password(self):
  207. label = Label(self, text="原密码", anchor="e")
  208. label.place(x=360, y=40, width=100, height=30)
  209. return label
  210. def __tk_input_original_password(self):
  211. ipt = Entry(self, show='*')
  212. ipt.place(x=490, y=40, width=150, height=30)
  213. return ipt
  214. def __tk_label_new_password(self):
  215. label = Label(self, text="新密码", anchor="e")
  216. label.place(x=360, y=110, width=100, height=30)
  217. return label
  218. def __tk_input_new_password(self):
  219. ipt = Entry(self, show='*')
  220. ipt.place(x=490, y=110, width=150, height=30)
  221. return ipt
  222. def __tk_label_confirm_password(self):
  223. label = Label(self, text="确认密码", anchor="e")
  224. label.place(x=360, y=180, width=100, height=30)
  225. return label
  226. def __tk_input_confirm_password(self):
  227. ipt = Entry(self, show='*')
  228. ipt.place(x=490, y=180, width=150, height=30)
  229. return ipt
  230. def __tk_button_update_stu_password(self):
  231. btn = Button(self, text="修改")
  232. btn.place(x=460, y=250, width=100, height=30)
  233. return btn
  234. class Win(WinGUI):
  235. def __init__(self, current_user):
  236. super().__init__()
  237. self.__event_bind()
  238. self.uid = current_user.get("uid")
  239. self.uclid = current_user.get("uclid")
  240. self.tk_label_current_user['text'] = "当前用户:" + current_user.get("uname")
  241. self.tk_tabs_content.tk_tabs_content_0.student_number.set(current_user.get("uid"))
  242. self.tk_tabs_content.tk_tabs_content_0.student_name.set(current_user.get("uname"))
  243. self.tk_tabs_content.tk_tabs_content_0.tk_tk_select_stu_gender.current(0 if current_user.get("ugender") == '男' else 1)
  244. self.tk_tabs_content.tk_tabs_content_0.student_identify.set(current_user.get("uidentify"))
  245. self.tk_tabs_content.tk_tabs_content_0.student_email.set(current_user.get("uemail"))
  246. # 插入数据示例
  247. self.score_table_dataset = Dao.getScoreByUid(self.uid)
  248. # 导入初始数据
  249. if self.score_table_dataset.get("code") == 0 and self.score_table_dataset.get("data"):
  250. for data in self.score_table_dataset.get("data"):
  251. self.tk_tabs_content.tk_tabs_content_1.tk_table_stu_score.insert('', END, values=list(data.values()))
  252. def logout(self):
  253. messagebox.showwarning('提示', '欢迎下次使用!')
  254. self.destroy()
  255. login = Login.Win()
  256. login.mainloop()
  257. def updateStudentInfo(self, evt):
  258. __stu_name = self.tk_tabs_content.tk_tabs_content_0.tk_input_stu_name.get()
  259. __stu_gender = self.tk_tabs_content.tk_tabs_content_0.tk_tk_select_stu_gender.get()
  260. __stu_identify = self.tk_tabs_content.tk_tabs_content_0.tk_input_stu_identity.get()
  261. __stu_email = self.tk_tabs_content.tk_tabs_content_0.tk_input_stu_email.get()
  262. if not __stu_name or not __stu_gender or not __stu_identify or not __stu_email:
  263. messagebox.showinfo("提示", "必填项不能为空!")
  264. return
  265. 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):
  266. messagebox.showinfo("提示", "身份证格式不合法!")
  267. return
  268. if not re.match(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$', __stu_email):
  269. messagebox.showinfo("提示", "电子邮箱格式不合法!")
  270. return
  271. res = Dao.updateUser(self.uid, __stu_name, __stu_gender, __stu_identify, self.uclid, __stu_email)
  272. messagebox.showinfo("提示", res.get("msg"))
  273. self.tk_label_current_user['text'] = "当前用户:" + __stu_name
  274. print("更新学生信息", evt)
  275. def stu_reset(self, evt):
  276. self.tk_tabs_content.tk_tabs_content_0.student_number.set(self.userInfo[0])
  277. self.tk_tabs_content.tk_tabs_content_0.student_name.set(self.userInfo[1])
  278. self.tk_tabs_content.tk_tabs_content_0.tk_tk_select_stu_gender.current(0 if self.userInfo[2] else 1)
  279. self.tk_tabs_content.tk_tabs_content_0.student_identify.set(self.userInfo[3])
  280. self.tk_tabs_content.tk_tabs_content_0.student_email.set(self.userInfo[5])
  281. def analysisStudentScore(self, evt):
  282. result = Dao.getScoreByUid(self.uid).get("data")
  283. plt.title('成绩统计图')
  284. # 设置x轴数据
  285. x = [i.get("cname") for i in result]
  286. # 每组数据n有3个类型
  287. total_width, n = 0.6, 3
  288. width = total_width / n
  289. y1 = [i.get("score") for i in result]
  290. y2 = [i.get("avg_score") for i in Dao.getAllCourseAvgScore(self.uid).get("data")]
  291. plt.bar(x, y1, color="b", width=width, label='我的成绩')
  292. plt.plot(x, y2, color="g", label='科目平均成绩')
  293. # x和y轴标题
  294. plt.xlabel("课程")
  295. plt.ylabel("分数")
  296. plt.legend(loc="best")
  297. plt.ylim((0, 100))
  298. # 设置纵轴起始,终止和间距
  299. my_y_ticks = np.arange(0, 100, 10)
  300. plt.yticks(my_y_ticks)
  301. plt.rcParams['font.sans-serif'] = ['SimHei'] # 支持中文显示
  302. plt.show()
  303. print("成绩分析图表绘制")
  304. def searchStudentScore(self, evt):
  305. __score_query = self.tk_tabs_content.tk_tabs_content_1
  306. __nature = __score_query.tk_select_box_course_nature.get()
  307. __department = __score_query.tk_select_box_course_department.get()
  308. __exammethod = __score_query.tk_select_box_exam_method.get()
  309. if __score_query.tk_select_box_course_nature.current() == 0:
  310. __nature = ''
  311. if __score_query.tk_select_box_course_department.current() == 0:
  312. __department = ''
  313. if __score_query.tk_select_box_exam_method.current() == 0:
  314. __exammethod = ''
  315. for _ in map(__score_query.tk_table_stu_score.delete, __score_query.tk_table_stu_score.get_children("")):
  316. pass
  317. self.score_table_dataset = Dao.getScoreByUid(self.uid, __nature, __department, __exammethod)
  318. # 导入初始数据
  319. if self.score_table_dataset.get("code") == 0 and self.score_table_dataset.get("data"):
  320. for data in self.score_table_dataset.get("data"):
  321. __score_query.tk_table_stu_score.insert('', END, values=list(data.values()))
  322. __score_query.tk_select_box_course_nature.current(0)
  323. __score_query.tk_select_box_course_department.current(0)
  324. __score_query.tk_select_box_exam_method.current(0)
  325. print(f"查询学生{self.uid}的成绩!")
  326. def exportStudentScore(self, evt):
  327. path = filedialog.askdirectory()
  328. try:
  329. book = openpyxl.Workbook()
  330. sheet = book.active
  331. fff = list(self.tk_tabs_content.tk_tabs_content_1.tk_table_stu_score_columns.keys()) # 获取表头信息
  332. sheet.append(fff)
  333. dataset = [list(data_item.values()) for data_item in
  334. self.score_table_dataset.get("data")]
  335. print(dataset)
  336. for i in dataset:
  337. sheet.append(i)
  338. book.save(f"{path}/{self.uid}.xlsx")
  339. messagebox.showinfo("提示", "导出成功!")
  340. except Exception as e:
  341. messagebox.showinfo("提示", "导出失败!")
  342. print(e)
  343. print("<Button-1>事件未处理", evt)
  344. def updateStudentPassword(self, evt):
  345. __original_pwd = self.tk_tabs_content.tk_tabs_content_3.tk_input_original_password.get()
  346. __new_pwd = self.tk_tabs_content.tk_tabs_content_3.tk_input_new_password.get()
  347. __confirm_pwd = self.tk_tabs_content.tk_tabs_content_3.tk_input_confirm_password.get()
  348. if __original_pwd == '' or __new_pwd == '' or __confirm_pwd == '':
  349. messagebox.showwarning("提示", "必填项未填写!")
  350. return
  351. if not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __original_pwd) \
  352. or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __new_pwd) \
  353. or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __confirm_pwd):
  354. messagebox.showwarning("提示", "密码格式应为6-18位数字、字母、特殊字符的组合!")
  355. return
  356. if __new_pwd != __confirm_pwd:
  357. messagebox.showwarning("提示", "两次密码输入不一致")
  358. return
  359. res = Dao.updatePassword(self.uid, __original_pwd, __new_pwd)
  360. messagebox.showinfo("提示", res.get("msg"))
  361. if res.get("code") == 0:
  362. self.destroy()
  363. login = Login.Win()
  364. login.mainloop()
  365. print("修改密码", evt)
  366. def logout_user(self, evt):
  367. messagebox.showwarning('提示', '欢迎下次使用!')
  368. self.destroy()
  369. login = Login.Win()
  370. login.mainloop()
  371. def __event_bind(self):
  372. self.protocol('WM_DELETE_WINDOW', self.logout)
  373. self.tk_tabs_content.tk_tabs_content_0.tk_button_stu_update.bind('<Button-1>', self.updateStudentInfo)
  374. self.tk_tabs_content.tk_tabs_content_0.tk_button_stu_reset.bind('<Button-1>', self.stu_reset)
  375. self.tk_tabs_content.tk_tabs_content_1.tk_button_analysis.bind('<Button-1>', self.analysisStudentScore)
  376. self.tk_tabs_content.tk_tabs_content_1.tk_button_search.bind('<Button-1>', self.searchStudentScore)
  377. self.tk_tabs_content.tk_tabs_content_1.tk_button_export.bind('<Button-1>', self.exportStudentScore)
  378. self.tk_tabs_content.tk_tabs_content_3.tk_button_update_stu_password.bind('<Button-1>',
  379. self.updateStudentPassword)
  380. self.tk_button_logout.bind('<Button-1>', self.logout_user)

数据库采用mysql 8.0,库名和表如下:

d05ca003ad1c475297b73b3e0afbcf3a.png

 Dao层代码如下:用于访问数据库,向数据库发送sql语句,完成成绩与科目等增删改查任务

Dao.py:

  1. import pymysql
  2. def getConnect():
  3. """
  4. 获取数据库连接
  5. :return:
  6. """
  7. conn = pymysql.Connect(
  8. host='localhost',
  9. port=3306,
  10. user='#你的数据库用户名',
  11. password='#你的数据库密码',
  12. db='stu_sc_sys',
  13. charset='utf8',
  14. cursorclass=pymysql.cursors.DictCursor
  15. )
  16. cursor = conn.cursor()
  17. return conn, cursor
  18. def getUserByIdAndPwd(username, password):
  19. conn, cursor = getConnect()
  20. sql = f"select uid, uname, ugender, uidentify, uclid, uemail, urole from user where uid='{username}' " \
  21. f"and upwd='{password}'"
  22. cursor.execute(sql)
  23. res = {
  24. "code": 0,
  25. "msg": "success",
  26. "data": cursor.fetchone()
  27. }
  28. cursor.close()
  29. conn.close()
  30. return res
  31. def getUserInfoById(uid):
  32. conn, cursor = getConnect()
  33. sql = f"select uid, uname, ugender, uidentify, uclid, uemail, urole from user where uid='{uid}'"
  34. cursor.execute(sql)
  35. res = cursor.fetchone()
  36. cursor.close()
  37. conn.close()
  38. return res
  39. def updatePassword(uid, origin_pwd, new_pwd):
  40. conn, cursor = getConnect()
  41. res = {
  42. "code": 1,
  43. "msg": "修改密码失败!"
  44. }
  45. if not getUserByIdAndPwd(uid, origin_pwd).get("data"):
  46. res = {
  47. "code": 1,
  48. "msg": "原密码不正确!"
  49. }
  50. else:
  51. sql = f"update user set upwd = '{new_pwd}' where uid = '{uid}'"
  52. try:
  53. cursor.execute(sql)
  54. conn.commit()
  55. res = {
  56. "code": 0,
  57. "msg": "修改成功!"
  58. }
  59. except Exception as e:
  60. conn.rollback()
  61. print(e)
  62. return res
  63. def getScoreByUid(uid, nature='', department='', exam_method=''):
  64. """
  65. 通过学号获取成绩
  66. :param uid:
  67. :param nature:
  68. :param department:
  69. :param exam_method:
  70. :return:
  71. """
  72. conn, cursor = getConnect()
  73. sql = f"select ROW_NUMBER() over () as id, uc.cname, c.cnature, c.cdepartment, c.cexammethod, c.ccredit, score " \
  74. f"from user_course uc inner join user u on uc.uid = u.uid inner join course c on uc.cname = c.cname " \
  75. f"where u.uid = '{uid}' and c.cnature like '%{nature}%' and " \
  76. f"c.cdepartment like '%{department}%' and c.cexammethod like '%{exam_method}%'"
  77. print(sql)
  78. cursor.execute(sql)
  79. res = {
  80. "code": 0,
  81. "msg": "success",
  82. "data": cursor.fetchall()
  83. }
  84. cursor.close()
  85. conn.close()
  86. return res
  87. def getAllUsers():
  88. connection, cursor = getConnect()
  89. sql = 'select uid, uname, ugender, uidentify, uclid, uemail, upwd, urole from user'
  90. cursor.execute(sql)
  91. res = {
  92. "code": 0,
  93. "msg": "success",
  94. "data": cursor.fetchall()
  95. }
  96. cursor.close()
  97. connection.close()
  98. return res
  99. def getAllStudents():
  100. connection, cursor = getConnect()
  101. sql = "select row_number() over () as id, uid, uname, ugender, uidentify, uclid, uemail from user where urole = 1"
  102. cursor.execute(sql)
  103. res = {
  104. "code": 0,
  105. "msg": "success",
  106. "data": cursor.fetchall()
  107. }
  108. cursor.close()
  109. connection.close()
  110. return res
  111. def searchStudents(uname, ugender):
  112. """
  113. 学生信息搜索
  114. :param uname:
  115. :param ugender:
  116. :return:
  117. """
  118. connection, cursor = getConnect()
  119. sql = f"select row_number() over () as id, uid, uname, ugender, uidentify, uclid, uemail, upwd, urole from user " \
  120. f"where urole = 1 and uname like '%{uname}%' and ugender like '%{ugender}%'"
  121. cursor.execute(sql)
  122. res = {
  123. "code": 0,
  124. "msg": "success",
  125. "data": cursor.fetchall()
  126. }
  127. cursor.close()
  128. connection.close()
  129. return res
  130. def addStudent(uid, uname, ugender, uidentify, uclid, uemail):
  131. """
  132. 添加一个学生信息,密码默认为123456
  133. :param uid:
  134. :param uname:
  135. :param ugender:
  136. :param uidentify:
  137. :param uclid:
  138. :param uemail:
  139. :return:
  140. """
  141. connection, cursor = getConnect()
  142. sql = f"insert into user(uid, uname, ugender, uidentify, uclid, uemail, upwd) values ('{uid}', '{uname}'" \
  143. f", '{ugender}', '{uidentify}', '{uclid}', '{uemail}', '123456') "
  144. res = {
  145. "code": 0,
  146. "msg": "添加成功!"
  147. }
  148. try:
  149. cursor.execute(sql)
  150. connection.commit()
  151. except Exception as e:
  152. res = {
  153. "code": 1,
  154. "msg": "添加失败!"
  155. }
  156. connection.rollback()
  157. print(e)
  158. cursor.close()
  159. connection.close()
  160. return res
  161. def deleteUser(uid):
  162. """
  163. 通过uid删除用户
  164. :param uid:
  165. :return:
  166. """
  167. connection, cursor = getConnect()
  168. sql = f"delete from user where uid = '{uid}'"
  169. res = {
  170. "code": 0,
  171. "msg": "删除成功!"
  172. }
  173. try:
  174. cursor.execute(sql)
  175. connection.commit()
  176. except Exception as e:
  177. res = {
  178. "code": 1,
  179. "msg": "删除失败!"
  180. }
  181. connection.rollback()
  182. print(e)
  183. cursor.close()
  184. connection.close()
  185. return res
  186. def updateUser(uid, uname, ugender, uidentify, uclid, uemail):
  187. """
  188. 通过uid更新用户信息
  189. :param uid:
  190. :param uname:
  191. :param ugender:
  192. :param uidentify:
  193. :param uclid:
  194. :param uemail:
  195. :return:
  196. """
  197. connection, cursor = getConnect()
  198. sql = f"update user set uname = '{uname}', ugender = '{ugender}', uidentify = '{uidentify}', uclid = '{uclid}'" \
  199. f", uemail ='{uemail}' where uid = '{uid}'"
  200. print(sql)
  201. res = {
  202. "code": 0,
  203. "msg": "修改成功!"
  204. }
  205. try:
  206. cursor.execute(sql)
  207. connection.commit()
  208. except Exception as e:
  209. res = {
  210. "code": 1,
  211. "msg": "修改失败!"
  212. }
  213. connection.rollback()
  214. print(e)
  215. cursor.close()
  216. connection.close()
  217. return res
  218. def getAllCourses():
  219. """
  220. 获取所有的课程信息
  221. :return:
  222. """
  223. connection, cursor = getConnect()
  224. sql = "select cid, cname, ccredit, cnature, cdepartment, cexammethod from course"
  225. cursor.execute(sql)
  226. res = {
  227. "code": 0,
  228. "msg": "success",
  229. "data": cursor.fetchall()
  230. }
  231. cursor.close()
  232. connection.close()
  233. return res
  234. def getCourseByCid(cid):
  235. """
  236. 获取cid的课程
  237. :return:
  238. """
  239. connection, cursor = getConnect()
  240. sql = f"select cid, cname, cnature, ccredit, cdepartment, cexammethod from course where cid = '{cid}'"
  241. cursor.execute(sql)
  242. res = {
  243. "code": 0,
  244. "msg": "success",
  245. "data": cursor.fetchall()
  246. }
  247. cursor.close()
  248. connection.close()
  249. return res
  250. def getDataDictByType(dtype):
  251. """
  252. 获取dtype类型的数据字典
  253. :param:
  254. :return:
  255. """
  256. connection, cursor = getConnect()
  257. sql = f"select d.ddtkey as k, d.ddtvalue as v from dictionary d where d.ddtype = '{dtype}'"
  258. cursor.execute(sql)
  259. res = {
  260. "code": 0,
  261. "msg": "success",
  262. "data": cursor.fetchall()
  263. }
  264. cursor.close()
  265. connection.close()
  266. return res
  267. def getAllDepartments():
  268. """
  269. 获取所有的学院
  270. :return:
  271. """
  272. connection, cursor = getConnect()
  273. sql = "select did as k, dname as v from department"
  274. cursor.execute(sql)
  275. res = {
  276. "code": 0,
  277. "msg": "success",
  278. "data": cursor.fetchall()
  279. }
  280. cursor.close()
  281. connection.close()
  282. return res
  283. def getMaxStuNumber(s_num_prefix):
  284. """
  285. 获取以s_num_prefix开头的最大学号
  286. :return:
  287. """
  288. connection, cursor = getConnect()
  289. sql = f"select MAX(uid) as max_id from user where uid like '{s_num_prefix}%'"
  290. cursor.execute(sql)
  291. res = {
  292. "code": 0,
  293. "msg": "success",
  294. "data": cursor.fetchall()
  295. }
  296. cursor.close()
  297. connection.close()
  298. return res
  299. def addCourse(cname, nature, credit, department, exam_method):
  300. """
  301. 添加课程
  302. :return:
  303. """
  304. connection, cursor = getConnect()
  305. sql = f"insert into course(cname, cnature, ccredit, cdepartment, cexammethod) VALUES ('{cname}', '{nature}'" \
  306. f", '{credit}', '{department}', '{exam_method}')"
  307. res = {
  308. "code": 0,
  309. "msg": "添加课程成功!"
  310. }
  311. try:
  312. cursor.execute(sql)
  313. connection.commit()
  314. except Exception as e:
  315. res = {
  316. "code": 1,
  317. "msg": "添加课程失败!"
  318. }
  319. connection.rollback()
  320. print(e)
  321. cursor.close()
  322. connection.close()
  323. return res
  324. def deleteCourse(cid):
  325. """
  326. 删除课程
  327. :return:
  328. """
  329. connection, cursor = getConnect()
  330. sql = f"delete from course where cid = {cid}"
  331. res = {
  332. "code": 0,
  333. "msg": "删除课程成功!"
  334. }
  335. try:
  336. cursor.execute(sql)
  337. connection.commit()
  338. except Exception as e:
  339. res = {
  340. "code": 1,
  341. "msg": "删除课程失败!"
  342. }
  343. connection.rollback()
  344. print(e)
  345. cursor.close()
  346. connection.close()
  347. return res
  348. def searchCourses(department, exammethod):
  349. """
  350. 搜索课程信息
  351. :param department:
  352. :param exammethod:
  353. :return:
  354. """
  355. connection, cursor = getConnect()
  356. sql = f"select cid, cname, ccredit, cnature, cdepartment, cexammethod from course " \
  357. f"where cdepartment like '%{department}%' and cexammethod like '%{exammethod}%'"
  358. cursor.execute(sql)
  359. res = {
  360. "code": 0,
  361. "msg": "success",
  362. "data": cursor.fetchall()
  363. }
  364. cursor.close()
  365. connection.close()
  366. return res
  367. def updateCourseInfo(cid, cname, nature, credit, department, exammethod):
  368. """
  369. 修改课程信息
  370. :param cid:
  371. :param cname:
  372. :param nature:
  373. :param credit:
  374. :param department:
  375. :param exammethod:
  376. :return:
  377. """
  378. connection, cursor = getConnect()
  379. sql = f"update course set cname = '{cname}', cnature = '{nature}', ccredit = '{credit}'" \
  380. f", cdepartment = '{department}', cexammethod = '{exammethod}' where cid = '{cid}'"
  381. res = {
  382. "code": 0,
  383. "msg": "修改课程成功!"
  384. }
  385. try:
  386. cursor.execute(sql)
  387. connection.commit()
  388. except Exception as e:
  389. res = {
  390. "code": 1,
  391. "msg": "更新课程失败!"
  392. }
  393. connection.rollback()
  394. print(e)
  395. cursor.close()
  396. connection.close()
  397. return res
  398. def getScoreBandByCName(course_name):
  399. """
  400. 获取课程名为course_name的各个分段的学生人数
  401. :param course_name:
  402. :return:
  403. """
  404. connection, cursor = getConnect()
  405. 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, " \
  406. f"SUM(IF(score < 80 and score >= 70, 1, 0)) as C, SUM(IF(score < 70 and score >= 60, 1, 0)) as D, " \
  407. f"SUM(IF(score < 60, 1, 0)) as E from user_course where cname = '{course_name}'"
  408. cursor.execute(sql)
  409. res = {
  410. "code": 0,
  411. "msg": "success",
  412. "data": cursor.fetchall()
  413. }
  414. cursor.close()
  415. connection.close()
  416. return res
  417. def getMaxAndMinAndAvgScoreByCLid(class_id):
  418. """
  419. 获取班级号为class_id的班级的各科最高分、最低分以及平均分
  420. :param class_id:
  421. :return:
  422. """
  423. connection, cursor = getConnect()
  424. sql = f"select uc.cname, MAX(score) as max_score, MIN(score) as min_score, AVG(score) as avg_score " \
  425. f"from user_course uc inner join user u on uc.uid = u.uid where u.uclid = '{class_id}' group by uc.cname"
  426. cursor.execute(sql)
  427. res = {
  428. "code": 0,
  429. "msg": "success",
  430. "data": cursor.fetchall()
  431. }
  432. cursor.close()
  433. connection.close()
  434. return res
  435. def getOverallGradeLevelByCLid(class_id):
  436. """
  437. 获取班级号为class_id的班级综合成绩等级各分段人数
  438. :param class_id:
  439. :return:
  440. """
  441. connection, cursor = getConnect()
  442. sql = f"select SUM(IF(avg_score >= 85 and avg_score <= 100, 1, 0)) as A, " \
  443. f"SUM(IF(avg_score >= 70 and avg_score < 85, 1, 0)) as B, " \
  444. f"SUM(IF(avg_score >= 60 and avg_score < 70, 1, 0)) as C, " \
  445. f"SUM(IF(avg_score < 60, 1, 0)) as D from (" \
  446. f"select AVG(score) as avg_score from user_course uc " \
  447. f"inner join user u on uc.uid = u.uid where u.uclid = '{class_id}' group by u.uid" \
  448. f") s"
  449. cursor.execute(sql)
  450. res = {
  451. "code": 0,
  452. "msg": "success",
  453. "data": cursor.fetchall()
  454. }
  455. cursor.close()
  456. connection.close()
  457. return res
  458. def getAllClasses():
  459. """
  460. 获取用户表中已存在的班级号
  461. :return:
  462. """
  463. connection, cursor = getConnect()
  464. sql = f"select distinct uclid from user where urole = 1"
  465. cursor.execute(sql)
  466. res = {
  467. "code": 0,
  468. "msg": "success",
  469. "data": cursor.fetchall()
  470. }
  471. cursor.close()
  472. connection.close()
  473. return res
  474. def getAllCourseAvgScore(uid):
  475. """
  476. 获取所有课程的平均分
  477. :return:
  478. """
  479. connection, cursor = getConnect()
  480. sql = f"select cname, AVG(score) as avg_score from user_course where cname in " \
  481. f"(select cname from user_course where uid = '{uid}') group by cname"
  482. cursor.execute(sql)
  483. res = {
  484. "code": 0,
  485. "msg": "success",
  486. "data": cursor.fetchall()
  487. }
  488. cursor.close()
  489. connection.close()
  490. return res
  491. def searchStudentScore(course_name='', course_nature='', course_department=''):
  492. """
  493. 搜索学生成绩
  494. :param course_name:
  495. :param course_nature:
  496. :param course_department:
  497. :return:
  498. """
  499. connection, cursor = getConnect()
  500. sql = f"select ROW_NUMBER() over () as id, u.uid, u.uname, uc.cname, c.cnature, c.cdepartment, c.cexammethod, " \
  501. f"c.ccredit, score from user_course uc inner join user u on uc.uid = u.uid inner join course c " \
  502. f"on uc.cname = c.cname where c.cname like '%{course_name}%' and " \
  503. f"c.cnature like '%{course_nature}%' and c.cdepartment like '%{course_department}%'"
  504. cursor.execute(sql)
  505. res = {
  506. "code": 0,
  507. "msg": "success",
  508. "data": cursor.fetchall()
  509. }
  510. cursor.close()
  511. connection.close()
  512. return res
  513. def getScoreByUidAndCName(uid, course_name):
  514. """
  515. 查找学号为uid课程为course_name的学生成绩
  516. :param uid:
  517. :param course_name:
  518. :return:
  519. """
  520. connection, cursor = getConnect()
  521. sql = f"select uid, cname, score from user_course where uid = '{uid}' and cname = '{course_name}'"
  522. cursor.execute(sql)
  523. res = {
  524. "code": 0,
  525. "msg": "success",
  526. "data": cursor.fetchall()
  527. }
  528. cursor.close()
  529. connection.close()
  530. return res
  531. def addStudentScore(uid, course_name, score):
  532. connection, cursor = getConnect()
  533. if not cursor.execute(f"select uid from user where uid = '{uid}'"):
  534. return {
  535. "code": 1,
  536. "msg": "学号不存在!"
  537. }
  538. if cursor.execute(f"select 1 from user_course where uid = '{uid}' and cname = '{course_name}' limit 1"):
  539. return {
  540. "code": 1,
  541. "msg": f"该学生的{course_name}课程成绩已经存在!"
  542. }
  543. sql = f"insert into user_course(uid, cname, score) VALUES ('{uid}', '{course_name}', '{score}')"
  544. res = {
  545. "code": 0,
  546. "msg": "添加成绩成功!"
  547. }
  548. try:
  549. cursor.execute(sql)
  550. connection.commit()
  551. except Exception as e:
  552. res = {
  553. "code": 1,
  554. "msg": "添加成绩失败!"
  555. }
  556. connection.rollback()
  557. print(e)
  558. cursor.close()
  559. connection.close()
  560. return res
  561. def deleteStudentScore(uid, course_name):
  562. connection, cursor = getConnect()
  563. if not cursor.execute(f"select uid from user where uid = '{uid}'"):
  564. return {
  565. "code": 1,
  566. "msg": "学号不存在!"
  567. }
  568. sql = f"delete from user_course where uid = '{uid}' and cname = '{course_name}'"
  569. res = {
  570. "code": 0,
  571. "msg": "删除成绩成功!"
  572. }
  573. try:
  574. code = cursor.execute(sql)
  575. connection.commit()
  576. if code == 0:
  577. res = {
  578. "code": 0,
  579. "msg": f"该学生的{course_name}课程成绩不存在!"
  580. }
  581. except Exception as e:
  582. res = {
  583. "code": 1,
  584. "msg": "删除成绩失败!"
  585. }
  586. connection.rollback()
  587. print(e)
  588. cursor.close()
  589. connection.close()
  590. return res
  591. def updateStudentScore(uid, course_name, score):
  592. connection, cursor = getConnect()
  593. sql = f"update user_course set score = '{score}' where uid = '{uid}' and cname = '{course_name}'"
  594. res = {
  595. "code": 0,
  596. "msg": "修改成绩成功!"
  597. }
  598. try:
  599. cursor.execute(sql)
  600. connection.commit()
  601. except Exception as e:
  602. res = {
  603. "code": 1,
  604. "msg": "修改成绩失败!"
  605. }
  606. connection.rollback()
  607. print(e)
  608. cursor.close()
  609. connection.close()
  610. return res

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号