往期源码回顾: 【C++】图书管理系统(完整板) 【Python】实现爬虫,爬取天气情况并进行分析(完整版)
图书管理系统功能概览:
效果概览: 登录:输入用户名和密码,选择对应角色(管理员、学生、老师),点击登录,对应信息存储在txt文件中,程序会自动校验是否输入的用户名和密码存在并对应



用户界面(学生或老师):当用户登录成功后,进入操作界面,包括功能如下: 借书:

查看自己借阅情况

还书:

管理员界面: 包括功能如下: 增加书:

查看当前借阅情况:

查看所有图书:

查看借阅人详细信息:

目前该系统大致功能如上。
代码概览:
各个模块主要负责功能
主要用于数据处理、存储部分,类似后端
CBook.h 用于对书抽象,并实现了>>的重载,便于文件读入,读出
CUser.h 工具人,作为老师,学生的父类
CStudent.h 对学生进行的抽象
CTeacher.h 对老师进行的抽象
CAdministrator.h 对管理的抽象
CManagementBooks.h 用户所有的相关操作的中间执行者,有设计模式中代理的思想
QtLibrarySystem.cpp 界面的的实现与系统入口
主要用于数据暂时,处理用户输入,类似前端
RegistrationPage.h 注册界面实现类
UserPage.h用户界面实现类
LoginPage.h登录界面实现类
AdminPage.h管理员界面实现类全部代码与讲解:
CUser.cpp
#include "CUser.h"
#include<iostream>
#include<fstream>
using namespace std;
CUser::CUser()
{
m_name = "陈1";
}
void CUser::setId(string id)
{
m_id = id;
}
void CUser::setName(string name)
{
m_name = name;
}
void CUser::setGender(string gender)
{
m_gender = gender;
}
void CUser::setDepartment(string department)
{
m_department = department;
}
void CUser::setPhone(string phone)
{
m_phone = phone;
}
CUser::~CUser()
{
}
string CUser::returnBook(CManagementBooks& mb,string bookName)
{
int all = mb.checkBorrowedBook(m_id);
if (all == 0)
{
return "您暂未借书,无需归还";
}
else
{
if (mb.checkTrueBorrow(m_id, bookName))
{
mb.Return(m_id, bookName);
return "";
}
else
{
return "您并未借阅此书";
}
}
return "";
}
string CUser::getId()
{
return m_id;
}
string CUser::getName()
{
return m_name;
}
string CUser::getGender()
{
return m_gender;
}
string CUser::getDepartment()
{
return m_department;
}
string CUser::getPhone()
{
return m_phone;
}
std::ostream& operator<<(std::ostream& os, const CUser* user)
{
os << endl << user->m_id << " " << user->m_name << " " << user->m_gender << " " << user->m_department << " " << user->m_phone;
return os;
}
std::istream& operator>>(std::istream& is, CUser* user)
{
is >> user->m_id >> user->m_name >> user->m_gender >> user->m_department >> user->m_phone;
return is;
}CTeacher.cpp
#include "CTeacher.h"
#include<fstream>
CTeacher::CTeacher()
{
m_name = "刘一";
}
string CTeacher::borrowBookFromLibrary(CManagementBooks& mb, string name)
{
int all = mb.checkBorrowedBook(m_id);
if (all < 5)
{
if (mb.borrow(name))
{
ofstream writeFile("borrowedBook.txt", ios::app);
mb.setMapValue(m_id, name);
writeFile << endl << m_id << " " << name;
writeFile.close();
}
}
else
{
return "您已经超过了最大可借阅数";
}
return "";
}
void CTeacher::showInfo()
{
cout << "姓名:" << m_name << " " << "学号:" << m_id << " " << "性别:" << m_gender << " " << "院系:" << m_department << " " << "联系方式:" << m_phone << endl;
}CStudent.cpp
#include "CStudent.h"
#include<fstream>
using namespace std;
CStudent::CStudent()
{
m_class = "软件";
}
void CStudent::showInfo()
{
cout << "姓名:" << m_name << " " << "学号:" << m_id << " " << "性别:" << m_gender << " " << "院系:" << m_department << " " << "班级:" << m_class << " " << "联系方式:" << m_phone << endl;
}
string CStudent::borrowBookFromLibrary(CManagementBooks& mb, string name)
{
int all = mb.checkBorrowedBook(m_id);
if (all < 3)
{
if (mb.borrow(name))
{
ofstream writeFile("borrowedBook.txt", ios::app);
mb.setMapValue(m_id, name);
writeFile << endl << m_id << " " << name;
writeFile.close();
}
else
{
return "此书数量不足或暂无此书";
}
}
else
{
return "您已经超过了最大可借阅数";
}
return "";
}
void CStudent::setClass(string Class)
{
m_class = Class;
}
string CStudent::getClass()
{
return m_class;
}CManagementBooks.cpp
#include "CManagementBooks.h"
#include<algorithm>
using namespace std;
static bool cmp(CBook book1, CBook book2)
{
return book1.getNum() > book2.getNum();
}
void CManagementBooks::showCurrentAllBook()
{
sort(m_books.begin(), m_books.end(), cmp);
for (int i = 0; i < m_allBookNum; i++)
{
cout << "书名:" << m_books[i].getName() << " " << "剩余数量" << m_books[i].getNum() << endl;
}
}
CManagementBooks::CManagementBooks()
{
m_allBookNum = 0;
}
void CManagementBooks::addBook(CBook book)
{
int flag = 0;
for (int i = 0; i < m_allBookNum; i++)
{
if (m_books[i].getName() == book.getName())
{
flag = 1;
m_books[i].setNum(m_books[i].getNum() + book.getNum());
ofstream writeFile("library.txt", ios::out);
for (int i = 0; i < m_allBookNum; i++)
{
writeFile << m_books[i];
}
writeFile.close();
break;
}
}
if (!flag)
{
ofstream writeFile("library.txt", ios::app);
m_books.push_back(book);
m_allBookNum++;
writeFile << book;
writeFile.close();
}
}
int CManagementBooks::getAllBookNum()
{
return m_allBookNum;
}
void CManagementBooks::showAllBooksInfo()
{
sort(m_books.begin(), m_books.end(), cmp);
for (int i = 0; i < m_allBookNum; i++)
{
m_books[i].showInfo();
}
}
bool CManagementBooks::borrow(string name)
{
for (int i = 0; i < m_allBookNum; i++)
{
if (m_books[i].getName() == name)
{
if (m_books[i].getNum() >= 1)
{
m_books[i].setNum(m_books[i].getNum() - 1);
ofstream writeFile("library.txt");
for (int i = 0; i < m_allBookNum; i++)
{
writeFile << m_books[i];
}
writeFile.close();
return true;
}
else
{
return false;
}
}
}
return false;
}
void CManagementBooks::Return(string id, string bookName)
{
CBook book;
book.setName(bookName);
addBook(book);
ofstream writeFile("borrowedBook.txt", ios::out);
for (auto iter = m_outBookMap.begin(); iter != m_outBookMap.end(); ++iter)
{
if (iter->first == id && iter->second == bookName)
{
m_outBookMap.erase(iter);
break;
}
}
for (auto map : m_outBookMap)
{
writeFile << endl << map.first << " " << map.second;
}
writeFile.close();
}
void CManagementBooks::initOutBook()
{
ifstream readFile("borrowedBook.txt");
if (!readFile.is_open())
{
cout << "查看全体借书情况数据读取出错" << endl;
}
else
{
while (!readFile.eof())
{
string studentId, bookName;
readFile >> studentId >> bookName;
m_outBookMap.insert(pair<string, string>(studentId, bookName));
}
}
readFile.close();
}
void CManagementBooks::checekOutBook()
{
for (auto map : m_outBookMap)
{
cout << "借阅人学工号:" << map.first << " " << "借阅书名:" << map.second << endl;
}
}
void CManagementBooks::initBooks()
{
ifstream readFile;
readFile.open("library.txt");
if (!readFile.is_open())
{
cout << "图书数据读取错误" << endl;
readFile.close();
return;
}
while (!readFile.eof())
{
CBook book;
readFile >> book;
m_allBookNum++;
m_books.push_back(book);
}
readFile.close();
}
int CManagementBooks::checkBorrowedBook(string userId)
{
int flag = 0;
for (auto map : m_outBookMap)
{
if (userId == map.first)
{
if (!flag)
{
cout << "您已经借的全部图书如下:" << endl;
flag++;
}
else
{
flag++;
}
cout << map.second << " ";
}
}
if (!flag)
{
cout << "您目前没有借书" << endl;
}
cout << "共:" << flag << "本";
cout << endl;
return flag;
}
vector<userInfo> CManagementBooks::viewBorrowerDetails()
{
ifstream readFile("teacher.txt");
ifstream readFile1("student.txt");
vector<userInfo>users;
if (!readFile1.is_open() || !readFile.is_open())
{
cout << "用户数据读取错误" << endl;
}
while (!readFile1.eof())
{
string act1, name, department, gender,phone;
readFile1 >> act1 >> name >> gender >> department>> phone;
if(act1!="" && name != "")
users.push_back({ act1,name ,gender ,department,"学生",phone});
}
while (!readFile.eof())
{
string act1, name, department, gender, phone;
readFile >> act1 >> name >> gender >> department;
if (act1 != "" && name != "")
users.push_back({ act1,name ,gender ,department,"老师",phone });
}
readFile.close();
readFile1.close();
return users;
}
bool CManagementBooks::checkTrueBorrow(string id, string bookName)
{
for (auto map : m_outBookMap)
{
if (map.first == id && map.second == bookName)
{
return true;
}
}
return false;
}
void CManagementBooks::setMapValue(string userId, string bookName)
{
m_outBookMap.insert(pair<string, string>(userId, bookName));
}
vector<CBook> CManagementBooks::getAllBook()
{
return m_books;
}
unordered_multimap<string, string> CManagementBooks::getOutBookMap()
{
return m_outBookMap;
}CBook.cpp
#include "CBook.h"
#include <iostream>
#include<fstream>
using namespace std;
CBook::CBook()
{
string b = "";
string randStr = "0123456789X";
for (int i = 0; i <= 12; i++)
{
if (i == 1 || i == 5 || i == 11)
{
b += '-';
}
else
{
if (i == 12)
{
b += randStr[rand() % 11];
}
else
{
b += randStr[rand() % 10];
}
}
}
m_num = 1;
m_name = "等待戈多";
m_author = "xx元";
m_isbn = b;
m_page = rand();
m_pressInfo = "xx出版社";
m_price = rand();
}
void CBook::setNum(int num)
{
m_num = num;
}
int CBook::getNum()
{
return m_num;
}
void CBook::setName(string name)
{
m_name = name;
}
string CBook::getName()
{
return m_name;
}
void CBook::setIsbn(string isbn)
{
m_isbn = isbn;
}
string CBook::getIsbn()
{
return m_isbn;
}
void CBook::setPressInfo(string perssInfo)
{
m_pressInfo = perssInfo;
}
string CBook::getPressInfo()
{
return m_pressInfo;
}
void CBook::setPrice(double price)
{
m_price = price;
}
double CBook::getPrice()
{
return m_price;
}
void CBook::setPage(int page)
{
m_page = page;
}
int CBook::getPage()
{
return m_page;
}
void CBook::setAuthor(string author)
{
m_author = author;
}
string CBook::getAuthor()
{
return m_author;
}
void CBook::checkIsnb()
{
int sum = 0;
for (int i = 0, j = 1; i < m_isbn.size(); i++) {
if (m_isbn[i] != '-' && i != 12) {
sum += (m_isbn[i] - '0') * j;
j++;
}
}
sum %= 11;
char c = 'X';
if (sum < 10) c = sum + '0';
if (m_isbn[12] == c) puts("This book isbn are Right!");
else puts("This book isbn are wrong!");
}
bool CBook::isBorrowed()
{
if (m_num >= 1)
{
m_num--;
return true;
}
return false;
}
void CBook::showInfo()
{
cout << "作者:" << m_author << " " << "isbn号码:" << m_isbn << " " << "书本名称:" << m_name << " "
<< "总页数:" << m_page << " " << "出版社:" << m_pressInfo << " " << "价格:" << m_price
<< " " << "剩余本数:" << m_num << endl;
}
std::ostream& operator <<(std::ostream& os, const CBook& book)
{
os << endl << book.m_name << " " << book.m_isbn << " " << book.m_pressInfo << " " << book.m_price << " " << book.m_page << " " << book.m_author << " " << book.m_num;
return os;
}
std::istream& operator>>(std::istream& is, CBook& book)
{
is >> book.m_name >> book.m_isbn >> book.m_pressInfo >> book.m_price >> book.m_page >> book.m_author >> book.m_num;
return is;
}
}userPage.cpp 作为用户日常使用系统的主要交互界面类,UserPage.h 围绕不同用户角色(学生、教师)的个性化需求,提供定制化的功能界面与操作体验。它整合了用户在系统中常用的核心功能,如个人信息查看与编辑、图书借阅查询(包括在借图书、历史借阅记录)、图书预约、续借等操作入口。在界面布局上,采用模块化设计理念,将各功能模块以清晰的分区形式展示,方便用户快速定位与操作。对于学生用户,突出显示借阅规则限制、借阅额度剩余等信息;对于教师用户,则重点展示教学资源推荐、批量借阅管理等特色功能。同时,该类实时监听用户的操作行为,当用户触发某一功能时,UserPage.h 迅速响应,并根据操作类型调用相应的后端业务逻辑(如 CStudent.h 或 CTeacher.h 中对应的功能方法),获取操作结果后及时更新界面展示,确保用户能够实时获取最新信息,实现高效的人机交互,满足用户在图书管理系统中的多样化使用需求。
#include "UserPage.h"
#include <QMessageBox>
#include <QFont>
UserPage::UserPage(QWidget* parent) : QWidget(parent)
{
// 创建主布局
QVBoxLayout* mainLayout = new QVBoxLayout(this);
setWidgetFont(this);
// 创建选项卡部件
tabWidget = new QTabWidget(this);
// 借书选项卡
// 创建显示当前图书列表的QTableWidget
QTableWidget* currentBooksList = new QTableWidget(borrowTab);
currentBooksList->setObjectName("currentBooksList");
setWidgetFont(currentBooksList);
// 创建标签用于说明图书列表
QLabel* currentBooksLabel = createStyledLabel("当前图书列表:");
borrowLayout->addWidget(currentBooksLabel);
borrowLayout->addWidget(currentBooksList);
// 添加书名输入标签和输入框
QLabel* bookNameLabel = createStyledLabel("输入要借的书名:");
borrowLayout->addWidget(bookNameLabel);
borrowLayout->addWidget(bookNameEdit);
borrowLayout->addWidget(borrowButton);
tabWidget->addTab(borrowTab, "借书");
// 查看借书情况选项卡
// 还书选项卡
mainLayout->addWidget(tabWidget);
// 设置编码
codec = QTextCodec::codecForName("GBK");
// 连接借书按钮点击事件
connect(borrowButton, &QPushButton::clicked, this, &UserPage::onBorrowButtonClicked);
// 连接还书按钮点击事件
connect(returnButton, &QPushButton::clicked, this, &UserPage::onReturnButtonClicked);
connect(tabWidget, &QTabWidget::currentChanged, [this](int index) {
if (index == tabWidget->indexOf(borrowedBooksTab)) {
onViewBorrowedBooksClicked();
}
else if (index == tabWidget->indexOf(returnTab)) {
onShowBorrowedBooksForReturnClicked();
}
else if (index == tabWidget->indexOf(borrowTab)) {
onBorrowTabClicked();
}
});
mb.initBooks();
mb.initOutBook();
initCurrentBookList();
}
void UserPage::onBorrowButtonClicked()
{
QString bookName = bookNameEdit->text();
if (bookName.isEmpty())
{
QMessageBox::warning(this,"借书提示","请输入要借的书名");
return;
}
std::string allow = user->borrowBookFromLibrary(mb, codec->fromUnicode(bookName).toStdString());
if (allow != "")
{
QMessageBox::critical(this, "借书失败", codec->toUnicode(allow.c_str()));
return;
}
// 尝试获取当前图书列表部件
QTableWidget* currentBooksList = this->findChild<QTableWidget*>("currentBooksList");
if (currentBooksList)
{
QList<QTableWidgetItem*> foundItems = currentBooksList->findItems(bookName, Qt::MatchExactly);
if (!foundItems.isEmpty())
{
QTableWidgetItem* itemToModify = foundItems.first();
int row = currentBooksList->row(itemToModify);
// 获取当前可借数量并减1
QTableWidgetItem* numItem = currentBooksList->item(row, 6);
int currentNum = numItem->text().toInt();
if (currentNum > 0)
{
currentNum--;
numItem->text() = QString::number(currentNum);
QMessageBox::information(this, "借书成功", "已成功借阅 " + bookName);
// 重新加载图书数据
onBorrowTabClicked();
}
}
}
}
void UserPage::onReturnButtonClicked()
{
QList<QTableWidgetItem*> selectedItems = returnableBooksList->selectedItems();
if (selectedItems.isEmpty())
{
QMessageBox::warning(this, "还书提示", "请选择要归还的书籍");
return;
}
// 使用QSet来避免重复添加书籍ID
QSet<QString> addedBookIds;
QList<QString> bookIds;
for (QTableWidgetItem* item : selectedItems)
{
// 获取该项所在行的索引
int row = returnableBooksList->row(item);
// 获取该行第二列的表格项(索引为1)
QTableWidgetItem* secondColumnItem = returnableBooksList->item(row, 1);
if (secondColumnItem)
{
QString bookId = secondColumnItem->text();
if (!addedBookIds.contains(bookId))
{
bookIds.append(bookId);
addedBookIds.insert(bookId);
}
}
}
// 执行还书操作,假设user有还书相关函数,mb是管理书籍相关数据的对象
std::string result;
for (const QString& bookId : bookIds)
{
// 这里调用还书函数,根据实际情况可能需要调整参数传递方式
result = user->returnBook(mb, codec->fromUnicode(bookId).toStdString());
if (result != "")
{
break;
}
}
if (result == "")
{
// 还书成功,更新界面显示
QMessageBox::information(this, "还书成功", "已成功归还所选书籍");
// 重新加载当前用户借阅的书籍列表,以更新界面显示
onShowBorrowedBooksForReturnClicked();
}
else
{
QMessageBox::warning(this, "还书失败", codec->toUnicode(result.c_str()));
}
}
QLabel* UserPage::createStyledLabel(const QString& text)
{
QLabel* label = new QLabel(text);
setWidgetFont(label);
return label;
}
void UserPage::setWidgetFont(QWidget* widget)
{
QFont font;
font.setFamily("宋体");
font.setPointSize(16);
widget->setFont(font);
}
void UserPage::initCurrentBookList()
{
// 清空之前的显示内容
QTableWidget* currentBooksList = this->findChild<QTableWidget*>("currentBooksList");
currentBooksList->setEditTriggers(QAbstractItemView::NoEditTriggers);
if (currentBooksList)
{
// 设置表格列数和表头
currentBooksList->setColumnCount(7);
QStringList headers;
headers << "作者" << "isbn号码" << "书本名称" << "总页数" << "出版社" << "价格" << "剩余本数";
currentBooksList->setHorizontalHeaderLabels(headers);
// 设置表格字体大小
QFont tableFont;
tableFont.setPointSize(10); // 设置字体大小为12,你可以根据需要调整这个值
currentBooksList->setFont(tableFont);
// 设置表头字体大小
QHeaderView* headerView = currentBooksList->horizontalHeader();
QFont headerFont;
headerFont.setPointSize(10); // 设置字体大小为12,你可以根据需要调整这个值
headerView->setFont(headerFont);
// 添加书籍信息
for (auto& book : mb.getAllBook())
{
int row = currentBooksList->rowCount();
currentBooksList->insertRow(row);
QTableWidgetItem* authorItem = new QTableWidgetItem(codec->toUnicode(book.getAuthor().c_str()));
QTableWidgetItem* isbnItem = new QTableWidgetItem(codec->toUnicode(book.getIsbn().c_str()));
QTableWidgetItem* nameItem = new QTableWidgetItem(codec->toUnicode(book.getName().c_str()));
QTableWidgetItem* pressInfoItem = new QTableWidgetItem(codec->toUnicode(book.getPressInfo().c_str()));
QTableWidgetItem* pagesItem = new QTableWidgetItem((QString::number(book.getPage())));
QTableWidgetItem* priceItem = new QTableWidgetItem((QString::number(book.getPrice())));
QTableWidgetItem* numItem = new QTableWidgetItem(QString::number(book.getNum()));
currentBooksList->setItem(row, 0, authorItem);
currentBooksList->setItem(row, 1, isbnItem);
currentBooksList->setItem(row, 2, nameItem);
currentBooksList->setItem(row, 3, pagesItem);
currentBooksList->setItem(row, 4, pressInfoItem);
currentBooksList->setItem(row, 5, priceItem);
currentBooksList->setItem(row, 6, numItem);
}
}
// 设置列宽,这里的宽度值可以根据实际情况调整
currentBooksList->setColumnWidth(0, 150);
currentBooksList->setColumnWidth(1, 150);
currentBooksList->setColumnWidth(2, 200);
currentBooksList->setColumnWidth(3, 100);
currentBooksList->setColumnWidth(4, 200);
currentBooksList->setColumnWidth(5, 100);
currentBooksList->setColumnWidth(6, 100);
}
void UserPage::onUserUpdated(CUser* user)
{
this->user = user;
}
void UserPage::onViewBorrowedBooksClicked()
{
// 清空之前的显示内容
borrowedBooksList->clearContents();
borrowedBooksList->setRowCount(0);
// 设置表格列数和表头
borrowedBooksList->setColumnCount(2);
borrowedBooksList->setEditTriggers(QAbstractItemView::NoEditTriggers);
QStringList headers;
headers << "借阅者账号" << "借阅图书";
borrowedBooksList->setHorizontalHeaderLabels(headers);
// 获取当前用户的借书信息列表
std::unordered_multimap<string, string> borrowedBooks = mb.getOutBookMap();
// 添加借书信息到表格中
for (const auto& book : borrowedBooks) {
if (book.first != user->getId()) continue;
int row = borrowedBooksList->rowCount();
borrowedBooksList->insertRow(row);
QTableWidgetItem* bookNameItem = new QTableWidgetItem(codec->toUnicode(book.first.c_str()));
QTableWidgetItem* authorItem = new QTableWidgetItem(codec->toUnicode(book.second.c_str()));
borrowedBooksList->setItem(row, 0, bookNameItem);
borrowedBooksList->setItem(row, 1, authorItem);
}
borrowedBooksList->setColumnWidth(0, 500);
borrowedBooksList->setColumnWidth(1, 500);
}
void UserPage::onShowBorrowedBooksForReturnClicked()
{
// 设置选择模式为单选整行
returnableBooksList->setSelectionBehavior(QAbstractItemView::SelectRows);
returnableBooksList->setSelectionMode(QAbstractItemView::SingleSelection);
}
void UserPage::onBorrowTabClicked()
{
// 清空之前的显示内容
}loginPage.cpp 承担着用户身份验证与系统访问控制的关键职责,是用户进入系统的第一道安全屏障。该类通过设计简洁且安全的登录界面,要求用户输入用户名和密码进行登录操作。在界面交互设计上,提供了友好的视觉反馈,如输入框焦点提示、密码显示 / 隐藏切换等功能,提升用户输入的便捷性与准确性。同时,集成了先进的加密算法与安全验证机制,在用户提交登录信息时,对密码进行加密处理,防止信息在传输过程中被窃取。LoginPage.h 将加密后的登录数据传递给后端登录验证模块(如 COperationManagement.h 中的登录功能),由后端模块依据用户数据库进行身份验证。根据验证结果,若成功则将用户引导至对应的用户界面(学生界面、教师界面或管理员界面),并在后台完成用户会话管理与权限初始化;若失败,则在界面上给予清晰明确的错误提示(如用户名或密码错误、账号未激活等),帮助用户快速定位问题并重新尝试登录,有效保障系统的安全性与用户访问的合法性。
#include "LoginPage.h"
LoginPage::LoginPage(QWidget* parent) : QWidget(parent)
{
// 创建用户名输入框
usernameEdit = new QLineEdit(this);
// 创建密码输入框,并设置为密码模式
passwordEdit = new QLineEdit(this);
setWidgetFontAndSize(passwordEdit);
setInputBoxHeight(passwordEdit, 35); // 设置用户名输入框高度
// 创建角色选择下拉框
roleLoginComboBox = new QComboBox(this);
roleLoginComboBox->addItems({ "学生", "老师", "管理员" });
setWidgetFont(roleLoginComboBox);
// 创建登录按钮
loginButton = new QPushButton("登录", this);
setWidgetFont(loginButton);
// 创建注册按钮
registerButton = new QPushButton("注册", this);
setWidgetFont(registerButton);
// 设置布局
QVBoxLayout* mainLayout = new QVBoxLayout(this);
QHBoxLayout* usernameLayout = new QHBoxLayout();
usernameLayout->addWidget(createStyledLabel("用户名:"));
usernameLayout->addWidget(usernameEdit);
mainLayout->addLayout(usernameLayout);
QHBoxLayout* passwordLayout = new QHBoxLayout();
passwordLayout->addWidget(createStyledLabel("密码:"));
passwordLayout->addWidget(passwordEdit);
mainLayout->addLayout(passwordLayout);
QHBoxLayout* roleLoginLayout = new QHBoxLayout();
roleLoginLayout->addWidget(createStyledLabel("角色:"));
roleLoginLayout->addWidget(roleLoginComboBox);
mainLayout->addLayout(roleLoginLayout);
QHBoxLayout* buttonLayout = new QHBoxLayout();
buttonLayout->addWidget(loginButton);
buttonLayout->addWidget(registerButton);
mainLayout->addLayout(buttonLayout);
// 连接按钮点击事件到相应的槽函数
connect(loginButton, &QPushButton::clicked, this, &LoginPage::onLoginButtonClicked);
connect(registerButton, &QPushButton::clicked, this, &LoginPage::onRegisterButtonClicked);
}
void LoginPage::onLoginButtonClicked()
{
QString account = usernameEdit->text();
QString password = passwordEdit->text();
QString role = roleLoginComboBox->currentText();
CUser* user = nullptr;
CAdministrator admin;
if (account.isEmpty() || password.isEmpty())
{
QMessageBox::critical(this, "错误", "用户名或密码不能为空!");
return;
}
std::ifstream readFile;
std::ifstream readFile1;
if (role == "老师")
{
readFile.open("teacherLogin.txt");
readFile1.open("teacher.txt");
user = new CTeacher();
}
else if(role == "学生")
{
readFile1.open("student.txt");
readFile.open("studentLogin.txt");
user = new CStudent();
}
else
{
readFile1.open("admin.txt");
readFile.open("adminLogin.txt");
int flag = 0;
while (!readFile.eof())
{
std::string act;
readFile >> act;
if (act == account.toStdString())
{
std::string pwd;
readFile >> pwd;
if (pwd == password.toStdString())
{
QMessageBox::about(this, "登录成功", "登录成功!");
flag = 1;
while (!readFile1.eof())
{
readFile1 >> admin;
if (admin.getId() == act)
{
emit adminUpdated(admin);
break;
}
}
break;
}
}
}
if (!flag)
{
QMessageBox::critical(this, "错误", "用户名或密码错误!");
return;
}
emit adminLoginSuccess();
readFile.close();
readFile1.close();
return;
}
int flag = 0;
while (!readFile.eof())
{
std::string act;
readFile >> act;
if (act == account.toStdString())
{
std::string pwd;
readFile >> pwd;
if (pwd == password.toStdString())
{
QMessageBox::about(this, "登录成功", "登录成功!");
flag = 1;
while (!readFile1.eof())
{
readFile1 >> user;
if (user != nullptr && user->getId() == act)
{
emit userUpdated(user);
break;
}
}
break;
}
}
}
if (!flag)
{
QMessageBox::critical(this, "错误", "用户名或密码错误!");
return;
}
emit loginSuccess();
readFile.close();
readFile1.close();
}
void LoginPage::onRegisterButtonClicked()
{
emit registerButtonClicked();
}
// 设置输入框宽度的函数
void LoginPage::setInputBoxWidth(QWidget* widget, int width)
{
widget->setFixedWidth(width);
}
// 创建带有指定样式的标签函数
QLabel* LoginPage::createStyledLabel(const QString& text)
{
QLabel* label = new QLabel(text);
setWidgetFont(label);
return label;
}
// 设置输入框字体和大小的函数
void LoginPage::setWidgetFontAndSize(QWidget* widget)
{
QFont font;
font.setFamily("宋体");
font.setPointSize(16);
widget->setFont(font);
}
void LoginPage::setInputBoxHeight(QWidget* widget, int height)
{
widget->setFixedHeight(height);
}
// 设置按钮字体的函数
void LoginPage::setWidgetFont(QWidget* widget)
{
QFont font;
font.setFamily("宋体");
font.setPointSize(16);
widget->setFont(font);
}register.cpp 专注于用户注册流程的界面实现与交互逻辑处理。该类以简洁、易用为设计原则,通过构建直观的注册表单界面,引导用户准确输入注册所需信息,如用户名、密码、邮箱、身份类型(学生 / 教师)等必要字段。在界面设计上,严格遵循人机交互规范,合理布局输入框、提示信息、提交按钮等 UI 元素,提升用户操作的便捷性与舒适度。同时,它内置了强大的输入验证机制,在用户提交注册信息前,对输入内容进行实时校验,包括密码强度检测、邮箱格式验证、用户名唯一性检查等,有效避免无效或非法数据流入系统。当用户完成信息输入并提交后,RegistrationPage.h 将收集到的注册数据进行封装,并通过预先定义的接口将数据传递给后端注册逻辑模块(如 COperationManagement.h 中的注册功能),完成用户账号的创建与数据持久化操作,并根据后端返回的处理结果,在界面上及时给予用户相应的成功或失败提示,保障注册流程的完整性与用户体验的连贯性。
#include "RegistrationPage.h"
#include <QFont>
RegistrationPage::RegistrationPage(QWidget* parent) : QWidget(parent)
{
// 创建用户名输入框
usernameEdit = new QTextEdit(this);
setWidgetFontAndSize(usernameEdit);
setInputBoxHeight(usernameEdit, 35); // 设置用户名输入框高度
// 创建姓名输入框
nameEdit = new QTextEdit(this);
setWidgetFontAndSize(nameEdit);
setInputBoxHeight(nameEdit, 35); // 设置姓名输入框高度
// 创建部门输入框
departmentEdit = new QTextEdit(this);
setWidgetFontAndSize(departmentEdit);
setInputBoxHeight(departmentEdit, 35); // 设置部门输入框高度
// 创建电话输入框
phoneEdit = new QTextEdit(this);
setWidgetFontAndSize(phoneEdit);
setInputBoxHeight(phoneEdit, 35); // 设置电话输入框高度
// 创建密码输入框,并设置为密码模式
passwordEdit = new QTextEdit(this);
setWidgetFontAndSize(passwordEdit);
setInputBoxHeight(passwordEdit, 35); // 设置密码输入框高度
// 创建性别选择下拉框
genderComboBox = new QComboBox(this);
genderComboBox->addItems({ "男", "女" });
setWidgetFont(genderComboBox);
// 创建角色选择下拉框
roleLoginComboBox = new QComboBox(this);
roleLoginComboBox->addItems({ "学生", "老师", "管理员" });
setWidgetFont(roleLoginComboBox);
// 创建注册按钮
registerButton = new QPushButton("注册", this);
setWidgetFont(registerButton);
// 创建登录按钮
loginButton = new QPushButton("登录", this);
setWidgetFont(loginButton);
// 连接注册按钮的点击事件到槽函数
connect(registerButton, &QPushButton::clicked, this, &RegistrationPage::onRegisterButtonClicked);
connect(loginButton, &QPushButton::clicked, this, &RegistrationPage::onLoginButtonClicked); // 连接登录按钮点击事件
}
void RegistrationPage::onRegisterButtonClicked()
{
QString act = usernameEdit->toPlainText();
QString name = nameEdit->toPlainText();
QString department = departmentEdit->toPlainText();
QString phone = phoneEdit->toPlainText();
QString pwd = passwordEdit->toPlainText();
QString gender = genderComboBox->currentText();
QString role = roleLoginComboBox->currentText();
if (act == "" || name == "" || department == "" || phone == "")
{
QMessageBox::critical(this, "错误", "请将信息补充完整!");
return;
}
if (role == "管理员")
{
QMessageBox::critical(this, "错误", "管理员无法注册!");
return;
}
std::ofstream writeFile;
std::ofstream writeFile1;
if (role == "老师")
{
writeFile1.open("teacher.txt", std::ios::app);
writeFile.open("teacherLogin.txt", std::ios::app);
}
else
{
writeFile1.open("student.txt", std::ios::app);
writeFile.open("studentLogin.txt", std::ios::app);
}
writeFile << std::endl << act.toStdString() << " " << pwd.toStdString();
writeFile1 << std::endl << act.toStdString() << " " << name.toStdString() << " " << gender.toStdString() << " " << department.toStdString() << " " << phone.toStdString();
writeFile.close();
writeFile1.close();
QMessageBox::about(this, "注册成功", "快去登录系统吧");
// 发射注册成功信号
emit registrationSuccess();
}
void RegistrationPage::onLoginButtonClicked()
{
}
// 设置控件字体和字号的函数
void RegistrationPage::setWidgetFont(QWidget* widget)
{
QFont font;
font.setFamily("宋体");
font.setPointSize(16);
widget->setFont(font);
}
// 设置输入框宽度的函数
void RegistrationPage::setInputBoxWidth(QWidget* widget, int width)
{
widget->setFixedWidth(width);
}
// 创建带有指定样式的标签函数
QLabel* RegistrationPage::createStyledLabel(const QString& text)
{
QLabel* label = new QLabel(text);
setWidgetFont(label);
return label;
}
// 设置输入框字体和大小的函数
void RegistrationPage::setWidgetFontAndSize(QWidget* widget)
{
QFont font;
font.setFamily("宋体");
font.setPointSize(16);
widget->setFont(font);
}
void RegistrationPage::setInputBoxHeight(QWidget* widget, int height)
{
widget->setFixedHeight(height);
}