前言
课程设计用的是vfp,但是我对vfp很不感冒。但是没办法,硬着头皮写吧。我这里先写个python草稿
之前接单的时候有过很类似的项目,可以说是一模一样,由于写过一次我觉得还是没有难度的
题目分析
程序必须实现的功能如下:
- 登陆(查)
- 车辆信息管理(增删改查)
- 驾驶员信息管理(增删改查)
- 投诉信息管理(表连接,增删改查)
- 驾驶员信息浏览(查)
- 投诉信息浏览(查)
- 用户权限管理(查)
- CS架构(mysql服务器作为server端,client端直接处理返回的数据即可,不必另做server端)
程序实现
登陆模块
很简单就能实现
流程图
ui设计
这里我用我自己以前接单的项目掏了一个登陆和注册ui过来,名字为”login.ui”
登陆模块如下
注册模块如下
然后用pyuic转换一下,生成ui的py代码
代码实现
ui代码
创建一个py文件,命名为main
from login import Ui_MainWindow1 from PyQt5.QtWidgets import QApplication, QMainWindow,QMessageBox,QGroupBox,QHeaderView,QMenu,QAbstractItemView from PyQt5.QtGui import QIcon,QStandardItemModel,QStandardItem,QCursor from PyQt5.Qt import QThread, pyqtSignal,QSize,QColor,QBrush,QMutex,QThreadPool,QCoreApplication from PyQt5 import QtCore,QtWidgets import sys class mylogin(QMainWindow, Ui_MainWindow1): def __init__(self): super(mylogin, self).__init__() # 继承父类 self.setupUi(self) # 对应Ui_MainWindow1.setupUI if __name__ == "__main__": app = QApplication(sys.argv) loginUI = mylogin() # 实例化类 loginUI.show() # 展示界面 sys.exit(app.exec())
|
效果如下
逻辑设计
登陆按钮的对象名为pushButton
由于clicked作为一个信号,直接调用connect方法即可
self.pushButton.clicked.connect(self.login)
|
接下来写login方法,由于需要进入数据库查询,首先得搭建个本地数据库,关于数据库的搭建方法请跳转我的csdn文章
这里直接上建表sql过程,打开powershell,输入如下命令并输入密码链接数据库
CREATE DATABASE classDesign;
|
CREATE TABLE loginAccount ( username CHAR(20) NOT NULL, password CHAR(20) NOT NULL, group1 CHAR(20) NOT NULL, PRIMARY KEY(username) );
|
至此建表完成
接下来接着写login方法
import pymysql def login(self): mysqlConnect = pymysql.connect( host='127.0.0.1', port=3306, user='root', # 你的用户名 passwd='', # 你的数据库密码 db='classDesign') inPutUsername = self.lineEdit.text() # 取得现在输入的用户名 inPutPassword = self.lineEdit_2.text() # 取得现在输入的密码 cur = mysqlConnect.cursor() if inPutUsername.strip("") == "" or inPutPassword.strip("") == "": QMessageBox.information(None, "提示", "请输入用户名或密码", QMessageBox.Yes) return try: cur.execute('SELECT * FROM loginAccount WHERE username = "{}";'.format(inPutUsername)) result = cur.fetchall() # 返回数组[username,password]形式 password = result[0][1] if inPutPassword == password: # 如果返回的密码和输入的密码正确 QMessageBox.information(None, "提示", "登陆成功", QMessageBox.Yes) else: QMessageBox.information(None, "提示", "密码不正确", QMessageBox.Yes) except Exception as e: QMessageBox.information(None,"提示","用户名不存在",QMessageBox.Yes) # 如果sql语句找不到username就会返回错误,这里使用了try-except捕获错误 mysqlConnect.close()
|
同理写注册逻辑
def register(self): mysqlConnect = pymysql.connect( host='127.0.0.1', port=3306, user='root', # 你的用户名 passwd='', # 你的数据库密码 db='classDesign') inPutUsername = self.lineEdit_3.text() # 取得现在输入的用户名 if self.lineEdit_4.text() != self.lineEdit_5.text(): QMessageBox.information(None,"提示","两次输入的账号密码不同",QMessageBox.Yes) inPutPassword = self.lineEdit_4.text() # 取得现在输入的密码 cur = mysqlConnect.cursor() try:
cur.execute('INSERT INTO loginAccount (username,password)VALUES(%s,%s);', [inPutUsername, inPutPassword]) mysqlConnect.commit() QMessageBox.information(None, "提示", "注册成功", QMessageBox.Yes) except Exception as e: QMessageBox.information(None,"提示","用户名已存在",QMessageBox.Yes) mysqlConnect.close()
|
运行效果如下
注册
登陆
正确情况
没输入用户名密码情况
用户名不正确情况
密码不正确情况
自动登陆和保存账号密码
使用python自带的configparser库实现保存设置
步骤无非2个,取得数据,保存到当前文件夹的.ini文件
我这里写在了mylogin类的初始化上
但是这样做会有个问题,如果初始化了,那么登陆过后,下面的show()方法依旧运行
就会变成这样
那么在这里的show()加上一个判断条件即可解决
顺便把保存做成一个接口,以后想要保存直接self.save()就可以代码复用
main完整代码
from login import Ui_MainWindow1 from PyQt5.QtWidgets import QApplication, QMainWindow,QMessageBox,QGroupBox,QHeaderView,QMenu,QAbstractItemView from PyQt5.QtGui import QIcon,QStandardItemModel,QStandardItem,QCursor from PyQt5.Qt import QThread, pyqtSignal,QSize,QColor,QBrush,QMutex,QThreadPool,QCoreApplication from PyQt5 import QtCore,QtWidgets import sys import pymysql class mylogin(QMainWindow, Ui_MainWindow1): def __init__(self): super(mylogin, self).__init__() # 继承父类 self.setupUi(self) # 对应Ui_MainWindow1.setupUI self.pushButton.clicked.connect(self.login) # 登陆 self.pushButton_2.clicked.connect(self.close) # 退出 self.pushButton_5.clicked.connect(self.register) # 注册 self.pushButton_4.clicked.connect(self.close) # 退出
def login(self): mysqlConnect = pymysql.connect( host='127.0.0.1', port=3306, user='root', # 你的用户名 passwd='', # 你的数据库密码 db='classDesign') inPutUsername = self.lineEdit.text() # 取得现在输入的用户名 inPutPassword = self.lineEdit_2.text() # 取得现在输入的密码 cur = mysqlConnect.cursor() if inPutUsername.strip("") == "" or inPutPassword.strip("") == "": QMessageBox.information(None, "提示", "请输入用户名或密码", QMessageBox.Yes) return try: cur.execute('SELECT * FROM loginAccount WHERE username = "{}";'.format(inPutUsername)) result = cur.fetchall() # 返回数组[username,password]形式 password = result[0][1] if inPutPassword == password: # 如果返回的密码和输入的密码正确 QMessageBox.information(None, "提示", "登陆成功", QMessageBox.Yes) else: QMessageBox.information(None, "提示", "密码不正确", QMessageBox.Yes) except Exception as e: QMessageBox.information(None,"提示","用户名不存在",QMessageBox.Yes) # 如果sql语句找不到username就会返回错误,这里使用了try-except捕获错误 mysqlConnect.close() def register(self): mysqlConnect = pymysql.connect( host='127.0.0.1', port=3306, user='root', # 你的用户名 passwd='', # 你的数据库密码 db='classDesign') inPutUsername = self.lineEdit_3.text() # 取得现在输入的用户名 if self.lineEdit_4.text() != self.lineEdit_5.text(): QMessageBox.information(None,"提示","两次输入的账号密码不同",QMessageBox.Yes) inPutPassword = self.lineEdit_4.text() # 取得现在输入的密码 cur = mysqlConnect.cursor() try:
cur.execute('INSERT INTO loginAccount (username,password)VALUES(%s,%s);', [inPutUsername, inPutPassword]) mysqlConnect.commit() QMessageBox.information(None, "提示", "注册成功", QMessageBox.Yes) except Exception as e: QMessageBox.information(None,"提示","用户名已存在",QMessageBox.Yes) mysqlConnect.close()
if __name__ == "__main__": app = QApplication(sys.argv) loginUI = mylogin() # 实例化类 loginUI.show() # 展示界面 sys.exit(app.exec())
|
主程序模块
实现用户权限管理
我的思路是通过新增一个表,并且在loginAccount中新增权限(group)字段,通过连接表实现权限,这是受到linux读写权限启发得来
添加权限表
表设计如下
group |
add |
delete |
update |
select |
editAccount |
admin |
1 |
1 |
1 |
1 |
1 |
user |
0 |
0 |
0 |
1 |
0 |
admin权限组可以实现增删改查,user权限组只能修改自己的密码(默认权限,这里省略字段了),查询表
制作ui
创建一个新窗口
ctrl+s保存为myMainWindow.ui
添加tab widget,方便其他功能使用
使用栅格布局,改变ui的观感
改变tab1的名字,改为用户管理
以下略
我设计ui的水瓶一般,随便看看就好
查询按钮实现
好懒不想写细节了,大概思路就是添加一个tableView,然后请求数据库返回的信息处理后,往tableView写数据,我这里直接在表格右键实现了添加修改删除三个功能
主要说一下遇到的麻烦
添加
主要解决添加以后直接显示添加出来数据
由于提前把刷新数据做了一个方法接口,直接在插入数据以后调用即可
修改
修改密码倒是简单,主要解决修改用户名
用户名修改的时候有两个问题
- 用户名是主键,如果修改容易出事情
- 用户名右键修改的时候,没法获取原来的用户名
问题1我选择了删除主键,修改,然后再增加主键的做法,以前是先把这一条数据保存起来,再删除,再添加回去新修改的数据
问题2,由于我选择了删除主键,修改,没有保存原来的数据,在这里耗费了很多时间。
我在mainUI.setData()方法里添加了一个self.data用于保存原先的数据
于是问题迎刃而解了
删除
由于删除会直接改变表格的数据条数,删除以后会导致表格存在重复项没有消去
我的解决方法是直接保存当前行所在的序号,然后删除后直接调用removeRow(index),直接删掉对应行
修改密码按钮实现
我直接对着改密按钮clicked信号链接到一个创建新ui,并且调用新ui的方法实现相应逻辑
问题在于修改密码以后自动登录会乱掉。比如如果密码错误,之前已经删除掉了show()方法,登陆按钮在弹出密码错误的框以后不会显示。
在login添加一个自动登陆的flag,实现相应的逻辑
车辆信息
由于接下来要实现的功能和上面高度相似,需要注意的问题是复用表,其他的我觉得没有必要再写了,添加个标题看起来整齐点
建表sql语句
CREATE TABLE carProfile( type char(10), brand char(2), engineNo char(10), carNo char(8), Num char(6), PRIMARY KEY(Num) )
|
主要是实现单独查询的功能,我这里给右键菜单添加了一个独特查询按键
点进去是这样的
如果要查询桂A23348这个车辆,那么就在这里找到他的车牌然后点击查询,会打开一个新表
驾驶员信息
同上一模一样的功能,也是右键查询
CREATE TABLE driverProfile( name char(12), IDcard char(18), address char(30), contact char(11), code char(6), driverNo char(8), PRIMARY KEY(driverNo) )
|
投诉信息
CREATE TABLE issue( carNo char(10), reason char(50), time datetime(0) NOT NULL DEFAULT now(), opinion char(50), operator char(12), Num char(8), PRIMARY KEY(Num) )
|
这里比较重要的是实现的车辆信息必须先查询,把sql语句改一下就行了
这样就能查询对应的车辆是否存在违规信息
字段约束
我考虑的是在添加,修改的时候额外添加一个窗口,和之前的用表格修改区别开来
吃饭先