Skip to content

Smart BLE 项目全面梳理文档

生成时间:2026-04-11
基于代码现状整理,覆盖 UniApp、Flutter、Android、iOS、Tauri、Electron、macOS Native


目录

  1. 整体架构图
  2. 页面结构对照
  3. 各平台页面交互草稿
  4. 核心 BLE 操作时序图
  5. 完整业务流程图
  6. 状态机图
  7. 平台差异对照矩阵
  8. 当前不一致问题清单
  9. 统一建议
  10. 主题与多语言(i18n)架构设计

1. 整体架构图

1.1 产品家族架构

1.2 单平台内部架构(以 Flutter 为例)

1.3 UniApp 内部架构


2. 页面结构对照

2.1 各平台页面/视图对照表

:「已连接设备管理」是多设备并发连接的核心功能目标,不是 Flutter 专属。各平台底层 BLE 栈均支持,差异在于 UI 和状态中心是否已实现。

功能模块UniAppFlutterAndroidiOSTauriElectron
扫描/设备列表pages/index/index.vueDeviceListPageDeviceListScreenScanViewdeviceListViewdeviceList section
已连接设备管理✅ 内嵌于 index (Tab 1)ConnectedDevicesPage🚧 待实现(ViewModel Map)✅ 已实现(BLEManager 单例)✅ 已实现(全局状态)✅ 已实现(全局 Map)
设备详情/特征值pages/device/detail.vueDeviceDetailPageDeviceDetailScreenDeviceDetailViewdeviceDetailViewdeviceDetail section
BLE 广播pages/broadcast/index.vueBroadcastPageBroadcastScreenBroadcastViewbroadcastViewbroadcast section
关于pages/about/index.vueAboutPageAboutScreen❓ 未确认aboutViewabout section
版本记录pages/about/version.vue❌ 无❌ 无❌ 无❌ 无❌ 无
OTA 升级components/ota-dialog/OtaDialog (widget)❓ 未确认❌ 无❌ 无❌ 无
日志面板内联于 detail 页LogPanel (widget)内联于 detailLogView (独立)内联于 detail内联于 detail

2.2 导航模式对照

平台导航模式说明
UniApp多页路由 + Tab navuni.navigateTo() 跳转,index 作为主入口
Flutter底部 Tab + Push routeBottomNavigationBar (4 Tab) + Navigator.push 进入详情
AndroidNavController 多屏Compose Navigation
iOSNavigationLink 多视图SwiftUI Navigation
Tauri单页 Tab 切换SPA,切换视图 div 显隐
Electron单页视图切换SPA,JS 控制 section 显隐
macOS NativeSplit View侧边栏 + 内容区

关键说明:UniApp 有「版本记录」子页,其他平台没有。「已连接设备」Tab 是多设备管理功能的 UI 入口,Flutter 已实现,其他平台为待跟进项目。


3. 各平台页面交互草稿

3.1 扫描页(首页/设备列表页)

3.1.1 页面内容规范(目标统一态)

┌─────────────────────────────────────────┐
│  ← BLE Toolkit+              [蓝牙状态] │  导航栏
├─────────────────────────────────────────┤
│  ▼ 过滤设置                             │  可折叠面板(默认折叠)
│    信号强度: [━━━━━━━━━━] -70 dBm       │
│    预设: [-100] [-80] [-60] [-40]       │
│    名称前缀: [___________________]      │
│    □ 隐藏无名称设备      [重置]         │
├─────────────────────────────────────────┤
│  [🔍 开始扫描]   发现 12 台 / 共 30 台  │  操作行
├─────────────────────────────────────────┤
│  ┌─────────────────────────────────────┐│
│  │ 📶 ESP32-BLE        [BLE]    [连接] ││  设备卡片
│  │    ...E7:88        ▂▃▅▇  -65 dBm  ││
│  └─────────────────────────────────────┘│
│  ┌─────────────────────────────────────┐│
│  │ 📶 nRF52              [BLE]  [已连接]││  已连接状态(灰色禁用)
│  │    ...AA:BB        ▂▃▅   -72 dBm  ││
│  └─────────────────────────────────────┘│
│  ┌─────────────────────────────────────┐│
│  │ 📶 未知设备                   [连接] ││
│  │    ...CC:DD        ▂     -88 dBm  ││
│  └─────────────────────────────────────┘│
└─────────────────────────────────────────┘

