Featured image of post 车辆管理系统课程设计

车辆管理系统课程设计

使用pyqt+mysql设计一个车辆管理系统

前言

课程设计用的是vfp,但是我对vfp很不感冒。但是没办法,硬着头皮写吧。我这里先写个python草稿 之前接单的时候有过很类似的项目,可以说是一模一样,由于写过一次我觉得还是没有难度的

题目分析

程序必须实现的功能如下:

  1. 登陆(查)
  2. 车辆信息管理(增删改查)
  3. 驾驶员信息管理(增删改查)
  4. 投诉信息管理(表连接,增删改查)
  5. 驾驶员信息浏览(查)
  6. 投诉信息浏览(查)
  7. 用户权限管理(查)
  8. CS架构(mysql服务器作为server端,client端直接处理返回的数据即可,不必另做server端)

程序实现

登陆模块

很简单就能实现

流程图

流程图

ui设计

这里我用我自己以前接单的项目掏了一个登陆和注册ui过来,名字为"login.ui" 图片-1667876905294 登陆模块如下 登录模块 注册模块如下 注册模块 然后用pyuic转换一下,生成ui的py代码

图片-1667876970413

代码实现

ui代码

创建一个py文件,命名为main

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
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())

效果如下 图片-1667877396001

逻辑设计

登陆按钮的对象名为pushButton 图片-1667877464913

图片-1667877615155 由于clicked作为一个信号,直接调用connect方法即可

1
self.pushButton.clicked.connect(self.login)

接下来写login方法,由于需要进入数据库查询,首先得搭建个本地数据库,关于数据库的搭建方法请跳转我的csdn文章

这里直接上建表sql过程,打开powershell,输入如下命令并输入密码链接数据库

1
mysql -uroot -p

图片-1667878040350

1
CREATE DATABASE classDesign;

图片-1667878134673

1
USE classDesign;

图片-1667878176038

1
2
3
4
5
6
7
CREATE TABLE loginAccount
(
username CHAR(20) NOT NULL,
password CHAR(20) NOT NULL,
group1 CHAR(20) NOT NULL,
PRIMARY KEY(username)
);

图片-1667878307328

至此建表完成

接下来接着写login方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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()

同理写注册逻辑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
    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()

运行效果如下

注册

图片-1667879726747

图片-1667879770962

登陆

正确情况 图片-1667880005833

没输入用户名密码情况 图片-1667880272574 用户名不正确情况 图片-1667880289917 密码不正确情况 图片-1667880096638

自动登陆和保存账号密码

使用python自带的configparser库实现保存设置 步骤无非2个,取得数据,保存到当前文件夹的.ini文件 我这里写在了mylogin类的初始化上 图片-1667897628343

但是这样做会有个问题,如果初始化了,那么登陆过后,下面的show()方法依旧运行

图片-1667895306836

就会变成这样 那么在这里的show()加上一个判断条件即可解决 图片-1667895332640 顺便把保存做成一个接口,以后想要保存直接self.save()就可以代码复用 图片-1667895959581

main完整代码
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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

创建一个新窗口 图片-1667884692553

ctrl+s保存为myMainWindow.ui 图片-1667884746822

添加tab widget,方便其他功能使用 图片-1667884801005 使用栅格布局,改变ui的观感 图片-1667884858148

改变tab1的名字,改为用户管理 图片-1667884941799

以下略

我设计ui的水瓶一般,随便看看就好 图片-1667885661134

查询按钮实现

图片-1667885916904

好懒不想写细节了,大概思路就是添加一个tableView,然后请求数据库返回的信息处理后,往tableView写数据,我这里直接在表格右键实现了添加修改删除三个功能

主要说一下遇到的麻烦

添加

主要解决添加以后直接显示添加出来数据 由于提前把刷新数据做了一个方法接口,直接在插入数据以后调用即可 图片-1667908313869

修改

修改密码倒是简单,主要解决修改用户名 用户名修改的时候有两个问题

  1. 用户名是主键,如果修改容易出事情
  2. 用户名右键修改的时候,没法获取原来的用户名

问题1我选择了删除主键,修改,然后再增加主键的做法,以前是先把这一条数据保存起来,再删除,再添加回去新修改的数据

问题2,由于我选择了删除主键,修改,没有保存原来的数据,在这里耗费了很多时间。 我在mainUI.setData()方法里添加了一个self.data用于保存原先的数据 于是问题迎刃而解了 图片-1667908490904

删除

由于删除会直接改变表格的数据条数,删除以后会导致表格存在重复项没有消去 我的解决方法是直接保存当前行所在的序号,然后删除后直接调用removeRow(index),直接删掉对应行 图片-1667908504804

修改密码按钮实现

图片-1667908632933 我直接对着改密按钮clicked信号链接到一个创建新ui,并且调用新ui的方法实现相应逻辑 问题在于修改密码以后自动登录会乱掉。比如如果密码错误,之前已经删除掉了show()方法,登陆按钮在弹出密码错误的框以后不会显示。 在login添加一个自动登陆的flag,实现相应的逻辑 图片-1667908770468

车辆信息

由于接下来要实现的功能和上面高度相似,需要注意的问题是复用表,其他的我觉得没有必要再写了,添加个标题看起来整齐点 建表sql语句

1
2
3
4
5
6
7
8
CREATE TABLE carProfile(
type char(10),
brand char(2),
engineNo char(10),
carNo char(8),
Num char(6),
PRIMARY KEY(Num)
)

主要是实现单独查询的功能,我这里给右键菜单添加了一个独特查询按键 图片-1667990917864 点进去是这样的 图片-1667990958445 如果要查询桂A23348这个车辆,那么就在这里找到他的车牌然后点击查询,会打开一个新表 图片-1667990996153

驾驶员信息

同上一模一样的功能,也是右键查询

1
2
3
4
5
6
7
8
9
CREATE TABLE driverProfile(
name char(12),
IDcard char(18),
address char(30),
contact char(11),
code char(6),
driverNo char(8),
PRIMARY KEY(driverNo)
)

投诉信息

1
2
3
4
5
6
7
8
9
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语句改一下就行了 图片-1667991438091

图片-1667991460318 这样就能查询对应的车辆是否存在违规信息

字段约束

我考虑的是在添加,修改的时候额外添加一个窗口,和之前的用表格修改区别开来 吃饭先