完成了开卡部分(除了硬件部分)。

This commit is contained in:
Jingfan Ke 2024-07-30 02:13:05 +08:00
parent 26f9ff604e
commit ad40ab7ecd
7 changed files with 558 additions and 10 deletions

View File

@ -43,13 +43,15 @@ bool Device::is_depositAllowed()
void Device::setDevice(QString name, Database* db)
{
QSqlQuery query(db->getDatabase());
QString sql = QString("select * from device where `name` = '%1';").arg(name);
query.exec(sql);
query.prepare(QString("select depositAllowed from device "
"where name = :name;"));
query.bindValue(":name", name);
query.exec();
if (query.next())
{
verified = true;
this->name = name;
depositAllowed = query.value(2).toBool();
depositAllowed = query.value(0).toBool();
}
else
{
@ -70,7 +72,7 @@ void Device::setDevice(QString name, Database* db)
* @author
* @date 2024-07-28
*/
QString Device::getName()
QString Device::getNameAndDepositAllowed()
{
if (verified) {
if (depositAllowed) return name + QString("(可充值)");
@ -78,3 +80,19 @@ QString Device::getName()
}
else return QString("未指定设备名");
}
/**
* @brief
* @param void
* @return QString类name属性
* - "未指定设备名"
* -
* @author
* @date 2024-07-29
*/
QString Device::getName()
{
if (verified) return name;
else return QString("未指定设备名");
}

View File

@ -24,6 +24,7 @@ public:
void setDevice(QString name, Database *db);
QString getName();
QString getNameAndDepositAllowed();
bool is_verified();
bool is_depositAllowed();

View File

@ -35,12 +35,14 @@ MainWindow::MainWindow(QWidget *parent)
databaseLabel = new QLabel("数据库无连接");
ui->statusBar->addWidget(databaseLabel);
deviceLabel = new QLabel(device.getName());
deviceLabel = new QLabel(device.getNameAndDepositAllowed());
ui->statusBar->addWidget(deviceLabel);
// 清空部分输入框
ui->userIdBox->clear();
userIdFilled = false;
connect(ui->userIdBox, &QSpinBox::valueChanged, [this]{ userIdFilled = true; });
// 设置启动页面
@ -52,4 +54,3 @@ MainWindow::~MainWindow()
{
delete ui;
}

View File

@ -7,6 +7,7 @@
#include <QStackedWidget>
#include <QMessageBox>
#include <QSqlQuery>
#include <QInputDialog>
#include <readerAPI.h>
#include <databaseAPI.h>
@ -28,6 +29,12 @@ public:
void updateStatusBarComNumber();
bool ready();
bool bindUserWithCard(int userId, QString cardId, QString &info);
bool getNewUserInfo(QString &username, QString &password, QString &info);
bool createUser(int userId, QString &info);
bool verifyUser(int userId, QString prompt, QString &info);
bool transferCard(int userId, QString newCardId, QString oldCardId, QString &info);
bool reopenCard(QString cardId, QString &info);
private slots:
void on_settingAction_triggered();
@ -38,6 +45,7 @@ private slots:
void on_confirmQuitButton_clicked();
void on_connectDatabaseButton_clicked();
void on_inventoryButton_clicked();
void on_newCardButton_clicked();
private:
Ui::MainWindow *ui;
@ -53,5 +61,7 @@ private:
QCheckBox *databaseConnectStatusCheckBox;
QLabel *databaseLabel;
QLabel *deviceLabel;
bool userIdFilled; ///< 初始时学/工号填写框被清空该变量为false当用户填写后该变量为true
};
#endif // MAINWINDOW_H

View File

@ -296,6 +296,9 @@
<property name="maximum">
<number>99999999</number>
</property>
<property name="value">
<number>21281280</number>
</property>
</widget>
</item>
<item row="0" column="1">
@ -337,7 +340,7 @@
</item>
</layout>
</widget>
<widget class="QPushButton" name="pushButton">
<widget class="QPushButton" name="newCardButton">
<property name="geometry">
<rect>
<x>300</x>

View File

@ -40,5 +40,520 @@ void MainWindow::on_inventoryButton_clicked()
{
QStringList cardIdList = reader.inventory(10); // 最多显示10张卡
ui->cardIdBox->clear();
ui->cardIdBox->addItems(cardIdList);
if (cardIdList.empty())
{
QMessageBox::warning(this, "查询卡结果", "未发现卡片,请将卡片放置于读卡器上方。");
}
else
{
ui->cardIdBox->addItems(cardIdList);
}
}
/**
* @brief
*
* ID
*
* @details
* ID和填写的用户ID
* ID退
*
* -
* -
* -
*
*
* @param void
* @return void
* @author
* @date 2024-07-29
*/
void MainWindow::on_newCardButton_clicked()
{
if (ui->cardIdBox->currentIndex() == -1)
{
QMessageBox::warning(this, "提示", "请放置卡片并点击查询按钮。");
return;
}
if (!userIdFilled)
{
QMessageBox::warning(this, "提示", "请填写学/工号。");
return;
}
QString cardIdSelected = ui->cardIdBox->currentText();
int userId = ui->userIdBox->value();
// 查询卡片能否使用
QSqlQuery query(db->getDatabase());
query.finish();
query.prepare(QString("select `status`, userId from card "
"where id = :cardId;"));
query.bindValue(":cardId", cardIdSelected);
bool success = query.exec();
if (!success)
{
qDebug() << "select `status`, userId from card where id = :cardId;1";
QMessageBox::warning(this, "提示", QString("数据库异常。开卡失败,请重试。"));
return;
}
int cardStatus; ///< 0未启用1已启用-1已挂失
if (query.next())
{
cardStatus = query.value("status").toInt();
if (cardStatus == 1) // 已被启用,不能开卡
{
QMessageBox::warning(this, "卡状态提示", "本卡已被启用,开卡失败。");
return;
}
if (cardStatus == -1) // 已被挂失,需要密码重开
{
// 弹出验证用户界面,要求用户输入密码(注意这里需要查询数据库得到挂失卡的用户)
int cardUserId = query.value("userId").toInt();
query.finish();
query.prepare("select `name` from `user` "
"where id = :userId");
query.bindValue(":userId", cardUserId);
bool success = query.exec();
if (!success || !query.next())
{
QMessageBox::warning(this, "提示", QString("数据库异常。\n重开卡失败,请重试。"));
return;
}
QString cardUserName = query.value("name").toString();
QString prompt = QString("本卡关联的学/工号为") + QString::number(cardUserId);
prompt += QString(",关联的姓名为") + cardUserName + QString("\n");
prompt += QString("如需重开本卡,请输入密码。");
QString info;
success = verifyUser(cardUserId, prompt, info);
if (!success)
{
QMessageBox::warning(this, "提示", info + QString("\n验证用户失败,请重试。"));
return;
}
success = reopenCard(cardIdSelected, info);
if (!success)
{
QMessageBox::warning(this, "提示", info + QString("\n重开卡失败,请重试。"));
return;
}
return;
}
}
else // 该卡不在数据库中,将该卡在数据库中初始化,设置为未启用
{
query.finish();
query.prepare("insert into card "
"values (:cardId, 0, 0.00, null);");
query.bindValue(":cardId", cardIdSelected);
query.exec();
}
// 检查是否是新用户
query.finish();
query.prepare("select 1 from `user` "
"where id = :userId;");
query.bindValue(":userId", userId);
success = query.exec();
if (!success)
{
qDebug() << "select 1 from `user` where id = :userId;";
QMessageBox::warning(this, "提示", QString("数据库异常。开卡失败,请重试。"));
return;
}
if (!query.next()) // 库中无用户记录,将新用户插入数据库并开卡
{
QString info;
bool success = createUser(userId, info); // 将新用户插入数据库
if (!success)
{
QMessageBox::warning(this, "提示", info + QString("\n注册失败,请重新开卡。"));
return;
}
success = bindUserWithCard(userId, cardIdSelected, info); // 将新用户和卡绑定(卡在读取时已写入数据库)
if (!success)
{
QMessageBox::warning(this, "提示", info + QString("\n注册失败,请重新开卡。"));
return;
}
QMessageBox::information(this, "提示", "新用户开卡成功。");
return;
}
else // 库中有用户记录
{
// 检查用户是否有卡,不可开卡/有挂失卡,是否需要移资
query.finish();
query.prepare("select `status`, id from card "
"where userId = :userId;");
query.bindValue(":userId", userId);
bool success = query.exec();
if (!success)
{
qDebug() << "select `status`, id from card where userId = :userId;2";
QMessageBox::warning(this, "提示", QString("数据库异常。开卡失败,请重试。"));
return;
}
if (query.next()) // 用户有卡
{
int userCardStatus = query.value("status").toInt();
if (userCardStatus == 1) // 用户已启用卡
{
QMessageBox::warning(this, "提示", "该用户已有正在使用的卡,开卡失败。\n如需开新卡,请挂失正在使用的卡。");
return;
}
else if (userCardStatus == -1) // 用户有挂失卡,需要移资
{
/// @todo 弹出验证用户界面,要求用户输入密码;将挂失卡的信息和消费记录移到新卡
QString info, prompt = QString("如需将挂失卡移资到本卡,请输入密码。");
bool success = verifyUser(userId, prompt, info);
if (!success)
{
QMessageBox::warning(this, "提示", info + QString("\n验证用户失败。移资失败,请重试。"));
return;
}
QString userCardId = query.value("id").toString();
success = transferCard(userId, cardIdSelected, userCardId, info);
if (!success)
{
QMessageBox::warning(this, "提示", info + QString("\n移资失败,请重试。"));
return;
}
QMessageBox::information(this, "提示", "移资成功。");
return;
}
}
else // 用户无卡
{
QString info;
bool success = bindUserWithCard(userId, cardIdSelected, info); // 将新用户和卡绑定(卡在读取时已写入数据库)
if (!success)
{
QMessageBox::warning(this, "提示", info + QString("\n注册失败,请重新开卡。"));
return;
}
QMessageBox::information(this, "提示", "新用户开卡成功。");
return;
}
}
}
/**
* @brief
* ID
*
* @details
* QSqlQuery对象SQL语句10
* ID绑定到卡片IDSQL执行失败info并返回false
* @param userId /
* @param cardId
* @param info
* @return
* - true
* - false
* @author
* @date 2024-07-30
*/
bool MainWindow::bindUserWithCard(int userId, QString cardId, QString &info)
{
QSqlQuery query(db->getDatabase());
query.finish();
query.prepare(QString("update card "
"set `status` = :status, balance = :balance, userId = :userId "
"where id = :cardId;"));
query.bindValue(":status", 1);
query.bindValue(":balance", (double)0.00);
query.bindValue(":userId", userId);
query.bindValue(":cardId", cardId);
bool updateCardIsExecuted = query.exec();
if (!updateCardIsExecuted)
{
info = QString("数据库异常。");
return false;
}
/// @todo 写卡
return true;
}
/**
* @brief
* `getNewUserInfo`
* ID一起插入到数据库中
* @details
* `getNewUserInfo`
* SQL语句ID `user`
* SQL执行失败
* @param userId /
* @param info
* @return bool
* - true
* - false
* @author
* @date 2024-07-30
*/
bool MainWindow::createUser(int userId, QString &info)
{
QString username, password;
if (!getNewUserInfo(username, password, info)) return false;
QSqlQuery query(db->getDatabase());
query.finish();
query.prepare(QString("insert into `user` "
"values (:id, :name, :password);"));
query.bindValue(":id", userId);
query.bindValue(":name", username);
query.bindValue(":password", password);
bool insertUserIsExecuted = query.exec();
if (!insertUserIsExecuted)
{
info = QString("数据库异常。");
return false;
}
return true;
}
/**
* @brief
*
*
* @details
*
* -
* -
* -
* @param username
* @param password
* @param info
* @return bool
* - true
* - false
* @author
* @date 2024-07-30
*/
bool MainWindow::getNewUserInfo(QString &username, QString &password, QString &info)
{
bool ok = false;
username = QInputDialog::getText(this, tr("新用户注册"), tr("请输入姓名"), QLineEdit::Normal, 0, &ok);
if (!ok || username.isEmpty())
{
info = QString("输入信息异常。");
return false;
}
ok = false;
password = QInputDialog::getText(this, tr("新用户注册"), tr("请输入密码"), QLineEdit::Password, 0, &ok);
if (!ok || password.isEmpty())
{
info = QString("输入信息异常。");
return false;
}
ok = false;
QString confirmPassword = QInputDialog::getText(this, tr("新用户注册"), tr("请再次输入密码"), QLineEdit::Password, 0, &ok);
if (!ok || confirmPassword.isEmpty())
{
info = QString("输入信息异常。");
return false;
}
if (confirmPassword != password)
{
info = QString("两次输入的密码不一致。");
return false;
}
return true;
}
/**
* @brief
*
*
* @details
*
* ID和密码
*
* @param userId /
* @param prompt
* @param info
* @return bool
* - true
* - false
* @author
* @date 2024-07-30
*/
bool MainWindow::verifyUser(int userId, QString prompt, QString &info)
{
bool ok = false;
QString text;
if (prompt.isEmpty()) text = QString("请输入密码");
else text = prompt + QString("\n请输入密码");
QString password = QInputDialog::getText(this, tr("验证用户"), text, QLineEdit::Password, 0, &ok);
if (!ok || password.isEmpty())
{
info = QString("输入信息异常。");
return false;
}
QSqlQuery query(db->getDatabase());
query.finish();
query.prepare(QString("select `password` from `user` "
"where id = :id;"));
query.bindValue(":id", userId);
if (!query.exec())
{
info = QString("数据库异常。");
return false;
}
if (query.next())
{
QString validPassword = query.value(0).toString();
if (validPassword != password)
{
info = QString("密码不正确");
return false;
}
else
{
return true;
}
}
else
{
info = QString("学/工号不存在");
return false;
}
}
/**
* @brief
*
* -
* - ID
* - ID替换为新卡ID
* -
* @details
*
* info并返回false
* @param userId /
* @param newCardId ID
* @param oldCardId ID
* @param info
* @return bool
* - true
* - false
* @author
* @date 2024-07-30
*/
bool MainWindow::transferCard(int userId, QString newCardId, QString oldCardId, QString &info)
{
QSqlQuery query(db->getDatabase());
bool isExecuted = false;
// 查询旧卡余额
query.finish();
query.prepare("select balance from card "
"where userId = :userId;");
query.bindValue(":userId", oldCardId);
isExecuted = query.exec();
if (!isExecuted || query.next())
{
info = QString("数据库异常。");
return false;
}
double balance = query.value("balance").toDouble();
// 更新新卡信息
query.finish();
query.prepare(QString("update card "
"set `status` = :status, balance = :balance, userId = :userId "
"where id = :cardId;"));
query.bindValue(":status", 1);
query.bindValue(":balance", balance);
query.bindValue(":userId", userId);
query.bindValue(":cardId", newCardId);
isExecuted = query.exec();
if (!isExecuted)
{
info = QString("数据库异常。");
return false;
}
// 更新所有记录将旧卡ID替换为新卡ID
query.finish();
query.prepare(QString("update record "
"set cardId = :newCardId "
"where cardId = :oldCardId;"));
query.bindValue(":newCardId", newCardId);
query.bindValue(":oldCardId", oldCardId);
isExecuted = query.exec();
if (!isExecuted)
{
info = QString("数据库异常。");
return false;
}
// 删除旧卡信息
query.finish();
query.prepare(QString("delete from card "
"where id = :cardId;"));
query.bindValue(":cardId", oldCardId);
isExecuted = query.exec();
if (!isExecuted)
{
info = QString("数据库异常。");
return false;
}
/// @todo 将数据库上的记录写到新卡上
return true;
}
/**
* @brief
* -11
* @details
* QSqlQuery对象SQL语句1
* SQL执行失败info并返回false
* @param userId /
* @param info
* @return bool
* - true
* - false
* @author
* @date 2024-07-30
*/
bool MainWindow::reopenCard(QString cardId, QString &info)
{
// 卡信息和记录都还在数据库中只是status为-1更改即可
QSqlQuery query(db->getDatabase());
query.finish();
query.prepare("update card "
"set `status` = 1 "
"where id = :cardId");
query.bindValue(":cardId", cardId);
bool success = query.exec();
if (!success)
{
info = QString("数据库异常。");
return false;
}
/// @todo 看看是否有写卡需求
return true;
}

View File

@ -100,7 +100,7 @@ void MainWindow::on_connectDatabaseButton_clicked()
{
QMessageBox::warning(this, QString("设备名提示"), QString("该设备名无效,请重试。"));
}
deviceLabel->setText(device.getName());
deviceLabel->setText(device.getNameAndDepositAllowed());
}