Flutter for OpenHarmony实战:构建跨端盲盒App的完整技术方案
做一个盲盒抽奖App的活儿现在摆在面前的第一个问题不是业务逻辑而是技术选型。团队接到的是一个需要在国产系统上跑起来的项目目标平台是OpenHarmony生态产品形态是一个集商城和抽奖玩法于一体的盲盒App。我当时的想法很简单与其用三方技术栈重复造轮子不如试试Flutter for OpenHarmony这套方案把UI层和业务层一并搞定。这篇文章就把整个项目的实战过程记录下来从商城列表的搭建到盲盒抽奖的核心逻辑完整拆给你看希望对在国产化平台上做跨端开发的读者有帮助。1. 为什么用Flutter for OpenHarmony做盲盒App1.1 跨端方案对比与我的选型思路盲盒App这个业务形态比较特殊它的界面重、交互多、动画频繁还需要商城列表的大图浏览、卡片滑动、商品详情跳转传统Web方案在体验上容易翻车。我们最初考虑过三条路线纯ArkTS开发、uni-app适配、Flutter for OpenHarmony。纯ArkTS开发的问题在于如果后续还要做iOS和Android端代码要推倒重来。我们的产品规划里明确说了OpenHarmony只是第一站后面其余移动端都有可能上所以一套代码多端复用是硬性诉求。uni-app虽然也能跨端但在复杂动画和高频交互的性能表现不稳定尤其是一些物理惯性滚动手感跟原生体验有差距。Flutter for OpenHarmony的优势在于它保留了Flutter的渲染引擎和Dart语言的开发手感UI层的代码几乎可以无缝搬迁到OpenHarmony平台。我们调研实测下来结论是列表滚动和粒子动效都能达到接近原生的流畅度动画的物理模拟精度比Web方案好不少。最后定下来的技术栈是Flutter for OpenHarmony Provider状态管理 自研随机算法服务端只管返回奖品池和保底标记随机性放在客户端做降低服务端压力。1.2 项目整体架构与模块划分这个项目的代码量大概在1.8万行Dart代码左右分为三个大模块。第一个是商城列表模块负责商品瀑布流、分类筛选、购物车和结算。第二个是抽奖模块负责奖池配置、概率计算、开盒动画、中奖记录。第三个是用户模块负责登录态、订单管理、地址管理。模块之间用Provider和路由解耦。抽奖模块不直接依赖商城模块的UI只依赖一个注入进来的商品数据服务接口这样后续如果要做“抽奖送优惠券”或“积分兑换抽奖次数”就不需要大改。值得强调的是在OpenHarmony上用Flutter不能用原生Flutter的路由包地很舒服因为生态的插件支持度还不完善。我的做法是全部用Navigator 2.0的RouterDelegate做自定义路由表URL直接映射到页面组件这样天然支持页面级生命周期管理也能在路由切换时做埋点。2. 商城列表模块设计与实现2.1 数据模型与状态管理方案商城列表的第一件事是定义数据模型。盲盒商品比普通商品多一个“款式数量”“隐藏款概率”“系列名”字段这些字段直接决定抽奖逻辑。数据模型我是这样设计的class BlindBoxProduct { final String seriesId; final String productId; final String title; final String coverUrl; final double price; final int totalStyles; final int onSaleCount; final bool hasHiddenStyle; final double hiddenProbability; final ListSkuInfo skuList; }状态管理方面我最终选择了Provider而不是Riverpod或Bloc核心原因是团队已有代码里大量使用了Provider新项目不需要重新培训成本。商城列表页的状态类型有数据加载状态、筛选条件状态、滚动位置状态、购物车状态我把它们拆成三个独立的Provider避免整个页面频繁重建。列表数据我用了一个Channel拆分策略前两屏数据走内存缓存第三屏之后走服务端分页。这个决策的有效性在于盲盒商品的图片普遍较大如果一次性加载全部数据内存峰值会快速冲到200MB以上在OpenHarmony的低端设备上很危险。2.2 列表渲染优化与下拉刷新加载Flutter在OpenHarmony上的列表性能关键在复用机制。我们项目里没有用普通的ListView而是用了CustomScrollView SliverList的组合因为盲盒商城首页需要头部Banner、分类标签区、商品瀑布流三大区域混排整体滑动的联动感更统一。一个必须提的优化细节是itemExtent。盲盒商品卡片的布局是从封面图、标题、价格、购买按钮四行高度是固定的。如果不设置itemExtentSliverList需要根据每个item的实际高度动态计算布局滚动过程会出现抖动设置了固定高度之后滚动性能提升非常明显。我在真机上实测过设置了itemExtent之后快速滑动时候的掉帧率从8%降到了2%。下拉刷新我用了RefreshIndicator配合ScrollController监听位置。这里有个OpenHarmony上的适配坑RefreshIndicator的默认指示器在OpenHarmony上会有些渲染黑屏的问题原因是系统的Splash控件跟Flutter的CompositingLayer叠加冲突。解决方式是自定义一个RefreshIndicator的notificationPredicate把指示器换成一个纯Flutter绘制的圆弧控件。骨架屏也是这个项目里的体验重点。盲盒商城的用户很多人是用低端机访问的网络加载期间如果白屏跳出率会很高。我实现了一个Shimmer效果组件用ShaderMask做渐变动画在数据到达前展示商品卡片骨架。这个组件不是简单的灰色方块而是按照真实卡片的比例绘制出封面区、文字区、价格区的占位形状视觉过渡非常自然。2.3 商品卡片组件与瀑布流布局瀑布流在Flutter里的常见方案是用GridView配不同比例的图片但图片比例不一致时固定行高的Grid会导致卡片错位。我最终采用的是SliverGrid 自定义SliverGridDelegateWithFixedCrossAxisCountAndFixedHeight统一固定卡片高度。盲盒商品的封图比例是用九宫格切图避开的服务端返回的是适应两列排版的方形图本地再通过BoxFit.cover裁剪到固定的正方形区域。卡片的热区我做了一个小优化点击区域是整个卡片但购买按钮在右下角它会拦截触摸事件并弹出商品详情底窗。这里如果用GestureDetector嵌套底层卡片的点击事件会冒泡触发。我的做法是卡片用InkWell按钮用Listener的onPointerDown里面手动调用stopPropagation()操作实测很稳。卡片上的“剩余数量”展示是个容易被忽略的点。盲盒的稀缺性是这个产品的核心卖点所以我在卡片右上角用Positioned放了一个红色角标显示剩余库存库存低于3个时角标变成“即将售罄”的呼吸灯效果用AnimationController循环控制透明度。3. 盲盒抽奖核心逻辑与公平性实现3.1 抽奖流程与状态机设计抽奖环节是整个App最复杂的业务模块因为它不是一个单纯的随机中奖流程它需要处理余额扣减、库存预占、奖品稀有度校验、隐藏款特殊判定等一长串逻辑。为了不让代码变成一团乱麻我用一个状态机来管理整个抽奖生命周期。状态机包含以下状态Idle、Drawing、WaitServerConfirm、RevealAnimating、Finished、Failed。IDLE表示用户还没点击“开盒”Drawing是客户端正在向服务端请求抽奖结算WaitServerConfirm表示订单已创建但未确认奖品RevealAnimating是开盒动画播放中Finished表示本轮抽奖完成Failed表示余额不足或库存异常。状态迁移的核心逻辑是这样的用户点击开盒先检查余额和库存满足条件则进入Drawing状态同时客户端本地立即根据概率池生成一个临时中奖结果用于动画预演此时服务端也在做同样的随机判定。返回结果后如果服务端结果与本地预演一致就直接进入Finished如果不一致这通常意味着服务端酒池里没有对应奖品需要重新走一次隐藏款修正逻辑然后重新播放动画。这里有个深坑需要提醒预演结果不能直接入库只是用来让动画先行否则服务端的库存扣减和你本地随机池一旦对不上订单就会被卡死。我们的方案是服务端结果为准本地预演纯粹是视觉体验优化。3.2 权重随机算法与保底机制实现盲盒抽奖最敏感的环节是概率控制。我们的奖池采用了区间累计法这是业界最直观的权重随机方式。假设奖池有四个档位普通款、稀有款、典藏款、隐藏款权重分别是78、15、6、1那么可以生成一个累计区间数组然后随机生成一个0到100之间的小数落在哪个区间就中对应的档位。class WeightedRandomPool { final ListBlindBoxSku skus; final Listdouble _accumulatedRanges; WeightedRandomPool(this.skus) : _accumulatedRanges _buildRanges(skus); static Listdouble _buildRanges(ListBlindBoxSku skus) { var total 0.0; return skus.map((sku) { total sku.weight; return total; }).toList(); } BlindBoxSku draw() { final rand Random.secure().nextDouble() * _accumulatedRanges.last; for (var i 0; i _accumulatedRanges.length; i) { if (rand _accumulatedRanges[i]) { return skus[i]; } } return skus.last; } }初版上线后运营反馈说连续开盒的情况里总有用户连续抽到同一个系列的非隐藏款体验不好。这是因为纯随机算法无视历史结果用户在一轮连抽10次时重复概率很大。解决方式有两种一种是概率去重抽到某款后立即降低该款权重另一种是保底机制记录用户连续未中隐藏款的次数达到N次后强制出货。我们最终采用了“保底 局部去重”的双层方案。保底逻辑里设置了一个阈值比如连续49次未中典藏级及以上到第50次直接给典藏保底。这个计数由客户端本地存储服务端用订单流水同步校验。使用中需要注意本地时钟和时区问题会影响“按天重置保底计数”的逻辑所以保底计数建议存储为自增整数而不是依赖日期字符串这样在服务端统计时才不会错乱。3.3 开盒动画与交互动效拆解盲盒开盒的动画是这个产品的门面我花了大量精力去打磨。最初我们用的是GIF动图方案但导入后发现GIF在OpenHarmony上的解码性能极差播放过程中有明显的CPU spike。后来换成了Flutter自带的动画系统用AnimationController配合RotationTransition和ScaleTransition模拟真实的盒子打开过程。开盒动画分四段第一段是盒子进入屏幕Scale从0.8到1.0曲线用Curves.easeOutBack产生弹跳感第二段是盒盖旋转Transform动画让盒盖绕着顶部中心点做45度旋转展开第三段是一束光从缝隙中射出来用Opacity和一个RadialGradient容器实现第四段是内容物显示。为了让“开出隐藏款”有独特的仪式感我单独写了一个粒子特效组件用CustomPainter绘制上百个小的随机粒子它们从中心位置向外扩散配合不同的透明度衰减曲线形成类似星芒爆炸的效果。粒子数量控制在200个以内否则低端机掉帧明显。加入交互动效时的一个重要心得动画必须支持“跳过”。用户如果看了这个动画超过5次会显著感到烦躁我在App设置里加了一个“快速开盒”开关开启后动画时长压缩到0.8秒并且粒子数量减半。这在留存数据上体现了正向收益值得向大家推荐。4. 完整业务闭环从下单到开盒的流程实现4.1 库存扣减与订单创建机制盲盒和普通电商商品的区别在于下单价和开盒结果不是同一个SKU因此库存系统要处理的是“抽奖库存池”和“具体SKU库存池”两个概念。用户在商城页面购买的是抽奖次数支付成功后进入待开盒状态此时扣除的是抽奖次数库存而不是具体的某个盲盒款式库存。当用户点击开盒、结果确定之后服务端才真正扣减对应SKU的库存。这个机制避免了“预扣所有SKU库存”导致的结果膨胀也是开盒结果能在客户端本地随机预演的前提。订单状态机分为四个阶段Created、Paid、AwaitingReveal、Done。Created是用户点击下单但没付款Paid是支付成功此时锁定抽奖次数AwaitingReveal是用户尚未开盒Done是已经开盒且结果已确认。特别提醒一下“AwaitingReveal”订单如果长期不处理会占着抽奖次数不释放因此需要一套定时任务超过24小时未开盒的订单自动退款并释放库存。4.2 支付回调与并发安全支付回调是抽奖系统最容易出事故的环节。第一次联调时我们用了一个常规实现支付回调里直接修改订单状态并发货结果压测时发现同一笔订单被支付平台重试回调了多次导致抽奖次数被多扣。解决方案是在支付回调入口加一个分布式锁。锁的key是orderId值是一个随机生成的uuid服务端拿到回调后先尝试获取锁获取失败就直接丢弃不执行后续逻辑。同时订单表里的状态字段用乐观锁版本号来控制更新只有版本号匹配的更新才会成功。这里还有一个小坑服务端的抽奖次数余额查询如果直接用数据库的“读后写”会查不到刚支付过来的最新状态因为主库和读库存在延迟。我们的做法是支付回调成功之后走一次强制刷新缓存同时写一个补偿定时任务每5分钟扫一遍最近1小时的Paid订单确认有没有漏发抽奖次数。4.3 用户端开盒结果处理与记录展示用户开盒之后结果记录要在“我的奖品”页面展示并且支持“直接发货”和“合成碎片”两种操作。这个页面的实现不算难但有一个细节要注意多订单的奖品记录要分页加载每页20条不要一把梭全量加载否则用户开了几百个盒子之后页面会非常卡。开盒记录的卡片我用了展开式布局。默认状态下只显示封面和稀有度图标用户点击“展开详情”后才滑出完整的批次信息、购买时间、发货状态。这里的动画用了AnimatedContainer的高度动画需要注意在数据刷新时旧的展开状态要保持否则每次setState都会把列表折叠回初始状态体验很差。在“我的奖品”列表里我给每一类奖品加了标签普通款用灰色标签稀有款用蓝色典藏款用金色隐藏款用彩虹渐变。用户在这里能看到自己的“欧皇指数”这个指数是后端根据历史开盒记录算出来的前端只负责展示。很多用户会为了提升指数去连抽这个点对留存很有帮助。5. 性能优化、常见问题与实操心法5.1 性能优化列表滚动与动画整个项目做完之后性能优化主要集中在前三点列表滚动流畅度、动画内存峰值、页面启动速度。列表滚动方面除了前面提到的itemExtent和复用机制外还有一个重要的优化点是图片解码。盲盒商品封面图动辄几百KB如果直接用网络图加载列表滑动时会频繁解码导致出现锯齿感。我的做法是用cached_network_image配合自定义的CacheManager把图片的内存缓存上限设在80MB磁盘缓存上限设在200MB同时在图片解码时统一压缩到实际显示尺寸的1.5倍不从网络加载原始大图。动画内存方面粒子特效如果不做释放会让内存持续增长。我的做法是在每次动画结束后立即调用controller.dispose()清空AnimationController粒子的Paint对象也要用缓存避免每次动画重新new一个Paint。页面启动速度上有一个容易被忽略的点首帧渲染前如果执行了太多同步操作黑屏时间会增加。我们的首页启动时有一系列初始化比如读取本地缓存、注册推送、拉取配置如果全部放在main()里同步执行会让首屏等待时间拉满。优化方案是把非必要初始化全部异步延迟执行只有缓存读取和路由表注册是必敏路径上的操作。5.2 常见问题排查速查表问题现象可能原因排查思路与解决方案状态栏与页面顶部重叠OpenHarmony的状态栏高度与Flutter的MediaQuery不一致使用平台通道读取真实状态栏高度在Scaffold外层设置内边距补偿图片加载黑块图片解码格式不支持部分WebP变体在OpenHarmony解码失败服务端统一输出PNG或JPEG禁掉WebP一类的有损格式下拉刷新卡顿RefreshIndicator与系统Splash冲突自定义刷新指示器用纯Flutter绘制替换系统默认组件抽奖动画掉帧严重粒子数量过多或controller未释放限制粒子数量上限200动画结束后手动dispose支付回调重复入账回调重试导致幂等缺失加分布式锁和乐观锁版本号锁的key用orderId开盒结果与预演不一致服务端奖池状态与本地缓存不一致以服务端结果为准本地预演只做展示增加隐藏款修正逻辑商品列表滚动抖动SliverGrid高度估算不正确设置固定itemExtent或固定高度避免动态测量5.3 实战心法分享最后分享几条我做这个项目的核心体会。第一Flutter for OpenHarmony的性能和兼容性已经能够支撑商业级App但不要朝“无脑跨端”的方向想。一些特殊的平台行为差异比如状态栏高度、系统Splash、图片解码格式都会在真机上暴露。开发阶段一定要准备一台真机模拟器上的表现不能作为性能参考依据。第二盲盒玩法的随机算法一定要留够改造空间。我们上线三个月内调整了四次概率策略从纯权重大保底、到局部去重、再到按用户活跃度分档概率。如果一开始就把抽奖逻辑写死在页面里后续每次调策略都要发版那是灾难。把算法封装成独立的服务类并且用配置中心下发权重参数是值得推荐的架构方向。第三不要忽视离线场景。用户在地铁、电梯里打开App网络不稳定时列表会一直转圈。我们在列表层加了一个“断网重试”的缓存策略如果之前已经加载过同一页数据网络失败时优先展示缓存数据同时后台继续拉新数据。这功能对留存率的提升很有帮助。

