# 人脸识别考勤系统 基于 Qt 6 Quick/QML 开发的跨平台人脸识别考勤管理客户端,用于连接考勤服务端,完成签到记录查看、筛选导出、统计分析、签到时段配置、学生与班级名称映射、人脸照片与学号绑定等管理工作。 本项目是纪田野的个人毕业设计作品,主要用于人脸识别考勤场景的功能展示、系统联调和学习研究。 ## 项目特点 - 跨平台客户端:支持 Windows 桌面端和 Android 端构建。 - 单窗口管理:考勤记录、统计分析、配置中心、人脸管理和系统说明集中在一个界面中。 - 响应式界面:针对手机窄屏做了独立布局适配,避免控件重叠和文字遮挡。 - 数据导出:支持将考勤记录和统计报表导出为 CSV 文件。 - 本地配置缓存:服务端地址、签到时段、映射配置会保存到本地。 - 自动重连:服务端不可达时自动重连,并使用简短状态提示。 - Android 字体优化:Android 端使用原生文字渲染,并降低粗体权重,减少中文粗体重影。 - Android 路径兼容:Gradle 配置已允许中文路径构建,并启用 AndroidX。 ## 技术栈 | 分类 | 内容 | | --- | --- | | 开发语言 | C++17、QML | | UI 框架 | Qt Quick / Qt Quick Controls 2 | | Qt 模块 | Core、Gui、Qml、Quick、QuickControls2、Network | | 构建系统 | CMake 3.16+ | | 桌面编译器 | MinGW / MSVC / Clang / GCC | | Android 构建 | Qt for Android、Android SDK、Android NDK、JDK | | 加密处理 | AES-128-CBC,代码位于 `src/CryptoUtils.cpp` | ## 目录结构 ```text rewrite_qt/ ├── android/ # Android 打包补充资源和 Gradle 配置 │ ├── gradle.properties │ └── res/mipmap-*/ # Android 启动图标 ├── assets/ # 桌面端图标资源 ├── cmake/ # 平台相关模板文件 ├── qml/ │ └── Main.qml # 主界面 ├── src/ │ ├── ApiClient.* # 服务端 API 客户端 │ ├── AppController.* # QML 与业务逻辑中枢 │ ├── AttendanceTypes.h # 考勤数据结构 │ ├── CryptoUtils.* # AES 解密工具 │ ├── *ListModel.* # 暴露给 QML 的列表模型 │ └── crypto/tiny_aes.hpp # AES 底层实现 ├── CMakeLists.txt ├── LICENSE ├── README.md └── main.cpp ``` ## 功能说明 ### 考勤记录 考勤记录页用于查看和管理服务端同步下来的签到记录。 - 查看总记录数、今日签到数、当前筛选结果数。 - 按班级、学号、姓名关键字筛选记录。 - 按全部时间、今天、最近 7 天、最近 30 天、指定日期筛选。 - 刷新最新记录。 - 导出当前筛选结果为 CSV。 - 清空服务端全部考勤记录。 导出字段: ```text 签到时间,班级编号,班级名称,学号,姓名,置信度,状态 ``` ### 统计分析 统计分析页基于当前加载的考勤记录在本地计算统计结果。 - 支持今天、最近 7 天、最近 30 天、本月等快捷范围。 - 支持手动指定开始日期和结束日期。 - 展示统计学生数、统计记录数、统计范围。 - 按学生汇总总签到次数、今日签到次数、最后签到时间和平均置信度。 - 导出统计报表为 CSV。 导出字段: ```text 学号,姓名,总签到次数,今日签到,最后签到时间,平均置信度 ``` ### 配置中心 配置中心用于维护客户端与服务端交互所需的配置。 - 设置服务端地址。 - 测试服务端连接状态。 - 管理签到时段。 - 从服务端同步签到时段。 - 管理学号到姓名的映射。 - 管理班级编号到班级名称的映射。 - 保存配置并同步到服务端。 默认签到时段: | 名称 | 开始时间 | 结束时间 | 默认状态 | | --- | --- | --- | --- | | 上午签到 | 08:00 | 09:30 | 启用 | | 中午签退 | 12:00 | 13:00 | 启用 | | 下午签到 | 14:00 | 15:00 | 启用 | | 晚上签退 | 17:00 | 18:30 | 启用 | ### 人脸管理 人脸管理页用于维护 K210 上传的人脸照片记录与真实学号之间的映射关系。 - 同步人脸照片 ID。 - 同步服务端学生 ID。 - 展示人脸照片或无照片状态。 - 为人脸 ID 绑定真实学号。 - 保存人脸 ID 与学号映射。 - 删除指定人脸信息。 - 可选择同时删除该学生相关考勤记录。 照片访问地址格式: ```text {serverUrl}/api/face_photo/{id}?ts={timestamp} ``` 其中 `ts` 用于避免缓存导致照片不刷新。 ## 服务端配置 默认服务端地址: ```text http://27.106.113.205:8082 ``` 应用启动后会从本地配置读取已保存的服务端地址。用户可在“配置中心”中修改并保存。 本地保存键名: ```text server/url ``` ## 服务端 API 客户端会基于服务端地址拼接 `/api` 前缀访问接口。 | 方法 | 路径 | 用途 | | --- | --- | --- | | `GET` | `/api/records?limit={limit}&offset={offset}` | 获取考勤记录 | | `GET` | `/api/statistics` | 获取总数、今日数和服务端时间 | | `POST` | `/api/clear` | 清空全部记录 | | `DELETE` | `/api/record?timestamp={timestamp}&student_id={studentId}` | 删除单条记录 | | `GET` | `/api/timeslots` | 获取签到时段 | | `POST` | `/api/timeslots` | 保存签到时段 | | `GET` | `/api/mapping_config` | 获取学生和班级映射 | | `POST` | `/api/mapping_config` | 保存学生和班级映射 | | `GET` | `/api/face_id_mapping` | 获取人脸 ID 到学号映射 | | `POST` | `/api/face_id_mapping` | 保存人脸 ID 到学号映射 | | `GET` | `/api/face_photos` | 获取照片 ID 列表 | | `GET` | `/api/all_student_ids` | 获取所有学生 ID | | `GET` | `/api/face_photo/{id}` | 获取人脸照片 | | `DELETE` | `/api/face/{studentId}` | 删除人脸信息 | | `DELETE` | `/api/face/{studentId}?delete_records=true` | 删除人脸信息并删除相关考勤记录 | | `GET` | `/api/health` | 健康检查 | ### 考勤记录格式 `/api/records` 解密后应返回 JSON 数组。单条记录示例: ```json { "timestamp": "2026-04-24 08:10:23", "student_id": "20240001", "name": "张三", "confidence": 0.9821, "status": "success", "class_id": "1" } ``` ### 统计数据格式 ```json { "total": 120, "today": 8, "server_time": "2026-04-24 10:30:00" } ``` ### 签到时段格式 ```json { "time_slots": [ { "name": "上午签到", "start_time": "08:00", "end_time": "09:30", "enabled": true } ] } ``` ### 映射配置格式 ```json { "student_name_map": { "20240001": "张三" }, "class_name_map": { "1": "软件工程一班" } } ``` ### 人脸映射格式 ```json { "mappings": { "face_001": "20240001" } } ``` ## 加密响应 客户端对 `/api/records` 和 `/api/statistics` 请求添加请求头: ```text X-Encrypted-Response: true ``` 客户端期望服务端返回 Base64 编码的 AES-128-CBC 密文。 解密参数位于 `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` | ## 本地配置文件 应用使用 `QSettings` 和 `QStandardPaths::AppDataLocation` 保存本地状态。 | 配置 | 保存位置 | | --- | --- | | 服务端地址 | `QSettings`,键名 `server/url` | | 学生和班级映射 | `mapping_config.json` | | 签到时段配置 | `timeslot_config.json` | 应用信息: ```text ApplicationName: 人脸识别考勤系统 ApplicationVersion: 3.0.0 OrganizationName: STM32 Face Recognition ``` ## 构建环境 ### 基础要求 - Qt 6.2 或更高版本 - CMake 3.16 或更高版本 - 支持 C++17 的编译器 Windows 桌面端推荐使用 Qt 6.x MinGW 64-bit Kit。 Android 端需要额外配置: - Qt for Android - Android SDK - Android NDK - JDK - Android 平台版本,例如 `android-35` ## 使用 Qt Creator 构建 1. 打开 Qt Creator。 2. 选择项目根目录下的 `CMakeLists.txt`。 3. 选择对应 Kit,例如 Desktop Qt 6.x 或 Qt for Android。 4. 等待 CMake 配置完成。 5. 构建目标 `apprewrite_qt`。 6. 桌面端可直接运行;Android 端可部署到设备或模拟器。 ## 命令行构建 Windows 示例: ```powershell cmake -S . -B build -DCMAKE_PREFIX_PATH=D:/Qt/6.10.0/mingw_64 cmake --build build --target apprewrite_qt ``` Linux 示例: ```bash cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x/gcc_64 cmake --build build --target apprewrite_qt ``` 安装到系统路径: ```bash cmake --install build ``` ## Windows 独立运行 直接双击构建出来的 `apprewrite_qt.exe` 时,如果提示找不到 `Qt6Gui.dll`、`Qt6Core.dll` 等动态库,需要使用 `windeployqt` 收集运行时依赖。 示例: ```powershell D:\Qt\6.10.0\mingw_64\bin\windeployqt.exe "D:\path\to\build\Desktop_Qt_6_10_0_MinGW_64_bit-Debug\apprewrite_qt.exe" ``` 如果项目路径包含中文导致部署工具输出异常,建议复制 exe 到纯英文路径后部署: ```powershell mkdir C:\tmp\rewrite_qt_release copy "D:\path\to\apprewrite_qt.exe" C:\tmp\rewrite_qt_release\ D:\Qt\6.10.0\mingw_64\bin\windeployqt.exe C:\tmp\rewrite_qt_release\apprewrite_qt.exe ``` 部署完成后,将整个发布目录一起复制到目标电脑运行。 ## Android 构建说明 Android 相关配置位于 `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" ``` Android 补充配置位于 `android/gradle.properties`: ```properties android.overridePathCheck=true android.useAndroidX=true ``` 说明: - `android.overridePathCheck=true` 用于绕过 Windows 下 Android Gradle 对中文路径的检查。 - `android.useAndroidX=true` 用于启用 AndroidX,避免依赖检查失败。 - Android 桌面显示名由 `QT_ANDROID_APP_NAME` 设置为“人脸识别考勤系统”。 - Android 启动图标位于 `android/res/mipmap-*`。 如果 Android 构建目录已经生成过旧的 Gradle 工程,修改配置后建议清理对应构建目录或重新运行 CMake 配置。 ## 图标资源 桌面端图标位于 `assets/`: ```text assets/favicon.ico assets/favicon-16x16.png assets/favicon-32x32.png assets/favicon-48x48.png assets/favicon-64x64.png assets/favicon-128x128.png assets/favicon-192x192.png assets/favicon-256x256.png ``` Android 启动图标位于: ```text android/res/mipmap-mdpi/ic_launcher.png android/res/mipmap-hdpi/ic_launcher.png android/res/mipmap-xhdpi/ic_launcher.png android/res/mipmap-xxhdpi/ic_launcher.png android/res/mipmap-xxxhdpi/ic_launcher.png ``` 图标尺寸: | 目录 | 尺寸 | | --- | --- | | `mipmap-mdpi` | 48x48 | | `mipmap-hdpi` | 72x72 | | `mipmap-xhdpi` | 96x96 | | `mipmap-xxhdpi` | 144x144 | | `mipmap-xxxhdpi` | 192x192 | ## 界面与移动端适配 主界面位于 `qml/Main.qml`,采用 `ApplicationWindow`、`StackLayout`、`GridLayout`、`ColumnLayout` 等组件组织页面。 当前界面包含五个页面: - 考勤记录 - 统计分析 - 配置中心 - 人脸管理 - 关于 移动端适配要点: - `phoneLayout` 用于 560px 以下窄屏布局。 - 顶部页签使用统一的 `MobileNavTabButton` 样式。 - 考勤筛选区使用两列布局,按钮等宽排布。 - 统计页前两张统计卡左右排布,统计范围独占一整行。 - 表格在窄屏隐藏部分非关键列,避免横向溢出。 - 空状态卡片会根据可用高度自动缩小。 - Android 端使用 `sans-serif` 字体和 `Font.Medium` 加粗权重,减少粗体重影。 ## 运行状态提示 客户端通过底部 Toast 展示状态信息。服务端不可达时,提示会被压缩为简短文案: ```text 服务器未连接,稍后重试 ``` 重连过程中显示: ```text 正在重连服务器 ``` 这样可以避免将底层网络错误、URL 和长异常文本直接展示给用户。 ## 常见问题 ### Android 构建提示项目路径包含中文 项目已经在 `android/gradle.properties` 中配置: ```properties android.overridePathCheck=true ``` 如果仍然失败,清理 Android 构建目录后重新构建。 ### Android 构建提示 AndroidX 未启用 项目已经在 `android/gradle.properties` 中配置: ```properties android.useAndroidX=true ``` 如果旧构建目录仍然报错,删除生成的 `android-build-*` 目录后重新部署。 ### Android 端粗体文字重影 项目在 Android 端启用了原生文字渲染: ```cpp QQuickWindow::setTextRenderType(QQuickWindow::NativeTextRendering); ``` 同时 QML 中将 Android 端粗体权重降为 `Font.Medium`,避免合成粗体产生重影。 ### Windows 双击 exe 提示缺少 Qt DLL 使用 `windeployqt` 部署依赖后再运行。部署时建议使用和构建 Kit 一致的 Qt 目录。 ### 修改图标后没有变化 重新运行 CMake 配置并重新构建。Windows 资源管理器可能缓存 exe 图标,可尝试换构建目录、改输出文件名或重启资源管理器。 ### 启动后没有数据 检查服务端地址是否正确,并在配置中心点击“测试连接”。如果服务端不可达,底部会显示简短连接失败提示。 ### 姓名或班级显示不正确 在配置中心维护学生姓名映射和班级名称映射,保存后记录列表和统计结果会重新计算。 ### 人脸照片不显示 检查 `/api/face_photos` 是否返回照片 ID,并确认 `/api/face_photo/{id}` 可以访问。 ## 仓库与作者 仓库地址: ```text ssh://git@git.yzfh.eu.cc:2084/yzfh/qt.git ``` 作者: ```text 纪田野 ``` 关于页中也展示了仓库地址和查看账号信息。若项目公开发布,请避免在仓库中提交真实密码。 ## 维护建议 - 不要提交 `build/`、`build-codex/` 等构建目录。 - 修改 QML 后建议运行 `qmlformat` 保持格式一致。 - 服务端记录量超过 1000 条时,需要扩展分页加载逻辑。 - 服务端加密参数变化时,需要同步修改 `src/CryptoUtils.cpp`。 - 发布桌面版本时,使用 Qt 部署工具收集运行时依赖。 - 发布 Android 版本时,建议补充签名配置和 release 构建流程。 - 如果需要修改历史提交作者,请在推送前完成,避免远程协作历史冲突。 ## 开源协议 本项目采用 MIT License 开源,详见 `LICENSE` 文件。