Files
STM32F4-Base/ui_menu_tree.txt
wandering1 52e28885cb feat(UI): 装置维护 3 页落地(时钟 / 强制复归 / 清除记录),内容页黄金 27→40
三个薄页面模块 ui_page_clock / ui_page_reset / ui_page_clear,页面注册由生成器
自动写双端(裁定 A-1:「三叶各绑一页」与「零新增 .c」不可兼得,选薄页面加生成器,
不写手写 node switch——那种分发在增删叶子时会静默换功能,且没有任何门禁照得到)。

数据侧是注入式函数表:UI 不 include App 层的头。两条硬理由都实测过——分层方向
(layer-deps)之外,模拟器根本不链 sys_clock,ALLOW 豁免挡得住 layer-deps,
挡不住模拟器链接期。面板对时的唯一真判据是回读 RTC:sys_clock_set() 恒返 0
(RTC 写失败只打日志),所以真机侧写 1 后回读 1,最坏约 200 ms 落在一次「保存」
按键上,IWDG 800 ms 窗有余;上界与依据都写进注释。

「无时钟」徽标位置有两个像素级实测坑:放标题带右侧会被 4 字标题连成「时钟设置
无时钟」一句话;放页脚带左侧 x=7 会压住页脚——页脚从 x=6 起排,不是居中。
最终落在清单末行与页脚之间的空带 y=124。clear_done 那张顺带给出像素证据:
清 run.log 之后「操作记录」那一行从 2 变 3,页面上没缓存、没撒谎。

ui_w_records 的 UI_W_REC_LOG_* 顺序必须等于 syslog_id_t 顺序(7 类,只准尾追加),
已加编译期顺序守卫;执行侧 7 条映射表同样带编译期守卫。

测试与真值:内容页黄金 27 → 40 页(+13),文本断言 +68、反向断言 ABSENT +19;
27 张旧参考 git diff 为空 = 逐字节未变。往返池 5448 B 与菜单常驻堆 5368 B 均未变;
字库未扩(源码在用 171 并 KEEP_EXTRA 39 = 清单 183),font-charset 与 cn-chars、
cn-font 字节一致。@build 0 错误 0 警告;uiTask 静态最坏链 1,336 B / 16,384
(余 91%)与基线相同,页面钩子没进最坏链。

一条测试学结论单独留痕:反向断言不能当「位置不重叠」的证据——本脚本的字形匹配
把 y 带判得比字面宽(徽标在 125..136、页脚在 144..155,仍被 (140,160) 判命中)。
该防线改由正向断言「页脚未被徽标压住」承担(压字那一版实测过不了它)。

两条自我更正一并记档(作者自报,按真值而非原口径):
① 先前报「文案零新增汉字」是错的——观测行拟用「动作元件」,「元」不在子集,
cn-chars 与 font-charset 如实红;最终改「保护动作 N」才让「零新增」成为事实。
顺序是:先按机器红,再按真值写结论。
② 先前报「6 个文件 BOM 逐个核过」被 bom-guard 证伪:丢 BOM 发生在上一次编译之后,
正是 AGENTS 那句「历史 0 警告不代表安全」的活例;此后一律以退出码为准。

未覆盖项不假装:台架「N>0 → N=0」在产品构建的未标定闭锁期拿不到(闭锁期 N 恒 0),
判据显式退化为「页面受理 + 落一条操作记录」,写在 rs_watch 注释里。

生成物入库例外照用:uvprojx 只加 3 个 ui_page_ 的 FilePath(真增删源文件),
CMakeLists 同批;两处都由 gen_menu.py 自己写,没手写。

本笔先走了一次真钩子:20 条钩子实跑通过(ui-golden 菜单 8 状态加内容页 40 页、
generated-fresh、registration-check、font-charset、ui-data 单测、cppcheck、
coding-standard、bom、mojibake、id-check、doc-links 等),只有 mem-numbers 与
mem-budget 两条红——磁盘上的 .map 出自 20:39 那次构建、含三条在飞道的代码,
与 HEAD 台账必然不同码。按仓库既有约定(这两条等台账回填时允许 --no-verify 并
正文留证)落这一笔;回填由我统一在收尾一笔做。

三条在飞道(task-26 崩溃证据路径、task-16 与 task-17 谓词收敛和卷锁观测、
task-36 台架工具)的未暂存改动被 autostash 暂时收走,钩子看到的是 HEAD 加本笔;
过程中曾把 comm 道未跟踪的 iec104_comm.c 临时移出(它不在 stash 覆盖面内),
那次移出反而让 ui-golden 撞见 CMake 缓存里的悬空引用而红——已改用「先落 comm
那笔、再落本笔」的顺序消掉这个中间态。ui_data_maint_ready() 待删(只有测试在读
的自检口),排在本笔之后单独一笔。
2026-10-26 22:43:54 +08:00

61 lines
2.6 KiB
Plaintext

# 主菜单层级定义(声明式源)
# 规则:缩进即层级,每级 2 空格;`#` 开头为注释;空行忽略。
# 行尾可选 ` #P` = 该叶子需密码(密码页按所输密码授权:查看密码→只读 / 修改密码→可修改);无尾注 = 不需密码页(直接进,只读)。
# 密码值:Drivers/BSP/UI/ui_pwd_def.h 编译期配置(查看/修改各一个,改值 = 重新编译)。
# 行尾可选 ` #page=<模块名>` = 该叶子绑定一个内容页实例(UI 页面原型化的页面注册表):
# 模块名 = Drivers/BSP/UI/ui_page_<模块名>.c,其描述符符号须为 ui_page_<模块名>_desc。
# 声明了 #page 但实例文件缺失/符号不符 → 生成器报错(不产出半成品表)。
# 未被任何叶子 #page 引用的 ui_page_*.c 同样报错(写了却从不生效的死代码)。
# 注:密码页**不是**节点绑定的(任何 #P 叶子都进同一页),故由下方 @password 指令单独声明。
# 指令(整份文件级,写在注释行里):
# # @password=<模块名> = 需密码叶子统一进的内容页模块名(省略 = 无密码页)。
# 改菜单/改页面绑定只需编辑本文件,然后重跑:
# python tools/menu_gen/gen_menu.py
# 产物:Drivers/BSP/UI/ui_menu_tab.c / ui_menu_tab.h
# Drivers/BSP/UI/ui_page_registry.c / ui_page_registry.h(节点→页面注册表,自动生成)
# 生成器并自动把新增的 ui_page_*.c 写进 MDK-ARM/STM32F407-Demo.uvprojx 与
# simulator/CMakeLists.txt 两处显式列表(双端注册),无需手工编辑注册文件。
# @password=password
主界面
装置信息 #page=device_info
实时数据
交流量 #page=ac
直流量 #page=dc
遥信量 #page=yx
参数定值
整定
参数 #P #page=view_param
定值 #P #page=view_set
控制字 #P #page=view_word
软压板 #P #page=view_plate
查看
参数 #page=view_param
定值 #page=view_set
控制字 #page=view_word
软压板 #page=view_plate
三遥设置
遥测死区 #P
遥测系数 #P
遥信类型 #P
遥信防抖 #P
双点遥信 #P
装置维护
时钟设置 #P #page=clock
强制复归 #P #page=reset
手动录波 #P
清除记录 #P #page=clear
通讯参数
通讯设置 #P
网口设置 #P #page=net_cfg
SNTP设置 #P
记录查询
SOE记录 #page=soe
事故记录
操作记录
保护告警
保护启动
遥控记录
自检记录 #page=selftest
运行记录 #page=runlog
运行报告