新闻详情

新闻详情

首页 / 资讯中心 / 详情

Flutter鸿蒙闹钟App设置Tab:状态管理与平台通道实战

发布时间:2026/10/2 14:35:29来源:尧图网络
Flutter鸿蒙闹钟App设置Tab:状态管理与平台通道实战
Flutter 写 UI 的能力在跨端圈已经不需要再证明了但把它跑在 OpenHarmony 上、并且做一个闹钟这种强交互、强系统能力的 App还是要费不少周折。我这段时间把一个 Flutter for OpenHarmony 的高级闹钟 App 从零搭到了可交付状态里面最花时间的其实是设置 Tab——看起来只是几个开关和下拉框背后却牵着状态管理、持久化、平台通道和系统权限差异。这篇内容就是冲着“设置 Tab 实现”来的适合两类人一类是刚把 Flutter 开发环境切到 OpenHarmony、想知道工程怎么落地的人另一类是已经跑通 Hello World、但卡在“Flutter 页面怎么跟鸿蒙原生能力打交道”这个坎上的人。闹钟只是载体里面涉及的 EventChannel 通信、配置持久化、Tab 状态同步、多端权限差异放到别的工具类 App 一样能用。1. 闹钟场景的项目定位与 Tab 架构设计1.1 为什么拿 Flutter 写 OpenHarmony 闹钟先说结论闹钟 App 的核心竞争力在 UI 交互和配置灵活性不在原生性能。铃声渐强、贪睡、跳过节假日、重复规则这些功能本质是“状态机 定时触发”Flutter 的声明式 UI 和状态管理生态处理这类逻辑非常顺手。OpenHarmony 原生的 ArkUI 也能写但如果你团队里已经有一批 Flutter 工程师或者还有 Android/iOS 版本要同步维护Flutter 的跨端优势就很明显了。我在选型时对比过两条路一是纯 ArkTS 重写熟练工大概两个礼拜能出一个能跑的版本但后面维护成本高二是 Flutter for OpenHarmony 适配分支UI 层全部复用只把系统能力通过平台通道接出去。我选了后者理由是闹钟的界面复杂度摆在那里——环形渐变、滑动手势、交互动效这些都更适合在 Flutter 里做。OpenHarmony 这边的 Flutter 适配已经不再是“能不能跑”的阶段而是“怎么跑得稳”的阶段。工程初始化、热重载、打包、三方插件适配都有成熟路径只是踩坑点跟 Android 不完全一样。这篇文章里提到的版本和命令以我自己当前用的 OpenHarmony 5.0 配套工具链为准你用的时候注意看自己 SDK 分支。1.2 Tab 布局与设置页的定位整个 App 我设计了四个 Tab闹钟列表、世界时钟、秒表、设置。设置放在 Tab 而不是独立页面是产品决策也是工程决策。从产品角度说闹钟 App 的设置项分成两类一类是全局配置默认铃声、震动强度、贪睡时长另一类是单闹钟配置某个闹钟的重复星期、标签。单闹钟配置应该放在闹钟编辑页里全局配置才有资格进设置 Tab。把设置做成常驻 Tab用户随时能切过去改改完切回闹钟页立刻生效心智负担最小。从工程角度说设置页需要承载的状态比较多通知权限状态、默认铃声路径、震动档位、渐强时长这些状态要被闹钟页、响铃逻辑、原生侧同时读取。单独拆一个 Tab 出来状态的作用域反而好控制——我不用把配置参数在页面跳转时传来传去只要有一个全局 SettingsController 挂着就行。四个 Tab 的切换我用的是 Flutter 自带的NavigationBarIndexedStack。注意这里没有用PageView因为IndexedStack会保留每个 Tab 的状态切到设置页再切回来闹钟列表的滚动位置不会丢。这个细节在 Flutter 里是个经典问题很多人用Navigator切页面导致列表状态丢失后面已经在热词里面试场景被问烂了。1.3 工具链与项目结构准备Flutter for OpenHarmony 的工程搭建比 Android 稍微绕一点。标准流程是先装 DevEco Studio再拉 OpenHarmony 适配过的 Flutter SDK用flutter create --platforms ohos生成项目骨架。我实际用的命令大概是fvm use 你的ohos适配版本 flutter create --org com.example --platforms ohos alarm_app生成后的目录比普通 Flutter 项目多了一个ohos目录这就是鸿蒙侧的原生工程。flutter run在 OpenHarmony 上不像 Android 那样直接识别设备得先用 DevEco 把设备连上再用hdc list targets确认设备在线最后执行flutter run -d device-id这里容易踩的一个坑是如果你之前装过普通 Flutter SDK命令行里的flutter可能不是你想要的 OpenHarmony 分支构建时会报 “Target platform ohos is not supported”。解决办法是把环境变量的 PATH 指到适配版 SDK 的 bin 目录或者用 fvm 锁版本。项目内部我按功能模块划分而不是按页面划分。结构大概是lib/ core/ # 主题、常量、工具函数 features/ alarm/ # 闹钟列表与编辑 settings/ # 设置Tab worldclock/ # 世界时钟 stopwatch/ # 秒表 shared/ controllers/ # 全局状态控制器 models/ # AppSettings等数据模型 platform/ channels.dart # 平台通道封装 event_handler.dart # EventChannel订阅管理这样划分的好处是设置 Tab 的模块只依赖shared和platform不会反向依赖闹钟列表避免两个页面互相 import 之后改一处崩一片。2. 设置 Tab 核心功能拆解与实现2.1 设置项的数据模型设计设置 Tab 看起来就是几行列表项但数据模型如果偷懒后面闹钟逻辑、持久化、平台通道都会跟着返工。我先把设置项按用途整理成一张表设置项类型默认值影响范围默认铃声String资源路径assets/ringtones/classic.mp3新建闹钟时自动带上的铃声震动模式枚举无/轻/强轻响铃时是否震动及强度贪睡时长int分钟5闹钟贪睡间隔渐强时长int秒0铃声从无声到最大的过渡时间重复规则默认值List[false * 7]新建闹钟的默认重复星期通知权限状态bool由系统决定显示权限提示条AppSettings我用了一个不可变类 copyWith。不可变的核心原因是 Flutter 的setState比较引用能快速判断是否需要重建 UI如果设置对象可变每次修改都会触发全量重建设置页里又有滑条又有开关性能会很难看。class AppSettings { final String defaultRingtone; final VibrationMode vibrationMode; final int snoozeMinutes; final int fadeSeconds; final Listbool repeatDays; const AppSettings({ this.defaultRingtone assets/ringtones/classic.mp3, this.vibrationMode VibrationMode.light, this.snoozeMinutes 5, this.fadeSeconds 0, this.repeatDays const [false, false, false, false, false, false, false], }); AppSettings copyWith({ String? defaultRingtone, VibrationMode? vibrationMode, int? snoozeMinutes, int? fadeSeconds, Listbool? repeatDays, }) { return AppSettings( defaultRingtone: defaultRingtone ?? this.defaultRingtone, vibrationMode: vibrationMode ?? this.vibrationMode, snoozeMinutes: snoozeMinutes ?? this.snoozeMinutes, fadeSeconds: fadeSeconds ?? this.fadeSeconds, repeatDays: repeatDays ?? this.repeatDays, ); } }枚举用中文名还是英文名无所谓但序列化时一定要存字符串或索引不要直接存枚举对象。2.2 状态管理与跨组件通信设置页的数据要被三个地方消费设置 Tab 自己的 UI、闹钟编辑页新建闹钟时的默认值、响铃逻辑读取配置。如果不用全局状态就要在页面跳转时层层传参闹钟编辑页还好说响铃逻辑根本拿不到 Flutter 层的页面参数所以必须有一个全局控制器。我选了 Provider没上 Bloc 也没上 Riverpod。原因很简单这个项目规模不需要 Bloc 那套 event-action 的仪式感Provider 的ChangeNotifier对中小型 App 足够清晰。Riverpod 当然更好但团队里有人不熟学习成本也是成本。class SettingsController extends ChangeNotifier { AppSettings _settings const AppSettings(); AppSettings get settings _settings; Futurevoid load() async { // 从持久化层读取见2.4 } void update(AppSettings newSettings) { _settings newSettings; notifyListeners(); // 同时触发持久化写盘注意防抖 } }跨组件通信这里有个容易被忽略的问题闹钟编辑页读取默认值时SettingsController可能还没加载完成。我处理方式是App 启动时在main()里先await controller.load()再runApp()。这样首帧出来之前数据已经就绪虽然启动会慢几十毫秒但避免了空值到处判断。如果实在不想阻塞启动可以用FutureBuilder包一层加载完成前显示空白页也行但已经在生产环境用过几轮后我推荐还是阻塞首帧一个设置文件的 JSON 解析撑死几毫秒不值得做异步壳子。Provider 的挂载方式我写在 App 顶层void main() async { WidgetsFlutterBinding.ensureInitialized(); final settingsController SettingsController(); await settingsController.load(); runApp( ChangeNotifierProvider( create: (_) settingsController, child: const AlarmApp(), ), ); }这种写法比在create里异步初始化要稳因为create是懒加载的第一个读取状态的 Widget 构建时才会触发如果那时候闹钟编辑页刚打开用户会看到一次“设置未加载”的闪烁。2.3 设置页 UI 组件开关、下拉框、滑条的组合设置页的 UI 我拆成了通用SettingsTile相当于一个“标题 右侧控件 点击回调”的容器。不要每个设置项都写一个独立 Widget分组复用才是正经做法。class SettingsTile extends StatelessWidget { final String title; final String subtitle; final Widget trailing; final VoidCallback? onTap; const SettingsTile({ required this.title, this.subtitle , required this.trailing, this.onTap, }); override Widget build(BuildContext context) { return ListTile( title: Text(title), subtitle: subtitle.isEmpty ? null : Text(subtitle), trailing: trailing, onTap: onTap, ); } }然后各个设置项就是往trailing里塞不同控件默认铃声DropdownButtonString数据来自预置铃声列表震动模式SegmentedButton或者三个单选按钮推荐 SegmentedButton视觉更紧凑贪睡时长Slider 右侧显示当前分钟数渐强时长Slider范围 0-60 秒0 表示关闭重复规则弹一个底部弹窗里面放七个 Switch每个设置项更新时都走同一个方法controller.update(controller.settings.copyWith(...))然后notifyListeners自动刷新所有订阅了状态的页面。这里有个实际体验滑条更新频率很高如果每次拖动都触发copyWithnotifyListeners 写盘设置页会掉帧状态栏还有可能被磁盘 IO 卡到。我的做法是滑条松手时onChangeEnd才写盘拖动过程只更新内存。2.4 配置持久化JSON 文件方案设置数据要不要用数据库我的答案是“看复杂度”。闹钟列表肯定要用数据库但设置项就十几个 key用 JSON 文件存在应用沙箱里完全够。OpenHarmony 侧有ohos.data.preferencesFlutter 层也有shared_preferences的鸿蒙适配版但我选了自己封装一个 JSON 文件读写原因有三一是设置项以后大概率会加嵌套结构比如“智能跳过节假日的节假日列表”SharedPreferences的扁平 key-value 存嵌套很痛苦二是 JSON 文件调试期可以直接hdc file recv拉出来看排查问题非常直观三是写入时机我统一用防抖控制文件 IO 频次很低。class SettingsPersistence { static const _fileName app_settings.json; FutureAppSettings load() async { final dir await getApplicationSupportDirectory(); final file File(${dir.path}/$_fileName); if (!await file.exists()) return const AppSettings(); final map jsonDecode(await file.readAsString()) as MapString, dynamic; return AppSettings.fromJson(map); } Futurevoid save(AppSettings settings) async { final dir await getApplicationSupportDirectory(); final file File(${dir.path}/$_fileName); await file.writeAsString(jsonEncode(settings.toJson())); } }getApplicationSupportDirectory来自path_provider这个插件在 OpenHarmony 上也有适配没有的话就自己写一个 MethodChannel 拿沙箱路径不算复杂。持久化还有一个细节写盘要防抖。用户连续拖动滑条到 10 分钟再停下来中间可能有 20 次copyWith如果每次都写文件低端设备会卡顿。我封装一个Timer延迟 500ms 写盘逻辑很粗暴但有效Timer? _debounce; void _scheduleSave() { _debounce?.cancel(); _debounce Timer(const Duration(milliseconds: 500), save); }配置加载的优先级也要注意AppSettings.fromJson里对缺失字段要给默认值不要因为某个旧版本没存过fadeSeconds就崩溃。我习惯用map[fadeSeconds] as int? ?? 0这种写法。3. 平台通道设置 Tab 与 OpenHarmony 原生侧交互的硬骨头3.1 MethodChannel 与 EventChannel 怎么分工闹钟 App 绕不开原生能力读取系统铃声列表、查询通知权限、检测电池优化白名单、后台响铃。Flutter 层跟 OpenHarmony 原生侧打交道就两条路MethodChannel是“一问一答”模式适合主动调用EventChannel是“持续订阅”模式适合原生侧主动推事件。我用一个具体场景来解释这两者的差异。设置页里显示“当前通知权限状态”这个状态 App 启动时要查一次用户去系统设置里改了之后回到 App 还要能刷新。查询用 MethodChannel 一次性读监听用户从系统设置返回这种事件就必须用 EventChannel 订阅生命周期变化原生侧在应用回到前台时把最新状态 push 给 Flutter。分工原则很简单同步操作的返回值走 MethodChannel异步流式事件走 EventChannel。千万别用 EventChannel 去实现“一次性的数据查询”事件流一旦订阅就是长期占用没需求就 close否则原生侧资源一直被握着。// Dart 侧 MethodChannel 封装 class SettingsPlatformChannel { static const _channel MethodChannel(com.example.alarm/settings); Futurebool checkNotificationPermission() async { return await _channel.invokeMethod(checkNotificationPermission); } FutureListString getSystemRingtoneList() async { return await _channel.invokeMethod(getSystemRingtoneList); } }原生侧实现位置在ohos目录下核心是FlutterPlugin的onMethodCall分发。我用的是 DevEco 自动生成的模版在AlarmPlugin.ets里加分支处理// ohos 侧关键逻辑 onMethodCall(call: MethodCall, result: MethodResult) { switch (call.method) { case checkNotificationPermission: // 调用通知管理接口检查通知是否开启 break; case getSystemRingtoneList: // 查询系统铃声目录返回资源路径列表 break; } }这个文件在鸿蒙侧是 ArkTS 写的类型系统比 Flutter 严格Map 的 key 类型经常要显式as string写的时候注意点。3.2 EventChannel 订阅系统事件设置 Tab 里我用了两个 EventChannel一个监听系统时区变化一个监听 App 回到前台。时区变化直接影响闹钟列表里“世界各地时间”的显示App 回前台则要刷新权限状态。Dart 侧订阅代码class SystemEventService { static const _eventChannel EventChannel(com.example.alarm/system_events); Streamdynamic get eventStream { return _eventChannel.receiveBroadcastStream(); } }使用的时候注意receiveBroadcastStream返回的是一次性 Stream如果订阅关系断掉需要重新建立。我写了一个StreamSubscription管理器页面销毁时统一 cancel避免内存泄漏。原生侧实现 StreamHandler两个方法onListen时把事件源接上onCancel时断开。这里有个常见的坑EventChannel 的onListen会被多次触发如果没有把事件发送源做成单例会出现原生侧重复发送、Flutter 侧收到重复事件的情况。权限状态刷新这块鸿蒙原生侧可以在onPageShow或者onConfigurationUpdated回调里主动调用eventSink.success(permissionStatus)把这个 boolean 推给 Flutter。3.3 后台响铃与代理提醒的边界这是闹钟 App 里水最深的地方。老实说Flutter 层管不了后台保活你不能指望一个纯 Dart 的 Timer 在 App 被系统挂起之后还能准点响铃。OpenHarmony 有自己的代理提醒ReminderAgent闹钟时间到了由系统来触发这套机制在原生侧实现Flutter 层只负责“提交闹钟任务”。所以我的设计是闹钟编辑页保存时不管前台后台都通过 MethodChannel 把闹钟时间、重复规则、铃声路径提交给原生侧原生侧用 ReminderAgent 注册系统级提醒。响铃发生时如果 App 在前台原生侧通过 EventChannel 推一个“闹钟响了”的事件Flutter 弹自定义全屏闹钟页如果 App 在后台或已杀死系统级响铃界面接管用户点击“贪睡”或“停止”后结果再同步回 Flutter 层。这个分工决定了设置 Tab 里的“渐强时长”和“铃声选择”不能只存在 Flutter 配置里还要同步给原生侧。我是在设置保存时调一个syncSettingsToNative的 MethodChannel把AppSettings整体序列化传过去。这一步漏了的话用户改了默认铃声但后台闹钟还在用旧铃声属于上线后会被骂死的 bug。后台响铃的权限检查也别落下。OpenHarmony 的电池优化策略跟 Android 类似App 可能被限制后台运行。设置页里我用一个专门的条目显示“电池优化白名单状态”点击直接跳转系统设置页这部分也是 MethodChannel 调原生。4. 工程化落地调试、打包与常见问题排查实录4.1 高频报错与解决速查表整个开发周期里我记录了一批比较典型的报错和排查路径整理成表格方便你对照报错 / 现象原因解决办法Target platform ohos is not supportedflutter 命令用的是原版 SDK不是 OpenHarmony 适配版把 PATH 指向适配版 SDK或 fvm 锁定适配版本运行时报MissingPluginException调用的 MethodChannel 没有在原生侧实现或者插件没有 ohos 分支检查ohos目录下 FlutterPlugin 注册列表缺什么补什么x86_64 模拟器上 PlatformView 白屏模拟器的图形渲染与原生 View 合成不兼容换真机调试或者升级模拟器镜像中文字体在小字号模糊未打包字体到 assets设置页标题和正文统一走 TextTheme不依赖系统字体兜底设置修改重启后丢失持久化写盘没走防抖或者保存被异常中断把save方法加上 try/catch失败时回滚内存状态并弹出错误提示hdc list targets看不到设备DevEco 的 hdc 与命令行 hdc 版本不一致用 DevEco 内置终端执行 hdc或统一 hdc 路径热重载失效改代码没反应ohos 侧原生代码改动不能热重载Flutter 层改动可以热重载原生侧改完必须重新编译部署最坑的是MissingPluginException因为 OpenHarmony 的三方插件生态还在补全很多 Flutter 插件只在 Android 实现了你直接拿过来跑鸿蒙必然报错。我的原则是核心插件优先找官方 ohos 适配版本没有适配的要么自己封装 MethodChannel要么换一个鸿蒙原生能力替代。比如我在工程里就没用flutter_local_notifications而是直接用 ReminderAgent 封装自己的通知服务。4.2 性能与耗电优化注意点设置 Tab 的性能压力不在 UI 渲染在状态刷新和原生通道频率。UI 层面设置页的 ListTile 不太可能掉帧但如果你把DropdownButton塞进ListView里弹出的选择菜单在某些鸿蒙设备上会有渲染层级问题。建议下拉选择改成底部弹窗或者包一层Overlay实测在低端设备上更稳。状态刷新层面设置项跟闹钟列表联动时容易产生无效重建。比如SettingsController.update每次调用都notifyListeners但闹钟页其实只关心defaultRingtone和repeatDays两个字段。我在闹钟页用了context.select而不是context.watch整个 controller只监听需要的字段。final defaultRingtone context.select( (SettingsController c) c.settings.defaultRingtone, );这样设置页改震动模式时闹钟页不会重建省掉不必要的 build 开销。耗电层面EventChannel 订阅不要全局常驻。我原来是main()里订阅时区变化但后来发现时区变化一年发生不了几次改成进入世界时钟 Tab 时才订阅离开时取消。闹钟响铃状态订阅也做了同样处理只有 App 在前台且有活跃闹钟时才挂事件流。原生侧的代理提醒提交频率也要控制。每次设置保存都重新注册所有闹钟没必要我做了个 diff只提交“修改时间”和“删除时间”的闹钟没变的闹钟不碰原生接口。4.3 发布前检查清单从“能跑”到“能发”中间至少隔着一份检查清单。我把这次实战里最可能翻车的检查项列出来第一权限声明。闹钟 App 要通知权限、闹钟权限鸿蒙这边还有后台运行权限。module.json5里漏声明一个用户真机安装后功能会静默失效不报错不崩溃就是闹钟不响。第二自启动和电池优化白名单引导。这块如果不做杀后台之后闹钟直接失灵。设置页里我放了一个“后台运行保护”入口用户点进去能看到三种状态允许自启动、忽略电池优化、通知权限。每个状态都用绿色/红色标识点击可以直接跳系统设置实测对用户理解帮助很大。第三铃声资源打包。预置铃声放在 Flutter 的assets目录后记得在pubspec.yaml里声明。但原生侧后台提醒播放的铃声路径需要能拿到“原生能访问到”的文件路径。这里我走了原生侧的rawfile目录而不是 Flutter assets因为后台响铃时 Flutter 引擎可能还没起来原生侧根本加载不到 Flutter 的 asset。# pubspec.yaml 片段 flutter: assets: - assets/ringtones/// module.json5 片段ohos侧 requestPermissions: [ { name: ohos.permission.NOTIFICATION_CONTROLLER }, { name: ohos.permission.KEEP_BACKGROUND_RUNNING } ]第四桌面图标和启动页。OpenHarmony 的 App 图标要多个尺寸启动页背景色要跟 Flutter 首屏背景一致否则冷启动时会闪一下白屏。我之前吃了一次教训启动页纯白、Flutter 首屏纯黑用户安装后第一印象非常差。第五测试覆盖。闹钟这种 App 的时间逻辑测试比 UI 测试更重要。我用test包覆盖了AppSettings的序列化、重复规则计算、贪睡时间边界。设置 Tab 的copyWith逻辑属于纯 Dart可以完全脱离设备跑单测建议把这块做成 CI 的一部分。5. 设置 Tab 扩展方向与我的个人体会如果你不想止步于基础设置设置 Tab 还可以继续往“高级”方向做。我后续计划加的有两个一是“法定节假日跳过”开关通过原生侧读节假日配置与重复规则联动计算下一次响铃时间二是“铃声淡入淡出曲线”设置不只是渐强时长还能选线性/指数渐强。这两块都需要在设置页里增加新的设置项和原生通道能力数据结构上因为我用了 JSON 文件方案扩展字段很容易。做完这一整套我一个比较深的体会是Flutter for OpenHarmony 的坑大部分不在 Flutter 而在对鸿蒙系统特性的理解。比如后台闹钟必须交给 ReminderAgent、事件通道的生命周期管理、权限模型的差异这些东西你在文档里看不到完整答案得把 Android 的经验迁移过来再消化一遍。设置 Tab 看起来简单实际上是把 Flutter 的响应式状态管理、平台通道、系统权限和一个真实业务场景揉在一起的综合练习。做完了它你对 Flutter 组件通信的理解会在实战里真正落地而不是停留在面试题层面。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

