/* * 模块名称:UI 定值表共享组件(ui_w_setlist) * 模块功能:把"参数/定值/控制字/软压板"四类视图的列表渲染与整定输入抽象成 * 一份实现——行表 + 数据回调注入(取数/写工作副本/提交/状态回读/ * 越界行查询),同一份组件供多个页面实例复用: * 查看视图(commit=NULL:无保存行、ENTER 无效)与整定视图 * (commit 非空:末行固定为"保存"行,ENTER 投递整表提交)只差绑定; * 数值行走 ui_w_editor 逐位编辑(范围校验提交),二态文字行 * (控制字"告警/跳闸"、软压板"投入/退出")ENTER 直接切换; * 保存失败后的越界行经 bad 回调反显高亮; * 分页跟随内容页框架内置(8 行/页,UI_LIST_ROWS) * 适用范围:Drivers/BSP/UI(标准列表页骨架几何:UI_LIST_TOP/ROW_PITCH/ * ROW_BAND_H/LIST_ROWS/RIGHT_X 令牌;页面描述符须 selectable=1、 * key_intercept=1、rows_per_page=UI_LIST_ROWS、text_dy=0) * 说明:数据绑定全部经回调注入(批 2 ui_data/prot_set 交接时由页面薄跳板 * 提供实现),组件不 include 任何 App 头(分层门禁方向); * 实例化使用——每个页面文件 static 一份实例,钩子包一层 &inst 转调 * (同 ui_w_records 模式) * 作者:王建锋 * 创建日期:2026-10-25 * 修改记录: * v1.0 2026-10-25 王建锋 创建(道B task-5;规格 = 页面扩充详细方案.md * §3.2 四视图表/§3.2.6 查看与整定差别/§3.2.7 编辑 * 交互/§4.2 bind 要点;保存行 ENTER/WAIT/OK/ERR * 沿用 ui_page_net_cfg 交接显示先例) */ #ifndef UI_W_SETLIST_H #define UI_W_SETLIST_H #ifdef __cplusplus extern "C" { #endif #include #include #include "ui_content_page.h" /* lvgl(lv_key_t/lv_layer_t)+ 框架类型 */ #include "ui_w_editor.h" /* 保存交接显示态(值列 ENTER/WAIT/OK/ERR,与 net_cfg 保存行同字面) */ typedef enum { UI_W_SETLIST_ST_IDLE = 0, /* 空闲:保存行显示 ENTER */ UI_W_SETLIST_ST_WAIT, /* 请求已投递、属主任务处理中:WAIT */ UI_W_SETLIST_ST_OK, /* 上轮提交成功:OK */ UI_W_SETLIST_ST_FAIL /* 上轮提交失败:ERR */ } ui_w_setlist_st_t; /* 行种类 */ #define UI_W_SETLIST_KIND_NUM 0u /* 数值行:ui_w_editor 逐位编辑(min/max/decimals 有效) */ #define UI_W_SETLIST_KIND_ENUM 1u /* 二态文字行:ENTER 在 opts 串表内循环切换 */ /* * 视图行描述(Flash const 表,一行一条) * 值通道统一 int32_t 定点: * 数值行 = 工程量 * 10^decimals(如 10.24 A -> 1024) * 二态行 = opts 串表下标(0/1/...) */ typedef struct { const char *name; /* 中文名 <= 7 字(字体子集已预置) */ uint8_t id; /* 应用侧枚举 ID:组件只透传给回调,不解释语义 */ uint8_t kind; /* UI_W_SETLIST_KIND_NUM / _ENUM */ uint8_t decimals; /* 数值行小数位 0..3(二态行忽略) */ int32_t min; /* 数值行下限(含;>=0;二态行忽略) */ int32_t max; /* 数值行上限(含;二态行忽略) */ const char *const *opts; /* 二态行:NUL 结尾 Flash 字符串串表(数值行 NULL) */ } ui_w_setlist_row_t; /* 数据回调组(均 uiTask 上下文、页面绘制/按键链内调用;实现由批 2 页面跳板提供, * 组件不 include 任何 App 头——数据绑定经此注入) */ /* * 函数功能:读某行当前值(数值行 = 工程量 * 10^decimals;二态行 = 串表下标) * 入口参数:id - 行表登记的枚举 ID uint8_t * 返回值:当前值 int32_t */ typedef int32_t (*ui_w_setlist_get_fn)(uint8_t a_id); /* * 函数功能:写某行 RAM 工作副本(不写盘;落盘统一经 commit 整表提交) * 入口参数:id - 行枚举 ID uint8_t * val - 新值(口径同 get) int32_t * 返回值:无 */ typedef void (*ui_w_setlist_set_fn)(uint8_t a_id, int32_t a_val); /* * 函数功能:整表提交(一次封存一次校验和;实现只投递请求到属主任务,不阻塞) * 入口参数:无 * 返回值:无(投递结果经 state 回调回读) */ typedef void (*ui_w_setlist_commit_fn)(void); /* * 函数功能:保存交接态回读(保存行值列显示源) * 入口参数:无 * 返回值:当前交接态 ui_w_setlist_st_t */ typedef ui_w_setlist_st_t (*ui_w_setlist_state_fn)(void); /* * 函数功能:查询某数据行是否为"保存失败越界行"(需反显高亮) * 入口参数:row - 数据行下标(不含保存行) uint16_t * 返回值:true = 需反显;false = 正常(提问谓词,非错误通道) bool */ typedef bool (*ui_w_setlist_bad_fn)(uint16_t a_row); /* * 定值表实例 * 用法(页面跳板示例,批 2): * static ui_w_setlist_t s_sl = { .rows = s_rows, .count = N, .get = get, ... }; * count_cb -> ui_w_setlist_count(&s_sl) * refresh -> ui_w_setlist_refresh(&s_sl, row, name, value) * key_cb -> ui_w_setlist_key(&s_sl, key) * draw_cb -> ui_w_setlist_draw(&s_sl, layer, clip) * init_cb -> ui_w_setlist_reset(&s_sl) */ typedef struct { const ui_w_setlist_row_t *rows; /* Flash 行表 */ uint16_t count; /* 数据行数(不含保存行) */ ui_w_setlist_get_fn get; /* 必填 */ ui_w_setlist_set_fn set; /* 必填(整定提交前的 RAM 副本写入口) */ ui_w_setlist_commit_fn commit; /* NULL = 查看视图(无保存行、禁编辑) */ ui_w_setlist_state_fn state; /* NULL = 保存行恒显示 ENTER */ ui_w_setlist_bad_fn bad; /* NULL = 不做越界行反显 */ ui_w_editor_t ed; /* 数值编辑实例 */ uint16_t ed_row; /* 编辑中行下标(仅 editing 时有效) */ } ui_w_setlist_t; /* * 函数功能:开页复位(清编辑态;接页面 init_cb) * 入口参数:inst - 定值表实例 ui_w_setlist_t * * 返回值:无 * 限定条件:无 */ void ui_w_setlist_reset(ui_w_setlist_t *a_inst); /* * 函数功能:总行数(接框架 count_cb:数据行 + 保存行[仅整定视图]) * 入口参数:inst - 定值表实例 const ui_w_setlist_t * * 返回值:总行数 uint16_t * 限定条件:rows 非空(空表防御返回 0) */ uint16_t ui_w_setlist_count(const ui_w_setlist_t *a_inst); /* * 函数功能:逐行取数(接框架 refresh:名 = 行表、值 = 回调读/编辑器实时串/保存态) * 入口参数:inst - 定值表实例 ui_w_setlist_t * * row - 全局行下标 uint16_t * name - 名输出缓冲(UI_BUF_STRLEN) char * * value - 值输出缓冲(同上) char * * 返回值:无 * 限定条件:页面打开(框架绘制链内调用) * 函数说明:编辑中行的值列显示编辑器当前串(实时随 ↑↓ 变,同 net_cfg); * 保存行(最后一行、整定视图)值 = ENTER/WAIT/OK/ERR(state 回调) */ void ui_w_setlist_refresh(ui_w_setlist_t *a_inst, uint16_t a_row, char *a_name, char *a_value); /* * 函数功能:按键处理(接框架 key_cb;配合描述符 key_intercept=1 转发 LEFT) * 入口参数:inst - 定值表实例 ui_w_setlist_t * * key - LVGL 键值 lv_key_t * 返回值:1 = 已消费(框架跳过内置);0 = 交回框架(↑↓ 移选、← 关页等) * (键分发标志非错误通道,取 uint8_t——BSP 公开 API 约定) * 限定条件:页面打开(内部经 ui_content_page_selected_row / is_editable 判态) * 函数说明:1. 数值编辑中:↑↓ 步进 / ←→ 移位 / ENTER 提交(越界拒绝)全由 * ui_w_editor 消费;提交成功即经 set 回调写工作副本 * 2. 正常态 ENTER(可编辑权限):数值行进编辑(光标个位); * 二态行循环切换;保存行投递整表提交(一次封存一次校验和, * 整表提交口径见 页面补齐规划.md §3.2) * 3. 只读权限 ENTER 一律不消费;ESC 恒关页(框架,未提交编辑丢弃, * 已经 ENTER 提交到工作副本的调整保留、不落盘——net_cfg 先例) */ uint8_t ui_w_setlist_key(ui_w_setlist_t *a_inst, lv_key_t a_key); /* * 函数功能:自绘(接框架 draw_cb:编辑光标反显 + 保存失败越界行反显) * 入口参数:inst - 定值表实例 ui_w_setlist_t * * layer - 绘制层 lv_layer_t * * clip - 重绘区 const lv_area_t * * 返回值:无 * 限定条件:页面打开;框架内置区块(行/带/页脚)已绘完 * 函数说明:行槽 y 按标准列表骨架 + 当前页窗口换算(与框架 cp_draw_rows 同式: * first = sel / UI_LIST_ROWS * UI_LIST_ROWS) */ void ui_w_setlist_draw(ui_w_setlist_t *a_inst, lv_layer_t *a_layer, const lv_area_t *a_clip); #ifdef __cplusplus } #endif #endif /* UI_W_SETLIST_H */