# bookManager **Repository Path**: Underwood520/book-manager ## Basic Information - **Project Name**: bookManager - **Description**: 大一下Qt图书管理系统 - **Primary Language**: C++ - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 8 - **Forks**: 1 - **Created**: 2021-08-24 - **Last Updated**: 2025-02-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: Qt, C语言 ## README # bookManager ## 一、程序的主要功能 - 图书管理系统能完成收银、图书销售和库存管理。该系统的主要功能: - 能够计算总的销售额和销售税; - 当用户购买一本书后,能够将其从书库中扣除; - 能够对书库进行增加、修改和查找; - 能够显示多种报表; - 采用文件保存数据。所有对书库的操作,例如增删查改,都可以反映在文件中; - 本系统采用了UI界面,允许用户在图形界面进行操作 ## 二、系统总框架图 图 1 总框架图 ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps1.jpg) ## 三、程序各个类的说明 | **自编类名称** | **继承关系** | **作用** | | ------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | collectMoney | 继承自:QMainWindow(QT5的类) | 用来辅助图书销售;用户输入购买图书的数量和编号,计算销售额和销售税,此外从书库中扣除该书 | | libraryManagment | 该类管理书库文件;允许用户对图书进行增删查改 | | | MainWindow | 该类操作菜单界面,通过用户点击进入不同模块 | | | statement | 该类管理六种报表显示 | | | QT自带类QMainWindow:用来进行图形界面的调用 | | | | LB_searchbook | 继承自:QDialog(QT5的类) | 操作文件,在文件中搜索某书,支持模糊查找 | | LB_deletbook; | 操作文件,在文件中搜索某书,支持模糊查找,找到后删除 | | | LB_changetex | 改变税率 | | | LB_modifybook | 操作文件,在文件中搜索某书,支持模糊查找,找到后修改书的信息 | | | LB_addbook | 操作文件,向文件添加某书信息 | | | QT自带类QDialog:用来弹出对话框 | | | | BookData | 父类 | 用来描述每本书的类 | ## 四、模块分析 ### 1. **收银模块** 用户进入该模块后,会显示操作界面: ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps2.jpg) 若需购买书,在“输入书本ISBN”框中输入图书ISBN,点击搜索后,会弹出一个框显示该书信息(在输入书本ISBN:框中输161910204) ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps3.jpg) 弹出的框会提示选择购买数量,在“购买数量”框中输入需要购买的数量; ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps4.jpg) 输入后买数量点击确定,会在右方“消费合计”中显示“销售合计”、“零售税”和“应付总额”,书库中相应书的数量会减少。 完成购买后点击“完成购买”按钮退出该模块。 ***\*收银模块函数介绍:\**** | ***\*函数\**** | ***\*作用\**** | | ------------------------------------------------------------ | ------------------------------------------------------------ | | collectMoney::**collectMoney**(QWidget *parent) : QMainWindow(parent),ui(new Ui::collectMoney) | 构造函数:创建一个UI界面,并初始化界面 | | collectMoney::~***collectMoney\***() | 析构函数:析构UI界面 | | void collectMoney::**on_btn_over_clicked**() | 槽函数:用户点击后调用此函数,关闭UI界面 | | void collectMoney::**on_btn_search_clicked**() | 槽函数:用户输入ISBN号并点击“搜索”按钮后,信号传递至该函数,进行调用,在书库中搜索该书,并显示信息 | ### 2. **书库管理模块** ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps5.jpg) 在总菜单中输入2点击确定,来到“怡园图书管理系统” - 查找某本书的信息 可以输入书名或ISBN号,支持模糊查询 ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps6.jpg) | | 函数 | 功能 | | ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | | | LB_searchbook::**LB_searchbook**(QWidget *parent) : QDialog(parent), ui(new Ui::LB_searchbook) | 构造函数:创建一个UI搜索界面,并初始化界面 | | | LB_searchbook::~***LB_searchbook\***() | 析构函数:析构UI搜索界面 | | | void LB_searchbook::**on_pushButton_clicked**() | 槽函数:用户点击搜索按钮后将输入信息传递至查询函数,并且刷新表格界面 | | | void LB_searchbook::**doQuery**(QString cnt) | 槽函数:在上面的函数调用结束后将用户输入的信息传递至此函数,进行书库查询并显示在表格中 | | | void LB_searchbook::**on_pushButton_2_clicked**() | 槽函数;用户点击退出后调用此函数,关闭界面 | 增加书 ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps7.jpg) 点击确定 ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps8.jpg) | LB_addbook::**LB_addbook**(QWidget *parent) : QDialog(parent), ui(new Ui::LB_addbook) | 构造函数:创建一个UI搜索界面,并初始化界面 | | ------------------------------------------------------------ | ------------------------------------------------------------ | | LB_addbook::~***LB_addbook\***() | 析构函数:析构UI搜索界面 | | bool LB_addbook::**checkTimeWrongOrNot**(QString date) | 输入检查函数:检查输出的信息是否合乎规范 | | void LB_addbook::**on_pushButton_clicked**() | 槽函数:获取用户输入在输入框中的信息,并存储到书库中 | | void LB_addbook::**clearUserInterFace**() | 清空输入框函数:用户如果想输入下一本书,点击确定后,输入框的信息会清除 | | void LB_addbook::**on_pushButton_2_clicked**() | 槽函数:用户点击退出,调用此函数关闭此界面 | - 修改书的信息 ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps9.jpg) | LB_modifybook::**LB_modifybook**(QWidget *parent) : QDialog(parent), | 构造函数:创建一个UI搜索界面,并初始化界面 | | ------------------------------------------------------------ | ---------------------------------------------------------- | | LB_modifybook::~***LB_modifybook\***() | 析构函数:析构UI搜索界面 | | void LB_modifybook::**on_btn_search_clicked**() | 此函数涉及到底层数据的修改,因此在函数结束前要覆盖底层文件 | | void LB_modifybook::**modifyBookInfo**() | 槽函数:用户修改完信息后点击此按钮,进行底层数据修改 | | void LB_modifybook::**on_btn_sure_clicked**() | 槽函数:用户点击退出,调用此函数关闭此界面 | - 删除书 ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps10.jpg) | ***\*函数\**** | ***\*功能\**** | | ------------------------------------------------------------ | ------------------------------------------ | | LB_deletbook::**LB_deletbook**(QWidget *parent) : QDialog(parent), ui(new Ui::LB_deletbook) | 构造函数:创建一个UI搜索界面,并初始化界面 | | LB_deletbook::~***LB_deletbook\***() | 析构函数:析构UI搜索界面 | | void LB_deletbook::**on_pushButton_clicked**() | | | void LB_deletbook::**on_pushButton_2_clicked**() | | - 修改税率 ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps11.jpg) | 函数 | 功能 | | ------------------------------------------------------------ | ---------------------------------------------- | | LB_changetex::**LB_changetex**(QWidget *parent) : QDialog(parent), ui(new Ui::LB_changetex) | 构造函数:创建一个UI搜索界面,并初始化界面 | | LB_changetex::~***LB_changetex\***() | 析构函数:析构UI搜索界面 | | void LB_changetex::**on_pushButton_clicked**() | 槽函数:获取用户输入的新税率 | | void LB_changetex::**on_pushButton_2_clicked**() | 槽函数:用户点击“退出”按钮,调用此函数关闭界面 | ### 3. **报表模块** ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps12.jpg) 下图为按照批发价列表图 ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps13.jpg) | ***\*函数\**** | ***\*功能\**** | | ------------------------------------------------------------ | ---------------------------------------------- | | statement::**statement**(QWidget *parent) : QMainWindow(parent), | 构造函数:创建一个UI搜索界面,并初始化界面 | | statement::~***statement\***() | 析构函数:析构UI搜索界面 | | void statement::**display**(BookData *obj) | 显示函数:将书库信息显示在表格里 | | void statement::**on_btn_none_clicked**() | 槽函数:总列表 | | void statement::**on_btn_sale_clicked**() | 槽函数:按零售价列表 | | void statement::**on_btn_retail_clicked**() | 槽函数:按批发价列表 | | void statement::**on_btn_qty_clicked**() | 槽函数:按库存量列表 | | void statement::**on_btn_wholesale_clicked**() | 槽函数:按批发价总额列表 | | bool statement::**compareDate**(QString day, QString another) | 比较日期函数 | | void statement::**on_btn_time_clicked**() | 槽函数:按日期列表 | | void statement::**on_btn_over_clicked**() | 槽函数:用户点击“退出”按钮,调用此函数关闭界面 | ## 五、**比较有特色的函数** ### **1.时间信息输入检查---可以检查闰年** ```c++ bool LB_addbook::**checkTimeWrongOrNot**(QString date) { QStringList Time = date.split('-'); int check = 0; int wrongDay = 0; if(Time.at(0).size()!= 4){ check = 1;//年份应填四位 ​ wrongDay = 101; } if(Time.at(1).toInt()<=0||Time.at(1).toInt()>=13){ ​ check = 2;//月份在1-12内 ​ wrongDay = 102; } switch (Time.at(1).toInt()) { case 1: ​ if(Time.at(2).toInt()>=32||Time.at(2).toInt()<=0) wrongDay = 1; ​ break; case 2: ​ if((Time.at(0).toInt()%4==0&&Time.at(0).toInt()%100!=0)||(Time.at(0).toInt()%400==0)){ ​ if(Time.at(2).toInt()>=30||Time.at(2).toInt()<=0){ ​ wrongDay = 21;//闰年如果日期超过30天犯第一类错,记做21 ​ } ​ }else{//如果是平年 ​ if(Time.at(2).toInt()>=29||Time.at(2).toInt()<=0) ​ wrongDay = 22;//平年超过28天犯第二类错误,记为22 ​ } ​ break; case 3: ​ if(Time.at(2).toInt()>=32||Time.at(2).toInt()<=0) wrongDay = 3; ​ break; case 4: ​ if(Time.at(2).toInt()>=31||Time.at(2).toInt()<=0) wrongDay = 4; ​ break; case 5: ​ if(Time.at(2).toInt()>=32||Time.at(2).toInt()<=0) wrongDay = 5; ​ break; case 6: ​ if(Time.at(2).toInt()>=31||Time.at(2).toInt()<=0) wrongDay = 6; ​ break; case 7: ​ if(Time.at(2).toInt()>=32||Time.at(2).toInt()<=0) wrongDay = 7; ​ break; case 8: ​ if(Time.at(2).toInt()>=32||Time.at(2).toInt()<=0) wrongDay = 8; ​ break; case 9: ​ if(Time.at(2).toInt()>=31||Time.at(2).toInt()<=0) wrongDay = 9; ​ break; case 10: ​ if(Time.at(2).toInt()>=32||Time.at(2).toInt()<=0) wrongDay = 10; ​ break; case 11: ​ if(Time.at(2).toInt()>=31||Time.at(2).toInt()<=0) wrongDay = 11; ​ break; case 12: ​ if(Time.at(2).toInt()>=32||Time.at(2).toInt()<=0) wrongDay = 12; ​ break; default: ​ break; } // if(isbn.length()>14 || booktitle.length()<0) wrongDay = 50; return wrongDay; } ``` ### **2.删除一本书——用标记为消失取代删除** ```c++ void LB_deletbook::**on_pushButton_clicked**() { QString del_isbn = this->ui->le_delete->text(); int i = 0; int check = 0; for(i = 0;i < 100;i++){ ​ if(del_isbn == dataArray[i].isbn){ ​ QString content = "ISBN:" + dataArray[i].isbn + '\n' + "书名:" + dataArray[i].bookTitle + '\n' + "作者:" + dataArray[i].author + '\n' + "出版社:" + dataArray[i].publisher ​ \+ '\n' + "进书日期:" + dataArray[i].dataAdded + '\n' + "库存量:" + dataArray[i].qtyOnHand + '\n' + "批发价:" + dataArray[i].wholesale + '\n' + "零售价" + dataArray[i].retail; ​ int ans = QMessageBox::question(this,"请确要删除该书吗??",content,"Yes","No"); ​ if(ans == 0){ ​ dataArray[i].removeBook(i);//如果要删除一本书,将它的existOrNot置为false,置为false的数组元素将不能将自己的信息储存到文件中 ​ qDebug()<<"删除"<model->setItem(row,0,new QStandardItem(dataArray[i].isbn)); ​ this->model->setItem(row,1,new QStandardItem(dataArray[i].bookTitle)); ​ this->model->setItem(row,2,new QStandardItem(dataArray[i].author)); ​ this->model->setItem(row,3,new QStandardItem(dataArray[i].publisher)); ​ this->model->setItem(row,4,new QStandardItem(dataArray[i].dataAdded)); ​ this->model->setItem(row,5,new QStandardItem(dataArray[i].qtyOnHand)); ​ this->model->setItem(row,6,new QStandardItem(dataArray[i].wholesale)); ​ this->model->setItem(row,7,new QStandardItem(dataArray[i].retail)); ​ row++; ​ } } } ``` ## 六、**存在的不足与对策** | | 不足 | 对策 | | ------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | 类的构造方面 | 大多数用的是共有成员,私有成员用的较少,导致封装性不够好 | 将对应的数据成员设置为私有成员,编写函数调用私有数据 | | 图形界面方面 | 图形界面使用的是默认配置,因此整体风格比较老旧,此外因为QT语法不够熟练,导致背景图片比较单一 | 继续学习QT,掌握基本操作 | | 窗口显示方面 | 在打开一个窗口的时候之前的父窗口被置于下一层,而不是被子窗口覆盖掉,导致有较多窗口堆积 | 设置窗口调用顺序,比如子窗口打开的时候父窗口会关闭,且如果有父窗口存在,那么将无法对其进行操作。 | | 对象数组方面 | 本程序定义了一个100个长度的对象数组,用来储存从文件中读取的图书信息,因此图书种类如果超过100,本系统将无法正常工作 | 使用可变长数组 | ## 七、**编程体会** 1. 概述:本次图书管理系统的实现耗时较长,断断续续有一个多月。分析其原因,一是没有在编程前制定好每天的计划;二是临时决定使用QT,前半段时间多半用来去学习这门语言;三是对C++的面向对象编程理解不够深入。 2. QT语言:决定用QT的想法来源于厌倦编写黑乎乎的交互界面,然而在实现这个想法的时候遇到了很多困难。比如刚开的软件下载,由于笔记本的管理员用户名使用了中文字符,而QT5要求下载路径里只能是英文字符,导致我不得不搬出了之前的台式机来编写QT;其次,在学习QT的时候没有系统地学习,而是基于项目进行功利化的学习,导致后续在编写的时候要抽出时间去学习这门语言,从而延缓原本的编程计划。 3. C++语言:在编写该图书管理系统时所理解的面向对象还处于“类的初、中级部分”,因此对于构造函数、重载运算符和多态等性质的使用较少,整体程序结构偏向扁平化。 4. 图形界面设计+数据库设计+后端代码:在设计图书管理系统时,我在思考图形界面、数据存储方式和函数调用应该有某种联系,三者在实现之前应该统一约定好规则,不然在将数据从用户那里储存在文件中时会出现很多麻烦。 5. 文件和对象数组:刚开始没有搞清楚既要文件储存又要对象数组是什么意思,这两者在存储数据方面不是重复了吗?在后面的操作中发现,在将数据存储在文件中,与将数据从文件读进来进行增删查改等工作需要一个载体,因此,我明白了对象数组其实是用来中转数据的媒介。在我的代码中这块的逻辑是:菜单界面弹出后会自动调用构造函数,将文件中的数据存储到对象数组中,之后的增删查改等工作都是对数组进行操作,这样就避免了反复打开关闭文件,造成不必要的麻烦。 ## 八、**程序源代码** ![img](file:///C:\Users\22939\AppData\Local\Temp\ksohtml11612\wps14.jpg) | ***\*头文件\**** | ***\*源代码\**** | ***\*UI源代码\**** | | ------------------------------------------ | -------------------------------------------- | -------------------------------------------- | | [collectmoney.h](#_collectmoney.h) | [collectmoney.cpp](#_collectmoney.cpp) | [collectmoney.ui](#_collectmoney.ui) | | [bookdata.h](#_bookdata.h) | [bookdata.cpp](#_bookdata.cpp) | [lb_addbook.ui](#_lb_addbook.ui) | | [lb_addbook.h](#_lb_addbook.h) | [lb_addbook.cpp](#_lb_addbook.h) | [lb_changetex.ui](#_lb_changetex.ui) | | [lb_changetex.h](#_lb_changetex.h_1) | [lb_changetex.cpp](#_lb_changetex.h) | [lb_deletebook.ui](#_lb_deletebook.ui) | | [lb_deletebook.h](#_lb_deletebook.h) | [lb_deletebook.cpp](#_lb_deletebook.cpp) | [lb_modifybook.ui](#_lb_modifybook.ui) | | [lb_modifybook.h](#_lb_modifybook.h) | [lb_modifybook.cpp](#_lb_modifybook.h) | [lb_searchbook.ui](#_lb_searchbook.ui) | | [lb_searchbook.h](#_lb_searchbook.h) | [lb_searchbook.cpp](#_lb_searchbook.h) | [librarymanagment.ui](#_librarymanagment.ui) | | [librarymanagment.h](#_librarymanagment.h) | [librarymanagment.cpp](#_librarymanagment.h) | [mainwindow.ui](#_mainwindow.ui) | | [mainwindow.h](#_mainwindow.h) | [mainwindow.cpp](#_mainwindow.cpp) | [statement.ui](#_statement.ui) | | [statement.h](#_statement.h_1) | [statement.cpp](#_statement.cpp) | | | | [main.cpp](#_main.cpp) | |