完成查询功能的“使用学/工号查询”和“查询卡的所有记录”功能;还未完成卡内记录查询

This commit is contained in:
Jingfan Ke 2024-07-31 10:31:58 +08:00
parent f06ce5828c
commit 63fc2d966c
7 changed files with 681 additions and 7 deletions

View File

@ -18,6 +18,7 @@ SOURCES += \
main.cpp \ main.cpp \
mainwindow.cpp \ mainwindow.cpp \
newCardPage.cpp \ newCardPage.cpp \
queryPage.cpp \
quitAppPage.cpp \ quitAppPage.cpp \
readerAPI.cpp \ readerAPI.cpp \
reportLossPage.cpp \ reportLossPage.cpp \

View File

@ -7,6 +7,7 @@
#include "reportLossPage.cpp" #include "reportLossPage.cpp"
#include "depositPage.cpp" #include "depositPage.cpp"
#include "consumePage.cpp" #include "consumePage.cpp"
#include "queryPage.cpp"
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
@ -53,6 +54,35 @@ MainWindow::MainWindow(QWidget *parent)
connect(ui->depositUserIdBox, &QSpinBox::valueChanged, [this]{ depositUserIdFilled = true; }); connect(ui->depositUserIdBox, &QSpinBox::valueChanged, [this]{ depositUserIdFilled = true; });
connect(ui->queryUserIdBox, &QSpinBox::valueChanged, [this]{ queryUserIdFilled = true; });
// 查询表格设置
ui->queryResultTable->setShowGrid(true); //设置显示格子线
ui->queryResultTable->setSelectionBehavior(QAbstractItemView::SelectRows); //整行选中
ui->queryResultTable->setEditTriggers(QAbstractItemView::NoEditTriggers); //禁止编辑
ui->queryResultTable->horizontalHeader()->setStretchLastSection(true); //行头自适应表格
ui->queryResultTable->horizontalHeader()->setHighlightSections(false); //点击表头时不对表头光亮
ui->queryResultTable->setSortingEnabled(true); //启动排序
// 设置表头字体加粗
QFont queryResultTableFont = ui->queryResultTable->horizontalHeader()->font();
queryResultTableFont.setBold(true);
ui->queryResultTable->horizontalHeader()->setFont(queryResultTableFont);
// 设置表头内容
QStringList queryResultTableHeader;
queryResultTableHeader << "时间" << "类型" << "金额" << "余额" << "设备" << "交易号";
ui->queryResultTable->setColumnCount(queryResultTableHeader.size()); //设置列数
ui->queryResultTable->setHorizontalHeaderLabels(queryResultTableHeader);
ui->queryResultTable->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter); // 每列居中对齐
ui->queryResultTable->setColumnWidth(0, 130);
ui->queryResultTable->setColumnWidth(1, 40);
ui->queryResultTable->setColumnWidth(2, 60);
ui->queryResultTable->setColumnWidth(3, 80);
ui->queryResultTable->setColumnWidth(4, 100);
ui->queryResultTable->setColumnWidth(5, 240);
// 设置启动页面 // 设置启动页面
ui->stackedWidget->setCurrentWidget(ui->settingPage); ui->stackedWidget->setCurrentWidget(ui->settingPage);

View File