相关新闻

Linux进程状态全解析:从R/S/D/Z到内核调度与排查实战

Linux进程状态全解析:从R/S/D/Z到内核调度与排查实战

两三年前我第一次遇到一批D状态进程堆积在服务器上的场景时,第一反应是找应用日志、分析服务线程,折腾了一个多小时毫无头绪,最后才发现问题是宿主机存储链路超时,所有进程都在等底层磁盘回包。那次之后我才真正意识到&#xff1a…

2026/10/13 7:26:02 阅读更多 →
Linux下SQL Server分区实战:性能优化与I/O协同

Linux下SQL Server分区实战:性能优化与I/O协同

1. 项目概述:为什么在 Linux 上谈 SQL Server 分区,不是“炫技”,而是刚需SQL Server On Linux 自 2017 年正式发布以来,已从“能跑”走向“稳跑”,再到如今的“高效跑”。但很多团队在迁移或新建 Linux 环境下的 SQL …

2026/10/13 7:25:02 阅读更多 →
NModbus Tools 实战:Modbus RTU/TCP 调试与避坑指南

NModbus Tools 实战:Modbus RTU/TCP 调试与避坑指南

简介:NModbus Tools 是一套基于 NModbus4 开源库构建的 Modbus 协议工具集,面向工业自动化领域的开发者、测试工程师及工控学习者,用于串行链路、TCP 网络与协议报文数值的处理。它可帮助使用者完成 Modbus RTU 与 Modbus TCP 的数据读写、报…

