Files
STM32F4-Base/Drivers/BSP/UI/ui_page_reset.c
T
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

154 lines
7.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:UI Page reset (强制复归内容页)
* 模块功能:装置维护 → 强制复归 叶子(node 25,#P 受密码保护)的内容页——
* 复用 ui_page_action 共享确认链(一次确认 → 二次确认 → 执行回报),
* 并在同一屏画一行"保护动作 N"(N = 当前处于动作态的保护元件个数):
* 复归前 N > 0、复归请求被 protectTask 消费后 N 归 0,这个变化就是
* "动作位真的复归了"的屏上证据,不用翻页、不用外接表;
* 执行只做两件事:投复归请求 + 补一条本地操作记录留痕;
* 只读进入(查看密码)整页拒执行并显式说"没权限"(LOCK)——
* 破坏性动作不给"看着像能按"的第二次机会;
* 本文件零 App include、零存储触点(分层方向由注入表守住)
* 为什么这么薄:确认链的形态(含二次确认与回报)是共享件,四个维护/操作类叶子
* 共用一份实现;本文件只把"这一页问什么、执行什么、观测什么"三项
* 配置接进框架的描述符骨架(同 ui_page_runlog 之于 ui_w_records)
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-26
* 修改记录:
* v1.0 2026-10-26 DTU 项目组 创建(道F task-3;判据 docs/任务规划/UI补齐.md
* §2 第 3 行「强制复归确认后动作位复归且有 SOE」)
*/
/* 头文件包含区 */
#include "ui_page_reset.h"
#include "ui_content_page.h"
#include "ui_data.h"
#include "ui_page_action.h"
/* 私有宏定义区 */
/*
* 本地这条操作记录的描述串:ASCII 20 字节 < SYSLOG_DESC_MAX(28)。
* 与远端那条(App/protocol/iec104/iec104_pts.c 的 "force reset")**刻意不同串**——
* 操作记录是审计面,两条一样就再也分不出"是主站下发的还是现场有人按面板",
* 而那正是查遥控事故时第一个要问的问题。
* 为什么由页面投而不是由 prot_elm_request_reset() 投:那条函数在 algo 层,
* 在那里投会把 sys_log.h 拽进算法层(并把记录通道的依赖摊到 test/host/prot_dim
* 的 include 路径上);而"这是本地发起的"这个事实只有页面知道(口径真源
* App/log/README.md 五类记录表 + task-10 结论)。
*/
#define RS_OPER_NOTE "force reset by panel"
/* 私有函数声明区(静态初始化器要引用下面两个函数的地址,故先声明) */
static bool rs_ok(void);
static uint32_t rs_watch(void);
/* 静态变量定义区 */
/*
* 本页操作页实例(配置全为 Flash 字面量与函数地址;运行态两字节由组件写)。
* 字段顺序 = ui_page_action_t 声明序(ARMCC v5 = C99 要求指定顺序一致)。
*/
static ui_page_action_t s_act = {
"确认复归保护?", /* prompt:问句用字已在字库(确/认/复/归/保/护 + '?') */
"已请求复归", /* done_text:回报"请求已受理",不谎称"已复归完成" */
rs_ok, /* ok_cb */
1u, /* need_modify:只读进入一律拒执行 */
"保护动作", /* watch_label(用字全在既有子集内;曾拟"动作元件",
其中"元"不在子集 —— 见本行下方注释与终报) */
rs_watch, /* watch_cb */
0u, /* stage(运行态初值) */
0u /* err (运行态初值) */
};
/* 函数定义区 */
/*
* 函数功能:执行投递——请求复归,受理成功后补投本地操作记录
* 入口参数:无
* 返回值:true = 已受理(组件转成功回报);false = 拒收(组件显示 ERR) bool
* 限定条件:由 ui_page_action_key 在第二次 ENTER 时调用(uiTask 上下文)
* 函数说明:两条腿的次序即判据——**先请求后留痕**:请求被拒时一条记录都不投,
* 给一次没发生过的操作写审计记录,比少一条记录坏得多(同
* App/task/iec104_serv.c 对时留痕"只在真改成功之后才投"那条纪律)。
* 维护通道未注入(装配缺一半)也走拒收这条腿:屏上显 ERR,
* 比"按了像成功其实什么都没发生"诚实
*/
static bool rs_ok(void) {
if (ui_data_maint_reset_req() != 0) {
return false;
}
(void)ui_data_maint_oper_note(RS_OPER_NOTE);
return true;
}
/*
* 函数功能:取当前处于动作态的保护元件数(观测行 "保护动作 N" 的 N)
* 入口参数:无
* 返回值:元件数(未注入时 0) uint32_t
* 限定条件:绘制路径可直调(一次转发,零 I/O、零锁)
* 函数说明:⚠ 台架判据的前提要写清:产品构建现处"未标定闭锁"
* (App/task/protect_task.c 停走判据),闭锁态下元件本就是复位态,
* "N 从 >0 变 0"这一眼要等两点标定解卡后才成立;解卡前该判据
* 退化为"页面受理 + 操作记录落一条",不得把闭锁态报成复归无效
*/
static uint32_t rs_watch(void) {
return ui_data_maint_active_count();
}
/*
* 函数功能:开页复位确认链(框架 init_cb)
* 入口参数:无
* 返回值:无
* 限定条件:框架开页链内调用
* 函数说明:复位由组件做(stage/err 是它的运行态),本页不重复清一遍
*/
static void pg_init(void) {
ui_page_action_init(&s_act);
}
/*
* 函数功能:自绘(框架 draw_cb;四行居中全由组件画)
* 入口参数:a_layer / a_clip - 契约见 ui_content_page.h
* 返回值:无
* 限定条件:框架绘制链末尾调用
*/
static void pg_draw(lv_layer_t *a_layer, const lv_area_t *a_clip) {
ui_page_action_draw(&s_act, a_layer, a_clip);
}
/*
* 函数功能:按键转发(框架 key_cb)
* 入口参数:a_key - LVGL 键值 lv_key_t
* 返回值:true = 本页已消费;false = 交回框架 bool
* 限定条件:框架按键链内
* 函数说明:确认链的判定全在组件里(含只读拒执行),本页只如实透传返回值,
* 不在这层"顺手"加判据——两处各判一次早晚分家
*/
static bool pg_key(lv_key_t a_key) {
return (ui_page_action_key(&s_act, a_key) != 0u);
}
/*
* 页面描述符(外部链接:生成物 ui_page_registry.c 按菜单树 #page=reset 绑定引用)
* 表单/操作页形态:无浅 V、无页脚、无行列表(用户密钥页与网口设置页先例);
* edit_capable=1 是**能不能改**的那半,另半(本次进入授予的权限)由
* ui_content_page_is_editable() 给——两半都在,组件才能判出"只读";
* key_intercept=0:LEFT 不拦截,关页 = 取消(本链没有"编辑到一半"的状态要保)
*/
const content_page_def_t ui_page_reset_desc = {
.id = "reset",
.title = "强制复归",
.hide_deco = 1u,
.hide_footer = 1u,
.selectable = 0u,
.key_intercept = 0u,
.edit_capable = 1u,
.init_cb = pg_init,
.draw_cb = pg_draw,
.key_cb = pg_key,
};