/* * 模块名称:UI 记录页共享组件实现 * 模块功能:见 ui_w_records.h(逻辑照搬合并前的 ui_page_runlog.c / ui_page_selftest.c, * 两文件差异仅为记录源编号与符号名,其余逐字相同;数据经注入 reader 取) * 适用范围:Drivers/BSP/UI * 作者:王建锋 * 创建日期:2026-10-20 * 修改记录: * v1.0 2026-10-20 王建锋 创建(W6) * v2.0 2026-10-25 王建锋 reader 注入(道B task-6):syslog_count/syslog_get_record * 直调改为 s_reader 函数表调用;未注入按空态渲染 */ #include #include "ui_w_records.h" #include "ui_tokens.h" /* 静态变量定义区 */ /* 注入的记录 reader(模块级单例,理由见头注;NULL = 未注入 → 空态) */ static const ui_rec_reader_t *s_reader; /* 函数定义区 */ /* * 函数功能:注入记录 reader */ void ui_w_records_bind(const ui_rec_reader_t *a_reader) { s_reader = a_reader; } /* * 函数功能:按记录源编号查条数(不经行缓存的裸计数) * 入口参数:log_id - 记录源编号(UI_W_REC_LOG_*) uint8_t * 返回值:条数;未注入 reader 或编号未知一律 0,即空态,调用方按"无记录"显示 * uint16_t * 限定条件:uiTask 上下文(记录侧绘制/按键链) * 函数说明:为什么开这个口子——清除记录页要在 7 行上分行显示各类条数(点完 * "清除"之后条数归零就是它唯一的真反馈),而 reader 是本组件私有 * 的注入表;不开放一个只读入口,页面就只能自己去注第二份 reader, * 那正好把 task-6 刚削掉的分层反向边又接回来(口径见 * docs/UI设计/UI_数据供给设计说明.md §7.2/§7.3)。 * 本函数不带行缓存:缓存属于"某一条记录的字段",与条数无关 */ uint16_t ui_w_records_count_of(uint8_t a_log_id) { if (s_reader == NULL) { return 0u; } return s_reader->count(a_log_id); } /* * 函数功能:总行数(动态;每条记录 2 行,空日志 = 单条伪行"无记录") * 入口参数:a_inst - 记录页实例 ui_w_records_t * * 返回值:总行数 uint16_t * 函数说明:未注入 reader 视同 0 条(空态伪行),两端启动期绑定前的开页窗口 * 也被覆盖(防御不崩) */ uint16_t ui_w_records_count(ui_w_records_t *a_inst) { uint32_t n = (s_reader != NULL) ? s_reader->count(a_inst->log_id) : 0u; if (n == 0u) { return 1u; /* 空态伪行(页脚"共 1 页",避免"共 0 页") */ } return (uint16_t)(n * 2u); } /* * 函数功能:逐行取数(偶数行 = 时间戳、奇数行 = 描述;值列恒空) * 入口参数:a_inst - 记录页实例 ui_w_records_t * * a_row - 全局行下标 uint16_t * a_name - 名输出缓冲 char * * a_value- 值输出缓冲(恒写空串) char * * 限定条件:页面打开中(框架绘制/按键上下文,uiTask) */ void ui_w_records_refresh(ui_w_records_t *a_inst, uint16_t a_row, char *a_name, char *a_value) { uint32_t n = (s_reader != NULL) ? s_reader->count(a_inst->log_id) : 0u; a_value[0] = '\0'; if (n == 0u) { (void)memcpy(a_name, "无记录", sizeof("无记录")); return; } { uint32_t rec = a_row / 2u; if (!a_inst->cache_valid || rec != a_inst->last_rec) { if ((s_reader->get)(a_inst->log_id, rec, a_inst->ts, sizeof(a_inst->ts), a_inst->desc, sizeof(a_inst->desc)) != 0) { a_inst->cache_valid = 0u; a_name[0] = '\0'; /* 读失败(越界/存储异常):空行防御 */ return; } a_inst->last_rec = rec; a_inst->cache_valid = 1u; } if ((a_row % 2u) == 0u) { (void)memcpy(a_name, a_inst->ts, sizeof(a_inst->ts)); } else { (void)memcpy(a_name, a_inst->desc, sizeof(a_inst->desc)); } } }