更新文档
This commit is contained in:
+297
-489
@@ -1,150 +1,200 @@
|
||||
# Qt管理端当前功能文档
|
||||
# Qt 管理端文档
|
||||
|
||||
## 1. 文档目的
|
||||
## 1. Qt 管理端是什么
|
||||
|
||||
本文档用于说明 `QT/` 管理端重构后的实际架构、当前已经实现的功能、服务端接口依赖、构建方式和已知限制。
|
||||
Qt 管理端是整个系统的图形化后台。它支持 Windows 桌面端和 Android 端,主要用于:
|
||||
|
||||
本文结论以当前源码为准,不再沿用旧版 Widgets 管理端中 `MainWindow`、`NetworkApiManager`、多个独立 `Dialog` 的描述。
|
||||
1. 查看考勤记录。
|
||||
2. 按班级、学号、姓名、日期筛选记录。
|
||||
3. 导出记录 CSV。
|
||||
4. 查看统计分析。
|
||||
5. 导出统计 CSV。
|
||||
6. 配置服务端地址。
|
||||
7. 配置签到时间段。
|
||||
8. 配置学号到姓名、班级编号到班级名的显示映射。
|
||||
9. 查看 K210 上传的人脸照片。
|
||||
10. 给 K210 face_id 绑定真实学号。
|
||||
11. 删除人脸信息,并可选择删除相关考勤记录。
|
||||
|
||||
## 2. 模块定位
|
||||
## 2. 相关文件
|
||||
|
||||
Qt 管理端是人脸识别考勤系统的跨平台管理客户端,主要负责:
|
||||
| 文件 | 作用 |
|
||||
| --- | --- |
|
||||
| `QT/main.cpp` | Qt 程序入口,设置应用信息、图标、QML 引擎 |
|
||||
| `QT/qml/Main.qml` | 主界面,包括所有页面和对话框 |
|
||||
| `QT/src/AppController.*` | QML 与 C++ 业务逻辑的中枢 |
|
||||
| `QT/src/ApiClient.*` | HTTP API 客户端 |
|
||||
| `QT/src/AttendanceTypes.h` | 考勤记录、统计、时间段结构体 |
|
||||
| `QT/src/CryptoUtils.*` | AES 解密工具 |
|
||||
| `QT/src/RecordListModel.*` | 考勤记录模型 |
|
||||
| `QT/src/StatisticsListModel.*` | 统计模型 |
|
||||
| `QT/src/TimeSlotListModel.*` | 时间段模型 |
|
||||
| `QT/src/MappingListModel.*` | 姓名/班级映射模型 |
|
||||
| `QT/src/FaceListModel.*` | 人脸管理模型 |
|
||||
| `QT/CMakeLists.txt` | Qt/CMake 构建配置 |
|
||||
| `QT/android/` | Android Gradle 配置和图标 |
|
||||
| `QT/assets/` | 桌面端图标 |
|
||||
|
||||
- 从服务端拉取考勤记录、统计信息和配置数据。
|
||||
- 查看、筛选、导出考勤记录。
|
||||
- 按学生维度生成本地统计报表。
|
||||
- 管理服务端地址、签到时间段、学生姓名映射、班级名称映射。
|
||||
- 管理 K210 上传的人脸照片和人脸 ID 到学号的绑定关系。
|
||||
- 在服务端不可达时给出简短状态提示,并自动重连。
|
||||
## 3. 技术栈
|
||||
|
||||
当前 Qt 端已经重构为 Qt 6 Quick/QML 架构,主要源码位置如下:
|
||||
| 分类 | 内容 |
|
||||
| --- | --- |
|
||||
| 语言 | C++17、QML |
|
||||
| UI | Qt Quick、Qt Quick Controls 2 |
|
||||
| Qt 模块 | Core、Gui、Qml、Quick、QuickControls2、Network |
|
||||
| 构建系统 | CMake 3.16+ |
|
||||
| 样式 | `QQuickStyle::setStyle("Basic")` |
|
||||
| Android 文字渲染 | `NativeTextRendering` |
|
||||
| 本地配置 | `QSettings`、`QStandardPaths::AppDataLocation` |
|
||||
|
||||
| 模块 | 路径 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 程序入口 | `QT/main.cpp` | 初始化应用信息、图标、QML 引擎和 `AppController` |
|
||||
| 主界面 | `QT/qml/Main.qml` | 单窗口 QML 页面,包含记录、统计、配置、人脸、关于五个页面 |
|
||||
| 业务中枢 | `QT/src/AppController.*` | 连接 QML 和业务逻辑,负责筛选、统计、配置保存、重连调度 |
|
||||
| 网络接口 | `QT/src/ApiClient.*` | 封装 HTTP API、请求超时、加密响应解密和 JSON 解析 |
|
||||
| 数据结构 | `QT/src/AttendanceTypes.h` | 考勤记录、统计项、签到时段等结构定义 |
|
||||
| 列表模型 | `QT/src/*ListModel.*` | 向 QML 暴露记录、统计、时间段、映射、人脸列表 |
|
||||
| 加密工具 | `QT/src/CryptoUtils.*` | AES-128-CBC Base64 响应解密 |
|
||||
| AES 实现 | `QT/src/crypto/tiny_aes.hpp` | AES 底层实现 |
|
||||
| 构建配置 | `QT/CMakeLists.txt` | Qt 6 CMake 构建、资源、图标、Android 配置 |
|
||||
| 平台资源 | `QT/assets/`、`QT/android/`、`QT/cmake/` | 桌面图标、Android 图标与平台模板 |
|
||||
## 4. 应用基础信息
|
||||
|
||||
## 3. 技术栈与界面结构
|
||||
位置:`QT/main.cpp`
|
||||
|
||||
当前客户端使用:
|
||||
| 项 | 值 |
|
||||
| --- | --- |
|
||||
| ApplicationName | `人脸识别考勤系统` |
|
||||
| ApplicationVersion | `3.0.0` |
|
||||
| OrganizationName | `STM32 Face Recognition` |
|
||||
| 主 QML | `qrc:/qml/Main.qml` |
|
||||
| 默认窗口大小 | `1560 x 920` |
|
||||
| PC 最小窗口 | `900 x 620` |
|
||||
| Android 最小窗口 | `360 x 560` |
|
||||
|
||||
- C++17
|
||||
- Qt 6.2+
|
||||
- Qt Quick / Qt Quick Controls 2
|
||||
- Qt Core、Gui、Qml、Quick、QuickControls2、Network
|
||||
- CMake 3.16+
|
||||
## 5. 页面结构
|
||||
|
||||
界面由 `ApplicationWindow` 承载,内部使用 `StackLayout` 切换五个页面:
|
||||
Qt 管理端是单窗口应用,共 5 个页面:
|
||||
|
||||
- 考勤记录
|
||||
- 统计分析
|
||||
- 配置中心
|
||||
- 人脸管理
|
||||
- 关于
|
||||
| 页面 | 作用 |
|
||||
| --- | --- |
|
||||
| 考勤记录 | 查看、筛选、导出、清空记录 |
|
||||
| 统计分析 | 按时间范围统计学生签到情况 |
|
||||
| 配置中心 | 服务端地址、签到时间段、名称映射 |
|
||||
| 人脸管理 | 查看照片、绑定学号、删除人脸 |
|
||||
| 关于 | 系统说明、版本和作者信息 |
|
||||
|
||||
QML 不直接访问网络。所有页面操作统一调用 `AppController` 暴露的 `Q_INVOKABLE` 方法和 `Q_PROPERTY` 状态,数据表格通过 `RecordListModel`、`StatisticsListModel`、`TimeSlotListModel`、`MappingListModel`、`FaceListModel` 渲染。
|
||||
PC 宽屏显示左侧导航栏;窄屏和 Android 显示顶部/底部更紧凑的导航布局。
|
||||
|
||||
## 4. 当前已实现功能
|
||||
## 6. 网络访问规则
|
||||
|
||||
### 4.1 启动与服务连接
|
||||
|
||||
应用启动流程:
|
||||
|
||||
1. `main.cpp` 创建 `QGuiApplication`。
|
||||
2. 设置应用名称、版本、组织名和窗口图标。
|
||||
3. Android 平台启用原生文字渲染,改善中文粗体显示。
|
||||
4. 创建 `AppController`。
|
||||
5. 将 `appController` 注入 QML 上下文。
|
||||
6. 加载 `qrc:/qml/Main.qml`。
|
||||
|
||||
`AppController` 构造时会:
|
||||
|
||||
- 读取本地服务端地址、映射配置和时间段配置。
|
||||
- 设置 `ApiClient` 的服务端地址。
|
||||
- 启动健康检查。
|
||||
- 如果服务端可用,同步记录、统计、时间段和映射配置。
|
||||
- 如果服务端不可用,进入自动重连流程。
|
||||
|
||||
默认服务端地址:
|
||||
Qt 端的服务端地址默认是:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:8082
|
||||
```
|
||||
|
||||
用户可以在“配置中心”修改服务端地址。保存后会写入 `QSettings` 的 `server/url`,下次启动会读取并使用。
|
||||
用户可在“配置中心”修改服务端地址。保存后写入本地 `QSettings`:
|
||||
|
||||
### 4.2 自动重连与状态提示
|
||||
```text
|
||||
server/url
|
||||
```
|
||||
|
||||
当前实现了基于 `/api/v1/system/health` 的连接检查:
|
||||
`ApiClient::buildUrl` 会在地址后自动拼接 `/api`,例如:
|
||||
|
||||
- 网络请求超时时间为 5 秒。
|
||||
- 服务端不可达时显示简短提示:`服务器未连接,稍后重试`。
|
||||
- 自动重连间隔为 5 秒。
|
||||
- 重连期间显示:`正在重连服务器`。
|
||||
- 服务恢复后自动刷新记录、统计、时间段、映射和人脸相关数据。
|
||||
```text
|
||||
服务端地址: http://127.0.0.1:8082
|
||||
传入 endpoint: /v1/system/health
|
||||
实际请求: http://127.0.0.1:8082/api/v1/system/health
|
||||
```
|
||||
|
||||
底部 Toast 会展示状态信息,避免把底层网络错误、URL 和长异常文本直接暴露给用户。
|
||||
所有请求都会带:
|
||||
|
||||
### 4.3 考勤记录查看
|
||||
```text
|
||||
X-Api-Token: <Token>
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
“考勤记录”页用于查看服务端同步下来的签到记录。
|
||||
Token 默认值写在 `QT/src/ApiClient.cpp`,也可以通过环境变量覆盖:
|
||||
|
||||
当前实现:
|
||||
```powershell
|
||||
$env:ATTENDANCE_API_TOKEN="你的Token"
|
||||
```
|
||||
|
||||
- 默认请求最新 `1000` 条记录。
|
||||
- 顶部显示总记录数、今日签到数、筛选结果数。
|
||||
- 记录按签到时间倒序显示。
|
||||
- 支持刷新记录。
|
||||
- 支持清空服务端全部考勤记录。
|
||||
- 支持导出当前筛选结果为 CSV。
|
||||
网络超时:
|
||||
|
||||
记录表格字段:
|
||||
```text
|
||||
5000 ms
|
||||
```
|
||||
|
||||
- 签到时间
|
||||
- 班级
|
||||
- 学号
|
||||
- 姓名
|
||||
- 置信度
|
||||
- 状态
|
||||
## 7. 启动流程
|
||||
|
||||
显示规则:
|
||||
Qt 启动后:
|
||||
|
||||
- 班级优先使用“班级编号 -> 班级名称”映射;未配置时显示原班级编号。
|
||||
- 姓名优先使用“学号 -> 姓名”映射;未配置时回退到服务端记录中的原始姓名。
|
||||
- 状态会被归一化判断是否成功,成功和失败在界面上使用不同样式显示。
|
||||
1. `main.cpp` 创建 `QGuiApplication`。
|
||||
2. 设置应用图标、应用名、版本号、组织名。
|
||||
3. Android 下启用原生文字渲染。
|
||||
4. 创建 `AppController`。
|
||||
5. `AppController` 读取本地服务端地址、映射配置、时间段配置。
|
||||
6. `ApiClient` 设置当前服务端地址。
|
||||
7. 启动自动重连状态并执行健康检查。
|
||||
8. QML 载入 `Main.qml`。
|
||||
9. QML 通过上下文对象 `appController` 调用 C++。
|
||||
|
||||
### 4.4 记录筛选
|
||||
## 8. 自动重连
|
||||
|
||||
记录页支持本地筛选。筛选条件包括:
|
||||
如果健康检查失败,`AppController` 会进入重连状态。
|
||||
|
||||
- 班级
|
||||
- 学号
|
||||
- 姓名关键字
|
||||
- 日期范围
|
||||
相关参数:
|
||||
|
||||
日期范围支持:
|
||||
```text
|
||||
ReconnectIntervalMs = 5000
|
||||
```
|
||||
|
||||
- 全部时间
|
||||
- 今天
|
||||
- 最近 7 天
|
||||
- 最近 30 天
|
||||
- 指定日期
|
||||
重连成功后,如果之前处于重连中,会调用:
|
||||
|
||||
筛选基于当前已经加载到客户端内存中的记录执行,不会为每次筛选重新请求服务端。
|
||||
1. `refreshAll()`
|
||||
2. `refreshFaces()`
|
||||
|
||||
### 4.5 记录导出与清空
|
||||
这样服务端恢复后,记录、配置、照片和映射会重新同步。
|
||||
|
||||
当前筛选结果可以导出为 CSV 文件。
|
||||
## 9. 考勤记录页
|
||||
|
||||
导出内容包括:
|
||||
功能:
|
||||
|
||||
1. 显示服务端记录。
|
||||
2. 显示总记录数、今日记录数、当前筛选结果数。
|
||||
3. 按班级筛选。
|
||||
4. 按学号筛选。
|
||||
5. 按姓名关键字筛选。
|
||||
6. 按日期范围筛选。
|
||||
7. 导出当前筛选结果。
|
||||
8. 清空服务端所有记录。
|
||||
|
||||
记录加载默认请求:
|
||||
|
||||
```text
|
||||
GET /api/v1/attendance/records?limit=1000&offset=0
|
||||
```
|
||||
|
||||
注意:当前 Qt 统计和筛选主要基于已加载的记录。如果服务端超过 1000 条,界面统计不一定覆盖全部历史记录。
|
||||
|
||||
## 10. 筛选规则
|
||||
|
||||
筛选在 Qt 本地完成。
|
||||
|
||||
支持:
|
||||
|
||||
| 筛选项 | 说明 |
|
||||
| --- | --- |
|
||||
| 班级 | `class_id` 匹配 |
|
||||
| 学号 | `student_id` 匹配 |
|
||||
| 姓名 | 映射姓名或原始 name 包含关键字 |
|
||||
| 日期 | 全部、今天、最近 7 天、最近 30 天、指定日期 |
|
||||
|
||||
姓名显示优先级:
|
||||
|
||||
1. 如果学生映射里有该学号,显示映射姓名。
|
||||
2. 否则显示服务端记录中的 `name`。
|
||||
3. 如果都没有,则显示原始学号。
|
||||
|
||||
班级显示优先级:
|
||||
|
||||
1. 如果班级映射里有该 `class_id`,显示映射班级名。
|
||||
2. 否则显示 `class_id`。
|
||||
|
||||
## 11. 记录导出
|
||||
|
||||
导出 CSV 文件时会写入:
|
||||
|
||||
```text
|
||||
# 考勤记录导出
|
||||
@@ -153,76 +203,85 @@ http://127.0.0.1:8082
|
||||
签到时间,班级编号,班级名称,学号,姓名,置信度,状态
|
||||
```
|
||||
|
||||
“清空记录”会调用服务端 `/api/v1/attendance/records/clear`。界面在执行前会弹出确认对话框,并提示该操作不可恢复。
|
||||
字段会做 CSV 转义,包含逗号、双引号、换行时会自动加引号并转义。
|
||||
|
||||
需要注意:当前界面只开放“清空全部记录”,没有在记录表中开放单条删除或批量删除入口。
|
||||
## 12. 统计分析页
|
||||
|
||||
### 4.6 统计分析
|
||||
统计页基于当前加载记录在本地计算。
|
||||
|
||||
“统计分析”页基于当前加载到客户端的考勤记录,在本地按学生维度计算统计结果。
|
||||
支持时间范围:
|
||||
|
||||
支持:
|
||||
1. 今天。
|
||||
2. 最近 7 天。
|
||||
3. 最近 30 天。
|
||||
4. 本月。
|
||||
5. 自定义开始和结束日期。
|
||||
|
||||
- 快捷选择统计范围。
|
||||
- 手动输入开始日期和结束日期。
|
||||
- 显示统计学生数、统计记录数、统计范围。
|
||||
- 导出统计报表 CSV。
|
||||
统计指标:
|
||||
|
||||
统计字段:
|
||||
|
||||
- 学号
|
||||
- 姓名
|
||||
- 总签到次数
|
||||
- 今日签到次数
|
||||
- 最后签到时间
|
||||
- 平均置信度
|
||||
| 指标 | 含义 |
|
||||
| --- | --- |
|
||||
| 统计学生数 | 当前范围内出现过的学生数量 |
|
||||
| 统计记录数 | 当前范围内记录数量 |
|
||||
| 总签到次数 | 每个学生在范围内的记录数量 |
|
||||
| 今日签到 | 每个学生今天的记录数量 |
|
||||
| 最后签到时间 | 每个学生最新一条记录时间 |
|
||||
| 平均置信度 | 每个学生记录的平均 confidence |
|
||||
|
||||
导出字段:
|
||||
|
||||
```text
|
||||
考勤统计报表,<范围>
|
||||
学号,姓名,总签到次数,今日签到,最后签到时间,平均置信度
|
||||
```
|
||||
|
||||
统计结果不是服务端全量统计,而是对当前客户端已经拉取的最多 `1000` 条记录进行本地计算。
|
||||
## 13. 配置中心
|
||||
|
||||
### 4.7 配置中心
|
||||
配置中心包含三块:
|
||||
|
||||
“配置中心”集中管理服务连接、签到时间段和名称映射。
|
||||
1. 服务端地址。
|
||||
2. 时间段配置。
|
||||
3. 名称映射配置。
|
||||
|
||||
#### 服务端地址
|
||||
### 13.1 服务端地址
|
||||
|
||||
支持:
|
||||
|
||||
- 查看当前服务端地址。
|
||||
- 修改并保存服务端地址。
|
||||
- 测试服务端连接。
|
||||
|
||||
保存后会写入本地 `QSettings`:
|
||||
字段示例:
|
||||
|
||||
```text
|
||||
server/url
|
||||
http://27.106.113.205:8082
|
||||
```
|
||||
|
||||
#### 签到时间段
|
||||
按钮:
|
||||
|
||||
支持:
|
||||
| 按钮 | 作用 |
|
||||
| --- | --- |
|
||||
| 保存地址 | 写入 `QSettings`,并立即切换 `ApiClient` 的服务端 |
|
||||
| 测试连接 | 请求 `/api/v1/system/health` |
|
||||
|
||||
- 查看当前时间段。
|
||||
- 新增时间段。
|
||||
- 编辑时间段。
|
||||
- 删除时间段。
|
||||
- 恢复默认时间段。
|
||||
- 从服务端同步时间段。
|
||||
- 保存时间段到本地并上传服务端。
|
||||
### 13.2 时间段配置
|
||||
|
||||
默认时间段:
|
||||
时间段格式:
|
||||
|
||||
| 名称 | 开始时间 | 结束时间 | 默认状态 |
|
||||
| --- | --- | --- | --- |
|
||||
| 上午签到 | 08:00 | 09:30 | 启用 |
|
||||
| 中午签退 | 12:00 | 13:00 | 启用 |
|
||||
| 下午签到 | 14:00 | 15:00 | 启用 |
|
||||
| 晚上签退 | 17:00 | 18:30 | 启用 |
|
||||
```json
|
||||
{
|
||||
"name": "上午签到",
|
||||
"start_time": "08:00",
|
||||
"end_time": "09:30",
|
||||
"enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
当前默认时间段为空。第一次使用时需要手动新增。
|
||||
|
||||
按钮:
|
||||
|
||||
| 按钮 | 作用 |
|
||||
| --- | --- |
|
||||
| 展开/收起 | 展示或隐藏时间段列表 |
|
||||
| 新增时段 | 打开新增对话框 |
|
||||
| 清空时段 | 清空本地时间段并保存同步到服务端 |
|
||||
| 从服务器同步/同步 | 从服务端读取时间段;服务端为空数组时也会清空本地时间段 |
|
||||
| 保存时间段/保存 | 保存到本地并上传服务端 |
|
||||
|
||||
本地文件:
|
||||
|
||||
@@ -230,20 +289,25 @@ server/url
|
||||
timeslot_config.json
|
||||
```
|
||||
|
||||
#### 名称映射
|
||||
如果本地文件中刚好是旧版本四个默认时间段,当前代码会自动迁移为空配置。
|
||||
|
||||
支持两类映射:
|
||||
### 13.3 名称映射配置
|
||||
|
||||
- 学号 -> 姓名
|
||||
- 班级编号 -> 班级名称
|
||||
学生映射:
|
||||
|
||||
支持操作:
|
||||
```json
|
||||
{
|
||||
"20240001": "张三"
|
||||
}
|
||||
```
|
||||
|
||||
- 新增映射。
|
||||
- 直接编辑映射键和值。
|
||||
- 删除映射。
|
||||
- 从服务端加载映射配置。
|
||||
- 保存到本地并上传服务端。
|
||||
班级映射:
|
||||
|
||||
```json
|
||||
{
|
||||
"1": "软件工程一班"
|
||||
}
|
||||
```
|
||||
|
||||
本地文件:
|
||||
|
||||
@@ -251,378 +315,122 @@ timeslot_config.json
|
||||
mapping_config.json
|
||||
```
|
||||
|
||||
映射会影响记录列表和统计报表中的姓名、班级显示。
|
||||
## 14. 人脸管理页
|
||||
|
||||
### 4.8 人脸管理
|
||||
人脸管理页把三类数据合并展示:
|
||||
|
||||
“人脸管理”页用于维护 K210 上传的人脸照片和人脸 ID 到学号的绑定关系。
|
||||
1. 服务端照片列表。
|
||||
2. 服务端已有学生 ID。
|
||||
3. 服务端 face_id 到学生 ID 映射。
|
||||
|
||||
当前实现:
|
||||
如果服务端已经把照片从原始 face_id 文件名重命名为学号文件名,Qt 仍会把已有映射中的原始 face_id 展示出来,保存时保留这类真实映射,并跳过未编辑的“ID 等于学号”的默认占位项。
|
||||
|
||||
- 从服务端同步人脸照片 ID。
|
||||
- 从服务端同步全部学生 ID。
|
||||
- 从服务端同步人脸 ID 到学号的映射。
|
||||
- 合并照片 ID 和学生 ID,生成统一管理列表。
|
||||
- 显示照片或“无照片”状态。
|
||||
- 编辑人脸 ID 对应的学号。
|
||||
- 保存人脸映射到服务端。
|
||||
- 删除指定人脸。
|
||||
- 删除时可选择同时删除该学生相关考勤记录。
|
||||
用户可以:
|
||||
|
||||
照片加载方式:
|
||||
1. 刷新人脸库。
|
||||
2. 为每张照片填写真实学号。
|
||||
3. 保存映射。
|
||||
4. 删除人脸。
|
||||
5. 删除人脸时选择是否同时删除该学生的考勤记录。
|
||||
|
||||
照片下载流程:
|
||||
|
||||
1. Qt 获取照片 ID 列表。
|
||||
2. 对每个 ID 请求 `/api/v1/faces/photos/<id>`。
|
||||
3. 下载成功后保存到本地缓存目录:
|
||||
|
||||
```text
|
||||
ApiClient -> GET /api/v1/faces/photos/{id} -> 本地 file:// 缓存 -> QML Image
|
||||
<AppDataLocation>/face_photos/<id>.jpg
|
||||
```
|
||||
|
||||
这样可以在请求照片时携带 `X-Api-Token`,避免 QML `Image` 直接访问受鉴权接口导致照片加载失败。
|
||||
4. QML 使用本地 file URL 显示图片。
|
||||
|
||||
### 4.9 关于页面
|
||||
## 15. 关于页面
|
||||
|
||||
“关于”页展示:
|
||||
关于页显示:
|
||||
|
||||
- 系统简介。
|
||||
- 功能范围。
|
||||
- 毕业设计说明。
|
||||
- 作者和仓库信息。
|
||||
1. 系统用途。
|
||||
2. 功能范围。
|
||||
3. 毕业设计说明。
|
||||
4. 作者和版权信息。
|
||||
5. 仓库地址。
|
||||
6. 演示账号信息。
|
||||
|
||||
当前关于页是 QML 页面的一部分,不再是独立窗口。
|
||||
这些文本在 `QT/qml/Main.qml` 中。
|
||||
|
||||
### 4.10 桌面端和移动端适配
|
||||
## 16. PC 和 Android 适配
|
||||
|
||||
当前 QML 已对窄屏进行适配:
|
||||
当前 QML 中有这些布局断点:
|
||||
|
||||
- `phoneLayout` 用于手机宽度布局。
|
||||
- 顶部导航在窄屏下使用紧凑按钮。
|
||||
- 筛选区、统计卡片和配置区会根据宽度调整列数。
|
||||
- 表格在窄屏下隐藏部分非关键列或调整宽度。
|
||||
- Android 端使用原生文字渲染并降低粗体权重,减少中文粗体重影。
|
||||
|
||||
## 5. 服务端 API 依赖
|
||||
|
||||
客户端基于服务端地址拼接 `/api` 前缀访问接口。刷新全部数据时优先使用统一同步接口:
|
||||
|
||||
| 方法 | 路径 | 用途 |
|
||||
| 属性 | 条件 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| `GET` | `/api/v1/sync/state?client=qt&last_version={version}` | 按版本同步 Qt 所需完整状态 |
|
||||
| `compactLayout` | `width < 1460` | PC 紧凑布局 |
|
||||
| `denseLayout` | `width < 1380` | 更密集显示 |
|
||||
| `narrowLayout` | `width < 1280` | 表格列裁剪 |
|
||||
| `slimLayout` | `width < 1040` | 隐藏侧边栏,使用移动导航 |
|
||||
| `phoneLayout` | PC 小于 560,Android 小于 640 | 手机布局 |
|
||||
|
||||
服务端版本无变化时返回 `changed:false`,Qt 不再重复拉取全部数据。局部刷新和保存操作使用下列 v1 子接口。
|
||||
Android 特殊处理:
|
||||
|
||||
| 方法 | 路径 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| `GET` | `/api/v1/attendance/records?limit={limit}&offset={offset}` | 获取考勤记录 |
|
||||
| `GET` | `/api/v1/attendance/statistics` | 获取总数、今日数和服务端时间 |
|
||||
| `POST` | `/api/v1/attendance/records/clear` | 清空全部记录 |
|
||||
| `DELETE` | `/api/v1/attendance/records?timestamp={timestamp}&student_id={studentId}` | 删除单条记录,当前 API 层保留,界面未开放 |
|
||||
| `GET` | `/api/v1/config/time-slots` | 获取签到时段 |
|
||||
| `POST` | `/api/v1/config/time-slots` | 保存签到时段 |
|
||||
| `GET` | `/api/v1/config/mappings` | 获取学生和班级映射 |
|
||||
| `POST` | `/api/v1/config/mappings` | 保存学生和班级映射 |
|
||||
| `GET` | `/api/v1/faces/mappings` | 获取人脸 ID 到学号映射 |
|
||||
| `POST` | `/api/v1/faces/mappings` | 保存人脸 ID 到学号映射 |
|
||||
| `GET` | `/api/v1/faces/photos` | 获取照片 ID 列表 |
|
||||
| `GET` | `/api/v1/faces/student-ids` | 获取所有学生 ID |
|
||||
| `GET` | `/api/v1/faces/photos/{id}` | 获取人脸照片 |
|
||||
| `DELETE` | `/api/v1/faces/{studentId}` | 删除人脸信息 |
|
||||
| `DELETE` | `/api/v1/faces/{studentId}?delete_records=true` | 删除人脸信息并删除相关考勤记录 |
|
||||
| `GET` | `/api/v1/system/health` | 健康检查 |
|
||||
1. 最小窗口宽度是 `360`。
|
||||
2. 最小窗口高度是 `560`。
|
||||
3. 字体使用 `sans-serif`。
|
||||
4. 粗体权重降低为 `Font.Medium`。
|
||||
5. 使用原生文字渲染,减少中文粗体重影。
|
||||
|
||||
### 5.1 考勤记录格式
|
||||
配置页卡片现在使用内容自适应高度,避免按钮遮挡。
|
||||
|
||||
`/api/v1/attendance/records` 解密后应返回 JSON 数组,单条记录示例:
|
||||
## 17. 本地持久化
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-04-24 08:10:23",
|
||||
"student_id": "20240001",
|
||||
"name": "张三",
|
||||
"confidence": 0.9821,
|
||||
"status": "success",
|
||||
"class_id": "1"
|
||||
}
|
||||
```
|
||||
Qt 使用两类本地持久化。
|
||||
|
||||
字段处理规则:
|
||||
### 17.1 QSettings
|
||||
|
||||
- `timestamp` 需要符合 `yyyy-MM-dd HH:mm:ss`。
|
||||
- `student_id` 不能为空。
|
||||
- `class_id` 为空时客户端按 `"0"` 处理。
|
||||
- `status` 可以是字符串、布尔值或数字,客户端会统一转换为显示状态。
|
||||
- `timestamp` 以 `0000-` 开头的记录会被忽略。
|
||||
|
||||
### 5.2 统计数据格式
|
||||
|
||||
```json
|
||||
{
|
||||
"total": 120,
|
||||
"today": 8,
|
||||
"server_time": "2026-04-24 10:30:00"
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 签到时段格式
|
||||
|
||||
```json
|
||||
{
|
||||
"time_slots": [
|
||||
{
|
||||
"name": "上午签到",
|
||||
"start_time": "08:00",
|
||||
"end_time": "09:30",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 5.4 映射配置格式
|
||||
|
||||
```json
|
||||
{
|
||||
"student_name_map": {
|
||||
"20240001": "张三"
|
||||
},
|
||||
"class_name_map": {
|
||||
"1": "软件工程一班"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.5 人脸映射格式
|
||||
|
||||
```json
|
||||
{
|
||||
"mappings": {
|
||||
"face_001": "20240001"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 加密响应
|
||||
|
||||
客户端对 `/api/v1/attendance/records` 和 `/api/v1/attendance/statistics` 请求添加请求头:
|
||||
保存服务端地址:
|
||||
|
||||
```text
|
||||
X-Encrypted-Response: true
|
||||
server/url
|
||||
```
|
||||
|
||||
客户端期望服务端返回 Base64 编码的 AES-128-CBC 密文。收到响应后处理流程为:
|
||||
### 17.2 AppDataLocation 文件
|
||||
|
||||
1. Base64 解码。
|
||||
2. AES-128-CBC 解密。
|
||||
3. PKCS#7 去填充。
|
||||
4. 解析 JSON。
|
||||
|
||||
加密参数位于 `QT/src/CryptoUtils.cpp`:
|
||||
|
||||
| 参数 | 值 |
|
||||
| 文件 | 内容 |
|
||||
| --- | --- |
|
||||
| 算法 | AES-128-CBC |
|
||||
| Padding | PKCS#7 |
|
||||
| Key | `2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c` |
|
||||
| IV | `00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f` |
|
||||
| `timeslot_config.json` | 时间段配置 |
|
||||
| `mapping_config.json` | 学生姓名和班级名称映射 |
|
||||
| `face_photos/*.jpg` | 下载后的人脸照片缓存 |
|
||||
|
||||
如果服务端没有按加密格式返回,记录和统计接口会解析失败。
|
||||
## 18. 构建方式
|
||||
|
||||
## 7. 本地配置持久化
|
||||
|
||||
应用使用 `QSettings` 和 `QStandardPaths::AppDataLocation` 保存本地状态。
|
||||
|
||||
应用信息:
|
||||
|
||||
```text
|
||||
ApplicationName: 人脸识别考勤系统
|
||||
ApplicationVersion: 3.0.0
|
||||
OrganizationName: STM32 Face Recognition
|
||||
```
|
||||
|
||||
本地保存内容:
|
||||
|
||||
| 配置 | 保存方式 |
|
||||
| --- | --- |
|
||||
| 服务端地址 | `QSettings`,键名 `server/url` |
|
||||
| 学生姓名映射和班级名称映射 | `mapping_config.json` |
|
||||
| 签到时段配置 | `timeslot_config.json` |
|
||||
|
||||
`mapping_config.json` 和 `timeslot_config.json` 位于 Qt 返回的 `AppDataLocation` 目录中,不在项目源码目录内。
|
||||
|
||||
## 8. 构建与运行
|
||||
|
||||
### 8.1 推荐构建方式
|
||||
|
||||
当前推荐使用 CMake 构建。旧版 `qmake` / `.pro` 文档不再适用于重构后的 Qt Quick 版本。
|
||||
|
||||
基础要求:
|
||||
|
||||
- Qt 6.2 或更高版本
|
||||
- CMake 3.16 或更高版本
|
||||
- 支持 C++17 的编译器
|
||||
|
||||
Windows 桌面端推荐使用 Qt 6.x MinGW 64-bit Kit。
|
||||
|
||||
### 8.2 Qt Creator 构建
|
||||
### 18.1 Qt Creator
|
||||
|
||||
1. 打开 Qt Creator。
|
||||
2. 打开 `QT/CMakeLists.txt`。
|
||||
3. 选择 Desktop Qt 6.x 或 Android Kit。
|
||||
4. 等待 CMake 配置完成。
|
||||
5. 构建目标 `apprewrite_qt`。
|
||||
5. 构建 `apprewrite_qt`。
|
||||
6. 桌面端直接运行;Android 端部署到设备或模拟器。
|
||||
|
||||
### 8.3 命令行构建
|
||||
### 18.2 命令行示例
|
||||
|
||||
Windows 示例:
|
||||
Windows:
|
||||
|
||||
```powershell
|
||||
cmake -S QT -B QT/build -DCMAKE_PREFIX_PATH=D:/Qt/6.10.0/mingw_64
|
||||
cmake --build QT/build --target apprewrite_qt
|
||||
cd D:\University\graduation\code\Reconstruct_Qt\QT
|
||||
cmake -S . -B build\Desktop -DCMAKE_PREFIX_PATH=D:\Qt\6.10.0\mingw_64
|
||||
cmake --build build\Desktop
|
||||
```
|
||||
|
||||
Linux 示例:
|
||||
实际路径要按本机 Qt 安装位置调整。
|
||||
|
||||
```bash
|
||||
cmake -S QT -B QT/build -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x/gcc_64
|
||||
cmake --build QT/build --target apprewrite_qt
|
||||
```
|
||||
|
||||
安装:
|
||||
|
||||
```bash
|
||||
cmake --install QT/build
|
||||
```
|
||||
|
||||
当前 `QT/CMakeLists.txt` 将运行产物输出到:
|
||||
|
||||
```text
|
||||
QT/dist
|
||||
```
|
||||
|
||||
### 8.4 Windows 独立运行
|
||||
|
||||
直接双击 `apprewrite_qt.exe` 时,如果提示缺少 `Qt6Gui.dll`、`Qt6Core.dll` 等运行库,需要使用和构建 Kit 一致的 `windeployqt` 收集依赖。
|
||||
|
||||
示例:
|
||||
|
||||
```powershell
|
||||
D:\Qt\6.10.0\mingw_64\bin\windeployqt.exe QT\dist\apprewrite_qt.exe
|
||||
```
|
||||
|
||||
如果路径包含中文导致部署工具异常,可以把 exe 复制到纯英文路径后部署。
|
||||
|
||||
### 8.5 Android 构建
|
||||
|
||||
Android 相关配置位于 `QT/CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android"
|
||||
QT_ANDROID_APP_NAME "${REWRITE_QT_DISPLAY_NAME}"
|
||||
QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
|
||||
```
|
||||
|
||||
补充配置位于 `QT/android/gradle.properties`:
|
||||
|
||||
```properties
|
||||
android.overridePathCheck=true
|
||||
android.useAndroidX=true
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `android.overridePathCheck=true` 用于绕过 Windows 下 Android Gradle 对中文路径的检查。
|
||||
- `android.useAndroidX=true` 用于启用 AndroidX。
|
||||
- Android 应用显示名为“人脸识别考勤系统”。
|
||||
- Android 启动图标位于 `QT/android/res/mipmap-*`。
|
||||
|
||||
## 9. 图标与资源
|
||||
|
||||
桌面图标资源位于:
|
||||
|
||||
```text
|
||||
QT/assets/favicon.ico
|
||||
QT/assets/favicon-16x16.png
|
||||
QT/assets/favicon-32x32.png
|
||||
QT/assets/favicon-48x48.png
|
||||
QT/assets/favicon-64x64.png
|
||||
QT/assets/favicon-128x128.png
|
||||
QT/assets/favicon-192x192.png
|
||||
QT/assets/favicon-256x256.png
|
||||
```
|
||||
|
||||
Android 启动图标位于:
|
||||
|
||||
```text
|
||||
QT/android/res/mipmap-mdpi/ic_launcher.png
|
||||
QT/android/res/mipmap-hdpi/ic_launcher.png
|
||||
QT/android/res/mipmap-xhdpi/ic_launcher.png
|
||||
QT/android/res/mipmap-xxhdpi/ic_launcher.png
|
||||
QT/android/res/mipmap-xxxhdpi/ic_launcher.png
|
||||
```
|
||||
|
||||
Linux 桌面文件模板位于:
|
||||
|
||||
```text
|
||||
QT/cmake/rewrite_qt.desktop.in
|
||||
```
|
||||
|
||||
Windows 图标资源模板位于:
|
||||
|
||||
```text
|
||||
QT/cmake/app_icon.rc.in
|
||||
```
|
||||
|
||||
## 10. 当前已知限制
|
||||
|
||||
### 10.1 记录和统计最多基于当前加载的 1000 条记录
|
||||
|
||||
`AppController::refreshRecords()` 当前固定调用:
|
||||
|
||||
```cpp
|
||||
m_apiClient.fetchRecords(1000, 0);
|
||||
```
|
||||
|
||||
因此记录列表、筛选结果和本地统计都只覆盖客户端当前加载的记录。如果服务端历史记录超过 `1000` 条,统计页不等于全量历史统计。
|
||||
|
||||
### 10.2 筛选和统计为本地计算
|
||||
|
||||
班级、学号、姓名、日期筛选以及统计分析都在客户端内存中完成,不会向服务端传递筛选条件。
|
||||
|
||||
优点是交互响应快;限制是数据范围受当前加载记录影响。
|
||||
|
||||
### 10.3 单条删除 API 保留但界面未开放
|
||||
|
||||
`ApiClient` 中保留了 `deleteRecord()` 和 `/api/v1/attendance/records` 调用,`AppController` 也连接了删除完成信号,但当前 QML 记录表没有提供单条删除或批量删除入口。
|
||||
|
||||
因此当前对外说明时,不应把“单条记录删除”或“批量删除记录”描述为已开放功能。
|
||||
|
||||
### 10.4 自动刷新不是定时拉取记录
|
||||
|
||||
当前代码实现的是服务端不可达后的自动重连检查,不是固定周期自动刷新记录。
|
||||
|
||||
用户需要手动点击“刷新”或“刷新全部数据”同步最新数据;服务恢复连接时也会自动刷新。
|
||||
|
||||
### 10.5 时间输入缺少强校验
|
||||
|
||||
签到时间段编辑框使用字符串输入,代码按 `HH:mm` 解析。如果输入非法时间,模型层不会弹出明确错误提示,可能产生无效时间值。后续可补充输入掩码或校验提示。
|
||||
|
||||
### 10.6 CSV 导出未做字段转义
|
||||
|
||||
导出逻辑直接用逗号拼接字段。如果姓名、班级名或状态中包含逗号、换行或引号,CSV 可能被表格软件解析成错误列。后续可补充标准 CSV 转义函数。
|
||||
|
||||
### 10.7 照片 URL 依赖服务端静态接口
|
||||
|
||||
人脸照片由 `ApiClient` 通过 `/api/v1/faces/photos/{id}` 携带鉴权头下载,并缓存为本地 `file://` 地址后交给 QML 显示。如果服务端返回格式或图片 ID 与学生 ID 规则变化,客户端的人脸列表合并逻辑需要同步调整。
|
||||
|
||||
## 11. 当前结论
|
||||
|
||||
重构后的 Qt 管理端已经从旧版 Widgets 多窗口结构迁移为 Qt 6 Quick/QML 单窗口客户端。当前核心链路已经完整:
|
||||
|
||||
- 服务端连接与健康检查。
|
||||
- 加密记录和统计接口访问。
|
||||
- 考勤记录查看、筛选、导出、清空。
|
||||
- 本地统计分析和统计导出。
|
||||
- 服务端地址、时间段、学生映射、班级映射配置。
|
||||
- 人脸照片、人脸映射和删除管理。
|
||||
- Windows 桌面端与 Android 端构建配置。
|
||||
|
||||
当前主要不足集中在数据分页、全量统计、记录级删除入口、输入校验和 CSV 转义。后续如果要提升为更完整的管理端,应优先补充分页加载或服务端筛选统计接口,再补齐记录级管理操作。
|
||||
## 19. 常见问题
|
||||
|
||||
| 现象 | 可能原因 | 处理 |
|
||||
| --- | --- | --- |
|
||||
| 测试连接失败 | 服务端没启动、地址错、Token 不一致 | 检查服务端健康接口和 `ATTENDANCE_API_TOKEN` |
|
||||
| 页面按钮重叠 | 旧版固定高度导致内容被裁切 | 当前已改为自适应高度 |
|
||||
| Android 文字发虚/重影 | 字体渲染方式问题 | 当前 Android 使用原生渲染和中等粗体 |
|
||||
| 人脸照片不显示 | 下载失败、本地缓存路径无效、服务端无照片 | 刷新人脸库,看服务端 `faces/` |
|
||||
| 统计数量少于服务端总量 | Qt 默认只拉取 1000 条记录 | 增加分页或服务端统计接口 |
|
||||
| 时间段为空导致无法签到 | 当前默认就是空配置 | 在配置中心新增时间段并保存 |
|
||||
| 保存映射后 K210 没变化 | K210 尚未同步或 WiFi 不通 | 等待同步或检查 K210 日志 |
|
||||
|
||||
Reference in New Issue
Block a user