@ -11,6 +11,9 @@
#include <QDateTime> #include <QDateTime>
#include <QRandomGenerator> #include <QRandomGenerator>
#include <vector>
#include <set>
#include <readerAPI.h> #include <readerAPI.h>
#include <databaseAPI.h> #include <databaseAPI.h>
#include <deviceAPI.h> #include <deviceAPI.h>
@ -32,6 +35,7 @@ public:
void updateStatusBarComNumber(); void updateStatusBarComNumber();
bool allReady(); bool allReady();
bool softwareReady(); bool softwareReady();
bool databaseReady();
bool bindUserWithCard(int userId, QString cardId, QString &info); bool bindUserWithCard(int userId, QString cardId, QString &info);
bool getNewUserInfo(QString &username, QString &password, QString &info); bool getNewUserInfo(QString &username, QString &password, QString &info);
bool createUser(int userId, QString &info); bool createUser(int userId, QString &info);
@ -41,6 +45,9 @@ public:
bool topUpCard(QString cardId, double topUpValue, double &originalBalance, double &finalBalance, QString &recordId, QString &info); bool topUpCard(QString cardId, double topUpValue, double &originalBalance, double &finalBalance, QString &recordId, QString &info);
QString getRecordId(QDateTime currentTime, int userId, int recordType); QString getRecordId(QDateTime currentTime, int userId, int recordType);
bool deductCard(QString cardId, double deductValue, double &originalBalance, double &finalBalance, QString &recordId, QString &info); bool deductCard(QString cardId, double deductValue, double &originalBalance, double &finalBalance, QString &recordId, QString &info);
void displayInTableWidget(std::vector<QStringList> transactionRecordList);
QStringList transactionRecord2QStringList(QDateTime time, int type, double value, double balance, QString device, QString id);
void queryPageInitContent();
private slots: private slots:
void on_settingAction_triggered(); void on_settingAction_triggered();
@ -49,6 +56,7 @@ private slots:
void on_reportLossAction_triggered(); void on_reportLossAction_triggered();
void on_depositAction_triggered(); void on_depositAction_triggered();
void on_ConsumptionAction_triggered(); void on_ConsumptionAction_triggered();
void on_QueryAction_triggered();
void on_connectReaderButton_clicked(); void on_connectReaderButton_clicked();
void on_confirmQuitButton_clicked(); void on_confirmQuitButton_clicked();
@ -61,6 +69,9 @@ private slots:
void on_depositByUserIdButton_clicked(); void on_depositByUserIdButton_clicked();
void on_consumeInventoryButton_clicked(); void on_consumeInventoryButton_clicked();
void on_consumeButton_clicked(); void on_consumeButton_clicked();
void on_queryInventoryButton_clicked();
void on_userRecordQueryButton_clicked();
void on_userIdRecordQueryButton_clicked();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
@ -80,5 +91,7 @@ private:
bool newCardUserIdFilled; ///< 开卡时:初始时学/工号填写框被清空该变量为false当用户填写后该变量为true bool newCardUserIdFilled; ///< 开卡时:初始时学/工号填写框被清空该变量为false当用户填写后该变量为true
bool reportLossUserIdFilled; ///< 挂失时:初始时学/工号填写框被清空该变量为false当用户填写后该变量为true bool reportLossUserIdFilled; ///< 挂失时:初始时学/工号填写框被清空该变量为false当用户填写后该变量为true
bool depositUserIdFilled; ///< 充值时:初始时学/工号填写框被清空该变量为false当用户填写后该变量为true bool depositUserIdFilled; ///< 充值时:初始时学/工号填写框被清空该变量为false当用户填写后该变量为true
bool queryUserIdFilled; ///< 查询时:初始时学/工号填写框被清空该变量为false当用户填写后该变量为true
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>708</width> <width>709</width>
<height>493</height> <height>514</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -17,8 +17,8 @@
<widget class="QStackedWidget" name="stackedWidget"> <widget class="QStackedWidget" name="stackedWidget">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>-50</x> <x>-40</x>
<y>-40</y> <y>0</y>
<width>701</width> <width>701</width>
<height>481</height> <height>481</height>
</rect> </rect>
@ -27,7 +27,7 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>3</number>
</property> </property>
<widget class="QWidget" name="quitAppPage"> <widget class="QWidget" name="quitAppPage">
<widget class="QPushButton" name="confirmQuitButton"> <widget class="QPushButton" name="confirmQuitButton">
@ -416,6 +416,243 @@
</property> </property>
</widget> </widget>
</widget> </widget>
<widget class="QWidget" name="queryPage">
<widget class="QTableWidget" name="queryResultTable">
<property name="geometry">
<rect>
<x>60</x>
<y>160</y>
<width>591</width>
<height>311</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="cardRecordQueryButton">
<property name="geometry">
<rect>
<x>420</x>
<y>130</y>
<width>91</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>查询卡内记录</string>
</property>
</widget>
<widget class="QPushButton" name="userRecordQueryButton">
<property name="geometry">
<rect>
<x>520</x>
<y>130</y>
<width>91</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>查询所有记录</string>
</property>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget_5">
<property name="geometry">
<rect>
<x>60</x>
<y>120</y>
<width>354</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>请选择卡:</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="queryCardIdBox">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="queryInventoryButton">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>读卡</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>60</x>
<y>80</y>
<width>350</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="label_14">
<property name="text">
<string>请输入学/工号:</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="queryUserIdBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="minimum">
<number>1000</number>
</property>
<property name="maximum">
<number>99999999</number>
</property>
<property name="value">
<number>21281280</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="userIdRecordQueryButton">
<property name="text">
<string>查询学/工号记录</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="gridLayoutWidget_2">
<property name="geometry">
<rect>
<x>440</x>
<y>20</y>
<width>211</width>
<height>104</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>卡状态</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>余额</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="queryCardStatusLabel">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="queryBalanceShowEdit">
<property name="minimumSize">
<size>
<width>150</width>
<height>60</height>
</size>
</property>
<property name="font">
<font>
<pointsize>20</pointsize>
<bold>true</bold>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QLabel" name="label_17">
<property name="geometry">
<rect>
<x>170</x>
<y>30</y>
<width>111</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string>查询交易记录</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</widget>
<widget class="QWidget" name="newCardPage"> <widget class="QWidget" name="newCardPage">
<widget class="QWidget" name="gridLayoutWidget"> <widget class="QWidget" name="gridLayoutWidget">
<property name="geometry"> <property name="geometry">

