├── main.py ├── school_teacher_information.sql └── 学校人事信息管理系统.exe /main.py: -------------------------------------------------------------------------------- 1 | """ 2 | @Author : wangxiaopeng 3 | @Date : 2020-1-13 4 | @Github : github.com/xiaopeng-whu 5 | """ 6 | 7 | from tkinter import * 8 | from tkinter.messagebox import * 9 | import pymysql # 导入 pymysql 10 | from tkinter import ttk 11 | 12 | 13 | # 每次显示信息时先执行该函数将表已显示内容清空 14 | def delButton(tree): 15 | x = tree.get_children() 16 | for item in x: 17 | tree.delete(item) 18 | 19 | 20 | def showAllInfo(tree, table): 21 | delButton(tree) 22 | db = pymysql.connect(host="localhost", user="root", 23 | password="123456", db="school_teacher_information", port=3306) 24 | cur = db.cursor() 25 | cur.execute("select * from %s" % table) # 执行sql语句 26 | results = cur.fetchall() # 获取查询的所有记录 27 | for item in results: 28 | tree.insert('', "end", values=item) 29 | cur.close() 30 | db.close() # 关闭连接 31 | 32 | 33 | # 还要考虑只有信息表存在的教职工才能在另外两个表中添加相关的新数据 34 | # 还要在添加基本信息表的信息时对sex项进行检查 35 | def appendInfo(tree, table, list): 36 | delButton(tree) 37 | list2 = [] # 存储输入框信息 38 | for i in range(len(list)): # 这里我直接规定一条信息的全部数据项均为not null,实际情况可能不是这样,但为了简洁(以及方便),暂时这样规定⑧ 39 | if list[i].get() == '': 40 | showerror(title='提示', message='输入不能为空') 41 | return 42 | else: 43 | list2.append(list[i].get()) 44 | # list[i].delete(0, END) # 每次获取到输入框的值后就清空输入框,但执行完这条就无法在findinfo获取输入框信息了,为了findInfo的一致性,暂时无法统一形式,索性先不删去输入 45 | 46 | x = tree.get_children() 47 | for item in x: 48 | tree.delete(item) 49 | 50 | db = pymysql.connect(host="localhost", user="root", password="123456", db="school_teacher_information", port=3306) 51 | cur = db.cursor() 52 | 53 | if table == 'teacher_basic': 54 | if list2[2] == '男' or list2[2] == '女': 55 | # 注意values中的%s要加单引号!!!(之前试的时候没有加也成功了,就很奇怪) 56 | cur.execute("insert into %s values('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')" % (table, list2[0], list2[1], list2[2], list2[3], list2[4], list2[5], list2[6], list2[7], list2[8], list2[9])) 57 | else: 58 | showinfo(title='提示', message='sex项必须为“男”or“女”!') 59 | showAllInfo(tree, table) 60 | return 61 | elif table == 'teaching': # 先判断新添加的数据的教职工号是否属于基本信息表中,再选择是否执行插入新数据操作 62 | if findInfo(0, tree, 'teacher_basic', list): # 因为我们没有使用到tree,所以这里不一定必须指定为Tree1 63 | cur.execute("insert into %s values('%s','%s','%s','%s','%s','%s','%s')" % (table, list2[0], list2[1], list2[2], list2[3], list2[4], list2[5], list2[6])) 64 | else: 65 | showinfo(title='提示', message='添加信息不在教职工基本信息表中,添加失败!') 66 | showAllInfo(tree, table) 67 | return 68 | else: # 同样要先进行判断 69 | if findInfo(0, tree, 'teacher_basic', list): 70 | cur.execute("insert into %s values('%s','%s','%s','%s','%s','%s')" % (table, list2[0], list2[1], list2[2], list2[3], list2[4], list2[5])) 71 | else: 72 | showinfo(title='提示', message='添加信息不在教职工基本信息表中,添加失败!') 73 | showAllInfo(tree, table) 74 | return 75 | db.commit() 76 | cur.execute("select * from %s" % table) 77 | results = cur.fetchall() 78 | for item in results: 79 | tree.insert('', "end", values=item) 80 | 81 | cur.close() 82 | db.close() 83 | showinfo(title='提示', message='插入/更新成功!') 84 | 85 | 86 | 87 | # 在删除第一个表(教职工信息表)数据的时候,也要将其他两个表的数据删除(以tea_no为索引) 88 | # 而删除其他两个表数据时,则不需要删除其他两个表的数据 89 | def deleteInfo(tree, table): 90 | if not tree.selection(): 91 | showerror(title='提示', message='Sorry ,please choose an item.') 92 | return 93 | for item in tree.selection(): 94 | selectedItem = tree.selection()[0] 95 | no1 = tree.item(selectedItem, 'values')[0] 96 | cno1 = tree.item(selectedItem, 'values')[2] 97 | dir1 = tree.item(selectedItem, 'values')[1] 98 | tree.delete(item) 99 | 100 | db = pymysql.connect(host="localhost", user="root", 101 | password="123456", db="school_teacher_information", port=3306) 102 | cur = db.cursor() 103 | if table == 'teacher_basic': 104 | cur.execute("delete from teacher_basic where tea_no = '%s'" % no1) # 通过输入框的教工号进行查找删除的,而不是选中行 105 | cur.execute("delete from teaching where tea_no = '%s'" % no1) 106 | cur.execute("delete from research where tea_no = '%s'" % no1) 107 | elif table == 'teaching': 108 | # 这里还有一个bug,删除一个老师的一条信息会把该老师的其他信息都删除,因为是根据tea_no进行delete的! 109 | cur.execute("delete from teaching where tea_no = '%s' AND cour_no = '%s'" % (no1, cno1)) # 如果不是信息表,则只删除该表信息即可 110 | else: 111 | cur.execute("delete from research where tea_no = '%s' AND research_dir = '%s'" % (no1, dir1)) 112 | 113 | db.commit() 114 | cur.close() 115 | db.close() 116 | showinfo(title='提示', message='删除成功!') 117 | 118 | 119 | # 更新也要考虑一个表对其他表的影响 120 | # 这里先进行的delete再进行的append,导致判断发生在append中,使得更新失败仍会删除原数据 121 | def checkexist(table, list): # 判断输入信息代表教职工是否在基本信息表中 122 | list2 = [] # 存储输入框信息 123 | flag = 0 # 作为返回值 124 | for i in range(len(list)): # 这里我直接规定一条信息的全部数据项均为not null,实际情况可能不是这样,但为了简洁(以及方便),暂时这样规定⑧ 125 | if list[i].get() == '': 126 | showerror(title='提示', message='输入不能为空') 127 | return 0 128 | else: 129 | list2.append(list[i].get()) 130 | 131 | db = pymysql.connect(host="localhost", user="root", password="123456", db="school_teacher_information", port=3306) 132 | cur = db.cursor() 133 | 134 | db.commit() 135 | cur.execute("select * from %s" % table) 136 | results = cur.fetchall() 137 | cur.close() 138 | db.close() 139 | 140 | for item in results: 141 | if item[0] == list[0].get(): 142 | flag = 1 143 | if not flag: 144 | showinfo(title='提示', message='更新信息不在教职工基本信息表中,更新失败!') 145 | 146 | return flag 147 | 148 | 149 | def updateInfo(tree, table, list): 150 | if not tree.selection(): 151 | showerror(title='提示', message='Sorry ,please choose an item.') 152 | return 153 | elif checkexist('teacher_basic', list): 154 | for item in tree.selection(): 155 | selectedItem = tree.selection()[0] 156 | no1 = tree.item(selectedItem, 'values')[0] 157 | tree.delete(item) 158 | 159 | db = pymysql.connect(host="localhost", user="root", 160 | password="123456", db="school_teacher_information", port=3306) 161 | cur = db.cursor() 162 | if table == 'teacher_basic': 163 | cur.execute("delete from teacher_basic where tea_no = '%s'" % no1) # 通过输入框的教工号进行查找删除的,而不是选中行 164 | cur.execute("delete from teaching where tea_no = '%s'" % no1) 165 | cur.execute("delete from research where tea_no = '%s'" % no1) 166 | else: 167 | cur.execute("delete from %s where tea_no = '%s'" % (table, no1)) # 通过输入框的学号进行查找删除的,而不是选中行 168 | 169 | db.commit() 170 | cur.close() 171 | db.close() 172 | appendInfo(tree, table, list) 173 | else: 174 | return 175 | 176 | 177 | # 暂时只按照tea_no查询,后续三个表可以使用if语句进行分支执行不同查询 178 | # 要求实现多种关联查询,因此还要作修改!!!***(/fad) 179 | def findInfo(check, tree, table, list): 180 | if check: # check=1表示是要在当前界面查询并显示,check=0表示只是调用一下查询结果 181 | delButton(tree) # 在appendInfo中调用时不能执行该语句,需修改 182 | db = pymysql.connect(host="localhost", user="root", 183 | password="123456", db="school_teacher_information", port=3306) 184 | cur = db.cursor() 185 | 186 | if table == 'multi_table': # 多表查询 187 | for i in range(len(list)): 188 | if list[i].get() == '': 189 | showerror(title='提示', message='输入不能为空') 190 | return 191 | cur.execute("select teacher_basic.tea_no,teacher_basic.tea_name,teacher_basic.sex,teaching.cour_name,research.patent " 192 | "from teacher_basic,teaching,research where dept = '%s' AND cour_no = '%s' AND research_dir = '%s'" 193 | % (entry_t1.get(), entry_t2.get(), entry_t3.get())) 194 | entry_t1.delete(0, END) 195 | entry_t2.delete(0, END) 196 | entry_t3.delete(0, END) 197 | else: # 单表查询(按照tea_no查询) 198 | cur.execute("select * from %s where tea_no = '%s'" % (table, list[0].get())) # 执行sql语句 199 | for i in range(len(list)): 200 | list[i].delete(0, END) 201 | # entry_tea_no.delete(0, END) # 按下查询按钮后输入框清空 202 | results = cur.fetchall() # 获取查询的所有记录 203 | 204 | if not len(results): 205 | if check: 206 | showinfo(title='提示', message='查询结果为空!') 207 | flag1 = 0 # 返回查询结果是否为空的标志 208 | else: 209 | if check: 210 | for item in results: 211 | tree.insert('', "end", values=item) 212 | flag1 = 1 213 | 214 | db.commit() 215 | cur.close() 216 | db.close() # 关闭连接 217 | return flag1 218 | 219 | 220 | def table1(): # 教职工基本信息表(teacher_basic) 221 | root1 = Tk() 222 | root1.geometry('950x1000') 223 | root1.title('教职工基本信息表') 224 | Label(root1, text='教职工基本信息表', bg='white', fg='red', font=('宋体', 15)).pack(side=TOP, fill='x') 225 | 226 | Label(root1, text="tea_no:").place(relx=0, rely=0.05, relwidth=0.1) 227 | Label(root1, text="tea_name:").place(relx=0.5, rely=0.05, relwidth=0.1) 228 | Label(root1, text="sex:").place(relx=0, rely=0.1, relwidth=0.1) 229 | Label(root1, text="degree:").place(relx=0.5, rely=0.1, relwidth=0.1) 230 | Label(root1, text="dept:").place(relx=0, rely=0.15, relwidth=0.1) 231 | Label(root1, text="graduate_sch:").place(relx=0.5, rely=0.15, relwidth=0.1) 232 | Label(root1, text="health:").place(relx=0, rely=0.2, relwidth=0.1) 233 | Label(root1, text="title:").place(relx=0.5, rely=0.2, relwidth=0.1) 234 | Label(root1, text="duty:").place(relx=0, rely=0.25, relwidth=0.1) 235 | Label(root1, text="award_or_punish:").place(relx=0.5, rely=0.25, relwidth=0.1) 236 | 237 | tea_no = StringVar() 238 | tea_name = StringVar() 239 | sex = StringVar() 240 | degree = StringVar() 241 | dept = StringVar() 242 | graduate_sch = StringVar() 243 | health = StringVar() 244 | title = StringVar() 245 | duty = StringVar() 246 | award_or_punish = StringVar() 247 | 248 | global entry_tea_no 249 | global entry_tea_name 250 | global entry_sex 251 | global entry_degree 252 | global entry_dept 253 | global entry_graduate_sch 254 | global entry_health 255 | global entry_title 256 | global entry_duty 257 | global entry_award_or_punish 258 | entry_tea_no = Entry(root1, textvariable=tea_no) 259 | entry_tea_no.place(relx=0.1, rely=0.05, relwidth=0.3, height=25) 260 | entry_tea_name = Entry(root1, textvariable=tea_name) 261 | entry_tea_name.place(relx=0.6, rely=0.05, relwidth=0.3, height=25) 262 | entry_sex = Entry(root1, textvariable=sex) 263 | entry_sex.place(relx=0.1, rely=0.1, relwidth=0.3, height=25) 264 | entry_degree = Entry(root1, textvariable=degree) 265 | entry_degree.place(relx=0.6, rely=0.1, relwidth=0.3, height=25) 266 | entry_dept = Entry(root1, textvariable=dept) 267 | entry_dept.place(relx=0.1, rely=0.15, relwidth=0.3, height=25) 268 | entry_graduate_sch = Entry(root1, textvariable=graduate_sch) 269 | entry_graduate_sch.place(relx=0.6, rely=0.15, relwidth=0.3, height=25) 270 | entry_health = Entry(root1, textvariable=health) 271 | entry_health.place(relx=0.1, rely=0.2, relwidth=0.3, height=25) 272 | entry_title = Entry(root1, textvariable=title) 273 | entry_title.place(relx=0.6, rely=0.2, relwidth=0.3, height=25) 274 | entry_duty = Entry(root1, textvariable=duty) 275 | entry_duty.place(relx=0.1, rely=0.25, relwidth=0.3, height=25) 276 | entry_award_or_punish = Entry(root1, textvariable=award_or_punish) 277 | entry_award_or_punish.place(relx=0.6, rely=0.25, relwidth=0.3, height=25) 278 | 279 | # 将输入框Entry放在一个列表中传入相关操作的函数中,利用get()获得输入值 280 | list1 = [entry_tea_no, entry_tea_name, entry_sex, entry_degree, entry_dept, entry_graduate_sch, entry_health, entry_title, entry_duty, entry_award_or_punish] 281 | 282 | # global Tree1 # 声明global貌似也不能在其他函数中使用,还是直接当做参数传入函数⑧,但不同table又在不同函数中,也没有相互调用,怎么传Tree1?每次关闭第一个表后Tree1就消失了 283 | Tree1 = ttk.Treeview(root1, show='headings', 284 | column=('tea_no', 'tea_name', 'sex', 'degree', 'dept', 'graduate_sch', 'health', 'title', 'duty', 'award_or_punish')) 285 | Tree1.column('tea_no', width=100, anchor="center") 286 | Tree1.column('tea_name', width=100, anchor="center") 287 | Tree1.column('sex', width=100, anchor="center") 288 | Tree1.column('degree', width=100, anchor="center") 289 | Tree1.column('dept', width=100, anchor="center") 290 | Tree1.column('graduate_sch', width=100, anchor="center") 291 | Tree1.column('health', width=100, anchor="center") 292 | Tree1.column('title', width=100, anchor="center") 293 | Tree1.column('duty', width=100, anchor="center") 294 | Tree1.column('award_or_punish', width=100, anchor="center") 295 | # 表格标题设置 296 | Tree1.heading('tea_no', text='tea_no') 297 | Tree1.heading('tea_name', text='tea_name') 298 | Tree1.heading('sex', text='sex') 299 | Tree1.heading('degree', text='degree') 300 | Tree1.heading('dept', text='dept') 301 | Tree1.heading('graduate_sch', text='graduate_sch') 302 | Tree1.heading('health', text='health') 303 | Tree1.heading('title', text='title') 304 | Tree1.heading('duty', text='duty') 305 | Tree1.heading('award_or_punish', text='award_or_punish') 306 | 307 | Tree1.place(rely=0.4, relwidth=0.99) 308 | 309 | # 使用lambda匿名函数传参 310 | Button(root1, text="显示所有信息", command=lambda: showAllInfo(tree=Tree1, table='teacher_basic')).place(relx=0.05, rely=0.3, width=100) 311 | Button(root1, text="追加信息", command=lambda: appendInfo(tree=Tree1, table='teacher_basic', list=list1)).place(relx=0.25, rely=0.3, width=100) 312 | Button(root1, text="删除信息", command=lambda: deleteInfo(tree=Tree1, table='teacher_basic')).place(relx=0.45, rely=0.3, width=100) 313 | Button(root1, text="更改信息", command=lambda: updateInfo(tree=Tree1, table='teacher_basic', list=list1)).place(relx=0.65, rely=0.3, width=100) 314 | Button(root1, text="查找信息(tea_no)", command=lambda: findInfo(check=1, tree=Tree1, table='teacher_basic', list=list1)).place(relx=0.85, rely=0.3, width=120) 315 | 316 | 317 | def table2(): # 教职工教学信息表(teaching) 318 | root2 = Tk() 319 | root2.geometry('950x1000') 320 | root2.title('教职工教学信息表') 321 | Label(root2, text='教职工教学信息表', bg='white', fg='red', font=('宋体', 15)).pack(side=TOP, fill='x') 322 | 323 | Label(root2, text="tea_no:").place(relx=0, rely=0.05, relwidth=0.1) 324 | Label(root2, text="tea_name:").place(relx=0.5, rely=0.05, relwidth=0.1) 325 | Label(root2, text="cour_no:").place(relx=0, rely=0.1, relwidth=0.1) 326 | Label(root2, text="cour_name:").place(relx=0.5, rely=0.1, relwidth=0.1) 327 | Label(root2, text="cour_hour:").place(relx=0, rely=0.15, relwidth=0.1) 328 | Label(root2, text="credit:").place(relx=0.5, rely=0.15, relwidth=0.1) 329 | Label(root2, text="cour_type:").place(relx=0, rely=0.2, relwidth=0.1) 330 | 331 | tea_no = StringVar() 332 | tea_name = StringVar() 333 | cour_no = StringVar() 334 | cour_name = StringVar() 335 | cour_hour = StringVar() 336 | credit = StringVar() 337 | cour_type = StringVar() 338 | 339 | global entry_tea_no 340 | global entry_tea_name 341 | global entry_cour_no 342 | global entry_cour_name 343 | global entry_cour_hour 344 | global entry_credit 345 | global entry_cour_type 346 | entry_tea_no = Entry(root2, textvariable=tea_no) 347 | entry_tea_no.place(relx=0.1, rely=0.05, relwidth=0.37, height=25) # 把place单独拿出来就可以??爷笑了! 348 | entry_tea_name = Entry(root2, textvariable=tea_name) 349 | entry_tea_name.place(relx=0.6, rely=0.05, relwidth=0.37, height=25) 350 | entry_cour_no = Entry(root2, textvariable=cour_no) 351 | entry_cour_no.place(relx=0.1, rely=0.1, relwidth=0.37, height=25) 352 | entry_cour_name = Entry(root2, textvariable=cour_name) 353 | entry_cour_name.place(relx=0.6, rely=0.1, relwidth=0.37, height=25) 354 | entry_cour_hour = Entry(root2, textvariable=cour_hour) 355 | entry_cour_hour.place(relx=0.1, rely=0.15, relwidth=0.37, height=25) 356 | entry_credit = Entry(root2, textvariable=credit) 357 | entry_credit.place(relx=0.6, rely=0.15, relwidth=0.37, height=25) 358 | entry_cour_type = Entry(root2, textvariable=cour_type) 359 | entry_cour_type.place(relx=0.1, rely=0.2, relwidth=0.37, height=25) 360 | 361 | # 将输入框Entry放在一个列表中传入相关操作的函数中,利用get()获得输入值 362 | list2 = [entry_tea_no, entry_tea_name, entry_cour_no, entry_cour_name, entry_cour_hour, entry_credit, entry_cour_type] 363 | 364 | Tree2 = ttk.Treeview(root2, show='headings', 365 | column=('tea_no', 'tea_name', 'cour_no', 'cour_name', 'cour_hour', 'credit', 'cour_type')) 366 | Tree2.column('tea_no', width=150, anchor="center") 367 | Tree2.column('tea_name', width=150, anchor="center") 368 | Tree2.column('cour_no', width=150, anchor="center") 369 | Tree2.column('cour_name', width=150, anchor="center") 370 | Tree2.column('cour_hour', width=150, anchor="center") 371 | Tree2.column('credit', width=150, anchor="center") 372 | Tree2.column('cour_type', width=150, anchor="center") 373 | # 表格标题设置 374 | Tree2.heading('tea_no', text='tea_no') 375 | Tree2.heading('tea_name', text='tea_name') 376 | Tree2.heading('cour_no', text='cour_no') 377 | Tree2.heading('cour_name', text='cour_name') 378 | Tree2.heading('cour_hour', text='cour_hour') 379 | Tree2.heading('credit', text='credit') 380 | Tree2.heading('cour_type', text='cour_type') 381 | 382 | Tree2.place(rely=0.35, relwidth=0.99) 383 | 384 | # 使用lambda匿名函数传参 385 | Button(root2, text="显示所有信息", command=lambda: showAllInfo(tree=Tree2, table='teaching')).place(relx=0.05, rely=0.25, width=100) 386 | Button(root2, text="追加信息", command=lambda: appendInfo(tree=Tree2, table='teaching', list=list2)).place(relx=0.25, rely=0.25, width=100) 387 | Button(root2, text="删除信息", command=lambda: deleteInfo(tree=Tree2, table='teaching')).place(relx=0.45, rely=0.25, width=100) 388 | Button(root2, text="更改信息", command=lambda: updateInfo(tree=Tree2, table='teaching', list=list2)).place(relx=0.65, rely=0.25, width=100) 389 | Button(root2, text="查找信息(tea_no)", command=lambda: findInfo(check=1, tree=Tree2, table='teaching', list=list2)).place(relx=0.85, rely=0.25, width=120) 390 | 391 | 392 | def table3(): # 教职工科研信息表(research) 393 | root3 = Tk() 394 | root3.geometry('950x1000') 395 | root3.title('教职工科研信息表') 396 | Label(root3, text='教职工科研信息表', bg='white', fg='red', font=('宋体', 15)).pack(side=TOP, fill='x') 397 | 398 | Label(root3, text="tea_no:").place(relx=0, rely=0.05, relwidth=0.1) 399 | Label(root3, text="research_dir:").place(relx=0.5, rely=0.05, relwidth=0.1) 400 | Label(root3, text="research_sit:").place(relx=0, rely=0.1, relwidth=0.1) 401 | Label(root3, text="patent:").place(relx=0.5, rely=0.1, relwidth=0.1) 402 | Label(root3, text="paper_name:").place(relx=0, rely=0.15, relwidth=0.1) 403 | Label(root3, text="paper_level:").place(relx=0.5, rely=0.15, relwidth=0.1) 404 | 405 | tea_no = StringVar() 406 | research_dir = StringVar() 407 | research_sit = StringVar() 408 | patent = StringVar() 409 | paper_name = StringVar() 410 | paper_level = StringVar() 411 | 412 | global entry_tea_no 413 | global entry_research_dir 414 | global entry_research_sit 415 | global entry_patent 416 | global entry_paper_name 417 | global entry_paper_level 418 | entry_tea_no = Entry(root3, textvariable=tea_no) 419 | entry_tea_no.place(relx=0.1, rely=0.05, relwidth=0.37, height=25) # 把place单独拿出来就可以??爷笑了! 420 | entry_research_dir = Entry(root3, textvariable=research_dir) 421 | entry_research_dir.place(relx=0.6, rely=0.05, relwidth=0.37, height=25) 422 | entry_research_sit = Entry(root3, textvariable=research_sit) 423 | entry_research_sit.place(relx=0.1, rely=0.1, relwidth=0.37, height=25) 424 | entry_patent = Entry(root3, textvariable=patent) 425 | entry_patent.place(relx=0.6, rely=0.1, relwidth=0.37, height=25) 426 | entry_paper_name = Entry(root3, textvariable=paper_name) 427 | entry_paper_name.place(relx=0.1, rely=0.15, relwidth=0.37, height=25) 428 | entry_paper_level = Entry(root3, textvariable=paper_level) 429 | entry_paper_level.place(relx=0.6, rely=0.15, relwidth=0.37, height=25) 430 | 431 | # 将输入框Entry放在一个列表中传入相关操作的函数中,利用get()获得输入值 432 | list3 = [entry_tea_no, entry_research_dir, entry_research_sit, entry_patent, entry_paper_name, entry_paper_level] 433 | 434 | Tree3 = ttk.Treeview(root3, show='headings', 435 | column=('tea_no', 'research_dir', 'research_sit', 'patent', 'paper_name', 'paper_level')) 436 | Tree3.column('tea_no', width=150, anchor="center") 437 | Tree3.column('research_dir', width=150, anchor="center") 438 | Tree3.column('research_sit', width=150, anchor="center") 439 | Tree3.column('patent', width=150, anchor="center") 440 | Tree3.column('paper_name', width=150, anchor="center") 441 | Tree3.column('paper_level', width=150, anchor="center") 442 | # 表格标题设置 443 | Tree3.heading('tea_no', text='tea_no') 444 | Tree3.heading('research_dir', text='research_dir') 445 | Tree3.heading('research_sit', text='research_sit') 446 | Tree3.heading('patent', text='patent') 447 | Tree3.heading('paper_name', text='paper_name') 448 | Tree3.heading('paper_level', text='paper_level') 449 | 450 | Tree3.place(rely=0.3, relwidth=0.99) 451 | 452 | # 使用lambda匿名函数传参 453 | Button(root3, text="显示所有信息", command=lambda: showAllInfo(tree=Tree3, table='research')).place(relx=0.05, rely=0.2, width=100) 454 | Button(root3, text="追加信息", command=lambda: appendInfo(tree=Tree3, table='research', list=list3)).place(relx=0.25, rely=0.2, width=100) 455 | Button(root3, text="删除信息", command=lambda: deleteInfo(tree=Tree3, table='research')).place(relx=0.45, rely=0.2, width=100) 456 | Button(root3, text="更改信息", command=lambda: updateInfo(tree=Tree3, table='research', list=list3)).place(relx=0.65, rely=0.2, width=100) 457 | Button(root3, text="查找信息(tea_no)", command=lambda: findInfo(check=1, tree=Tree3, table='research', list=list3)).place(relx=0.85, rely=0.2, width=120) 458 | 459 | 460 | def table4(): 461 | root4 = Tk() 462 | root4.geometry('950x1000') 463 | root4.title('多表查询') 464 | Label(root4, text='多表查询(以所属部门、课程号、研究方向为条件)', bg='white', fg='red', font=('宋体', 15)).pack(side=TOP, fill='x') 465 | 466 | # 举例:查找网安学院、课程号为001、研究方向为数据库的教职工相关信息(性别、课程名等) 467 | Label(root4, text="dept:").place(relx=0.2, rely=0.05, relwidth=0.1) 468 | Label(root4, text="cour_no:").place(relx=0.2, rely=0.1, relwidth=0.1) 469 | Label(root4, text="research_dir:").place(relx=0.2, rely=0.15, relwidth=0.1) 470 | 471 | t1 = StringVar() 472 | t2 = StringVar() 473 | t3 = StringVar() 474 | 475 | global entry_t1 476 | global entry_t2 477 | global entry_t3 478 | 479 | entry_t1 = Entry(root4, textvariable=t1) 480 | entry_t1.place(relx=0.3, rely=0.05, relwidth=0.37, height=25) 481 | entry_t2 = Entry(root4, textvariable=t2) 482 | entry_t2.place(relx=0.3, rely=0.1, relwidth=0.37, height=25) 483 | entry_t3 = Entry(root4, textvariable=t3) 484 | entry_t3.place(relx=0.3, rely=0.15, relwidth=0.37, height=25) 485 | 486 | # 将输入框Entry放在一个列表中传入相关操作的函数中,利用get()获得输入值 487 | list4 = [entry_t1, entry_t2, entry_t3] 488 | 489 | Tree4 = ttk.Treeview(root4, show='headings', column=('tea_no', 'tea_name', 'sex', 'cour_name', 'patent')) 490 | Tree4.column('tea_no', width=150, anchor="center") 491 | Tree4.column('tea_name', width=150, anchor="center") 492 | Tree4.column('sex', width=150, anchor="center") 493 | Tree4.column('cour_name', width=150, anchor="center") 494 | Tree4.column('patent', width=150, anchor="center") 495 | # 表格标题设置 496 | Tree4.heading('tea_no', text='tea_no') 497 | Tree4.heading('tea_name', text='tea_name') 498 | Tree4.heading('sex', text='sex') 499 | Tree4.heading('cour_name', text='cour_name') 500 | Tree4.heading('patent', text='patent') 501 | 502 | Tree4.place(rely=0.25, relwidth=0.99) 503 | 504 | # 使用lambda匿名函数传参 505 | Button(root4, text="查找信息", command=lambda: findInfo(check=1, tree=Tree4, table='multi_table', list = list4)).place(relx=0.4, rely=0.2, width=100) 506 | 507 | 508 | # 后续可以加一个登录界面,用户名密码就按照数据库的user和pwd进行比对,在之后的函数连接数据库部分就是用登录使用的变量值 509 | # 登录成功后的主界面 510 | def init(): 511 | root0 = Tk() 512 | root0.geometry('300x300') 513 | root0.title('学校人事信息管理系统') 514 | Label(root0, text='学校人事信息管理', bg='white', fg='red', font=('宋体', 15)).pack(side=TOP, fill='x') 515 | 516 | Button(root0, text="教职工基本信息表", command=table1).place(relx=0.5, rely=0.2, width=100, anchor=CENTER) 517 | Button(root0, text="教职工教学信息表", command=table2).place(relx=0.5, rely=0.4, width=100, anchor=CENTER) 518 | Button(root0, text="教职工科研信息表", command=table3).place(relx=0.5, rely=0.6, width=100, anchor=CENTER) 519 | Button(root0, text="多表查询", command=table4).place(relx=0.5, rely=0.8, width=100, anchor=CENTER) 520 | 521 | 522 | # 判断账号密码是否正确,若正确则进入主界面(这里还要关闭登录界面,待做!***) 523 | def sign_in(root, table, username, pwd): 524 | db = pymysql.connect(host="localhost", user="root", 525 | password="123456", db="school_teacher_information", port=3306) 526 | cur = db.cursor() 527 | cur.execute("select * from %s" % table) # 执行sql语句 528 | results = cur.fetchall() # 获取查询的所有记录 529 | for item in results: 530 | if (username.get() == item[0]) & (pwd.get() == item[1]): # 这里简单规定好管理员账号密码,日后可改为从数据库中获取比对 531 | root.destroy() # 进入主界面后,关闭登录窗口 532 | init() 533 | else: 534 | showinfo(title='提示', message='账号/密码错误!') 535 | cur.close() 536 | db.close() # 关闭连接 537 | 538 | 539 | root = Tk() 540 | root.geometry('300x250') 541 | root.title('Login') 542 | 543 | Label(root, text='学校人事信息管理系统', bg='white', fg='red', font=('宋体', 15)).pack(side=TOP, fill='x') 544 | Label(root, text='username').place(relx=0.1, rely=0.25) 545 | Label(root, text='pwd').place(relx=0.1, rely=0.4) 546 | username = StringVar() 547 | pwd = StringVar() 548 | 549 | entry_username = Entry(root, textvariable=username, show=None) 550 | entry_username.place(relx=0.5, rely=0.25, relwidth=0.37) 551 | entry_pwd = Entry(root, textvariable=pwd, show='*') 552 | entry_pwd.place(relx=0.5, rely=0.4, relwidth=0.37) 553 | 554 | # 将输入框作为参数传入函数中,再进行get,不能先判断,因为没有按下按钮触发动作,无法获取entry输入框的值 555 | Button(root, text="登录", command=lambda: sign_in(root=root, table='admin', username=entry_username, pwd=entry_pwd)).place(relx=0.5, rely=0.7, width=100, anchor=CENTER) 556 | 557 | root.mainloop() -------------------------------------------------------------------------------- /school_teacher_information.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : localhost_3306 5 | Source Server Version : 50627 6 | Source Host : localhost:3306 7 | Source Database : school_teacher_information 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50627 11 | File Encoding : 65001 12 | 13 | Date: 2020-01-13 20:31:52 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for `admin` 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `admin`; 22 | CREATE TABLE `admin` ( 23 | `username` varchar(15) NOT NULL, 24 | `password` varchar(15) NOT NULL, 25 | PRIMARY KEY (`username`) 26 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 27 | 28 | -- ---------------------------- 29 | -- Records of admin 30 | -- ---------------------------- 31 | INSERT INTO `admin` VALUES ('root', '123456'); 32 | 33 | -- ---------------------------- 34 | -- Table structure for `research` 35 | -- ---------------------------- 36 | DROP TABLE IF EXISTS `research`; 37 | CREATE TABLE `research` ( 38 | `tea_no` varchar(15) NOT NULL, 39 | `research_dir` varchar(15) NOT NULL DEFAULT '', 40 | `research_sit` varchar(15) DEFAULT NULL, 41 | `patent` varchar(10) DEFAULT NULL, 42 | `paper_name` varchar(20) DEFAULT NULL, 43 | `paper_level` varchar(5) DEFAULT NULL, 44 | PRIMARY KEY (`tea_no`,`research_dir`) 45 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 46 | 47 | -- ---------------------------- 48 | -- Records of research 49 | -- ---------------------------- 50 | INSERT INTO `research` VALUES ('1710111', '数据库应用', '进行中', '数据库安全技术', '数据库安全技术革命', 'A'); 51 | INSERT INTO `research` VALUES ('2', '2', '2', '2', '2', '2'); 52 | 53 | -- ---------------------------- 54 | -- Table structure for `teacher_basic` 55 | -- ---------------------------- 56 | DROP TABLE IF EXISTS `teacher_basic`; 57 | CREATE TABLE `teacher_basic` ( 58 | `tea_no` varchar(15) NOT NULL, 59 | `tea_name` varchar(5) NOT NULL, 60 | `sex` varchar(1) NOT NULL, 61 | `degree` varchar(5) NOT NULL, 62 | `dept` varchar(10) DEFAULT NULL, 63 | `graduate_sch` varchar(10) NOT NULL, 64 | `health` varchar(3) DEFAULT NULL, 65 | `title` varchar(5) DEFAULT NULL, 66 | `duty` varchar(10) DEFAULT NULL, 67 | `award_or_punish` varchar(20) DEFAULT NULL, 68 | PRIMARY KEY (`tea_no`) 69 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 70 | 71 | -- ---------------------------- 72 | -- Records of teacher_basic 73 | -- ---------------------------- 74 | INSERT INTO `teacher_basic` VALUES ('1710111', '周红', '女', '博士', '国家网络安全学院', '武汉大学', '良好', '教授', '授课', '最受欢迎的导师'); 75 | INSERT INTO `teacher_basic` VALUES ('1710112', '小明', '男', '硕士', '经管院', '华中科技大学', '良好', '教授', '授课', '青年学者'); 76 | INSERT INTO `teacher_basic` VALUES ('2', '2', '男', '2', '2', '2', '2', '2', '2', '2'); 77 | INSERT INTO `teacher_basic` VALUES ('3', '3', '女', '3', '3', '3', '3', '3', '3', '3'); 78 | 79 | -- ---------------------------- 80 | -- Table structure for `teaching` 81 | -- ---------------------------- 82 | DROP TABLE IF EXISTS `teaching`; 83 | CREATE TABLE `teaching` ( 84 | `tea_no` varchar(15) NOT NULL, 85 | `tea_name` varchar(5) NOT NULL, 86 | `cour_no` varchar(15) NOT NULL DEFAULT '', 87 | `cour_name` varchar(10) DEFAULT NULL, 88 | `cour_hour` varchar(10) DEFAULT NULL, 89 | `credit` varchar(3) DEFAULT NULL, 90 | `cour_type` varchar(5) DEFAULT NULL, 91 | PRIMARY KEY (`tea_no`,`cour_no`) 92 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 93 | 94 | -- ---------------------------- 95 | -- Records of teaching 96 | -- ---------------------------- 97 | INSERT INTO `teaching` VALUES ('1710111', '周红', '20181001', '数据库原理', '54', '3', '专业必修课'); 98 | INSERT INTO `teaching` VALUES ('2', '3', '3', '3', '3', '3', '3'); 99 | INSERT INTO `teaching` VALUES ('3', '4', '4', '4', '4', '4', '4'); 100 | -------------------------------------------------------------------------------- /学校人事信息管理系统.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaopeng-whu/Teacher_management_system/8ee206cfbbb3d6ca4a9a278979c7072f03d167cd/学校人事信息管理系统.exe --------------------------------------------------------------------------------