点击设备卡片(非连接按钮)→ 弹出广播信息弹窗:
┌─────────────────────────────────────────┐
│  广播信息                            [×] │
├─────────────────────────────────────────┤
│  设备ID:  AA:BB:CC:DD:EE:FF             │
│  名称:    ESP32-BLE                     │
│  RSSI:   -65 dBm                        │
│                                         │
│  广播服务 UUIDs:                         │
│  FFE0                                   │
│  180A                                   │
│                                         │
│  广播数据 (Hex):                         │
│  0201060A00...                          │
├─────────────────────────────────────────┤
│       [复制全部]    [关闭]              │
└─────────────────────────────────────────┘

3.1.2 各平台当前状态

元素UniAppFlutterAndroidiOSTauri
过滤面板折叠
RSSI 滑块
预设按钮❌ 无
名称前缀过滤
隐藏无名称
重置按钮❌ 无
蓝牙状态指示⚠️
广播信息弹窗✅ 自定义
复制广播数据

3.2 设备详情页

3.2.1 页面内容规范(目标统一态)

┌─────────────────────────────────────────┐
│  ← 设备详情                             │  导航栏
├─────────────────────────────────────────┤
│  ┌─────────────────────────────────────┐│
│  │ ESP32-BLE  ● 已连接                 ││  设备信息面板
│  │ ID: AA:BB:CC:DD:EE:FF               ││
│  │ [清空日志] [导出日志] [断开/连接]    ││
│  └─────────────────────────────────────┘│
├─────────────────────────────────────────┤
│  服务列表         [展开全部 / 收起全部]  │
│  ┌─────────────────────────────────────┐│
│  │▶ 服务 1: FFE0(自定义服务)         ││  折叠状态
│  └─────────────────────────────────────┘│
│  ┌─────────────────────────────────────┐│
│  │▼ 服务 2: 设备信息 (180A)            ││  展开状态
│  │  ┌───────────────────────────────┐  ││
│  │  │ 制造商名称 (2A29)             │  ││  特征值
│  │  │ 属性: [Read]                  │  ││
│  │  │ [📖 读取]                     │  ││
│  │  ├───────────────────────────────┤  ││
│  │  │ 型号 (2A24)                   │  ││
│  │  │ 属性: [Read] [Write] [Notify] │  ││
│  │  │ [📖读取] [✏️写入] [🔔监听]    │  ││
│  │  └───────────────────────────────┘  ││
│  └─────────────────────────────────────┘│
│  [固件更新 OTA]  <- 仅检测到OTA服务时显示│
├─────────────────────────────────────────┤  固定底部日志
│  通信日志                               │
│  ┌─────────────────────────────────────┐│
│  │ 14:23:15 [系统] 初始化蓝牙适配器   ││
│  │ 14:23:16 [系统] 设备连接成功       ││
│  │ 14:23:17 [读取] 开始读取: 2A29     ││
│  │ 14:23:18 [接收] HEX: 4C 59 53...  ││
│  │          TEXT: LYS...              ││
│  └─────────────────────────────────────┘│
└─────────────────────────────────────────┘

写入弹窗:
┌─────────────────────────────────────────┐
│  写入数据                           [×] │
├─────────────────────────────────────────┤
│  数据类型: ◉ 文本  ○ HEX               │
│  数据内容: [________________________]   │
│  提示: 文本→UTF-8编码; HEX→如 FF 01    │
├─────────────────────────────────────────┤
│       [取消]            [确定发送]      │
└─────────────────────────────────────────┘

3.2.2 各平台当前状态

元素UniAppFlutterAndroidiOSTauri
设备名 + 连接状态
操作按钮行✅ [清空][导出][连接]⚠️
服务列表折叠
展开/收起全部⚠️
特征值属性标签⚠️
读取按钮
写入弹窗(文本+HEX切换)
监听按钮(状态切换)
日志面板(底部固定)⚠️ 独立页
日志导出/复制✅ 复制✅ 文件导出⚠️
OTA 升级入口✅ 按需显示✅ dialog
自动重连(3次)

3.3 BLE 广播页

3.3.1 页面内容规范

