医院信息管理系统(pycharm+MySQL)
1. 利用sql语句创建数据库表
科室表:包括科室编号、科室名称、科室地址、科室电话
医生资料表:包括医生编号、医生姓名、职务、性别、年龄、所属科室
病房资料表:包括房间号、房间地址、所属科室
患者资料表:包括患者编号、患者名、性别、年龄、疾病、主治医生编号、所住病房编号、住院时间、预计出院时间
护士资料表:包括护士编号、护士姓名、性别、年龄
药品资料表:包括药品编号、药品名、供应商、库存、价格
患者使用药品记录表:包括患者编号、药品编号、用药数量
患者护理记录表:包括患者编号、护士编号、护理内容、护理时间
医院基本信息表:包括医院编号、医院名称、院长名称、地址、联系号码
2. 用python对数据进行操纵,并实现以下功能:
(1)以管理员的身份登录,对所创建的前8个基本表的数据进行增加、修改和删除
(2)以游客的身份登录,查看医院的基本信息
注意:
- 管理员的账号和密码,以及游客的登录账号和密码需要自己在数据库中添加,也可以运行文章最后的sql语句(在admin_login_k表和stu_login_k表中)
- 需要根据自己mysql实际的登录密码和登录名对以下代码进行修改,代码为:
- db = pymysql.Connect(
host=‘localhost’,
port=3306,
user=‘root’,
passwd=‘123456’,
db=‘hospital’,
charset=‘utf8’
) # 打开数据库连接
其中,分别表示主机名:localhost,用户名:root,密码:123456,数据库名:hospital
3.下面是界面的截图
主界面:
管理员登录界面:
游客登录界面:
功能选择界面:
科室表操作界面:
4.完整的python代码如下:
import pymysql
from tkinter import ttk
import tkinter as tk
import tkinter.font as tkFont
from tkinter import * # 图形界面库
import tkinter.messagebox as messagebox # 弹窗
class StartPage:
def __init__(self, parent_window):
parent_window.destroy() # 销毁子界面
self.window = tk.Tk() # 初始框的声明
self.window.title('医院信息管理系统')
self.window.geometry('600x700')
# 这里的乘是小x
# 创建一个图片管理类
photo = tk.PhotoImage(file="img3.png") # file:t图片路径
label =tk.Label(self.window,
text="医院信息管理系统",
justify=tk.LEFT,
image=photo,
compound=tk.CENTER,
font=("Verdana", 20),
fg="black")
# label=Label(self.window,text="医院信息管理系统", font=("Verdana", 20),image=photo) # 把图片整合到标签类中
label.pack(pady=10) # pady=100 界面的长度
Button(self.window, text="管理员登陆", font=tkFont.Font(size=16), command=lambda: AdminPage(self.window), width=30,
height=2,fg='white', bg='gray', activebackground='black', activeforeground='white').pack()
Button(self.window, text="游客登陆", font=tkFont.Font(size=16), command=lambda: StudentPage(self.window), width=30,
height=2, fg='white', bg='gray', activebackground='black', activeforeground='white').pack()
Button(self.window, text="关于", font=tkFont.Font(size=16), command=lambda: AboutPage(self.window), width=30,
height=2,fg='white', bg='gray', activebackground='black', activeforeground='white').pack()
Button(self.window, text='退出系统', height=2, font=tkFont.Font(size=16), width=30, command=self.window.destroy,
fg='white', bg='gray', activebackground='black', activeforeground='white').pack()
self.window.mainloop() # 主消息循环
# 管理员登陆页面的初始化
class AdminPage:
def __init__(self, parent_window):
parent_window.destroy() # 销毁主界面
self.window = tk.Tk() # 初始框的声明
self.window.title('管理员登陆页面')
self.window.geometry('400x400') # 这里的乘是小x
label = tk.Label(self.window, text='管理员登陆', bg='green', font=('Verdana', 20), width=30, height=2)
label.pack()
Label(self.window, text='管理员账号:', font=tkFont.Font(size=14)).pack(pady=25)
self.admin_username = tk.Entry(self.window, width=30, font=tkFont.Font(size=14), bg='Ivory')
self.admin_username.pack()
Label(self.window, text='管理员密码:', font=tkFont.Font(size=14)).pack(pady=25)
self.admin_pass = tk.Entry(self.window, width=30, font=tkFont.Font(size=14), bg='Ivory', show='*')
self.admin_pass.pack()
Button(self.window, text="登陆", width=8, font=tkFont.Font(size=12), command=lambda:Gongnengjiemian(self.window),fg='white', bg='gray', activebackground='black', activeforeground='white').pack(pady=20)
Button(self.window, text="返回首页", width=8, font=tkFont.Font(size=12), command=self.back,fg='white', bg='gray', activebackground='black', activeforeground='white').pack()
self.window.protocol("WM_DELETE_WINDOW", self.back) # 捕捉右上角关闭点击
self.window.mainloop() # 进入消息循环
def back(self):
StartPage(self.window) # 显示主窗口 销毁本窗口
#功能界面的初始化、实现管理员登录
class Gongnengjiemian:
def __init__(self, parent_window):
parent_window.destroy() # 销毁主界面
self.window= tk.Tk() # 初始框的声明
self.window.title('功能选择界面')
self.window.geometry('300x450') # 这里的乘是小x
Button(self.window, text="科室管理", width=18, font=tkFont.Font(size=12), command=lambda: AdminManage(self.window),fg='white', bg='green', activebackground='black', activeforeground='white').pack(pady=10)
Button(self.window, text="医生资料管理", width=18, font=tkFont.Font(size=12), command=lambda: AdminManage1(self.window),fg='white', bg='green', activebackground='black', activeforeground='white').pack(pady=10)
Button(self.window, text="护士资料管理", width=18, font=tkFont.Font(size=12),command=lambda: AdminManage2(self.window),fg='white', bg='green', activebackground='black', activeforeground='white').pack(pady=10)
Button(self.window, text="患者资料管理", width=18, font=tkFont.Font(size=12),command=lambda: AdminManage3(self.window),fg='white', bg='green', activebackground='black', activeforeground='white').pack(pady=10)
Button(self.window, text="药品资料管理", width=18, font=tkFont.Font(size=12),command=lambda: AdminManage4(self.window),fg='white', bg='green', activebackground='black', activeforeground='white').pack(pady=10)
Button(self.window, text="病房资料管理", width=18, font=tkFont.Font(size=12), command=lambda: AdminManage5(self.window),fg='white', bg='green', activebackground='black', activeforeground='white').pack(pady=10)
Button(self.window, text="病人用药记录管理", width=18, font=tkFont.Font(size=12), command=lambda: AdminManage6(self.window),fg='white', bg='green', activebackground='black', activeforeground='white').pack(pady=10)
Button(self.window, text="护士护理记录管理", width=18, font=tkFont.Font(size=12), command=lambda: AdminManage7(self.window),fg='white', bg='green', activebackground='black', activeforeground='white').pack(pady=10)
Button(self.window, text="返回首页", width=8, font=tkFont.Font(size=12), command=self.back,fg='white', bg='gray', activebackground='black', activeforeground='white').pack()
self.window.protocol("WM_DELETE_WINDOW", self.back) # 捕捉右上角关闭点击
self.window.mainloop() # 进入消息循环
def login(self):
print(str(self.admin_username.get()))
print(str(self.admin_pass.get()))
admin_pass = None
# 数据库操作 查询管理员表
db = pymysql.Connect(
host='localhost',
port=3306,
user='root',
passwd='123456',
db='hospital',
charset='utf8'
) # 打开数据库连接
cursor = db.cursor() # 使用cursor()方法获取操作游标
sql = "SELECT * FROM admin_login_k WHERE admin_id = '%s'" % (self.admin_username.get()) # SQL 查询语句
try:
# 执行SQL语句
cursor.execute(sql)
# 获取所有记录列表
results = cursor.fetchall()
for row in results:
admin_id = row[0]
admin_pass = row[1]
# 打印结果
print("admin_id=%s,admin_pass=%s" % (admin_id, admin_pass))
except:
print("Error: unable to fecth data")
messagebox.showinfo('警告!', '用户名或密码不正确!')
db.close() # 关闭数据库连接
print("正在登陆管理员管理界面")
print("self", self.admin_pass)
print("local", admin_pass)
if self.admin_pass.get() == admin_pass:
AdminManage(self.window) # 进入管理员操作界面
else:
messagebox.showinfo('警告!', '用户名或密码不正确!')
def back(self):
StartPage(self.window) # 显示主窗口 销毁本窗口
# 游客登陆页面的初始化
class StudentPage:
def __init__(self, parent_window):
parent_window.destroy() # 销毁主界面
self.window = tk.Tk() # 初始框的声明
self.window.title('游客登陆')
self.window.geometry('300x450') # 这里的乘是小x
label = tk.Label(self.window, text='游客登陆', bg='green', font=('Verdana', 20), width=30, height=2)
label.pack()
Label(self.window, text='游客账号:', font=tkFont.Font(size=14)).pack(pady=25)
self.student_id = tk.Entry(self.window, width=30, font=tkFont.Font(size=14), bg='Ivory')
self.student_id.pack()
Label(self.window, text='游客密码:', font=tkFont.Font(size=14)).pack(pady=25)
self.student_pass = tk.Entry(self.window, width=30, font=tkFont.Font(size=14), bg='Ivory', show='*')
self.student_pass.pack()
Button(self.window, text="登陆", width=8, font=tkFont.Font(size=12), command=self.login,fg='white', bg='gray', activebackground='black', activeforeground='white').pack(pady=40)
Button(self.window, text="返回首页", width=8, font=tkFont.Font(size=12), command=self.back,fg='white', bg='gray', activebackground='black', activeforeground='white').pack()
self.window.protocol("WM_DELETE_WINDOW", self.back) # 捕捉右上角关闭点击
self.window.mainloop() # 进入消息循环
def login(self):
print(str(self.student_id.get()))
print(str(self.student_pass.get()))
stu_pass = None
# 数据库操作 查询管理员表
db = pymysql.Connect(
host='localhost',
port=3306,
user='root',
passwd='123456',
db='hospital',
charset='utf8'
) # 打开数据库连接
cursor = db.cursor() # 使用cursor()方法获取操作游标
sql = "SELECT * FROM stu_login_k WHERE stu_id = '%s'" % (self.student_id.get()) # SQL 查询语句
try:
# 执行SQL语句
cursor.execute(sql)
# 获取所有记录列表
results = cursor.fetchall()
for row in results:
stu_id = row[0]
stu_pass = row[1]
# 打印结果
print("stu_id=%s,stu_pass=%s" % (stu_id, stu_pass))
except:
print("Error: unable to fecth data")
messagebox.showinfo('警告!', '用户名或密码不正确!')
db.close() # 关闭数据库连接
print("正在登陆游客查看界面")
print("self", self.student_pass.get())
print("local", stu_pass)
if self.student_pass.get() == stu_pass:
StudentView(self.window, self.student_id.get()) # 进入学生信息查看界面
else:
messagebox.showinfo('警告!', '用户名或密码不正确!')
def back(self):
StartPage(self.window) # 显示主窗口 销毁本窗口
# 科室资料管理操作界面
class AdminManage:
def __init__(self, parent_window):
parent_window.destroy() # 销毁主界面
self.window = Tk() # 初始框的声明
self.window.title('科室资料操作界面')
self.frame_left_top = tk.Frame(width=300, height=200)
self.frame_right_top = tk.Frame(width=300, height=200)
self.frame_center = tk.Frame(width=500, height=400)
self.frame_bottom = tk.Frame(width=650, height=50)
# 定义下方中心列表区域
self.columns = ("科室名", "编号", "地址", "电话")
self.tree = ttk.Treeview(self.frame_center, show="headings", height=18, columns=self.columns)
self.vbar = ttk.Scrollbar(self.frame_center, orient=VERTICAL, command=self.tree.yview)
# 定义树形结构与滚动条
self.tree.configure(yscrollcommand=self.vbar.set)
# 表格的标题
self.tree.column("科室名", width=150, anchor='center') # 表示列,不显示
self.tree.column("编号", width=150, anchor='center')
self.tree.column("地址", width=100, anchor='center')
self.tree.column("电话", width=100, anchor='center')
# 调用方法获取表格内容插入
self.tree.grid(row=0, column=0, sticky=NSEW)
self.vbar.grid(row=0, column=1, sticky=NS)
self.dpname = []
self.dpno = []
self.dpadr = []
self.dptel = []
# 打开数据库连接
db = pymysql.Connect(
host='localhost',
port=3306,
user='root',
passwd='123456',
db='hospital',
charset='utf8'
)
cursor = db.cursor() # 使用cursor()方法获取操作游标
sql = "SELECT * FROM department" # SQL 查询语句
try:
# 执行SQL语句
cursor.execute(sql)
# 获取所有记录列表
results = cursor.fetchall()
for row in results:
self.dpname.append(row[0])
self.dpno.append(row[1])
self.dpadr.append(row[2])
self.dptel.append(row[3])
# print(self.id)
# print(self.name)
# print(self.gender)
# print(self.age)
except:
print("Error: unable to fetch data")
messagebox.showinfo('警告!', '数据库连接失败!')
db.close() # 关闭数据库连接
print("test***********************")
for i in range(min(len(self.dpname), len(self.dpno), len(self.dpadr), len(self.dptel))): # 写入数据
self.tree.insert('', i, values=(self.dpname[i], self.dpno[i], self.dpadr[i], self.dptel[i]))
for col in self.columns: # 绑定函数,使表头可排序
self.tree.heading(col, text=col, command=lambda _col=col: self.tree_sort_column(self.tree, _col, False))
# 定义顶部区域
# 定义左上方区域
self.top_title = Label(self.frame_left_top, text="科室信息",bg='green', font=('Verdana', 20))
self.top_title.grid(row=0, column=0, columnspan=2, sticky=NSEW, padx=50, pady=10)
self.left_top_frame = tk.Frame(self.frame_left_top)
self.var_dpname = StringVar() # 声明科室名
self.var_dpno = StringVar() # 声明编号
self.var_dpadr = StringVar() # 声明地址
self.var_dptel = StringVar() # 声明电话
# 科室名
self.right_top_dpname_label = Label(self.frame_left_top, text="科室名:", font=('Verdana', 15))
self.right_top_dpname_entry = Entry(self.frame_left_top, textvariable=self.var_dpname, font=('Verdana', 15))
self.right_top_dpname_label.grid(row=1, column=0) # 位置设置
self.right_top_dpname_entry.grid(row=1, column=1)
# 编号
self.right_top_dpno_label = Label(self.frame_left_top, text="编号:",font=('Verdana', 15))
self.right_top_dpno_entry = Entry(self.frame_left_top, textvariable=self.var_dpno, font=('Verdana', 15))
self.right_top_dpno_label.grid(row=2, column=0) # 位置设置
self.right_top_dpno_entry.grid(row=2, column=1)
# 地址
self.right_top_dpadr_label = Label(self.frame_left_top, text="地址:", font=('Verdana', 15))
self.right_top_dpadr_entry = Entry(self.frame_left_top, textvariable=self.var_dpadr,font=('Verdana', 15))
self.right_top_dpadr_label.grid(row=3, column=0) # 位置设置
self.right_top_dpadr_entry.grid(row=3, column=1)
# 电话
self.right_top_dptel_label = Label(self.frame_left_top, text="电话:", font=('Verdana', 15))
self.right_top_dptel_entry = Entry(self.frame_left_top, textvariable=self.var_dptel, font=('Verdana', 15))
self.right_top_dptel_label.grid(row=4, column=0) # 位置设置
self.right_top_dptel_entry.grid(row=4, column=1)
# 定义右上方区域
self.right_top_title = Label(self.frame_right_top, text="操作", font=('Verdana', 20))
self.tree.bind('<Button-1>', self.click) # 左键获取位置
self.right_top_button1 = ttk.Button(self.frame_right_top, text='新建科室信息', width=20, command=self.new_row)
self.right_top_button2 = ttk.Button(self.frame_right_top, text='更新选中科室信息', width=20, command=self.updata_row)
self.right_top_button3 = ttk.Button(self.frame_right_top, text='删除选中科室信息', width=20, command=self.del_row)
# 位置设置
self.right_top_title.grid(row=1, column=0, pady=10)
self.right_top_button1.grid(row=2, column=0, padx=20, pady=10)
self.right_top_button2.grid(row=3, column=0, padx=20, pady=10)
self.right_top_button3.grid(row=4, column=0, padx=20, pady=10)
# 整体区域定位
self.frame_left_top.grid(row=0, column=0, padx=2, pady=5)
self.frame_right_top.grid(row=0, column=1, padx=30, pady=30)
self.frame_center.grid(row=1, column=0, columnspan=2, padx=4, pady=5)
self.frame_bottom.grid(row=2, column=0, columnspan=2)
self.frame_left_top.grid_propagate(0)
self.frame_right_top.grid_propagate(0)
self.frame_center.grid_propagate(0)
self.frame_bottom.grid_propagate(0)
self.frame_left_top.tkraise() # 开始显示主菜单
self.frame_right_top.tkraise() # 开始显示主菜单
self.frame_center.tkraise() # 开始显示主菜单
self.frame_bottom.tkraise() # 开始显示主菜单
self.window.protocol("WM_DELETE_WINDOW", self.back) # 捕捉右上角关闭点击
self.window.mainloop() # 进入消息循环
def back(self):
Gongnengjiemian(self.window) # 显示主窗口 销毁本窗口
def click(self, event):
self.col = self.tree.identify_column(event.x) # 列
self.row = self.tree.identify_row(event.y) # 行
print(self.col)
print(self.row)
self.row_info = self.tree.item(self.row, "values")
self.var_dpname.set(self.row_info[0])
self.var_dpno.set(self.row_info[1])
self.var_dpadr.set(self.row_info[2])
self.var_dptel.set(self.row_info[3])
self.right_top_dpname_entry = Entry(self.frame_left_top, state='disabled', textvariable=self.var_dpname,font=('Verdana', 15))
print('')
def tree_sort_column(self, tv, col, reverse): # Treeview、列名、排列方式
l = [(tv.set(k, col), k) for k in tv.get_children('')]
l.sort(reverse=reverse) # 排序方式
# rearrange items in sorted positions
for index, (val, k) in enumerate(l): # 根据排序后索引移动
tv.move(k, '', index)
tv.heading(col, command=lambda: self.tree_sort_column(tv, col, not reverse)) # 重写标题,使之成为再点倒序的标题
def new_row(self):
print('123')
print(self.var_dpname.get())
print(self.dpname)
if str(self.var_dpname.get()) in self.dpname:
messagebox.showinfo('警告!', '该科室已存在!')
else:
if self.var_dpname.get() != '' and self.var_dpno.get() != '' and self.var_dpadr.get() != '' and self.var_dptel.get() != '':
# 打开数据库连接
db = pymysql.Connect(
host='localhost',
port=3306,
user='root',
passwd='123456',
db='hospital',
charset='utf8'
)
cursor = db.cursor() # 使用cursor()方法获取操作游标
sql = "INSERT INTO department(dpname, dpno, dpadr, dptel) VALUES('%s', '%s', '%s', '%s') " % (self.var_dpname.get(), self.var_dpno.get(), self.var_dpadr.get(), self.var_dptel.get()) # SQL 插入语句
try:
cursor.execute(sql) # 执行sql语句
db.commit() # 提交到数据库执行
except:
db.rollback() # 发生错误时回滚
messagebox.showinfo('警告!', '数据库连接失败!')
db.close() # 关闭数据库连接
self.dpname.append(self.var_dpname.get())
self.dpno.append(self.var_dpno.get())
self.dpadr.append(self.var_dpadr.get())
self.dptel.append(self.var_dptel.get())
self.tree.insert('', len(self.dpname) - 1, values=(
self.dpname[len(self.dpname) - 1], self.dpno[len(self.dpname) - 1], self.dpadr[len(self.dpname) - 1],self.dptel[len(self.dpname) - 1]))
self.tree.update()
messagebox.showinfo('提示!', '插入成功!')
else:
messagebox.showinfo('警告!', '请填写科室数据')
def updata_row(self):
res = messagebox.askyesnocancel('警告!', '是否更新所填数据?')
if res == True:
if self.var_dpname.get() == self.row_info[0]: # 如果所填学号 与 所选学号一致
# 打开数据库连接
db =pymysql.Connect(
host='localhost',
port=3306,
user='root',
passwd='123456',
db='hospital',
charset='utf8'
)
cursor = db.cursor() # 使用cursor()方法获取操作游标
sql = "UPDATE department SET dpno = '%s', dpadr = '%s', dptel = '%s' WHERE dpname= '%s'" % (self.var_dpno.get(), self.var_dpadr.get(), self.var_dptel.get(), self.var_dpname.get()) # SQL 插入语句
try:
cursor.execute(sql) # 执行sql语句
db.commit() # 提交到数据库执行
messagebox.showinfo('提示!', '更新成功!')
except:
db.rollback() # 发生错误时回滚
messagebox.showinfo('警告!', '更新失败,数据库连接失败!')
db.close() # 关闭数据库连接
dpname_index = self.dpname.index(self.row_info[0])
self.dpname[dpname_index] = self.var_dpname.get()
self.dpadr[dpname_index] = self.var_dpadr.get()
self.dptel[dpname_index] = self.var_dptel.get()
self.tree.item(self.tree.selection()[0], values=(self.var_dpname.get(), self.var_dpno.get(), self.var_dpadr.get(),self.var_dptel.get()))
else:
messagebox.showinfo('警告!', '不能修改科室姓名!')
def del_row(self):
res = messagebox.askyesnocancel('警告!', '是否删除所选数据?')
if res == True:
print(self.row_info[0]) # 鼠标选中的学号
print(self.tree.selection()[0]) # 行号
print(self.tree.get_children()) # 所有行
# 打开数据库连接
db= pymysql.Connect(
host='localhost',
port=3306,
user='root',
passwd='123456',
db='hospital',
charset='utf8'
)
cursor = db.cursor() # 使用cursor()方法获取操作游标
sql = "DELETE FROM department WHERE dpname = '%s'" % (self.row_info[0]) # SQL 插入语句
try:
cursor.execute(sql) # 执行sql语句
db.commit() # 提交到数据库执行
messagebox.showinfo('提示!', '删除成功!')
except:
db.rollback() # 发生错误时回滚
messagebox.showinfo('警告!', '删除失败,数据库连接失败!')
db.close() # 关闭数据库连接
dpname_index = self.dpno.index(self.row_info[0])
print(dpname_index)
del self.dpname[dpname_index]
del self.dpno[dpname_index]
del self.dpadr[dpname_index]
del self.dptel[dpname_index]
print(self.dpno)
self.tree.delete(self.tree.selection()[0]) # 删除所选行
print(self.tree.get_children())
# 医生资料管理操作界面
class AdminManage1:
def __init__(self, parent_window):
parent_window.destroy() # 销毁主界面
self.window = Tk() # 初始框的声明
self.window.title('医生资料管理界面')
self.frame_left_top = tk.Frame(width=300, height=250)
self.frame_right_top = tk.Frame(width=200, height=200)
self.frame_center = tk.Frame(width=700, height=800)
self.frame_bottom = tk.Frame(width=700, height=10)
# 定义下方中心列表区域
self.columns = ("编号", "医生名", "职称", "性别","年龄","科室")
self.tree = ttk.Treeview(self.frame_center, show="headings", height=18, columns=self.columns)
self.vbar = ttk.Scrollbar(self.frame_center, orient=