View File

@ -433,7 +433,7 @@ bool MainWindow::verifyUser(int userId, QString prompt, QString &info)
QString validPassword = query.value(0).toString(); QString validPassword = query.value(0).toString();
if (validPassword != password) if (validPassword != password)
{ {
info = QString("密码不正确"); info = QString("密码不正确");
return false; return false;
} }
else else
@ -443,7 +443,7 @@ bool MainWindow::verifyUser(int userId, QString prompt, QString &info)
} }
else else
{ {
info = QString("学/工号不存在"); info = QString("学/工号不存在");
return false; return false;
} }
} }

377
queryPage.cpp Normal file
View File

@ -0,0 +1,377 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
/**
* @brief
*
* @param void
* @return void
* @author
* @date 2024-07-31
*/
void MainWindow::on_QueryAction_triggered()
{
queryPageInitContent();
ui->stackedWidget->setCurrentWidget(ui->queryPage);
}
/**
* @brief
*
*
* Inventory的查询结果10
* @param void
* @return void
* @author
* @date 2024-07-31
*/
void MainWindow::on_queryInventoryButton_clicked()
{
if (!reader.is_connected())
{
QMessageBox::warning(this, QString("提示"), QString("读卡器未连接,请设置。"));
if (ui->stackedWidget->currentWidget() != ui->settingPage)
{
ui->stackedWidget->setCurrentWidget(ui->settingPage);
}
return;
}
QStringList cardIdList = reader.inventory(10); // 最多显示10张卡
ui->queryCardIdBox->clear();
if (cardIdList.empty())
{
QMessageBox::warning(this, "提示", "未发现卡片,请将卡片放置于读卡器上方。");
}
else
{
ui->queryCardIdBox->addItems(cardIdList);
}
}
/**
* @brief
* ID查询该卡片的所有交易记录
* @param void
* @return void
* @details
*
*
* ID
*
* `QStringList`
* @author
* @date 2024-07-31
*/
void MainWindow::on_userRecordQueryButton_clicked()
{
if (!databaseReady())
{
QMessageBox::warning(this, QString("提示"), QString("数据库未连接,请设置。"));
if (ui->stackedWidget->currentWidget() != ui->settingPage)
{
ui->stackedWidget->setCurrentWidget(ui->settingPage);
}
return;
}
if (ui->queryCardIdBox->currentIndex() == -1)
{
QMessageBox::warning(this, "提示", "请放置卡片并点击查询按钮。");
return;
}
QString cardId = ui->queryCardIdBox->currentText();
int userId;
int cardStatus;
double balance;
// 检查和获取绑定用户
QSqlQuery query(db->getDatabase());
query.prepare(QString("select userId, `status`, balance from card "
"where id = :cardId;"));
query.bindValue(":cardId", cardId);
bool success = false;
success = query.exec();
if (!success)
{
QMessageBox::warning(this, QString("提示"), QString("数据库异常。查询失败。"));
queryPageInitContent();
return;
}
if (query.next()) // 卡已被注册获取用户ID
{
cardStatus = query.value("status").toInt();
if (cardStatus == 0)
{
QMessageBox::warning(this, QString("提示"), QString("此卡未被启用。"));
queryPageInitContent();
return;
}
if (cardStatus == -1)
{
ui->queryCardStatusLabel->setText(QString("已被挂失"));
}
userId = query.value("userId").toInt();
balance = query.value("balance").toDouble();
ui->queryBalanceShowEdit->setText(QString::number(balance, 'f', 2));
}
else // 卡没有注册
{
query.finish();
query.prepare(QString("insert into card "
"values (:cardId, 0, 0.0, null);"));
query.bindValue(":cardId", cardId);
success = query.exec();
if (!success)
{
QMessageBox::warning(this, QString("提示"), QString("数据库异常。查询失败。"));
queryPageInitContent();
return;
}
QMessageBox::warning(this, QString("提示"), QString("此卡未被启用。"));
queryPageInitContent();
return;
}
QString prompt = "查询用户所有交易记录需要验证用户身份。";
QString info;
success = verifyUser(userId, prompt, info);
if (!success)
{
QMessageBox::warning(this, "提示", info + QString("\n用户验证不通过。查询失败。"));
queryPageInitContent();
return;
}
query.finish();
query.prepare(QString("select time, type, value, balance, device, id from record_view "
"where cardId = :cardId;"));
query.bindValue(":cardId", cardId);
success = query.exec();
if (!success)
{
QMessageBox::warning(this, QString("提示"), QString("数据库异常。查询失败。"));
queryPageInitContent();
return;
}
std::vector<QStringList> transactionRecordList;
while (query.next())
{
QStringList transactionRecord = transactionRecord2QStringList
(
query.value("time").toDateTime(),
query.value("type").toInt(),
query.value("value").toDouble(),
query.value("balance").toDouble(),
query.value("device").toString(),
query.value("id").toString()
);
transactionRecordList.push_back(transactionRecord);
}
displayInTableWidget(transactionRecordList);
}
/**
* @brief /
* /
* @param void
* @return void
* @details
*
* //
*
* /ID
* `QStringList`
* @author
* @date 2024-07-31
*/
void MainWindow::on_userIdRecordQueryButton_clicked()
{
if (!softwareReady())
{
QMessageBox::warning(this, QString("提示"), QString("数据库未连接,请设置。"));
if (ui->stackedWidget->currentWidget() != ui->settingPage)
{
ui->stackedWidget->setCurrentWidget(ui->settingPage);
}
return;
}
if (!queryUserIdFilled)
{
QMessageBox::warning(this, "提示", "请填写学/工号。");
return;
}
int userId = ui->queryUserIdBox->value();
bool success = false;
QString prompt = "查询用户所有交易记录需要验证用户身份。";
QString info;
success = verifyUser(userId, prompt, info); // 内部会检查用户是否存在
if (!success)
{
QMessageBox::warning(this, "提示", info + QString("\n查询失败。"));
queryPageInitContent();
return;
}
QSqlQuery query(db->getDatabase());
query.prepare(QString("select id, `status`, balance from card "
"where userId = :userId;"));
query.bindValue(":userId", userId);
success = query.exec();
if (!success)
{
QMessageBox::warning(this, "提示", "数据库异常。查询失败。");
queryPageInitContent();
return;
}
if (!query.next())
{
QMessageBox::warning(this, "提示", "学/工号未绑定卡。查询失败。");
queryPageInitContent();
return;
}
QString cardId = query.value("id").toString();
int cardStatus = query.value("status").toInt();
double balance = query.value("balance").toDouble();
ui->queryBalanceShowEdit->setText(QString::number(balance, 'f', 2));
if (cardStatus == -1)
{
ui->queryCardStatusLabel->setText(QString("已被挂失"));
}
else if (cardStatus == 1)
{
ui->queryCardStatusLabel->setText(QString("启用中"));
}
query.finish();
query.prepare(QString("select time, type, value, balance, device, id from record_view "
"where cardId = :cardId;"));
query.bindValue(":cardId", cardId);
success = query.exec();
if (!success)
{
QMessageBox::warning(this, QString("提示"), QString("数据库异常。查询失败。"));
queryPageInitContent();
return;
}
std::vector<QStringList> transactionRecordList;
while (query.next())
{
QStringList transactionRecord = transactionRecord2QStringList
(
query.value("time").toDateTime(),
query.value("type").toInt(),
query.value("value").toDouble(),
query.value("balance").toDouble(),
query.value("device").toString(),
query.value("id").toString()
);
transactionRecordList.push_back(transactionRecord);
}
displayInTableWidget(transactionRecordList);
}
/**
* @brief QStringList
* `QStringList`便
* @param time QDateTime
* @param type
* @param value double
* @param balance double
* @param device QString
* @param id QString
* @return QStringList
* @details
* QStringList
* QString表示
* @author
* @date 2024-07-31
*/
QStringList MainWindow::transactionRecord2QStringList(QDateTime time, int type, double value, double balance, QString device, QString id)
{
QStringList stringList = {
time.toString("yyyy-MM-dd hh:mm:ss"),
type != 0 ? QString("充值") : QString("消费"),
QString::number((type != 0 ? value : -value), 'f', 2),
QString::number(balance, 'f', 2),
device,
id
};
return stringList;
}
/**
* @brief
* ID输入框
* @param void
* @return void
* @details
* queryUserIdFilled falseID
* ID输入框"-"
* @author
* @date 2024-07-31
*/
void MainWindow::queryPageInitContent()
{
queryUserIdFilled = false;
ui->queryUserIdBox->clear();
ui->queryResultTable->clearContents();
ui->queryBalanceShowEdit->clear();
ui->queryCardStatusLabel->setText(QString("-"));
}
/**
* @brief
* `QTableWidget`
* @param transactionRecordList `QStringList` `QStringList`
* @return void
* @details
* `QTableWidget` `transactionRecordList`
* `QTableWidget` 绿
*
* @author
* @date 2024-07-31
*/
void MainWindow::displayInTableWidget(std::vector<QStringList> transactionRecordList)
{
ui->queryResultTable->clearContents();
int numRows = transactionRecordList.size();
ui->queryResultTable->setRowCount(numRows);
for (int i = 0; i < numRows; i++)
{
QStringList transactionRecord = transactionRecordList[i];
bool is_deposit = transactionRecord[1] == QString("充值");
for (int j = 0; j < 6; j++)
{
QTableWidgetItem *item = new QTableWidgetItem(transactionRecord[j]);
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); // 设置右对齐
// 渲染:充值为绿色,消费为红色(不知为何不工作)
if (is_deposit)
item->setForeground(QBrush(QColor(Qt::green)));
else
item->setForeground(QBrush(QColor(Qt::red)));
ui->queryResultTable->setItem(i, j, item); // 设置内容
}
}
}

View File

@ -137,3 +137,19 @@ bool MainWindow::softwareReady()
if (!device.is_verified()) return false; if (!device.is_verified()) return false;
return true; return true;
} }
/**
* @brief
* @param void
* @return
* - true
* - false
* @author
* @date 2024-07-31
*/
bool MainWindow::databaseReady()
{
if (db == nullptr || !db->is_connected()) return false;
return true;
}