电路等效变换核心方法:串并联、Y-Δ与电源互换的化简实战 2026/10/2 16:54:17

电路等效变换核心方法:串并联、Y-Δ与电源互换的化简实战

1. 等效变换的核心思路:到底在“等效”什么1.1 对外特性一致,内部随它去刚开始学电路分析,最容易卡住的地方就是这个“等效”到底是什么意思。很多同学把电阻串并联公式背得滚瓜烂熟,但遇到一个复杂的网络就不知道怎么下手&#x…

阅读更多 →
等效变换在电阻电路中的核心应用:串并联、星三角与电源互换 2026/10/2 16:54:17

等效变换在电阻电路中的核心应用:串并联、星三角与电源互换

刚学电路那阵子,最让我头疼的不是欧姆定律,不是基尔霍夫定律,而是一张纸上画着一大坨电阻,有串联有并联还有桥接,看得人头皮发麻。后来才明白,那一坨东西其实可以“压缩”成一个电阻——这就是电阻电路的等…

阅读更多 →
LILYGO T-Display P4:嵌入式无线电开发实战指南 2026/10/2 16:54:17

LILYGO T-Display P4:嵌入式无线电开发实战指南

1. 项目概述:为什么一块小屏幕能成为无线电爱好者的掌上中枢?“LILYGO T-Display P4 变成掌上无线电瑞士军刀”——这个标题乍看像极了极客圈里常见的夸张修辞,但实打实拆开来看,它背后是一整套嵌入式系统工程的浓缩落地。我第一次…

阅读更多 →
VS Code 安装 OpenCode 插件使用教程:把 Base URL 改到 TaoToken 2026/10/2 16:54:17

VS Code 安装 OpenCode 插件使用教程:把 Base URL 改到 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
AIDA64深度实测:传感器面板、副屏监控与稳定性测试全解析 2026/10/2 16:54:17

AIDA64深度实测:传感器面板、副屏监控与稳定性测试全解析

装机这么多年,桌面上始终留着AIDA64这个“硬件检测全家桶”。从当年EVEREST时代一路用过来,版本换了不少,日常跑不开的就是传感器面板、稳定性测试、硬件参数读取这几件事。最近把主力的v6.50版本又系统折腾了一轮,把副屏模板、存…

阅读更多 →
【Claude Code】1、ClaudeCode安装(Windows系统)与TaoToken统一Key配置 2026/10/2 16:53:56

【Claude Code】1、ClaudeCode安装(Windows系统)与TaoToken统一Key配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