修改了一些bug。
1
.gitignore
vendored
@ -72,3 +72,4 @@ CMakeLists.txt.user*
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
*.drawio
|
@ -51,8 +51,10 @@ DISTFILES += \
|
||||
HF15693.dll \
|
||||
HF15693.lib
|
||||
|
||||
# LIBS += -L$$PWD/. -LHF15693
|
||||
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../release/ -lHF15693
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../debug/ -lHF15693
|
||||
else:unix: LIBS += -L$$PWD/../ -lHF15693
|
||||
|
||||
LIBS += -L. -lHF15693
|
||||
INCLUDEPATH += $$PWD/.
|
||||
DEPENDPATH += $$PWD/.
|
||||
|
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="i18n">
|
||||
<file alias="CardManageSystem_zh_CN.qm">D:/Courseware/Integrated_Practice_of_IoT_System/CardManageSystem/build/Desktop_Qt_6_7_2_MinGW_64_bit-Release/release/CardManageSystem_zh_CN.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -13,7 +13,8 @@ DROP PROCEDURE IF EXISTS sp_consumeCard;
|
||||
CREATE TABLE device (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(255) UNIQUE,
|
||||
depositAllowed TINYINT NOT NULL
|
||||
depositAllowed TINYINT NOT NULL,
|
||||
CONSTRAINT chk_device_depositAllowed CHECK (depositAllowed IN (0, 1))
|
||||
) AUTO_INCREMENT=1000;
|
||||
|
||||
CREATE TABLE `user` (
|
||||
@ -28,24 +29,26 @@ CREATE TABLE card (
|
||||
balance DECIMAL(6, 2) NOT NULL,
|
||||
userId INT,
|
||||
FOREIGN KEY (userId) REFERENCES `user`(id),
|
||||
CONSTRAINT chk_card_status CHECK (`status` IN (-1, 0, 1)),
|
||||
CONSTRAINT chk_card_balance CHECK (balance >= 0)
|
||||
);
|
||||
|
||||
CREATE TABLE record (
|
||||
id VARCHAR(255) PRIMARY KEY,
|
||||
cardId VARCHAR(16),
|
||||
cardId VARCHAR(16) NOT NULL,
|
||||
`time` DATETIME NOT NULL,
|
||||
`type` TINYINT NOT NULL,
|
||||
`value` DECIMAL(6, 2) NOT NULL,
|
||||
originalBalance DECIMAL(6, 2) NOT NULL,
|
||||
balance DECIMAL(6, 2) NOT NULL,
|
||||
deviceId INT,
|
||||
deviceId INT NOT NULL,
|
||||
FOREIGN KEY (cardId) REFERENCES card(id),
|
||||
FOREIGN KEY (deviceId) REFERENCES device(id),
|
||||
CONSTRAINT chk_value CHECK (`value` >= -300),
|
||||
CONSTRAINT chk_record CHECK (originalBalance + `value` = balance),
|
||||
CONSTRAINT chk_record_originalBalance CHECK (originalBalance >= 0),
|
||||
CONSTRAINT chk_record_balance CHECK (balance >= 0)
|
||||
CONSTRAINT chk_record_balance CHECK (balance >= 0),
|
||||
CONSTRAINT chk_record_type CHECK (`type` IN (0, 1))
|
||||
);
|
||||
|
||||
|
||||
|
523
doc/README.md
Normal file
@ -0,0 +1,523 @@
|
||||
<h1><center>一卡通管理系统说明</center></h1>
|
||||
|
||||
# 1 系统概述
|
||||
|
||||
## 1.1 系统简介
|
||||
|
||||
本系统是一个一卡通管理系统,该系统面向学校应用、基于 RFID 技术的构建。该系统基于 ISO/IEC15693 协议的 RFID 芯片( NXP ICS20 或 SL2S2002 )进行卡内数据读写,并实现与数据库交互记录的功能。
|
||||
|
||||
## 1.2 系统组成
|
||||
|
||||
### 1.2.1 系统架构
|
||||
|
||||

|
||||
|
||||
本系统由一卡通管理系统软件、数据库以及读卡器硬件组成。
|
||||
|
||||
其中:
|
||||
|
||||
- 一卡通管理系统软件
|
||||
- 为用户提供操作界面,实现读写数据库和硬件的逻辑;
|
||||
- 运行在 PC 机中,调用数据库连接插件与数据库通过网络交互,调用硬件驱动接口与读卡器进行交互;
|
||||
- 数据库软件
|
||||
- 存储一卡通管理系统的数据;
|
||||
- 运行在服务器中,通过网络与 PC 机连接;
|
||||
- 读卡器硬件
|
||||
- 读写卡片;
|
||||
- 通过 USB 串口与 PC 机连接。
|
||||
|
||||
使用软件前,用户需要将 PC 机连接网络,并将读卡器连接到 PC 机的 USB 口上。
|
||||
|
||||
### 1.2.2 系统功能
|
||||
|
||||
本系统的功能包括:
|
||||
|
||||
- 设置:连接和读写数据库、HF15693硬件;
|
||||
- 开卡:创建新用户、挂失重开卡、挂失移资新卡;
|
||||
- 挂失卡;
|
||||
- 充值:远程充值、线下充值;
|
||||
- 消费;
|
||||
- 查询:查询卡内记录及数据库内记录。
|
||||
|
||||
## 1.3 运行环境及开发工具
|
||||
|
||||
本软件运行在 Windows 操作系统中。
|
||||
|
||||
本软件基于 Qt 6.7.2,使用 Qt Creator 14.0.0 开发,使用了 MySQL 8.0.37 作为数据库软件。
|
||||
|
||||
本项目使用 Git 作为开发版本管理工具。
|
||||
|
||||
在开发完毕后,使用 Inno Setup 软件将程序及其动态链接库文件打包为安装程序。
|
||||
|
||||
|
||||
|
||||
# 2 功能设计
|
||||
|
||||
## 2.1 设置功能
|
||||
|
||||
### 2.1.1 设置读卡器连接
|
||||
|
||||
**内容**
|
||||
|
||||
该功能用于连接读卡器硬件。用户在输入框内输入连接的 COM 口号,并点击“连接”按钮连接。
|
||||
|
||||
- 连接成功后,软件窗口下方任务栏的读卡器连接状态勾选框显示勾选,同时显示连接的串口号;
|
||||
|
||||
- 若连接不成功,软件弹出提示框,提示用户该串口上未识别到读卡器,同时软件窗口下方任务栏勾选框取消勾选,显示“当前无连接”。
|
||||
|
||||
**流程**
|
||||
|
||||
首先获取 COM 口输入框组件的 COM 口号,调用读卡器 API 进行连接,得到连接结果。如果连接不成功,弹出提示框。最后根据连接结果更新状态栏信息。
|
||||
|
||||

|
||||
|
||||
### 2.1.2 设置数据库连接
|
||||
|
||||
**内容**
|
||||
|
||||
该功能用于连接数据库,以及设备名认证。
|
||||
|
||||
> **设备名**用于在交易记录中记录操作设备的名称。
|
||||
>
|
||||
> 对于每个设备名,数据库中设置了其操作权限:
|
||||
>
|
||||
> - 可充值:使用该设备名的设备拥有开卡、充值和消费权限(在管理员 PC 中使用);
|
||||
> - 仅可消费:使用该设备名的设备仅有消费权限(在食堂等消费场所的终端机中使用)。
|
||||
|
||||
用户首先要填写数据库的 IP 地址和端口,输入数据库的密码和要使用的设备名,点击连接按钮。
|
||||
|
||||
- 如果数据库连接不成功,软件弹出提示框,提示用户数据库连接失败,同时软件窗口下方任务栏的数据库连接状态勾选框取消勾选,显示“数据库未连接”、“未指定设备名”;
|
||||
|
||||
- 如果数据库连接成功,软件窗口下方任务栏的数据库连接状态勾选框显示勾选,同时显示连接的 IP 地址和端口;
|
||||
|
||||
连接成功后,将会进行设备名认证。
|
||||
|
||||
- 若设备名验证成功,软件窗口下方任务栏显示设备名及其操作权限;
|
||||
|
||||
- 若验证失败,软件弹出提示框,提示用户该设备名无效,同时软件窗口下方任务栏显示“未指定设备名”。
|
||||
|
||||
**流程**
|
||||
|
||||
从输入组件获取 IP 地址、端口、密码,连接数据库并更新任务栏显示信息。如果连接不成功,弹出提示框;如果连接成功,继续进行设备名认证。
|
||||
|
||||
查询数据库进行设备名认证,按认证结果更新任务栏显示信息。如果认证不成功,还要弹出提示框。
|
||||
|
||||

|
||||
|
||||
以下功能中,除了仅需输学/工号的功能仅需连接数据库外,其他所有功能都需同时连接读卡器和数据库。
|
||||
|
||||
## 2.2 开卡功能
|
||||
|
||||
### 2.2.1 新用户开卡
|
||||
|
||||
**内容**
|
||||
|
||||
本功能的使用条件是:用户使用了未启用卡和新学/工号。
|
||||
|
||||
> 本系统采用卡和用户一对一绑定的机制,即:一个学/工号在任一时刻只能绑定和使用 1 张卡。
|
||||
|
||||
> **卡**有三个状态:
|
||||
>
|
||||
> - 未启用:该卡未绑定任何用户,仅可用于开卡,不可用于查询、充值或消费。未启用的卡进行开卡操作后将绑定一个用户,进入“启用中”状态;
|
||||
> - 启用中:该卡绑定了一个用户,可以用于查询、充值和消费,不可用于开卡。如果该卡绑定的用户进行了挂失操作,该卡进入“已被挂失”状态;
|
||||
> - 已被挂失:该卡绑定了一个用户但在数据库中被标记为挂失,仅可用于查询和重开,不可用于充值或消费。如果绑定该卡的用户使用了另一卡号进行开卡,本卡在数据库中的余额和所有记录将会被移动到新卡,本卡在数据库中的数据被删除,再次被读取时将处于“未启用”状态。
|
||||
>
|
||||
> 实体卡内存储只存最多 6 条交易编号,其他信息全部存在数据库中。
|
||||
|
||||
>**用户**以学/工号唯一标识,拥有属性“姓名”和“密码”。
|
||||
>
|
||||
>- 学/工号支持4到8位数字
|
||||
>- 密码在创建用户时要求输入并二次确认。用于查询用户的所有交易记录和出现大额交易时验证用户身份。
|
||||
|
||||
用户需要在有开卡(充值)权限的设备上操作。
|
||||
|
||||
用户点击“查询”按钮扫描读卡器上的卡片,输入学/工号,然后点击“开卡”。如果用户没有点击”查询“按钮扫描,点击”开卡“按钮时会弹出提示框。
|
||||
|
||||
如果卡号和学/工号满足本功能条件,则在弹出的窗口中输入姓名、密码和二次确认密码。信息无误后,用户信息和卡信息会被写入数据库,卡片会被初始化,开卡成功。此时卡内余额为零。
|
||||
|
||||
**流程**
|
||||
|
||||
当”开卡“按钮被点击,获取界面上选中的卡号和输入的学/工号。如果没有发现选中的卡号(用户没有点击”查询“按钮),则弹出提示框。
|
||||
|
||||
在数据库中查询卡号:
|
||||
|
||||
- 如果查询不到卡片,则在数据库中插入该卡片信息,设置为未启用状态并继续;
|
||||
- 如果查询到卡片处于未启用状态,继续;
|
||||
- 否则提示用户卡片已被启用并退出开卡功能,或进入挂失重开功能。
|
||||
|
||||
在数据库中查询学/工号:
|
||||
|
||||
- 如果查询不到用户信息(未注册),弹出信息输入框获取数据,并检查二次确认密码。将用户信息写入数据库并继续;
|
||||
- 如果查询到用户,则在卡表中查询用户:
|
||||
- 如果查询不到数据,则将刚才插入的卡片记录绑定上用户;
|
||||
- 如果查询到数据,则视卡的状态进入挂失移资功能或提示用户已经绑定了卡,不可再开卡,并退出开卡功能。
|
||||
|
||||
流程图见 *2.2.3* 节。
|
||||
|
||||
### 2.2.2 重开卡
|
||||
|
||||
**内容**
|
||||
|
||||
本功能的使用条件是:卡号处于挂失状态。
|
||||
|
||||
用户需要在有开卡(充值)权限的设备上操作。
|
||||
|
||||
用户点击“查询”按钮扫描读卡器上的卡片,输入学/工号(尽管程序没有用到),然后点击“开卡”。如果用户没有点击”查询“按钮扫描,点击”开卡“按钮时会弹出提示框。
|
||||
|
||||
如果卡号满足本功能条件,则在弹出的窗口中输入密码验证用户身份。信息无误后,卡会被重新置为”启用中“状态,此时卡内余额为挂失前的余额。
|
||||
|
||||
**流程**
|
||||
|
||||
当”开卡“按钮被点击,获取界面上选中的卡号和输入的学/工号。如果没有发现选中的卡号(用户没有点击”查询“按钮),则弹出提示框。
|
||||
|
||||
在数据库中查询卡号:
|
||||
|
||||
- 如果已被挂失,查询数据库中绑定的用户学/工号和姓名。弹出输入窗口,显示绑定的用户姓名,询问用户是否输入密码并重新开卡:
|
||||
- 如果用户选择取消则退出;
|
||||
- 如果用户输入密码并点击确定,则验证用户:
|
||||
- 验证成功则修改数据库,重新启用该卡;
|
||||
- 验证失败则弹出提示框并退出。
|
||||
- 如果是其他状态,则对应进入挂失卡移资或新用户开卡功能。
|
||||
|
||||
流程图见 *2.2.3* 节。
|
||||
|
||||
### 2.2.3 挂失卡移资
|
||||
|
||||
**内容**
|
||||
|
||||
本功能的使用条件是:卡号处于未启用状态,且用户学/工号绑定的卡处于挂失状态。
|
||||
|
||||
用户需要在有开卡(充值)权限的设备上操作。
|
||||
|
||||
用户点击“查询”按钮扫描读卡器上的卡片,输入学/工号,然后点击“开卡”。如果用户没有点击”查询“按钮扫描,点击”开卡“按钮时会弹出提示框。
|
||||
|
||||
如果卡号满足本功能条件,则在弹出的窗口中输入密码验证用户身份。信息无误后,用户挂失的旧卡的记录将会被移植给新卡,此时新卡处于”启用中“状态,卡内余额为旧卡挂失前的余额。旧卡记录会被删除。
|
||||
|
||||
**流程**
|
||||
|
||||
当”开卡“按钮被点击,获取界面上选中的卡号和输入的学/工号。如果没有发现选中的卡号(用户没有点击”查询“按钮),则弹出提示框。
|
||||
|
||||
在数据库中查询卡号:
|
||||
|
||||
- 如果查询不到卡片,则在数据库中插入该卡片信息,设置为未启用状态并继续;
|
||||
- 如果查询到卡片处于未启用状态,继续;
|
||||
- 否则提示用户卡片已被启用并退出开卡功能,或进入挂失重开功能。
|
||||
|
||||
在数据库中查询学/工号:
|
||||
|
||||
- 如果查询不到用户信息(未注册),则进入新用户开卡功能;
|
||||
|
||||
- 如果查询到用户,则继续在卡表中查询用户:
|
||||
- 如果查询到用户,且用户绑定的卡处于挂失状态,则弹出输入框询问用户是否输入密码并重开新卡并移资。用户取消或验证失败则提示或退出;验证成功则修改数据库,将旧卡信息移植到新卡,删除旧卡信息。
|
||||
- 如果查询不到用户则进入新用户开卡功能;如果查询到用户但用户绑定的卡处于启用状态则弹出提示框,退出。
|
||||
|
||||
整个开卡功能的流程图如下:
|
||||
|
||||

|
||||
|
||||
其中绿色部分对应新用户开卡功能,橙色部分对应重开卡部分,蓝色部分对应挂失卡移资部分。
|
||||
|
||||
## 2.3 充值功能
|
||||
|
||||
### 2.3.1 远程充值
|
||||
|
||||
**内容**
|
||||
|
||||
本功能用于远程为卡余额充值。
|
||||
|
||||
> **卡余额**为小数点后两位精度的小数。金额不得超过 9999.99 元,不得低于 0.00 元。
|
||||
|
||||
本功能使用学/工号为卡充值,无需使用实体卡。
|
||||
|
||||
用户需要在有充值权限的设备上操作。首先输入金额(限制大于 0.00 元且小于 9999.99 元),然后输入学/工号。如果学/工号对应的卡处于”已启用“状态,且充值金额加上原金额不超过余额限制 9999.99 元,则充值成功。否则弹窗提示。
|
||||
|
||||
**流程**
|
||||
|
||||
首先检查设备是否具有充值权限。如果没有,弹出提示窗口。
|
||||
|
||||
获取金额和学/工号,检查金额是否超出限制,若超出限制弹出提示窗口并退出。
|
||||
|
||||
在数据库中查询与该学/工号绑定的卡。如果未查询到记录或卡的状态不是”启用中“,弹出提示窗口并退出。
|
||||
|
||||
检查查询到卡的余额与金额之和是否超过余额限制,若超出限制弹出提示窗口并退出。
|
||||
|
||||
生成交易号,将交易记录插入数据库,将交易号写入卡中。
|
||||
|
||||
> **交易号**为 30 位十六进制数:
|
||||
>
|
||||
> - 第 0 - 3 位:随机数;
|
||||
> - 第 4 位:0 或 1,1 表示该交易类型为充值,0 表示该交易类型为消费;
|
||||
> - 第 5 - 15 位:学/工号,将学/工号(十进制)的每一位数字依次填入(不转换为十六进制);
|
||||
> - 第 16 - 29 位:时间,从高到低分别是 yyyyMMddhhmmss ;
|
||||
|
||||

|
||||
|
||||
### 2.3.2 线下充值
|
||||
|
||||
**内容**
|
||||
|
||||
本功能用于使用卡片进行余额充值。
|
||||
|
||||
用户需要在有充值权限的设备上操作。首先输入金额(限制大于 0.00 元且小于 9999.99 元),然后点击”查询“扫描卡号并选择充值卡号。如果卡处于”已启用“状态,且充值金额加上原金额不超过余额限制 9999.99 元,则充值成功。否则弹窗提示。
|
||||
|
||||
**流程**
|
||||
|
||||
首先检查设备是否具有充值权限。如果没有,弹出提示窗口。
|
||||
|
||||
获取金额和卡号,检查金额是否超出限制,若超出限制弹出提示窗口并退出。
|
||||
|
||||
在数据库中查询卡号。如果未查询到记录或卡的状态不是”启用中“,弹出提示窗口并退出。
|
||||
|
||||
检查查询到卡的余额与金额之和是否超过余额限制,若超出限制弹出提示窗口并退出。
|
||||
|
||||
生成交易号,将交易记录插入数据库,将交易号写入卡中。
|
||||
|
||||

|
||||
|
||||
## 2.4 消费功能
|
||||
|
||||
**内容**
|
||||
|
||||
本功能用于使用卡片进行消费。
|
||||
|
||||
首先输入金额(限制不超过 300.00 元),然后点击”查询“扫描卡号并选择消费卡号。
|
||||
|
||||
- 如果卡处于”已启用“状态:
|
||||
- 消费金额不超过不超过余额:
|
||||
- 消费金额不超过 50.00 元,则消费成功;
|
||||
- 消费金额超过 50.00 元且小于 300.00 元,需要验证用户身份。验证通过后消费成功;
|
||||
- 消费金额超过限制 300.00 元,消费失败;
|
||||
- 消费金额超出余额,消费失败;
|
||||
- 卡片处于异常状态,消费失败。
|
||||
|
||||
**流程**
|
||||
|
||||
获取金额和卡号,在数据库中查询卡号。如果未查询到记录或卡的状态不是”启用中“,弹出提示窗口并退出。
|
||||
|
||||
检查金额是否超出余额、超出单次消费限制 300.00 元,若超出限制弹出提示窗口并退出。
|
||||
|
||||
检查金额是否超出 50.00 元,如果超出需要弹出输入窗口获取密码验证用户身份。
|
||||
|
||||
生成交易号,将交易记录插入数据库,将交易号写入卡中。
|
||||
|
||||

|
||||
|
||||
## 2.5 查询功能
|
||||
|
||||
### 2.5.1 查询卡内记录
|
||||
|
||||
**内容**
|
||||
|
||||
本功能用于查询卡内交易记录。
|
||||
|
||||
用户首先点击”读卡“并选择卡号,然后点击”查询卡内记录“按钮。
|
||||
|
||||
如果卡片处于未启用状态,则会弹出提示窗口。
|
||||
|
||||
如果卡片处于已启用或已被挂失状态,则余额框内显示余额,卡状态框内会显示卡状态,表格组件内显示卡内存储的交易编号(最多 6 条)对应的交易记录。
|
||||
|
||||
**流程**
|
||||
|
||||
程序获取卡号,查询数据库查看卡片状态。如果卡片未启用,弹出提示窗口并退出;
|
||||
|
||||
如果卡片已启用或已被挂失,在组件中显示余额、卡状态。
|
||||
|
||||
调用读卡器 API 读取卡内的交易编号,对每一条交易编号,查询数据库中的交易记录,并显示在表格组件中。
|
||||
|
||||

|
||||
|
||||
### 2.5.2 查询所有记录
|
||||
|
||||
**内容**
|
||||
|
||||
本功能用于查询用户所有交易记录。
|
||||
|
||||
用户可以通过两种方式触发此功能:
|
||||
|
||||
- 点击”读卡“并选择卡号,然后点击”查询所有记录“按钮;
|
||||
- 输入学/工号,然后点击”查询学/工号记录“按钮;
|
||||
|
||||
如果卡片处于未启用状态,则会弹出提示窗口。
|
||||
|
||||
如果卡片处于已启用或已被挂失状态,则余额框内显示余额,卡状态框内会显示卡状态,表格组件内显示该用户的所有交易记录。
|
||||
|
||||
**流程**
|
||||
|
||||
程序获取卡号或用户学/工号(通过学/工号查到卡号),查询数据库查看卡片状态。如果卡片未启用,弹出提示窗口并退出;
|
||||
|
||||
如果卡片已启用或已被挂失,在组件中显示余额、卡状态。
|
||||
|
||||
查询该用户在数据库内的所有交易记录,并显示在表格组件中。
|
||||
|
||||

|
||||
|
||||
## 2.6 挂失功能
|
||||
|
||||
**内容**
|
||||
|
||||
本功能用于挂失用户的卡。
|
||||
|
||||
用户输入学/工号,然后点击”挂失“按钮;
|
||||
|
||||
如果学/工号未绑定卡或绑定的卡已经被挂失,则会弹出提示窗口并退出。
|
||||
|
||||
将该用户的卡设置为已被挂失状态。
|
||||
|
||||
**流程**
|
||||
|
||||
程序获取用户学/工号,查询数据库查看卡片状态。
|
||||
|
||||
如果学/工号未绑定卡或绑定的卡已经被挂失,弹出提示窗口并退出。
|
||||
|
||||
修改数据库,将学/工号绑定的卡设置为挂失状态。
|
||||
|
||||

|
||||
|
||||
## 2.7 退出功能
|
||||
|
||||
**内容**
|
||||
|
||||
本功能用于退出软件。
|
||||
|
||||
**流程**
|
||||
|
||||
程序关闭读卡器连接和数据库连接,最后关闭图形化界面后退出。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# 3 数据设计
|
||||
|
||||
## 3.1 磁盘文件设计
|
||||
|
||||
本系统使用数据库保存数据。
|
||||
|
||||
本系统涉及的实体有:
|
||||
|
||||
- 用户:以学/工号作为唯一标识符,具有属性姓名和学号;
|
||||
- 卡:以卡号为唯一标识符,具有属性状态(未启用、已启用、已被挂失)和余额;
|
||||
- 交易记录:以交易记录号为唯一标识符,具有属性交易时间、交易类型(充值、消费)、交易金额(充值为正数,消费为负数)、原金额、交易后余额;
|
||||
- 设备:以设备编号作为唯一标识符,具有属性名称和充值权限。
|
||||
|
||||
实体-关系图如下:
|
||||
|
||||

|
||||
|
||||
因此在数据库中建立表:
|
||||
|
||||
- 用户(<u>学/工号</u>,姓名,密码)
|
||||
- 姓名、密码不能为空
|
||||
- 卡片(<u>卡号</u>,状态,余额,用户的学/工号)
|
||||
- 卡状态、余额不能为空
|
||||
- 余额不能小于 0 ;状态必须为 -1 或 0 或 1 (分别表示已被挂失、未启用和启用中)
|
||||
- 用户的学/工号为外键,引用用户表的学/工号字段
|
||||
- 交易记录(<u>交易记录号</u>,卡号,交易时间、交易类型、交易金额、原金额、交易后余额、设备编号)
|
||||
- 所有属性都不能为空
|
||||
- 卡号为外键,引用卡片表的卡号字段;设备编号为外键,引用设备表的编号字段
|
||||
- 交易金额不可小于 -300.00 ;原金额加上交易金额必须等于交易后金额;原金额和交易后金额都必须大于等于0 ;交易类型必须为 0 或 1 (分别表示消费和充值)
|
||||
- 设备(<u>设备编号</u>,名称,充值权限)
|
||||
- 所有属性不能为空
|
||||
- 名称必须互不相同
|
||||
- 充值权限必须为 0 或 1 (分别表示仅可消费、可充值)
|
||||
|
||||
数据库初始化脚本见 [initDb.sql](..\database\initDb.sql) 。
|
||||
|
||||
本软件使用数据库固定使用 `cardManageSystem` 数据库和 `cardManageSystem` 用户。
|
||||
|
||||
## 3.2 程序内数据设计
|
||||
|
||||
### 3.2.1 全局变量定义及使用方法
|
||||
|
||||
由于本软件是基于 QT 的一个 MainWindow 组件类对象搭建,各个子界面都是 MainWindow 的子组件,因此所有的全局变量都被设置为 MainWindow 对象的属性,包括:
|
||||
|
||||
- reader:自定义 Reader 类(定义在 [readerAPI.h](..\readerAPI.h) 中)对象:
|
||||
- 变量: COM 口号和卡内最大的记录条数限制
|
||||
- 方法:
|
||||
- `void setComNumber(int comNumber)` 设置 COM 口号
|
||||
- `int getComNumber()` 获取当前COM口号
|
||||
- `bool is_connected()` 判断读卡器是否已连接
|
||||
- `bool connect()` 连接读卡器
|
||||
- `void disconnect()` 关闭连接
|
||||
- `QStringList inventory(int maxViccNum)` 获取读卡器中卡片的UID列表
|
||||
- `bool insertRecord(QString record, QString cardId)` 插入一条交易记录
|
||||
- `QStringList readAllRecords(QString cardId, bool &ok)` 获取全部记录
|
||||
- `bool initCard(QString cardId)`卡初始化
|
||||
- db:自定义 Database 类(定义在 [databaseAPI.h](..\databaseAPI.h) 中)指针:
|
||||
- 变量:QT 的数据库对象、连接状态、固定的数据库名字符串和用户名字符串
|
||||
- 方法:
|
||||
- `Database(QSqlDatabase database)` 使用QSqlDatabase类初始化对象
|
||||
- `Database(QSqlDatabase database, QString hostName, int port, QString password)` 使用QSqlDatabase类、IP、端口、密码初始化对象
|
||||
- `void setHostName(QString hostName)` 设置hostName属性
|
||||
- `void setPort(int port)` 设置port属性
|
||||
- `void setPassword(QString password)` 设置password属性
|
||||
- `QSqlDatabase getDatabase()` 获取数据库对象属性
|
||||
- `int getPort()` 获取port属性
|
||||
- `QString getHostName()` 获取hostName属性
|
||||
- `bool is_connected()` 数据库是否已经连接
|
||||
- `bool open()` 连接数据库
|
||||
- device:自定义 Device 类(定义在 [deviceAPI.h](..\deviceAPI.h) 中)对象:
|
||||
- 变量:设备名认证状态、设备充值权限、设备名称和设备编号
|
||||
- 方法:
|
||||
- `void setDevice(QString name, Database *db)` 设置并认证设备
|
||||
- `QString getName()` 获取设备名
|
||||
- `QString getNameAndDepositAllowed()` 获取设备名及其充值权限
|
||||
- `int getId()` 获取设备ID
|
||||
- `bool is_verified()` 设备是否已经认证
|
||||
- `bool is_depositAllowed()` 设备是否可充值
|
||||
- 其他所有子组件的指针,通过 `ui->{组件名}` 的方法调用
|
||||
|
||||
### 3.2.2 交易记录定义
|
||||
|
||||
本系统中,交易记录主要存储在数据库中。交易记录作为变量出现在软件中的场景,是查询数据库得到某个用户的交易记录,显示在表格组件中。因此交易记录被定义为 QStringList 类对象(即 QString 类列表)。
|
||||
|
||||
使用 QSqlQuery 类方法查询到交易记录后,交易记录使用 QSqlQuery 类对象 query 的方法 value() 获取各个字段的值。获取后,将其转换为 QStringList 类对象,即可调用表格组件方法显示。该功能在 [queryPage.cpp](..\queryPage.cpp) 的 MainWindow::transactionRecord2QStringList() 方法中实现。
|
||||
|
||||
|
||||
|
||||
## 3.3 卡片内存储空间设计
|
||||
|
||||
卡片内存储 3 类数据:
|
||||
|
||||
| 内容 | 长度 | 位置 |
|
||||
| :------------------------: | :--------------------------------------------: | :------------------------------------: |
|
||||
| 卡内目前存储的交易记录数量 | 4 bits | block0 的 byte0 的 bit0-3 |
|
||||
| 最近一条交易记录的下标 | 4 bits | block0 的 byte0 的 bit4-7 |
|
||||
| 交易记录 | 每条记录 4 blocks,最多存 6 条记录占 24 blocks | block1-24,每连续 4 个block 为一条记录 |
|
||||
|
||||
每条交易记录只存储交易记录号(见 *2.3.1* 节)。
|
||||
|
||||
初始时,卡内目前存储的交易记录数量为 0 ,最近一条交易记录的下标为 5 。
|
||||
|
||||
写入记录时,程序首先读取最近一条交易记录的下标,然后将其加 1 模 6,在新下标的 blocks 中写入交易记录号,即循环写入,超过 6 条交易记录时,最新的交易记录会覆盖最早的交易记录。例如,最近一条交易记录的下标为 5 ,那么写入新记录时,将会到下标 (5 + 1) % 6 = 0 中写入,实际写入的 blocks 为 1 + 4 * 0 = 1 到 1 + 4 * (0 + 1) - 1 = 4 。
|
||||
|
||||
读取记录时,同样读取最近一条交易记录的下标,然后读取卡内目前存储的交易记录数量。接着循环读取,将按照读出的交易记录数量来读取交易记录。例如,最近一条交易记录的下标为 5 ,卡内目前存储的交易记录数量为 6 ,那么读取所有记录时,将会到最早的下标 (5 - 6 + 1) % 6 = 0 中开始读取,依次读取 blocks 为 1-4,5-8,9-12,13-16,17-20,21-24 。
|
||||
|
||||
|
||||
|
||||
# 4 软件功能概要
|
||||
|
||||
本系统的功能包括:
|
||||
|
||||
- 设置:连接和读写数据库、HF15693硬件;
|
||||
- 开卡:创建新用户、挂失重开卡、挂失移资新卡;
|
||||
- 挂失卡;
|
||||
- 充值:远程充值、线下充值;
|
||||
- 消费;
|
||||
- 查询:查询卡内记录及数据库内记录。
|
||||
|
||||
|
||||
|
||||
# 5 收获与建议
|
||||
|
||||
**收获**
|
||||
|
||||
- 在项目开发过程中,我将课堂上学到的物联网理论知识应用到实际项目中,深刻理解了RFID技术、数据库交互和Qt开发框架的原理和应用。
|
||||
- 项目开发中遇到了诸多问题,如数据库连接、数据读写和硬件通信等。通过查阅资料、调试代码,我逐步解决了这些问题,提升了自己的问题解决能力。
|
||||
- 通过项目,我熟练掌握了Qt框架的使用,增强了C++编程能力。同时,对数据库设计和SQL查询也有了更深入的理解和实践。
|
||||
- 在项目开发过程中,我学会了如何有效地管理项目进度,包括任务分解、时间安排和进度跟踪等。这些经验将对我未来的项目开发和管理大有裨益。
|
||||
- 我学会了遵循代码规范,编写清晰、易维护的代码。同时,我也注重项目文档的编写,为项目后续的维护和迭代提供了有力支持。
|
||||
|
||||
**建议**
|
||||
|
||||
- 一开始我学习了 MFC 开发,但了解 MFC 后,我发现这个开发框架已经过时,存在许多缺点,不满足现代软件开发的需求,因此我选择了使用 Qt 开发。建议以后该课程可以更新学习的开发工具,比如教学使用 Qt 、Electron 等最新开发框架技术。
|
4
doc/image/ER.drawio.svg
Normal file
After Width: | Height: | Size: 149 KiB |
4
doc/image/architecture.drawio.svg
Normal file
After Width: | Height: | Size: 166 KiB |
4
doc/image/consume.drawio.svg
Normal file
After Width: | Height: | Size: 327 KiB |
4
doc/image/deposit-useCard.drawio.svg
Normal file
After Width: | Height: | Size: 300 KiB |
4
doc/image/deposit-useId.drawio.svg
Normal file
After Width: | Height: | Size: 343 KiB |
4
doc/image/newCard.drawio.svg
Normal file
After Width: | Height: | Size: 562 KiB |
4
doc/image/query-all.drawio.svg
Normal file
After Width: | Height: | Size: 259 KiB |
4
doc/image/query-inCard.drawio.svg
Normal file
After Width: | Height: | Size: 197 KiB |
4
doc/image/quitApp.drawio.svg
Normal file
After Width: | Height: | Size: 64 KiB |
4
doc/image/reportLoss.drawio.svg
Normal file
After Width: | Height: | Size: 166 KiB |
4
doc/image/setting-setDatabase.drawio.svg
Normal file
After Width: | Height: | Size: 169 KiB |
4
doc/image/setting-setReader.drawio.svg
Normal file
After Width: | Height: | Size: 100 KiB |
@ -1,31 +0,0 @@
|
||||
<mxfile host="Electron" modified="2024-07-28T12:00:05.441Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.6.1 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="zDIfvHg48gbbwDQY4H_P" version="24.6.1" type="device">
|
||||
<diagram name="第 1 页" id="8yjcYh25Fj_Vruqp0e9_">
|
||||
<mxGraphModel dx="1434" dy="836" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-1" value="卡" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="400" y="200" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-2" value="用户" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="80" y="200" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-3" value="记录" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="400" y="440" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-4" value="学号" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="80" y="120" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-5" value="余额" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="560" y="200" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-6" value="卡号" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="400" y="120" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-7" value="状态" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="560" y="120" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
@ -1,147 +1,153 @@
|
||||
<mxfile host="Electron" modified="2024-07-28T12:31:43.332Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.6.1 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="HsDZe_ryQ9wAG3Kks_rW" version="24.6.1" type="device">
|
||||
<mxfile host="Electron" modified="2024-08-02T10:23:27.443Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.6.1 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="4ZaHNfXZlLg3Tqm3FgSD" version="24.6.1" type="device">
|
||||
<diagram name="第 1 页" id="8yjcYh25Fj_Vruqp0e9_">
|
||||
<mxGraphModel dx="1834" dy="836" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<mxGraphModel dx="1629" dy="899" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-11" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-1" target="ikCD32b5rJxaaIhKNZvf-5">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-11" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-1" target="ikCD32b5rJxaaIhKNZvf-5" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-18" value="1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-1" target="ikCD32b5rJxaaIhKNZvf-16">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-18" value="1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-1" target="ikCD32b5rJxaaIhKNZvf-16" edge="1">
|
||||
<mxGeometry y="10" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-1" value="卡" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-1" value="卡" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="400" y="200" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-8" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-2" target="ikCD32b5rJxaaIhKNZvf-4">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-8" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-2" target="ikCD32b5rJxaaIhKNZvf-4" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-14" value="1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-2" target="ikCD32b5rJxaaIhKNZvf-13">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-14" value="1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-2" target="ikCD32b5rJxaaIhKNZvf-13" edge="1">
|
||||
<mxGeometry y="10" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-2" value="用户" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="rXf3g1vUlJZsvpexLucj-2" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=1;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-2" target="rXf3g1vUlJZsvpexLucj-1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-2" value="用户" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="80" y="200" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-25" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;endArrow=none;endFill=0;entryX=1;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-3" target="ikCD32b5rJxaaIhKNZvf-21">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-25" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;endArrow=none;endFill=0;entryX=1;entryY=0;entryDx=0;entryDy=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-3" target="ikCD32b5rJxaaIhKNZvf-21" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-27" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-3" target="ikCD32b5rJxaaIhKNZvf-22">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-27" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-3" target="ikCD32b5rJxaaIhKNZvf-22" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-28" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-3" target="ikCD32b5rJxaaIhKNZvf-24">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-28" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-3" target="ikCD32b5rJxaaIhKNZvf-24" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-30" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-3" target="ikCD32b5rJxaaIhKNZvf-29">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-30" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-3" target="ikCD32b5rJxaaIhKNZvf-29" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-32" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=1;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-3" target="ikCD32b5rJxaaIhKNZvf-31">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-32" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=1;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-3" target="ikCD32b5rJxaaIhKNZvf-31" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-3" value="记录" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-3" value="记录" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="400" y="360" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-4" value="<u>学号</u>" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-4" value="<u>学/工号</u>" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="80" y="120" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-5" value="余额" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-5" value="余额" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="560" y="200" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-9" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-6" target="ikCD32b5rJxaaIhKNZvf-1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-9" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-6" target="ikCD32b5rJxaaIhKNZvf-1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-6" value="<u>卡号</u>" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-6" value="<u>卡号</u>" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="400" y="120" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-10" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-7" target="ikCD32b5rJxaaIhKNZvf-1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-10" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-7" target="ikCD32b5rJxaaIhKNZvf-1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-7" value="状态" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-7" value="状态" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="560" y="120" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-15" value="1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-13" target="ikCD32b5rJxaaIhKNZvf-1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-15" value="1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-13" target="ikCD32b5rJxaaIhKNZvf-1" edge="1">
|
||||
<mxGeometry y="10" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-13" value="绑定" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-13" value="绑定" style="rhombus;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
|
||||
<mxGeometry x="240" y="200" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-17" value="n" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-16" target="ikCD32b5rJxaaIhKNZvf-3">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-17" value="n" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-16" target="ikCD32b5rJxaaIhKNZvf-3" edge="1">
|
||||
<mxGeometry y="10" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-16" value="存储" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-16" value="存储" style="rhombus;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
|
||||
<mxGeometry x="400" y="280" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-20" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-19" target="ikCD32b5rJxaaIhKNZvf-3">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-20" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-19" target="ikCD32b5rJxaaIhKNZvf-3" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-19" value="<u>编号</u>" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-19" value="<u>编号</u>" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="240" y="280" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-21" value="金额" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-21" value="金额" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="240" y="440" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-22" value="原金额" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-22" value="原金额" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="400" y="440" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-24" value="类型" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-24" value="类型" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="560" y="360" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-29" value="余额" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-29" value="余额" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="560" y="440" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-31" value="时间" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-31" value="时间" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="560" y="280" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-46" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-35" target="ikCD32b5rJxaaIhKNZvf-44">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-46" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-35" target="ikCD32b5rJxaaIhKNZvf-44" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-35" value="设备名" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-35" value="设备名" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="80" y="360" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-37" value="n" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-36" target="ikCD32b5rJxaaIhKNZvf-3">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-37" value="n" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-36" target="ikCD32b5rJxaaIhKNZvf-3" edge="1">
|
||||
<mxGeometry y="10" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-38" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-36" target="ikCD32b5rJxaaIhKNZvf-35">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-38" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-36" target="ikCD32b5rJxaaIhKNZvf-35" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-40" value="1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="ikCD32b5rJxaaIhKNZvf-38">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-40" value="1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="ikCD32b5rJxaaIhKNZvf-38" vertex="1" connectable="0">
|
||||
<mxGeometry x="0.05" y="1" relative="1" as="geometry">
|
||||
<mxPoint y="-11" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-36" value="产生" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-36" value="产生" style="rhombus;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
|
||||
<mxGeometry x="240" y="360" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-42" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-41" target="ikCD32b5rJxaaIhKNZvf-35">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-42" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-41" target="ikCD32b5rJxaaIhKNZvf-35" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-41" value="<u>编号</u>" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-41" value="<u>编号</u>" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="80" y="280" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-45" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-43" target="ikCD32b5rJxaaIhKNZvf-35">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-45" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-43" target="ikCD32b5rJxaaIhKNZvf-35" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-43" value="充值权限" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-43" value="充值权限" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="-80" y="360" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-44" value="名称" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-44" value="名称" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="80" y="440" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-48" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="ikCD32b5rJxaaIhKNZvf-47" target="ikCD32b5rJxaaIhKNZvf-2">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-48" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="ikCD32b5rJxaaIhKNZvf-47" target="ikCD32b5rJxaaIhKNZvf-2" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-47" value="姓名" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxCell id="ikCD32b5rJxaaIhKNZvf-47" value="姓名" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
|
||||
<mxGeometry x="-80" y="200" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="rXf3g1vUlJZsvpexLucj-1" value="密码" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="120" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
|
@ -80,8 +80,6 @@ private:
|
||||
Device device;
|
||||
|
||||
QStatusBar *statusBar;
|
||||
QStackedWidget *stackedWidget;
|
||||
|
||||
QCheckBox *readerConnectStatusCheckBox;
|
||||
QLabel *comNumberLabel;
|
||||
QCheckBox *databaseConnectStatusCheckBox;
|
||||
|
@ -378,9 +378,7 @@ void MainWindow::on_cardRecordQueryButton_clicked()
|
||||
|
||||
query.finish();
|
||||
query.prepare(QString("select time, type, value, balance, device, id from record_view "
|
||||
"where cardId = :cardId and id = :recordId;"));
|
||||
query.bindValue(":cardId", cardId);
|
||||
|
||||
"where id = :recordId;"));
|
||||
|
||||
std::vector<QStringList> transactionRecordList;
|
||||
for (int i = 0; i < cardRecordIdList.size(); i++)
|
||||
|
@ -248,13 +248,14 @@ QStringList Reader::readAllRecords(QString cardId, bool &ok)
|
||||
{
|
||||
QStringList recordList;
|
||||
|
||||
int recordNum, recordStartIndex;
|
||||
bool success = readRecordNumber(recordNum, recordStartIndex, cardId);
|
||||
int recordNum, recordIndex;
|
||||
bool success = readRecordNumber(recordNum, recordIndex, cardId);
|
||||
if (!success)
|
||||
{
|
||||
ok = false;
|
||||
return recordList;
|
||||
}
|
||||
int recordStartIndex = ((recordIndex - recordNum + 1) % maxRecordNum + maxRecordNum) % maxRecordNum;
|
||||
|
||||
uchar_t cardIdHex[8] = {0};
|
||||
StringToHex(cardId.toLatin1().data(), cardIdHex);
|
||||
|
@ -36,7 +36,6 @@ public:
|
||||
void disconnect();
|
||||
QStringList inventory(int maxViccNum);
|
||||
bool insertRecord(QString record, QString cardId);
|
||||
bool writeRecords(QStringList recordList, QString cardId);
|
||||
QStringList readAllRecords(QString cardId, bool &ok);
|
||||
bool initCard(QString cardId);
|
||||
};
|
||||
|
@ -50,7 +50,7 @@ void MainWindow::on_reportLossButton_clicked()
|
||||
|
||||
// 查询学/工号是否存在
|
||||
QSqlQuery query(db->getDatabase());
|
||||
query.prepare(QString("select id from card "
|
||||
query.prepare(QString("select `status` from card "
|
||||
"where userId = :userId;"));
|
||||
query.bindValue(":userId", userId);
|
||||
bool success = query.exec();
|
||||
@ -64,6 +64,12 @@ void MainWindow::on_reportLossButton_clicked()
|
||||
QMessageBox::warning(this, "提示", "学/工号不存在,挂失失败。");
|
||||
return;
|
||||
}
|
||||
int cardStatus = query.value("status").toInt();
|
||||
if (cardStatus == -1)
|
||||
{
|
||||
QMessageBox::warning(this, "提示", "该卡已挂失,不可重复挂失。");
|
||||
return;
|
||||
}
|
||||
|
||||
QString info, prompt = QString("如需挂失该学/工号绑定的卡,请输入密码。");
|
||||
success = verifyUser(userId, prompt, info);
|
||||
|