已完成

This commit is contained in:
2026-05-01 10:43:27 +08:00
parent b4aa0082a0
commit 9de69ba60d
+353 -263
View File
@@ -1,236 +1,102 @@
# 人脸识别考勤系统 Qt 客户端说明文档
# 人脸识别考勤系统
## 1. 项目简介
基于 Qt 6 Quick/QML 开发的跨平台人脸识别考勤管理客户端,用于连接考勤服务端,完成签到记录查看、筛选导出、统计分析、签到时段配置、学生与班级名称映射、人脸照片与学号绑定等管理工作。
本项目是基于 Qt 6 Quick/QML 开发的人脸识别考勤系统客户端,用于连接考勤服务端,完成考勤记录查看、筛选导出、统计分析、签到时段配置、学生和班级名称映射、人脸照片映射管理等功能。
本项目是纪田野的个人毕业设计作品,主要用于人脸识别考勤场景的功能展示、系统联调和学习研究。
程序入口为 `main.cpp`。启动后创建 `QGuiApplication` 和 `AppController`,并将 `AppController` 通过 QML 上下文属性 `appController` 暴露给 `qml/Main.qml`。界面由 QML 实现,业务逻辑、网络请求、数据模型、配置保存和 CSV 导出由 C++ 实现。
## 项目特点
默认服务端地址:
- 跨平台客户端:支持 Windows 桌面端和 Android 端构建。
- 单窗口管理:考勤记录、统计分析、配置中心、人脸管理和系统说明集中在一个界面中。
- 响应式界面:针对手机窄屏做了独立布局适配,避免控件重叠和文字遮挡。
- 数据导出:支持将考勤记录和统计报表导出为 CSV 文件。
- 本地配置缓存:服务端地址、签到时段、映射配置会保存到本地。
- 自动重连:服务端不可达时自动重连,并使用简短状态提示。
- Android 字体优化:Android 端使用原生文字渲染,并降低粗体权重,减少中文粗体重影。
- Android 路径兼容:Gradle 配置已允许中文路径构建,并启用 AndroidX。
```text
http://27.106.113.205:8082
```
## 技术栈
## 2. 技术栈
| 分类 | 内容 |
| --- | --- |
| 开发语言 | 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` |
- 语言:C++17、QML
- 框架:Qt 6.2 或更高版本
- Qt 模块:Core、Gui、Qml、Quick、QuickControls2、Network
- 构建系统:CMake 3.16 或更高版本
- 加密处理:AES-128-CBC,相关代码位于 `src/CryptoUtils.cpp`
## 3. 当前目录结构
## 目录结构
```text
rewrite_qt/
├── CMakeLists.txt
├── README.md
├── main.cpp
├── android/
│ └── res/
│ ├── mipmap-mdpi/ic_launcher.png
│ ├── mipmap-hdpi/ic_launcher.png
│ ├── mipmap-xhdpi/ic_launcher.png
│ ├── mipmap-xxhdpi/ic_launcher.png
│ └── mipmap-xxxhdpi/ic_launcher.png
├── assets/
│ ├── favicon.ico
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon-48x48.png
│ ├── favicon-64x64.png
│ ├── favicon-128x128.png
│ ├── favicon-192x192.png
│ └── favicon-256x256.png
├── cmake/
│ ├── app_icon.rc.in
│ └── rewrite_qt.desktop.in
├── android/ # Android 打包补充资源和 Gradle 配置
│ ├── gradle.properties
│ └── res/mipmap-*/ # Android 启动图标
├── assets/ # 桌面端图标资源
├── cmake/ # 平台相关模板文件
├── qml/
│ └── Main.qml
└── src/
├── ApiClient.h/.cpp
├── AppController.h/.cpp
├── AttendanceTypes.h
├── CryptoUtils.h/.cpp
├── FaceListModel.h/.cpp
├── MappingListModel.h/.cpp
├── RecordListModel.h/.cpp
├── StatisticsListModel.h/.cpp
├── TimeSlotListModel.h/.cpp
└── crypto/tiny_aes.hpp
│ └── 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
```
## 4. 构建与运行
## 功能说明
### 4.1 环境要求
### 考勤记录
需要安装:
考勤记录页用于查看和管理服务端同步下来的签到记录。
- Qt 6.2+
- CMake 3.16+
- 支持 C++17 的编译器,例如 MSVC、MinGW、Clang 或 GCC
Android 构建还需要配置 Qt for Android、Android SDK、Android NDK 和 JDK。
### 4.2 使用 Qt Creator
1. 打开项目根目录下的 `CMakeLists.txt`。
2. 选择合适的 Qt Kit,例如 Desktop Qt 6.x 或 Android Qt 6.x。
3. 重新配置 CMake。
4. 构建并运行目标 `apprewrite_qt`。
### 4.3 使用命令行
Windows 示例:
```powershell
cmake -S . -B build -DCMAKE_PREFIX_PATH=D:/Qt/6.10.0/mingw_64
cmake --build build
```
Linux 示例:
```bash
cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/Qt/6.x/gcc_64
cmake --build build
```
安装到系统路径:
```bash
cmake --install build
```
## 5. 多平台图标配置
项目已经配置为多平台使用同一套应用图标。
### 5.1 Windows
Windows exe 图标使用:
```text
assets/favicon.ico
```
CMake 会在 Windows 构建时根据 `cmake/app_icon.rc.in` 生成资源文件,并把图标嵌入到可执行文件中。
### 5.2 桌面运行时图标
`main.cpp` 会设置应用窗口图标:
```cpp
QIcon appIcon(QStringLiteral(":/assets/favicon.ico"));
```
同时会加入多尺寸 PNG 作为回退资源:
```text
assets/favicon-256x256.png
assets/favicon-192x192.png
assets/favicon-128x128.png
assets/favicon-64x64.png
assets/favicon-48x48.png
assets/favicon-32x32.png
assets/favicon-16x16.png
```
这些图标文件会被加入 Qt 资源系统,路径前缀为 `:/assets/...`。
### 5.3 Linux
Linux 安装时会生成 `.desktop` 文件:
```text
cmake/rewrite_qt.desktop.in
```
并把不同尺寸的 PNG 安装到:
```text
share/icons/hicolor/{size}x{size}/apps/rewrite_qt.png
```
`.desktop` 文件中使用的图标名为:
```text
rewrite_qt
```
### 5.4 Android
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 |
CMake 中 Android 相关配置:
```cmake
QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android"
QT_ANDROID_APP_NAME "人脸识别考勤系统"
QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
```
`QT_ANDROID_APP_NAME` 用于设置 Android 桌面显示名,`QT_ANDROID_APP_ICON` 用于设置启动图标。
## 6. 功能说明
### 6.1 考勤记录
考勤记录页支持:
- 查看总记录数、今日记录数、已加载记录数和当前筛选结果数。
- 按班级、学号、姓名关键字筛选。
- 按今天、最近 7 天、最近 30 天或指定日期范围筛选。
- 查看总记录数、今日签到数、当前筛选结果数。
- 按班级、学号、姓名关键字筛选记录。
- 按全部时间、今天、最近 7 天、最近 30 天、指定日期筛选。
- 刷新最新记录。
- 导出当前筛选结果为 CSV。
- 清空服务端全部考勤记录。
导出的记录 CSV 字段:
导出字段:
```text
签到时间,班级编号,班级名称,学号,姓名,置信度,状态
```
### 6.2 统计分析
### 统计分析
统计页基于已加载记录在本地计算,支持:
统计分析页基于当前加载的考勤记录在本地计算统计结果。
- 今天、最近 7 天、最近 30 天、本月等快捷范围。
- 自定义统计日期范围。
- 按学生汇总签到次数、今日签到次数、最后签到时间和平均置信度。
- 导出统计结果为 CSV。
- 支持今天、最近 7 天、最近 30 天、本月等快捷范围。
- 支持手动指定开始日期和结束日期。
- 展示统计学生数、统计记录数、统计范围。
- 按学生汇总总签到次数、今日签到次数、最后签到时间和平均置信度。
- 导出统计报表为 CSV。
导出的统计 CSV 字段:
导出字段:
```text
学号,姓名,总签到次数,今日签到,最后签到时间,平均置信度
```
### 6.3 配置中心
### 配置中心
配置中心包含:
配置中心用于维护客户端与服务端交互所需的配置。
- 服务端地址配置和连接测试。
- 签到时段新增、编辑、删除、启用和禁用。
- 学号到姓名的映射。
- 班级编号到班级名称的映射。
- 设置服务端地址。
- 测试服务端连接状态。
- 管理签到时段。
- 从服务端同步签到时段。
- 管理学号到姓名的映射。
- 管理班级编号到班级名称的映射。
- 保存配置并同步到服务端。
默认签到时段:
@@ -241,16 +107,17 @@ QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
| 下午签到 | 14:00 | 15:00 | 启用 |
| 晚上签退 | 17:00 | 18:30 | 启用 |
### 6.4 人脸管理
### 人脸管理
人脸管理页支持:
人脸管理页用于维护 K210 上传的人脸照片记录与真实学号之间的映射关系。
- 从服务端同步人脸照片 ID。
- 从服务端同步所有学生 ID。
- 展示人脸照片和绑定状态。
- 同步人脸照片 ID。
- 同步服务端学生 ID。
- 展示人脸照片或无照片状态。
- 为人脸 ID 绑定真实学号。
- 保存人脸 ID 与学号映射。
- 删除指定人脸信息,可选择同时删除该学生的考勤记录。
- 删除指定人脸信息。
- 可选择同时删除该学生相关考勤记录。
照片访问地址格式:
@@ -258,24 +125,27 @@ QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
{serverUrl}/api/face_photo/{id}?ts={timestamp}
```
`ts` 参数用于避免缓存导致照片不刷新。
其中 `ts` 用于避免缓存导致照片不刷新。
## 7. 核心模块
## 服务端配置
| 文件 | 说明 |
| --- | --- |
| `main.cpp` | 初始化应用、设置应用信息和图标、加载 QML |
| `qml/Main.qml` | 主界面和用户交互 |
| `src/AppController.*` | 应用业务中枢,连接 QML、模型和网络客户端 |
| `src/ApiClient.*` | HTTP API 客户端 |
| `src/*ListModel.*` | 暴露给 QML 的列表模型 |
| `src/AttendanceTypes.h` | 业务数据结构 |
| `src/CryptoUtils.*` | AES-128-CBC 解密工具 |
| `src/crypto/tiny_aes.hpp` | AES 底层实现 |
默认服务端地址:
## 8. 服务端 API
```text
http://27.106.113.205:8082
```
客户端会把服务端地址与 `/api` 前缀拼接后访问接口。
应用启动后会从本地配置读取已保存的服务端地址。用户可在“配置中心”中修改并保存。
本地保存键名:
```text
server/url
```
## 服务端 API
客户端会基于服务端地址拼接 `/api` 前缀访问接口。
| 方法 | 路径 | 用途 |
| --- | --- | --- |
@@ -296,7 +166,7 @@ QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
| `DELETE` | `/api/face/{studentId}?delete_records=true` | 删除人脸信息并删除相关考勤记录 |
| `GET` | `/api/health` | 健康检查 |
### 8.1 考勤记录格式
### 考勤记录格式
`/api/records` 解密后应返回 JSON 数组。单条记录示例:
@@ -311,7 +181,7 @@ QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
}
```
### 8.2 统计数据格式
### 统计数据格式
```json
{
@@ -321,7 +191,7 @@ QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
}
```
### 8.3 签到时段格式
### 签到时段格式
```json
{
@@ -336,7 +206,7 @@ QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
}
```
### 8.4 映射配置格式
### 映射配置格式
```json
{
@@ -349,7 +219,7 @@ QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
}
```
### 8.5 人脸映射格式
### 人脸映射格式
```json
{
@@ -359,25 +229,9 @@ QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
}
```
## 9. 本地配置
## 加密响应
应用会保存以下本地状态:
- 服务端地址:`QSettings`,键名为 `server/url`。
- 映射配置:`QStandardPaths::AppDataLocation/mapping_config.json`。
- 签到时段配置:`QStandardPaths::AppDataLocation/timeslot_config.json`。
应用信息:
```text
ApplicationName: 人脸识别考勤系统
ApplicationVersion: 3.0.0
OrganizationName: STM32 Face Recognition
```
## 10. 加密响应
`/api/records` 和 `/api/statistics` 请求会带上:
客户端对 `/api/records` 和 `/api/statistics` 请求添加请求头:
```text
X-Encrypted-Response: true
@@ -387,41 +241,277 @@ X-Encrypted-Response: true
解密参数位于 `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`
| 参数 | 值 |
| --- | --- |
| 算法 | 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` |
## 11. 常见问题
## 本地配置文件
### 11.1 修改图标后没有变化
应用使用 `QSettings` 和 `QStandardPaths::AppDataLocation` 保存本地状态。
先重新运行 CMake 配置,再重新构建。Windows 资源管理器可能缓存 exe 图标,可以尝试换构建目录、改输出文件名或重启资源管理器。
| 配置 | 保存位置 |
| --- | --- |
| 服务端地址 | `QSettings`,键名 `server/url` |
| 学生和班级映射 | `mapping_config.json` |
| 签到时段配置 | `timeslot_config.json` |
### 11.2 启动后没有数据
应用信息:
检查服务端地址是否正确,并在配置中心点击连接测试。如果服务端不可达,状态栏会显示错误信息。
```text
ApplicationName: 人脸识别考勤系统
ApplicationVersion: 3.0.0
OrganizationName: STM32 Face Recognition
```
### 11.3 姓名或班级显示不正确
## 构建环境
在配置中心维护学生姓名映射和班级名称映射,然后保存。保存后记录列表和统计结果会重新计算。
### 基础要求
### 11.4 人脸照片不显示
- 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}` 可以访问。
### 11.5 Android 图标不生效
## 仓库与作者
确认使用 Qt 6.9 或更高版本,并重新配置 Android Kit。图标资源位于 `android/res/mipmap-*`,CMake 使用 `QT_ANDROID_APP_ICON "@mipmap/ic_launcher"` 指定启动图标。
仓库地址:
## 12. 维护建议
```text
ssh://git@git.yzfh.eu.cc:2084/yzfh/qt.git
```
- 构建目录已从项目中清理,后续重新构建时由 Qt Creator 或 CMake 自动生成。
- 如果服务端记录量超过 1000 条,需要扩展分页加载逻辑。
- 如果服务端加密参数变化,需要同步修改 `src/CryptoUtils.cpp`。
- 如果要发布桌面版本,建议使用 Qt 部署工具收集运行时依赖。
- 如果要发布 Android 版本,建议补充签名配置和 release 构建流程。
作者:
## 13. 开源协议
```text
纪田野
```
关于页中也展示了仓库地址和查看账号信息。若项目公开发布,请避免在仓库中提交真实密码。
## 维护建议
- 不要提交 `build/`、`build-codex/` 等构建目录。
- 修改 QML 后建议运行 `qmlformat` 保持格式一致。
- 服务端记录量超过 1000 条时,需要扩展分页加载逻辑。
- 服务端加密参数变化时,需要同步修改 `src/CryptoUtils.cpp`。
- 发布桌面版本时,使用 Qt 部署工具收集运行时依赖。
- 发布 Android 版本时,建议补充签名配置和 release 构建流程。
- 如果需要修改历史提交作者,请在推送前完成,避免远程协作历史冲突。
## 开源协议
本项目采用 MIT License 开源,详见 `LICENSE` 文件。