• 基于qt的图书管理系统----04sql功能开发


    参考b站:视频连接

    源码githubgithub

    1 封装一个全局的对象

    新建一个c++class,sqlmange,并且在.pro文件中添加上sql

    在这里插入图片描述

    使用c++单例模式:

    它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。

    在这里插入图片描述

    该代码实现了 SQLManange 类,该类可以用于管理数据库连接和操作。代码使用了单例模式,确保只有一个 SQLManange 实例存在,并提供了一些基本功能,例如测试数据库连接和操作。我不是很懂这部分先更着敲

    #ifndef SQLMANGE_H
    #define SQLMANGE_H
    
    #include 
    
    // sqlmange 类声明
    class sqlmange
    {
    public:
        // 构造函数
        sqlmange();
    
        // 单例模式:获取类唯一实例
        static sqlmange* getInstance();
    
        // 测试函数
        void test();
    
    private:
        // 私有构造函数,禁止外部直接创建对象
        sqlmange(const sqlmange&) = delete;
        // 私有赋值运算符,禁止外部直接赋值
        sqlmange& operator=(const sqlmange&) = delete;
    
        // 单例模式:类唯一实例指针
        static sqlmange* instance;
    };
    
    #endif // SQLMANGE_H
    
    
    #include "sqlmange.h"
    
    // sqlmange 类唯一实例指针初始化
    sqlmange* sqlmange::instance = nullptr;
    
    // sqlmange 类构造函数实现
    sqlmange::sqlmange() {}
    
    // sqlmange 类获取实例函数实现
    // 如果实例不存在,则创建新实例并赋值给 instance 指针
    // 然后返回 instance 指针
    sqlmange* sqlmange::getInstance()
    {
        if (nullptr == instance) {
            instance = new sqlmange();
        }
        return instance;
    }
    
    // sqlmange 类测试函数实现
    // 输出 "test" 到调试信息
    void sqlmange::test()
    {
        qDebug() << "test";
    }
    
    • 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

    在main函数中使用sqlmange::getInstance()->test();调用写好的接口

    2 设计所有接口

    // 构造函数
        sqlmange();
    
        // 单例模式:获取类唯一实例
        static sqlmange* getInstance();
    
        //初始化数据库
        void init();
    
        //登陆
        bool login(QString strUsername ,QString strPassword);
    
        //获取所有用户
        QVector<QStringList> getUsers(QString strCondition = "");
    
        //添加用户
        void AddUser(QVector<QStringList>);
    
        //删除用户
        void DelUser(QString strID);
    
        //获取所有图书
        QVector<QStringList> getBooks(QString strCondition = "");
    
        //增加图书
        void AddBook(QVector<QStringList>);
    
        //修改图书
        void ModBook(QString strID);
        //删除图书
        void DelBook(QString strID);
    
        //图书归还,谁还的,还的什么书
        QString ReturnBook(QString strUserID, QString strBookID);
    
        //图书借阅,谁借的,借的什么书
        QString BorrowBook(QString strUserID, QString strBookID);
    
        //获取借阅记录
        QVector<QStringList> getRecords(QString strCondition = "");
    
        //清空记录
        QString clearRecord();
    
    • 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

    2.1 初始化数据库接口

    使用QSqlDatabase库里的函数,官方给我们提供了参考

    在这里插入图片描述

    将之前写好的数据库放到应用程序所在目录下的db文件夹,编写代码

    void sqlmange::init()
    {
        // 打开数据库
        // 使用 QSQLITE 数据库驱动
        m_db = QSqlDatabase::addDatabase("QSQLITE");
        
        // 设置数据库名称
        // 数据库文件位于应用程序目录下的 db/book.db 文件
        m_db.setDatabaseName(QCoreApplication::applicationDirPath() + "/db/book.db");
        
        // 打开数据库
        // 并输出打开结果到调试信息
        qDebug() << m_db.open();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    此时发现没有驱动,排查发现是此时程序运行在打包好的路径里了,没有把现在用到的数据库打包上,所以我们回到bin文件夹把之前打包的库都删了就能够运行。

    找库的路径都是优先当前程序所在路径

    在这里插入图片描述

    在这里插入图片描述

    2.2 登陆接口

    使用查询语句查询用户名和密码是否对上即可

    bool sqlmange::login(QString strUsername, QString strPassword)
    {
        // 创建 SQL 查询对象
        QSqlQuery q(m_db);
        // 构建 SQL 查询语句
        // 使用占位符防止 SQL 注入攻击
        QString strSql = QString("select * from user where username = '%1' and password = '%2'").arg(strUsername).arg(strPassword);
        
        // 执行 SQL 查询
        bool ret = q.exec(strSql);
        
        // 如果查询失败,输出错误信息
        if(!ret)
        {
            qDebug()<<q.lastError().text();
        }
        
        // 返回查询结果
        return ret;
    }
    
    
    // 使用单例实例执行登录操作,并输出登录结果到调试信息
        qDebug() <<"login:"<< sqlmange::getInstance()->login("xiaoming","123456");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2.3 条件查询用户接口

    把 where后边的语句都用做条件,如where username like '%x' or nickname '小'

    QVector<QStringList> sqlmange::getUsers(QString strCondition)
    {
        // 创建 SQL 查询对象
        QSqlQuery q(m_db);
        // 构建 SQL 查询语句
        // 使用占位符防止 SQL 注入攻击
        // 使用 strCondition 作为查询条件
        QString strSql = QString("select * from user %1").arg(strCondition);
    
        // 存储查询结果的容器
        QVector<QStringList> vec;
    
    
        // 执行 SQL 查询
        bool ret = q.exec(strSql);
    
        // 如果查询失败,输出错误信息
        if(!ret)
        {
            qDebug()<<q.lastError().text();
        }
        else
        {
            // 获取查询结果的列数
            int iCols = q.record().count();
            // 临时存储每行的查询结果
            QStringList l;
    
            // 遍历查询结果
            while(q.next())
            {
                // 遍历每一列
                for (int i = 0;i< iCols;i++)
                {
                    // 将当前列的值添加到临时列表中
                    l<<q.value(i).toString();
                }
                // 将临时列表添加到最终结果容器中
                vec.push_back(l);
    
                // 清空临时列表
                l.clear();
            }
        }
        // 返回查询结果
        return vec;
    }
    
    • 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

    在mian里使用qDebug() <<"getuser:"<< sqlmange::getInstance()->getUsers("where username like '%xiao%' or nickname like '%小%'");

    3 用户接口

    3.1 初始化界面

    首先从数据库里读出数据展示在table view中,数据存在容器中相当于一个二维数组

    void Cell_Usermange::initPage(QString strCondition)
    {
        //查询数据库并且显示
        QVector<QStringList> l = sqlmange::getInstance()->getUsers(strCondition);
    
        // 清空之前的数据,以便显示新的查询结果
        m_model.clear();
    
        // 设置表格列头标签
        m_model.setHorizontalHeaderLabels(QStringList{"用户ID", "姓名", "年级", "权限","所属学院", "用户名", "密码"});
    
        for(int i = 0;i<l.size();i++)
        {
            // 创建一个新的行
            QList<QStandardItem *> items;
    
            // 遍历每一列
            for(int j = 0;j<l[i].size();j++)
            {
                // 创建一个新的单元格项并设置文本
                items.append(new QStandardItem(l[i][j]));
            }
            // 将行添加到表格模型中
            m_model.appendRow(items);
        }
    }
    
    • 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

    让页面切换时调用initpage函数

    if (str == "btn_user") {
                // 显示用户管理页面
                m_userpage->initPage("");
                ui->stackedWidget->setCurrentIndex(0);
                break;
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.2 删除用户

    先在cell—main里修改样式,添加一个按钮按下的状态 ​QPushButton[name = “btn”]:press{background: #3a8ee6;}​

    首先需要在sqlmange里把删除的逻辑写好

    void sqlmange::DelUser(QString strID)
    {
        // 创建 SQL 查询对象
        QSqlQuery q(m_db);
        // 构建 SQL 查询语句
        // 使用占位符防止 SQL 注入攻击
        QString strSql = QString("delete from user where userid = '%1'").arg(strID);
        // 执行 SQL 查询
        q.exec(strSql);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    然后我们再去编写点击按钮执行删除的操作,使用选中行的id,执行删除这个userid的行

    void Cell_Usermange::on_btn_del_clicked()
    {
        // 删除用户
        // 获取当前选中的行号
        int r = ui->tableView->currentIndex().row();
    
        // 判断是否选中行
        if (r < 0) {
            // 弹出错误提示框
            QMessageBox::information(nullptr, "错误", "没有选中用户");
        } else {
    // 获取选中行的用户ID,text变为QString
            QString id = m_model.item(r, 0)->text();
    
            // 使用 SQLManange 类删除用户
            sqlmange::getInstance()->DelUser(id);
    
            // 弹出成功提示框
            QMessageBox::information(nullptr, "成功", "删除成功");
    
            // 刷新页面
            initPage();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    3.3 搜索用户

    右击文编框,转到槽,使用textchanged槽

    在这里插入图片描述

    查询官方文档,有以下的信号,文本改变时text直接就是我们输入的文本

    在这里插入图片描述

    我们使用字符串拼接来达到搜索的目的,getuser里已经是select * from user %1,我们把这%1替换为模糊搜索语句,也就是最后运行sql语句select * from user where username like '%1%' or nickname like '%2%',这样很方便

    void Cell_Usermange::on_le_search_textChanged(const QString &text)
    {
        //搜索用户
        //使用字符串拼接来达到模糊搜索
        QString strCond = QString("where username like '%1%' or nickname like '%2%'").arg(text).arg(text);
        initPage(strCond);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.4 用户导入

    使用qFile读取csv文件,把里边的数据用“,”划分存储到容器vector中,在使用insert将容器里的数据导入数据库。此时写入数据库的代码是乱码,应为csv是gbk编码,数据是是utf-8编码,所以需要转换(暂未解决)

    在这里插入图片描述

    void sqlmange::AddUser(QVector<QStringList> addData)
    {
        // 开启数据库事务
        m_db.transaction();
        
        // 创建 SQL 查询对象
        QSqlQuery q(m_db);
        
        // 遍历用户数据
        for (int i = 0; i < addData.size(); i++)
        {
            // 构建 SQL 插入语句
            // 使用占位符防止 SQL 注入攻击
            // 将字符串转换为 UTF-8 编码,避免中文乱码
            QString strSql = QString("insert into user VALUES(NULL,'%1','%2','%3','%4','%5','%6')").arg(addData[i][0].toUtf8()).arg(addData[i][1].toUtf8()).arg(addData[i][2].toUtf8()).arg(addData[i][3].toUtf8()).arg(addData[i][4].toUtf8()).arg(addData[i][5].toUtf8());
            
            // 执行 SQL 插入
            q.exec(strSql);
        }
        
        // 提交数据库事务
        m_db.commit();
    }
    
    
    void Cell_Usermange::on_btn_import_clicked()
    {
        //导入用户并显示
        // 打开文件选择对话框
        QString strPath = QFileDialog::getOpenFileName(nullptr,"请输入文件路径");
        if(!strPath.isEmpty())
        {
            // 打开 CSV 文件
            QFile f(strPath);
            f.open(QFile::ReadOnly|QFile::Text);
    
            // 定义一个用于存储用户数据的容器
            QVector<QStringList> addData;
            while(!f.atEnd())
            {
               // 读取一行数据
                QString str = f.readLine();
    
    
                // 将一行数据分割成字符串列表
                QStringList l = str.split(",");
    
    
                // 判断列数是否正确
                if (l.size() != 6)
                {
                    // 弹出错误提示框
                    QMessageBox::information(nullptr, "错误", "导入失败,列数对不上");
                    return;
                }
    
                // 删除字符串末尾的换行符
                l[l.size() - 1].chop(2);
    
                // 将数据添加到容器中
                addData.push_back(l);
            }
    
            // 弹出成功提示框
            QMessageBox::information(nullptr, "成功", "导入成功");
    
            // 使用 SQLManange 类添加用户
            sqlmange::getInstance()->AddUser(addData);
    
            // 刷新页面
            initPage();
    
        }
    }
    
    • 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
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    乱码问题暂时还不会解决

    4 图书管理界面

    4.1 初始化图书接口

    代码和初始化用户接口一样,getbooks修改sql语句改为book,initpage一样,随后在main。cpp里加上m_bookpage->initPage("");展示记录

    ## 4.2 搜索接口

    拼接sql语句实现查询

    
    void Cell\_BookManger::on\_le\_search\_textChanged(const QString &arg1)
    
    {
    
    //搜索图书
    
    //使用字符串拼接来达到模糊搜索
    
    QString strCond = QString("where name like '%1%' or type1 like '%2%' or type2 like '%3%' or type3 like '%4%'").arg(arg1).arg(arg1).arg(arg1).arg(arg1);
    
    initPage(strCond);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.3 删除图书接口

    和删除用户接口一样

    4.4 图书添加和修改

    图书的增加和修改需要点击是在新弹出一个界面来输入

    新建一个qt界面设计师类,选择withoutbutton,搭建下图所示界面

    在这里插入图片描述

    在这里插入图片描述

    取消按钮的代码很简单,直接this->hide()隐藏了就行

    先编写sql的逻辑代码,一个是修改一个是插入(查百度即可)在套上之前写好的模板。

    void sqlmange::AddBook(QVector<QStringList> vec)
    {
        //增加图书
        // 创建 SQL 查询对象
        QSqlQuery q(m_db);
    
        if(vec.size() == 0)
        {
            return;
        }
        QStringList ldata = vec[0];
        // 构建 SQL 查询语句
        // 使用占位符防止 SQL 注入攻击
        QString strSql = QString("INSERT INTO book"
                                 "values(NULL,'%1','%2','%3','%4','%5','%6','')")
                             .arg(ldata[1])
                             .arg(ldata[2])
                             .arg(ldata[3])
                             .arg(ldata[4])
                             .arg(ldata[5])
                             .arg(ldata[6]);
        // 执行 SQL 查询
        q.exec(strSql);
    }
    
    void sqlmange::ModBook(QStringList ldata)
    {
        //更新图书
        // 创建 SQL 查询对象
        QSqlQuery q(m_db);
        // 构建 SQL 查询语句
        // 使用占位符防止 SQL 注入攻击
        
    QString strSql = QString("INSERT INTO book "
                                 "values(NULL,'%1','%2','%3','%4','%5',%6,'')")
                             .arg(ldata[1])
                             .arg(ldata[2])
                             .arg(ldata[4])
                             .arg(ldata[5])
                             .arg(ldata[6])
                             .arg(ldata[3]);
        // 执行 SQL 查询
        q.exec(strSql);
    }
    
    • 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

    在编写确定按钮的槽函数,通过UI界面那要需要修改的信息,通过一个判断将修改和增加写到一起

    // 函数声明:设置书籍ID
    void Dlg_BookAdd_Update::setType(int l)
    {
        // 将参数l赋值给成员变量m_id
        m_id = l;
    }
    
    // 函数声明:确认按钮槽函数
    void Dlg_BookAdd_Update::on_btn_ok_clicked()
    {
        // 定义一个QStringList用于存储书籍信息
        QStringList l;
    
        // 将书籍ID转换为QString并添加到l中
        l << QString::number(m_id);
    
        // 将书名、价格、数量、分类1、分类2、分类3添加到l中
        l << ui->le_name->text();
        l << ui->le_press->text();
        l << ui->le_count->text();
        l << ui->cb1->currentText();
        l << ui->cb2->currentText();
        l << ui->cb3->currentText();
        l << "";
    
        // 判断m_id是否为-1
        if (-1 != m_id) {
            // 更新书籍信息
            sqlmange::getInstance()->ModBook(l);
        } else {
            // 添加新书籍
            QVector<QStringList> vec;
            vec.push_back(l);
            sqlmange::getInstance()->AddBook(vec);
        }
    }
    
    • 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

    回到图书管理界面,导入更新图书的头文件,执行代码,id默认是-1所以是执行添加图书的操作,最后刷新界面展示记录

    void Cell_BookManger::on_btn_add_clicked()
    {
        //添加图书
        Dlg_BookAdd_Update dlg;
        dlg.exec();
        initPage();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    此时发现并没有添加进去,调试发现sql语句有问题,book后边没有空格,同时从需要将输入数据和数据库里的顺序一一对应,不然就无法加入

    在这里插入图片描述

    图书修改

    sql语句,UPDATE修改属性,注意语句的空格

    void sqlmange::ModBook(QStringList ldata)
    {
        //更新图书
        // 创建 SQL 查询对象
        QSqlQuery q(m_db);
        // 构建 SQL 查询语句
        // 使用占位符防止 SQL 注入攻击
        QString strSql = QString("UPDATE book "
                                 "set name = '%1',press = '%2',type1 = '%3',type2 = '%4',type3 = '%5',count = '%6' "
                                 "where bookid = '%7'")
                                .arg(ldata[1])
                                .arg(ldata[2])
                                .arg(ldata[4])
                                .arg(ldata[5])
                                .arg(ldata[6])
                                .arg(ldata[3])
                                .arg(ldata[0]);
        // 执行 SQL 查询
        q.exec(strSql);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    此时所有信息都要自己填入,我们需要在修改的时候让它自动显示原来的信息。不管是修改还是新增都获取原来图书的信息,如果有信息就展示

    void Dlg_BookAdd_Update::setType(int id)
    {
        // 将参数l赋值给成员变量m_id
        m_id = id;
        //获取当前选中行的图书信息
        QVector<QStringList> l = sqlmange::getInstance()->getBooks(QString("where bookid = %1 ").arg(m_id));
    
        if(l.size() == 1)
        {
            QStringList data = l[0];
            //使用set将文本填入到窗口
            ui->le_name->setText(data[1]);
            ui->le_press->setText(data[2]);
            ui->cb1->setCurrentText(data[3]);
            ui->cb2->setCurrentText(data[4]);
            ui->cb3->setCurrentText(data[5]);
            ui->le_count->setText(data[6]);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4.5 图书借阅

    新建一个qt界面,按下图搭建

    在这里插入图片描述

    先编写图书管理界面点击借阅的按钮,判断是否选中图书,选中开始执行,同时在进入对话框之前查询图书的数量是否为0,为0就失败

    void Cell_BookManger::on_btn_borrow_clicked()
    {
        //借阅图书
        // 获取当前选中的行号
        int r = ui->tableView->currentIndex().row();
    
        // 判断是否选中行
        if (r < 0) {
            // 弹出错误提示框
            QMessageBox::information(nullptr, "错误", "没有选中图书");
        }
        else
        {
            // 获取选中行的图书ID,text变为QString
            QString id = m_model.item(r, 0)->text();
    
            //获取数量
            QString count = m_model.item(r, 6)->text();
            if(count.toInt() <= 0 )
            {
                 QMessageBox::information(nullptr, "信息", "借阅失败,图书数量不足");
                return;
            }
    
            //执行借阅
            Dlg_book_bor dlg;
    
            //传入bookid
            dlg.setBookID(id.toInt());
            int ret = dlg.exec();
    
            // 弹出成功提示框
            QMessageBox::information(nullptr, "信息", ret?"借阅成功":"借阅失败");
    
            // 刷新页面
            initPage();
        }
    }
    
    • 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

    同时需要拿到userid,使用实参传递直接修改传进去的userid

    bool sqlmange::login(QString strUsername, QString strPassword,int &userid)
    {
        // 创建 SQL 查询对象
        QSqlQuery q(m_db);
        // 构建 SQL 查询语句
        // 使用占位符防止 SQL 注入攻击
        QString strSql = QString("select * from user where username = '%1' and password = '%2'").arg(strUsername).arg(strPassword);
    
        // 执行 SQL 查询
        bool ret = q.exec(strSql);
    
        // 如果查询失败,输出错误信息
        if(!ret)
        {
            qDebug()<<q.lastError().text();
        }
        else
        {
            //拿到用户id
            q.next();
            userid << q.value(0).toInt();
        }
        // 返回查询结果
        return ret;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    编写输入用户名和密码后的代码,调用login,获得userid和bookid,最后调用借阅书本的代码

    void Dlg_book_bor::on_btn_ok_clicked()
    {
    
        // 判断用户名密码是否正确
        do
        {
            // 获取用户名和密码
            QString username = ui->le_username->text();
            QString password = ui->le_password->text();
    
            // 用户 ID
            int m_userid = 0;
    
            // 登录验证
            bool ret = sqlmange::getInstance()->login(username, password, m_userid);
    
            // 登录失败
            if (!ret)
            {
                // 关闭对话框
                this->done(0);
    
                // 退出循环
                break;
            }
    
            // 生成借阅记录
            sqlmange::getInstance()->BorrowBook(QString::number(m_userid), QString::number(m_bookid));
    
            // 关闭对话框并返回成功状态
            this->done(1);
    
        } while (false);
    }
    
    • 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

    最后我们只需要写sql语句就可以,并且添加插入记录的sql语句,QDateTime可以获取当前的时间

    QString sqlmange::BorrowBook(QString strUserID, QString strBookID)
    {
        //借阅图书
        // 创建 SQL 查询对象
        QSqlQuery q(m_db);
        // 构建 SQL 查询语句
        // 查询书本数量-1
        QString strSql1 = QString("UPDATE book set count = count-1 where bookid = '%1'").arg(strBookID);
        //添加记录
        QString strSql2 = QString("INSERT into record VALUES(NULL,'%1','%2','%3','%4','')")
                                .arg(strBookID)
                                .arg(strUserID)
                                .arg(QDateTime::currentSecsSinceEpoch())
                                .arg(QDateTime::currentSecsSinceEpoch()+3600*24*10);
    
        bool ret1 = q.exec(strSql1);
        if(!ret1)
        {
            qDebug()<<q.lastError().text();
        }
    
        bool ret2 = q.exec(strSql2);
        if(!ret2)
        {
            qDebug()<<q.lastError().text();
        }
        return QString("");
    }
    
    • 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

    小功能,在借阅的时候显示图书的名称

    void Dlg_book_bor::setBookID(int id)
    {
        m_bookid = id;
        //查询对于id的书本名
        auto l = sqlmange::getInstance()->getBooks(QString("where bookid = %1").arg(m_bookid));
    
        //显示在label上
        ui->lb_bookname->setText(QString("图书名称: "+l[0][1]));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5 借阅记录管理界面

    5.1 初始化图书接口

    代码和初始化用户接口一样,getrecords修改sql语句改为record,initpage一样,随后在main。cpp里加上m_recordpage->initPage("");展示记录

    调用的借阅的界面,代码更图书借阅类似

    void Cell_RecordMange::on_btn_return_clicked()
    {
        //借阅图书
        // 获取当前选中的行号
        int r = ui->tableView->currentIndex().row();
    
        // 判断是否选中行
        if (r < 0) {
            // 弹出错误提示框
            QMessageBox::information(nullptr, "错误", "没有选中图书");
        }
        else
        {
            // 获取选中行的图书ID,text变为QString
            QString id = m_model.item(r, 0)->text();
    
            //执行借阅
            Dlg_book_bor dlg;
    
            //传入bookid
            dlg.setBookID(id.toInt());
            dlg.setType(true);
            int ret = dlg.exec();
    
            // 弹出成功提示框
            QMessageBox::information(nullptr, "信息", ret?"归还成功":"归还失败,账号或者密码错误");
    
            // 刷新页面
            initPage();
        }
    }
    
    • 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
  • 相关阅读:
    浏览器缓存
    web前端 html+css+javascript 绿色的随行旅游网页设计实例 企业网站制作
    linux根文件系统(二)的镜像制作
    【FPGA】通俗理解从VGA显示到HDMI显示
    跨境独立站语言unicode转希伯来语
    机器学习笔记:node2vec(论文笔记:node2vec: Scalable Feature Learning for Networks)
    C++之模板<template>
    upload-labs/Pass-07 未知后缀名解析漏洞复现
    Redis基本命令和常用数据类型
    Linux学习——exec函数族和守护进程
  • 原文地址:https://blog.csdn.net/szn1316159505/article/details/136282919