增加两页UI

This commit is contained in:
2026-09-09 13:18:06 +08:00
parent 8b8aac39a6
commit 146d160790
24 changed files with 1436 additions and 122 deletions
+30 -5
View File
@@ -16,6 +16,10 @@ simulator/
├── sim_port.c / sim_port.h # 模拟器显示/输入端口(SDL 窗口 + 键盘),替代 MCU 端 ui_port.c
├── lv_conf.h # 模拟器专用 LVGL 配置(与 MCU 端 Lib/lv_conf.h 相互独立)
├── i1_to_png.py # 截图转 PNG:把 --screenshot 的 I1(1bpp) 原始位图转成 PNG(见 §3.5)
├── tests/ # 无头回归脚本 + 黄金参考(见 §3.6,流程文档 docs/UI 设计/UI_自动化测试流程.md)
│ ├── check_menu_rows.py # 菜单 8 状态像素回归 + 池基线门禁
│ ├── check_content_pages.py # 内容页黄金参考回归 + 开页-关页往返池门禁(--update 刷参考)
│ └── ref/ # 黄金参考截图 shot_{info,ac,dc}.bin(I1 原始位图,随仓库提交)
├── dbg_log.h # 调试日志 stub:DBG_* 映射到 printf(覆盖 MCU 版头文件)
├── SDL2/
│ └── SDL2-2.32.10/ # SDL2 预编译 SDK(随仓库提供,无需安装)
@@ -38,6 +42,7 @@ simulator/
| `dbg_log.h` | MCU 版 `dbg_log.h` 依赖 `sys_clock.h`(RTC 时间戳),PC 无法编译。此 stub 把 `DBG_INFO/ERROR/DEBUG` 映射到 `printf`;因 `simulator/` 在 include 路径最前,**优先生效**覆盖 MCU 版 |
| `CMakeLists.txt` | 收集 LVGL 源码(`../Lib/lvgl`)+ 共享 UI 源码(`../Drivers/BSP/UI`)+ 本目录端口代码,链接预编译 SDL2,产出 `lvgl_sim.exe` |
| `i1_to_png.py` | 把 `--screenshot` 产出的 I1(1bpp) 原始位图转成 PNG,便于离线比对设计稿。详见 §3.5 |
| `tests/` | 无头回归脚本(菜单 8 状态像素回归、内容页黄金参考回归)+ 入库黄金参考截图。详见 §3.6 |
> **共享代码不复制**:`ui_menu.c` / `ui_font_cn_12.c` 直接引用 `Drivers/BSP/UI/` 下的原件,
> MCU 与 PC 两端永远同步。**不要**在本目录内复制 UI 源码。
@@ -170,9 +175,9 @@ cmake --build build --config Debug
cd simulator
# 1) 离屏渲染首帧,输出 I1(1bpp) 原始位图(已剥离 8 字节调色板,纯像素数据)
.\build\Debug\lvgl_sim.exe --screenshot shot.bin
# 2) 转 PNG(默认 160x160;--scale 放大便于查看)
python i1_to_png.py shot.bin # -> shot.png
python i1_to_png.py shot.bin -o 预览.png --scale 6
# 2) 转 PNG(默认 160x160;--scale 放大便于查看;python 统一用仓库 .venv,见 AGENTS.md「Python 环境」)
..\.venv\Scripts\python.exe i1_to_png.py shot.bin # -> shot.png
..\.venv\Scripts\python.exe i1_to_png.py shot.bin -o 预览.png --scale 6
```
**I1 位图格式**(`i1_to_png.py` 据此解析):1 位/像素,每字节 MSB 在左(bit7 = 该行最左像素),`bit=1` 前景 / `bit=0` 背景,每行 `宽/8` 字节、行内无填充。
@@ -188,7 +193,27 @@ python i1_to_png.py shot.bin -o 预览.png --scale 6
| `--fg / --bg` | 自定义前/背景色 `R,G,B`(默认黑白) |
| `--no-auto-palette` | 关闭调色板自动识别(按纯像素解析) |
> 依赖 Pillow(`pip install pillow`,本仓库已验证)。`shot.bin`/`shot*.png` 均已列入 `.gitignore`,可随时删除重生成。
> 依赖 Pillow(已含于仓库 `.venv`,见 `requirements.txt`)。`shot.bin`/`shot*.png` 均已列入 `.gitignore`,可随时删除重生成。
### 3.6 无头回归测试(tests/)
UI 改动的自动化门禁脚本(完整流程见 `docs/UI 设计/UI_自动化测试流程.md`)。脚本纯标准库、任意 python3 均可,为环境统一一律用仓库 `.venv`:
```powershell
# 仓库根目录执行(前置:本目录已构建出 build/Debug/lvgl_sim.exe)
.venv\Scripts\python.exe simulator/tests/check_menu_rows.py # 菜单 8 状态像素回归 + 池基线门禁
.venv\Scripts\python.exe simulator/tests/check_content_pages.py # 内容页黄金参考回归 + 开页-关页往返池门禁
```
| 脚本 | 原理 | 失败输出 |
|------|------|----------|
| `check_menu_rows.py` | 键序注入(u/d/e/s)跑 8 个菜单状态,断言选中行白带、非选行黑底白字、框体边框、往返状态逐像素一致;S0 池水位须等于脚本内 `MENU_POOL_BASELINE` | 未过断言清单 + 保留临时截图 |
| `check_content_pages.py` | 三内容页(info=`e` / ac=`dee` / dc=`dede`)无头截图与 `tests/ref/shot_*.bin` **逐字节**比对;另校验开页-关页往返池水位 = `POOL_AFTER_ROUNDTRIP` | 差异像素数 + 双方 ink runs 对照 |
- **黄金参考更新**(有意改视觉后):先肉眼确认新效果正确,再
`.venv\Scripts\python.exe simulator/tests/check_content_pages.py --update` 刷新 `ref/`,随代码提交。
- **池水位常量漂移**:菜单/页面结构变更导致门禁失败时,确认新值合理后再更新脚本内常量并登记流程文档变更记录;无法解释的漂移 = 内存回归 bug。
- 退出码均为 0=PASS / 1=断言失败 / 2=环境错误(exe 缺失等)。
---
@@ -208,7 +233,7 @@ python i1_to_png.py shot.bin -o 预览.png --scale 6
- `LV_USE_THEME_MONO = 1` 且 `sim_port_init` 中调用了 `lv_theme_mono_init`
- 主循环调用了 `lv_refr_now(NULL)`(PARTIAL 模式保证首帧)
- 没有重复设置 tick(SDL 驱动内部已 `lv_tick_set_cb`,**不要**再 `SDL_AddTimer` + `lv_tick_inc`)
4. **中文显示空白**:字体 `ui_font_cn_12` 是子集字体(当前 78 字),缺字渲染为空白。
4. **中文显示空白**:字体 `ui_font_cn_12` 是子集字体(当前 97 汉字 + ASCII,共 193 字形),缺字渲染为空白。
补字流程见 `docs/UI 设计/UI_中文字体生成与配置.md`(`tools/font_gen/` 两步脚本)。
5. **改了 UI 代码但模拟器没变化**:确认改的是 `Drivers/BSP/UI/ui_menu.c`(共享原件)而非本目录副本(本目录无副本),然后重新 `cmake --build`。
6. **编码**:UI 源码为 UTF-8(带 BOM),MSVC 已加 `/utf-8`。**不要**用 PowerShell `Set-Content` 等重写含中文的文件(编码铁律,见根目录 `AGENTS.md`)。