2026/10/13 7:25:02 阅读更多 →

最新新闻

RNOH TextInput 适配实战:属性映射、受控行为与中文输入法问题

RNOH TextInput 适配实战:属性映射、受控行为与中文输入法问题

1. 先说背景:TextInput 在 RNOH 组件体系中的位置1.1 为什么输入组件是跨端项目里最烧时间的一环跨端开发做得久了,你会发现一个规律:页面上那些花哨的动效、复杂的布局,解决起来其实都有套路,真正消耗大量调试时间的往…

2026/10/13 8:09:32 阅读更多 →
DM7客户端工具WIN64使用指南:环境配置、数据迁移与排错实战

DM7客户端工具WIN64使用指南:环境配置、数据迁移与排错实战

简介:DM7客户端工具WIN64是一款面向64位Windows操作系统的达梦数据库V7管理客户端,主要服务对象是数据库管理员、开发人员以及需要维护达梦库的技术工程师,解决他们在生产环境中连接数据库、执行SQL、管理对象与保障数据安全时的操作便利性问…

2026/10/13 8:09:32 阅读更多 →
PyQt5+MySQL轻量人事管理系统:从数据库设计到打包部署

PyQt5+MySQL轻量人事管理系统:从数据库设计到打包部署

简介:简易人事管理系统基于PyQt5与MySQL实现,面向初学桌面端开发与数据库联调的开发者,也适合作为ERP系统中人事模块的参考方案。资源包含完整的员工、部门、薪资、登录验证等管理界面与逻辑,通过Python脚本和SQL文件即可运行与二…