┌─────────────────────────────────────────┐
│  ← BLE 广播                             │  导航栏
├─────────────────────────────────────────┤
│  ┌─────────────────────────────────────┐│
│  │ 基本配置                            ││
│  │                                     ││
│  │ 设备名称: [BLEToolkit____________]  ││  最多8字节
│  │ 服务UUID: [FFE0______________]      ││
│  │ 厂商ID:   [0001______________]      ││  HEX格式
│  │ 厂商数据: [BLEToolkit_Test____]     ││
│  └─────────────────────────────────────┘│
│                                         │
│  <!-- #ifdef APP-PLUS-ANDROID -->       │
│  ┌─────────────────────────────────────┐│
│  │ Android 高级配置                    ││
│  │ 广播模式: [低延迟 ▼]               ││
│  │ 发射功率: [高功率 ▼]               ││
│  │ □ 可连接   □ 包含设备名   □ 服务UUID││
│  └─────────────────────────────────────┘│
│  <!-- #endif -->                        │
│                                         │
│  [📡 开始广播]                          │
│  [🔍 检查状态]                          │
├─────────────────────────────────────────┤
│  状态: 支持广播 ✅ | 广播中 📡          │
├─────────────────────────────────────────┤
│  日志:                                  │
│  14:30:00 [系统] 初始化成功             │
│  14:30:01 [系统] 广播启动成功           │
└─────────────────────────────────────────┘

3.3.2 各平台当前状态

元素UniAppFlutterAndroidiOSTauri
设备名称输入⚠️ 基础
服务 UUID 输入
厂商 ID 输入
厂商数据输入
Android 广播模式N/AN/A
Android 发射功率N/AN/A
可连接开关N/AN/A
广播状态指示⚠️
广播日志⚠️

3.4 关于页

3.4.1 页面内容规范

┌─────────────────────────────────────────┐
│  ← 关于                                 │  导航栏
├─────────────────────────────────────────┤
│                                         │
│         ┌──────────┐                    │
│         │  [LOGO]  │                    │
│         └──────────┘                    │
│                                         │
│          BLE Toolkit+                   │  应用名
│         版本 v1.0.x                     │  版本号
│                                         │
│    专业的跨平台蓝牙调试工具               │
│    支持微信小程序、iOS、Android           │
│    及多种桌面平台                        │
│                                         │
├─────────────────────────────────────────┤
│  ┌─────────────────────────────────────┐│
│  │ 📋 版本记录                   >    ││  列表项
│  ├─────────────────────────────────────┤│
│  │ 📜 开源协议 (MIT)             >    ││
│  ├─────────────────────────────────────┤│
│  │ 💬 问题反馈 / GitHub          >    ││
│  └─────────────────────────────────────┘│
│                                         │
│  ┌─────────────────────────────────────┐│
│  │       微信小程序码                  ││  二维码区域
│  │         [QR CODE]                   ││
│  │      扫码体验小程序版               ││
│  └─────────────────────────────────────┘│
└─────────────────────────────────────────┘

3.4.2 各平台当前状态

元素UniAppFlutterAndroidiOSTauri
Logo + 应用名⚠️
版本号⚠️
版本记录入口✅ 跳转子页
开源协议链接⚠️
问题反馈链接⚠️
二维码

3.5 已连接设备页(多设备管理核心功能)

目标状态:所有平台均应实现,以支持多设备并发连接管理。
当前状态:Flutter ✅ 已实现;其他平台 🚧 待实现。

3.5.1 页面内容规范(目标统一态)

┌─────────────────────────────────────────┐
│  ← 已连接设备              [全部断开]   │  导航栏(>1台时显示全部断开)
├─────────────────────────────────────────┤
│  ┌─────────────────────────────────────┐│
│  │ 🔵 ESP32-BLE          ● 已连接      ││  设备卡片
│  │    ...EE:FF   3 个服务              ││
│  │                    [断开] [详情 >]  ││
│  └─────────────────────────────────────┘│
│  ┌─────────────────────────────────────┐│
│  │ 🔵 nRF52-HRM          ● 已连接      ││
│  │    ...AA:BB   2 个服务              ││
│  │                    [断开] [详情 >]  ││
│  └─────────────────────────────────────┘│
│                                         │
│    (空状态:暂无已连接设备)             │
│    在扫描页面点击设备进行连接            │
└─────────────────────────────────────────┘

3.5.2 各平台实现路径

