Flutter 工业 HMI 仪表盘 UI 架构:3746 行的响应式控制面板设计
本文分析一个 Flutter 工业上位机仪表盘页面的 UI 架构——3746 行单文件 StatefulWidget,6 个导航面板、双端口串口调试、深色工业主题、响应式布局与 10 个可复用 Widget 模式。
flowchart TB subgraph UI[仪表盘 UI] U1[状态面板] U2[实时曲线] U3[参数配置表] U4[报警列表] end subgraph CTRL[控制器层] C1[HmiController] C2[Session 管理] end subgraph SERIAL[串口层] S1[SerialTransport] S2[协议编解码] end UI --> CTRL --> SERIAL style UI fill:transparent,stroke:#8dc7ff,color:#eaf4ff style CTRL fill:transparent,stroke:#8dc7ff,color:#eaf4ff style SERIAL fill:transparent,stroke:#8dc7ff,color:#eaf4ff
一、为什么用单文件写 3746 行
这是一个务实的工程选择而非架构失误:仪表盘页面是 HMI 的唯一主界面,没有二级页面路由。所有状态(串口连接状态、选择的面板、日志缓冲区)共享同一个作用域,拆分到多个文件反而增加跨文件状态传递的复杂度。代价是文件体量大,但受益于 Dart 的顶级函数和 Widget 抽取模式,维护性尚可。
二、整体布局结构
Scaffold
└─ SafeArea
└─ LayoutBuilder (compact 阈值: 1150px)
├─ 窄屏: Column[TopBar, CompactMenuBar, WorkArea]
└─ 宽屏: Row[Sidebar, Column[TopBar, WorkArea]]
两种布局模式:
- 宽屏(≥1150px):左侧 230px 渐变 Sidebar + 主内容区。Sidebar 包含应用标题 "HMI HOST"、双端口状态指示灯、6 项图标菜单
- 窄屏(<1150px):隐藏 Sidebar,顶部 CompactMenuBar 水平滚动药丸菜单替代。适应小屏笔记本或平板
双端口状态指示
Sidebar 顶部有两个端口指示灯:绿=已连接,红=断开。用户一眼可知双串口的通断情况。
三、6 个导航面板
| 面板 | 功能 |
|---|---|
| 串口配置 | 端口 A/B 波特率/校验位/数据位/停止位配置,连接/断开控制 |
| USART3 调试 | 5 个子选项卡:状态查询(0x41)、封口(0x43)、基础控制、维护诊断、电机点动 |
| USART1 Session | 3 个子页面:参数调校、系统状态、日志监控 |
| 帧调试器 | 原始 20B 帧手工拼装:地址/功能码/负载/CRC,发送/接收 |
| 协议日志 | 全量日志视图,HEX/Text/HEX+Text 切换,暂停/恢复/复制/导出/清除 |
| 栈水位统计 | MCU 7 任务栈使用率实时监控 + 折线趋势图 |
四、USART3 调试面板(最深)
5 个子选项卡,每个对应一组协议命令。使用统一的 _cmdRow() 模式:
Widget _cmdRow(String label, List controls, VoidCallback onSend) {
return Padding(
padding: ...,
child: Row(children: [
Text(label, style: ...),
...controls..., // 下拉框/输入框
_miniBtn(Icons.send, onSend),
]),
);
}
每个子选项卡的内容:状态查询(0x41)、封口(0x43)带 Z1 参数(Stop/Start/Poll)、基础控制(Start/Stop/ClearFlag)、维护诊断(RESET_FAULT/VERSION/ALARM_QUERY)、电机点动(步进+直流)。所有操作通过 HmiController.runCommand() 发送,结果以 SnackBar 反馈。
五、USART1 Session 面板
参数调校页面通过 HMIS 协议动态获取参数目录——无需固件升级即可适配新增参数。顶部操作栏(Sync Catalog/Read All/Save EEPROM/Load Defaults),主体为分组 ExpansionTile。系统状态页面显示 DGUS VP 寄存器(0x1000-0x1003)当前值。底部快速控制栏直接通过 Session 桥接命令(0x30-0x35)操作设备。
六、栈水位统计面板
实时监控 7 个 FreeRTOS 任务的栈使用情况:指标卡片(总/已用/剩余/风险任务)、数据表格、_StackLevelChartPainter CustomPainter 折线趋势图。数据来自 MonitorTask 的周期性推送,HMI 端 240 条环形缓冲 + StackTaskStats 合并渲染。
七、10 个可复用 Widget 模式
| 模式 | 用途 |
|---|---|
| _cmdRow() | 命令行:标签 + 控件 + 发送按钮 |
| _buildDropdown() | 紧凑数字下拉 |
| _buildPortToggle() | A/B 端口切换开关 |
| _miniBtn() | 小号图标按钮(发送/执行) |
| _buildMiniToolButton() | 工具栏图标按钮(复制/导出/清除) |
| _buildCard() / _buildCardHeader() | 一致的章节卡片容器 |
| _buildRowFields() | 灵活的字段行布局(Row vs Wrap 自适应) |
| _textField() / _inputDecoration() | 统一风格表单输入框 |
| _stackMetric() | KPI 指标卡片 |
| _InlineBaudRateField | 独立 StatefulWidget:波特率输入+验证 |
八、设计主题与交互反馈
- 深色工业主题:#08152A 底色、#0B1E3A 面板、#1B91D8 强调蓝
- 字体:IBM Plex Sans(标签)+ IBM Plex Mono(数据)
- 状态颜色:绿=已连接、红=断开、黄=TX、绿=RX、灰=LOG
- 反馈:_runCommand() 统一封装 SnackBar(绿=成功,红=失败,灰=超时/忙)
- 多断点:LayoutBuilder 在 460/500/620/700/760/1000/1150px 自适应
GENERIC_DEVICE · Flutter 3.41 · Dart 3.11
Comments NOTHING