2026/10/13 8:09:32 阅读更多 →
四旋翼无人机仿真与控制:MATLAB与SolidWorks联合开发实践

四旋翼无人机仿真与控制:MATLAB与SolidWorks联合开发实践

1. 项目背景与核心价值四旋翼飞行器的仿真与控制一直是无人机开发领域的关键环节。传统开发流程中,MATLAB/Simulink负责算法验证,而SolidWorks承担机械设计,两者往往独立进行导致效率低下。这个项目打通了从多体动力学仿真到三维模型控制的完…

2026/10/13 8:09:32 阅读更多 →
SpringBoot+Vue私房菜定制上门服务系统:全栈毕设项目实战解析

SpringBoot+Vue私房菜定制上门服务系统:全栈毕设项目实战解析

每年毕设季都有很多同学在选题边缘反复横跳:想做个前后端分离的项目,又怕工作量太大hold不住;想做商城系统,又觉得太泛滥没新意。今天聊的这个项目方向——SpringBoot Vue 私房菜定制上门服务系统管理平台,恰好属于那…

2026/10/13 8:09:32 阅读更多 →
Claude Code稳定使用指南:小任务、短会话、严审查

Claude Code稳定使用指南:小任务、短会话、严审查

最近两三周,我几乎把 Claude Code 用成了日常开发里最顺手的帮手。但说实话,刚上手那几天它并没有宣传里那么“开箱即用”:会话动不动就把上下文搞丢,改到一半的代码稍微切换一下任务就忘了自己刚才在干什么,碰上一个稍…

2026/10/13 8:08:32 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/12 18:11:17 阅读更多 →