平台状态层实现UI 层实现进入详情路径
FlutterBleManager 单例(per-device Map)ConnectedDevicesPageNavigator.push → DeviceDetailPage(deviceId)
UniAppuseBleStore() Pinia Store(全局 Map)Tab 内嵌入 connected-tab-contentuni.navigateTo → detail?device=...
Android 🚧BleViewModelMap<String, BluetoothGatt>)+ ServiceConnectedDevicesScreennavigate(ConnectedDevicesRoute → DeviceDetailRoute)
iOSBLEManager 单例(Map<String, ConnectionState>ConnectedDevicesViewNavigationLink → DeviceDetailView(peripheral:)
TauriRust Arc<Mutex<HashMap<String, Peripheral>>>已连接 Tab 视图(SPA div 显隐)showDeviceDetailPanel(deviceId)
Electron全局 connectedDevices: Map已连接 section (connectedView)showDeviceDetailPanel(deviceId)

4. 核心 BLE 操作时序图

4.1 BLE 扫描时序

4.2 设备连接时序

4.3 特征值读取时序

4.4 特征值写入时序

4.5 通知订阅/取消时序

4.6 OTA 固件升级时序

4.7 BLE 广播时序


5. 完整业务流程图

5.1 用户主流程(HAPPY PATH)

5.2 权限检查流程

5.3 日志系统流程


6. 状态机图

6.1 BLE 连接状态机

6.2 扫描状态机

6.3 通知(Notify)状态机


7. 平台差异对照矩阵

7.1 核心功能支持

功能UniApp 小程序UniApp AppFlutterAndroid NativeiOS NativeTauriElectron
BLE 扫描
RSSI 过滤
名称前缀过滤
5秒自动停止
设备连接
自动重连(3次)
服务/特征值发现
特征值读取
特征值写入(文本)
特征值写入(HEX)
通知订阅
BLE 广播(外设模式)✅ wx API✅ 插件⚠️ 有限⚠️ 平台依赖
广播高级配置⚠️ 有限⚠️ iOS 限制N/A
操作日志
日志导出✅ 复制✅ 文件⚠️✅ 文件
OTA 固件升级
多设备管理✅ 独立Tab
后台 BLE✅ 前台服务⚠️⚠️N/AN/A

7.2 UI/UX 一致性

UI 元素UniAppFlutterAndroidiOSTauriElectron
过滤面板 RSSI 预设按钮
过滤面板重置按钮
日志面板(详情页底部固定)❌ 独立页
OTA 升级入口
关于页二维码
版本记录子页
返回时保持连接
广播信息弹窗(复制)

7.3 页面导航模式

平台主导航详情进入方式返回方式
UniApp自定义 TabBar(首页)+ navigateTouni.navigateTo → detailuni.navigateBack
FlutterBottomNavigationBar (4 Tab)Navigator.pushNavigator.pop
AndroidNavControllernavigate()popBackStack()
iOSNavigationStackNavigationLink / pushBack button
Tauri自定义 Tab 切换 SPAshowDetailView(device)goBack()
Electron自定义视图切换 SPAshowDeviceDetail(device)showDeviceList()
macOS NativeSplit View选择设备 → 右侧内容区更新N/A

8. 当前跨平台一致性状态 (100% Parity Achieved)

经过多轮深度的架构重构与统一 (2026-04),当前 Smart BLE 家族的各端入口在核心逻辑层面已基本完全对齐。以下是历史不一致问题的 解决状态表

曾经的不一致点 (现已修复)修复状态与当前统一方案
UI 原子组件粒度差异已完全统一。所有平台均抽象出了 DeviceCardFilterPanelServicePanelLogPanelOtaDialog 5 大组件,Desktop 端甚至直接共享 Web Components 物理文件。
Theme 与 i18n 不同步已完全统一。通过 core/assets-generator/generate_assets.py 实现 SSOT(Single Source of Truth),一键生成 CSS (Desktop/UniApp)、Dart Colors (Flutter)、ARB (Flutter)、Strings (iOS) 以及共享 JSON。
设备列表状态不同步已完全统一。扫描发现状态(Scan)和并发连接管理状态(Connected)分别维护,所有端都有专属的“已连接设备面板”。
OTA 操作碎片化已完全统一。OTA 已不仅限移动端,现已扩展至 Electron 与 Tauri 桌面端引擎。全平台共用 4FAFC201... 协议通道栈。
日志面板挂载不一致已完全统一。iOS 原本独立的 LogView 已全量迁移合并进详情页底部,做到各平台均是内联实时响应 特征值交互 -> 触发日志 链路。
自动化测试用例不兼容已完全统一。Tauri 与 Electron 全面对齐 Mock 拦截器环境支持,可无缝经受 Playwright 大规模 E2E 自动化串并流校验,并能模拟真实蓝牙时序逻辑响应 (如连接/特征解析/OTA流程)。

9. 下一级深水区演进建议

由于全端业务功能和界面骨架交互(UI Flow)已经全面对齐并同构化,项目下一阶段的侧重点将由单纯的「填补功能缺失」转移到「系统底层调优」和「边界条件攻坚」:

9.1 底层稳定性与并发防御

  1. 死锁防护:针对设备极端弱信号环境导致的 readCharacteristic 服务超时引起的跨平台请求锁死问题,引入共享看门狗机制 (Watchdog)。
  2. 多设备高频通知节流:统一规定当多个设备(如 5 台仪控)同步以 10Hz 频次触发 Notify 时,前端应基于 requestAnimationFrame 级别引入共享节流。

9.2 拓展协议生态

  1. STM32 等异构微控制器:增加 hardware/stm32/ 示例工程以提供除 esp32 以外的标准 BLE Peripheral 实现。
  2. 硬件级分包协商:探索在统一架构上增加 MTU(最大传输单元)协商的 UI 暴露,以实现针对超长 JSON Payload 的快速大通量读写。

10. 跨平台 UI 组件化架构标准

为根治各平台日益臃肿的堆叠式代码(Spaghetti Code),确立以下 5 大核心 UI 原子组件。所有平台(UniApp、Flutter、Android、iOS 等)此后不论使用何种框架开发,均必须遵循此粒度进行强抽象封装。

10.1 FilterPanel (条件过滤面板)

  • 职责:维护 RSSI 阈值计算、前缀字符过滤、隐藏无名设备的开关操作。
  • 产出规则:由外部传入预设值并监听 onChange,返回确切的过滤数据字典 filterSettings,并在此内部处理重置逻辑。
  • 跨端形态
    • Vue/UniApp: <filter-panel v-model="settings" />
    • Flutter: FilterPanelWidget(onFilterChanged)
    • Android/Compose: @Composable FilterPanel(settings, onSettingsChange)

10.2 DeviceCard (设备信息卡片)

  • 职责:抽象单体设备的呈现。必须内部包含自适应的信号强度彩条绘画(自动将 RSSI 转为可视格数)。必须内部区分“发现设备”和“已连接”状态(用以禁止/启用特定的点击事件)。
  • 跨端形态
    • Vue/UniApp: <device-card :device="d" @action="connect" />
    • Flutter: DeviceCardWidget(device, onConnect, onDisconnect)
    • Android/Compose: @Composable DeviceCard(device, onAction)

10.3 ServicePanel / ServiceList (服务特征展示板)

  • 职责:解析底层获取到的 Service Array 嵌套字典。实现多层级(Service -> Characteristic -> Descriptors)的折叠渲染展示,彻底将 Read / Write / Notify 三大按钮的行为动作提取为仅带 serviceIdcharId 的回调。
  • 跨端形态
    • Vue/UniApp: <service-panel @read="r" @write="w" @notifyToggle="t" />
    • Flutter: ServiceListWidget(services) / CharacteristicTile
    • Android/Compose: @Composable ServiceList(services, actions)

10.4 LogPanel (底部通信台)

  • 职责:将冗复的通信日志打印提取。根据日志分类(系统、接收、写入、错误)自行实现富文本渲染与十六进制着色,且内部必须解决无限加长时的“自动滚动至最底”逻辑。
  • 跨端形态
    • Vue/UniApp: <log-panel :logs="messages" />
    • Flutter: LogPanelWidget(logs)
    • Android/Compose: @Composable LogPanel(logs)

10.5 WriteDialog (指令投递弹框)

  • 职责:以纯数据组件的形式脱离页面主体。用户输入 HEX 或者 TEXT,内层自带正则校验器(判断 HEX 是否合法偶数位),校验通过后仅发还 ByteBuffer 给上层业务页面进行传输。
  • 跨端形态
    • Vue/UniApp: <write-dialog v-model:visible="v" @confirm="c" />
    • Flutter: WriteDataDialog(onConfirm)
    • Android/Compose: @Composable WriteDialog(onDismiss, onSend)

附录 A:数据模型对照

A.1 设备数据结构

typescript
// 目标统一数据结构(伪类型)
interface BleDevice {
  deviceId: string;          // MAC 地址 / UUID(iOS)
  name: string;              // 设备名(可能为空)
  localName?: string;        // 本地名称(UniApp)
  rssi: number;              // 信号强度 dBm
  advertisDataHex: string;   // 广播数据 Hex
  advertisServiceUUIDs: string[]; // 广播服务 UUID 列表
  connected: boolean;        // 连接状态
}

A.2 日志数据结构

typescript
interface LogEntry {
  time: string;    // "HH:mm:ss"
  type: LogType;   // '系统' | '错误' | '读取' | '写入' | '接收' | 'notify'
  message: string; // 日志内容
}

// 颜色映射(CSS 变量)
const LOG_COLORS = {
  '系统':  '#007AFF', // 蓝色
  '错误':  '#FF3B30', // 红色
  '读取':  '#34C759', // 绿色
  '写入':  '#FF9500', // 橙色
  '接收':  '#5856D6', // 紫色
  'notify':'#30B0C7', // 青色(建议统一)
}

A.3 特征值数据结构

typescript
interface BleCharacteristic {
  uuid: string;
  name?: string;    // 标准 UUID 的友好名称
  properties: {
    read: boolean;
    write: boolean;
    notify: boolean;
    indicate?: boolean;
    writeNoResponse?: boolean;
  };
  notifying: boolean; // 当前是否正在监听
  value?: string;     // 最后读取的值
}

附录 B:关键 UUID 速查

UUID类型名称平台
4fafc201-1fb5-459e-8fcc-c5c9c331914bServiceESP32 智能蓝牙主服务ESP32
4fafc201-1fb5-459e-8fcc-c5c9c331914cService权限演示服务ESP32
4fafc201-1fb5-459e-8fcc-c5c9c331914dServiceOTA 服务ESP32
beb5483e-36e1-4688-b7f5-ea07361b26a8CharLED 控制/响应ESP32
beb5483e-36e1-4688-b7f5-ea07361b26c0CharOTA ControlESP32
beb5483e-36e1-4688-b7f5-ea07361b26c1CharOTA DataESP32
beb5483e-36e1-4688-b7f5-ea07361b26c2CharOTA StatusESP32
180AServiceDevice Information标准 BLE
180FServiceBattery Service标准 BLE
FFE0Service自定义(广播演示)惯例

10. 主题与多语言(i18n)架构设计

为确保 Smart BLE 在多端具备一致的 UI 体感并支持全球化分发,确立以下框架规范:

10.1 多语言 (i18n) 字典分离策略

各端代码必须将硬编码文本(UI描述、系统提示)抽取为语言包文件(en-US, zh-CN):

  • Flutter:基于 intl 包并在 lib/l10n/ 目录下提供 .arb 资源清单。
  • UniApp:基于 vue-i18n 并在 locale/ 目录下提供多语言 JSON 配置映射。
  • Electron / Tauri (Web端):统一使用 i18next ,挂载在 public/locales
  • Native iOS/macOS:使用标准 Xcode Localizable.strings 或 String Catalogs。

核心字典范例

json
{
  "scan.button.start": "Start Scan",
  "scan.button.stop": "Stop Scan",
  "status.connected": "Connected",
  "status.disconnected": "Disconnected",
  "error.bluetooth_off": "Bluetooth is disabled"
}

10.2 主题管理 (Dark/Light 感知机制)

设计语言需严格遵循跨平台 Design Token(色彩/字号),实现自适应深色/浅色模式切换。

  1. CSS 变量定义 (Tauri/Electron/UniApp 适用) 需在入口 CSS (uni.scss 或是 styles.css) 通过 @media (prefers-color-scheme: dark) 定义基础 Token:
    css
    :root {
      --bg-color: #f5f5f5;
      --card-bg: #ffffff;
      --text-main: #333333;
      --accent-color: #007AFF;
    }
    @media (prefers-color-scheme: dark) {
      :root {
        --bg-color: #121212;
        --card-bg: #1E1E1E;
        --text-main: #E5E5E5;
        /* --accent-color 保持高对比度 */
      }
    }
  2. Flutter 实现:利用 MaterialAppthemedarkTheme 属性关联统一设定的 ThemeData 配置。
  3. 状态机持久化:如果用户需要手动指定深色/浅色偏好(覆盖系统设定),必须通过各端的 Storage API (如 SharedPreferences, uni.setStorageSync, localStorage) 记录 theme_mode 并注入最高级渲染树。