news 2026/9/30 4:13:05

HarmonyOS系统级视觉AI控件:端侧视觉能力下沉UI框架

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOS系统级视觉AI控件:端侧视觉能力下沉UI框架

做端侧AI开发这几年,我最深的一个感触是:动手写模型不难,难的是把模型塞进真实业务里,还要让它在不同设备上都跑得稳。HarmonyOS这次在系统级场景化控件上把视觉AI的能力直接下沉到了UI框架层,等于把“会看”这件事从开发者的负担变成了系统的基础能力。这篇文章我从实际接入的角度,聊一聊这套控件的设计逻辑、接入细节和踩过的坑。

先说清楚它能做什么。如果你在开发应用时需要识别文档边缘、提取文字、检测人脸关键点、追踪物体,或者判断摄像头画面里有没有人,HarmonyOS 7直接给了你一套现成的UI控件。你不需要自己搭推理框架,不用处理模型格式转换,甚至连相机权限和画面流都帮你管了一部分。你只需要把控件放到页面上,配置几个参数,剩下的视觉分析流程就交给系统了。

这套方案适合谁?适合那些不想养AI算法团队,但又想给App加上视觉功能的应用开发者;也适合正在做端侧AI硬件部署验证的团队,想最快速度在鸿蒙设备上跑通一个视觉闭环。哪怕你完全不懂深度学习,也能在半天内把一个人脸检测功能集成到应用里。当然,如果你要的是完全定制化的模型行为,这套控件给不了你,你得走端侧AI硬件部署的自建路线。

1. 为什么端侧视觉一直这么难搞

视觉AI在端侧落地难,不是难在算法本身,而是难在它要照顾的东西太多了。首先是算力分配。一个目标检测模型在GPU服务器上跑,你只需要关心准确率;但在手机平板上跑,你要同时面对CPU占用、内存峰值、发热降频、NPU利用率这一堆问题。同一个模型,在不同设备上的性能差距能拉开三到五倍,这在云上是不会遇到的。

其次是设备适配。端侧Android和iOS生态,各家芯片的AI加速方案都不一样,GPU、NPU、DSP,底层计算单元五花八门。你要让模型在主力机型上跑得流畅,就得针对不同芯片做算子适配和性能调优。这个工作量比训练模型还要大。鸿蒙生态早期也面临同样的问题,一个应用里的视觉功能,在一款设备上优化好了,换一台设备就可能出现帧率骤降。

然后是工程复杂度。一个最简单的扫码功能,从零开始做,你需要摄像头预览、图像格式转换、检测模型管理、结果回调、UI绘制,中间还要处理权限申请、生命周期、内存回收。这些东西单拆出来都不难,但串在一起,整个链路的状态管理就会变得非常琐碎。更别提如果你要同时做好几个视觉功能,代码量会迅速膨胀。

我见过不少团队在做端侧视觉功能时,前期调研花了两周,模型选型花了一周,最后光是把模型封装成一个稳定可调的SDK就又花了一个月。HarmonyOS做系统级场景化控件,核心思路就是从系统层面把这一套复杂链路封装掉,让视觉AI变成和Button、List一样普通的UI组件。你不是在调AI,你是在摆控件。

那这套控件到底智能到什么程度?简单的扫码、人脸框选它当然没问题,更复杂一点的比如文档边角自动裁剪、手写文字识别、活体检测,它也都能在端侧完成。系统把这些能力做成了组件,开发者拿过来直接摆在业务页面里就行,真正的“扫码识别率”和“检测精度”都是系统团队在持续优化,不用你管。

2. 系统级视觉AI控件的设计逻辑

要理解这套控件,先得明白鸿蒙在端侧AI上的整体思路。HarmonyOS内部有一套统一的AI能力引擎,下接不同的硬件加速单元,上接各种业务场景。这套引擎统一管理模型生命周期和算力调度,而系统级场景化控件就是引擎暴露给开发者的最上层形态。

这意味着控件并不是简单地封装了一个SDK,而是在系统层面帮你管了算力分配。当你在页面上放置一个视觉AI控件时,系统会自动判断当前设备的硬件能力,决定用CPU、GPU还是NPU来跑底层的模型推理。对开发者来说,完全透明。你不需要关心设备当前是中端芯片还是旗舰芯片,只管功能表现就行。

控件的场景化体现在它“懂业务”。普通SDK只给你返回检测结果,比如“识别到一张脸”,至于接下来该干什么,那是开发者自己的事。但HarmonyOS的视觉AI控件是直接面向业务场景的,比如人脸检测控件,它不只是给你画个框,它还能返回人脸角度、关键点、活体状态,甚至能提供符合隐私规范的本地决策建议。很多业务逻辑系统已经帮你做了判断。

系统级控件还解决了一个特别现实的痛点——相机链路复用。同一个设备上,不同应用都在调摄像头做视觉分析,如果每家的图像采集格式和处理管线都不一样,调度冲突会是常态。系统统一接管了视觉处理的相机链路后,多个应用可以更协调地共享摄像头资源,系统也能对图像采集参数做统一优化。这一点在实机调试时感受特别明显。

从开发者的视角看,这套控件的分层也很清晰。最底层是统一的AI推理引擎,负责模型和算力调度;中间层是视觉算法能力集,提供各种检测和识别能力;最上层就是那些场景化控件,负责把能力和UI绑定。你可以只使用控件,也可以往下调用算法能力集做更灵活的开发,每一层都开放了对应的接口。

但是这里要注意一个边界。控件能帮你解决从“相机画面到识别结果”的完整链路,但识别结果怎么驱动业务,那是你的自由。比如文档扫描控件帮你输出了一张矫正后的图片,进一步做证件照生成、扫描件美化,这些后处理流程需要你自己写。理解了这条边界,接入的时候就不会产生预期偏差。

3. 实操拆解:四大类核心视觉控件

HarmonyOS 7的场景化视觉AI控件覆盖了应用开发中最常见的几个视觉场景。我把核心的几类梳理了一下,方便你对照自己的业务场景评估。

3.1 文档检测与扫描控件

这个控件解决的是“拍文档总是拍歪”的问题。以前我们要自己做人手检测、角点检测、透视变换,现在控件直接把这一整套流程封装好了。它实时识别画面中的文档区域,用四边形框出来,并实时做梯形矫正预览。用户在拍摄时就能看到“摆正后的效果”,而不是拍完再处理。

实际接入时,你只需要往页面里放一个文档检测控件,设置扫描模式和保存参数,剩下的都交给系统。控件内部会自动做边缘检测,识别出文档的四个角,然后计算透视变换矩阵,输出矫正后的图像。我在测试中发现它的抗干扰能力比较强,手挡住文档一角、桌面纹理复杂、光照不均这些情况,都能比较稳定地测出边界。

我建议你在接入时重点关注两个配置:自动拍摄的触发阈值和矫正后图像的压缩质量。如果阈值设得太低,页面里有一张名片都会触发自动拍摄;设得太高,用户对准发票半天也没反应。压缩质量则直接影响后续OCR的文字识别精度,一般建议首帧用85%以上的质量输出,二次展示再用压缩图。

3.2 OCR文字识别控件

OCR控件适合直接作为输入组件使用。你可以把它理解成一个“会识字的文本框”。用户对准菜单、名片、快递单、车牌拍照,控件直接提取里面的文字内容并结构化返回。它支持印刷体、手写体和多种版式,包括表格、证照这类结构化场景。

这次给我印象最深的是它对“弱光环境”的优化。以前做OCR,最怕光线昏暗加上手抖,拍出来的图噪点很多,识别率断崖式下跌。这个控件在系统层面做了图像增强预处理,低照度环境的识别准确率比我预想的好不少。它还支持识别结果实时流式输出,文字随着画面稳定逐渐变完整,体验上比一次性识别要舒服。

接入时最大的坑在于滑动冲突。OCR控件本身是可滚动的UI区域,放在 ScrollPage 或者 List 里,手势会打架。我测试时用了三分屏页面做识别,横向滑动切换Tab时,手一滑先触发OCR控件的取词子窗口,整个页面就卡住不动。解决方案是在控件初始化时限制子窗口的最大高度,并且只在长按取词时才激活滚动取词能力。

3.3 人脸视觉控件

人脸这块拆分得更细,有基础的人脸检测、人脸比对、关键点识别,还有针对金融场景的活体检测。区别于一般SDK只能告诉你“这里有一张脸”,这套控件还能告诉你脸的姿态角度、是否张嘴、是否眨眼、光线是否过暗。它是把人脸分析的完整能力都暴露出来了,可以用在很多业务场景里。

活体检测控件接入时,我建议直接使用系统推荐的交互模式,它已经在你眨眼的瞬间自动完成活体判断,不需要你额外设计“左转”“右转”的引导动画。系统会在UI层直接根据用户动作给出提示,比如“请眨眨眼”“请距离屏幕近一点”,你不用自己写任何提示逻辑。实测中动作引导动画的触发时延比第三方SDK普遍低了一两百毫秒。

不过注意,人脸控件的合规要求比其它视觉控件更严格。接入时系统要求你明确声明使用目的,而且人脸特征信息不允许上云,必须在端侧完成比对。我建议你在产品设计阶段就把“端侧比对、不留存原始人脸图像”这个原则写进你的隐私文档里,省得审核时来回改。

3.4 通用物体识别与目标追踪控件

这类控件的使用场景更广:相机识别花草、商品、宠物品种,或者在直播场景追踪画面中的特定物体。它的底层是一个轻量级图像分类加目标追踪引擎,可以在视频流中持续锁定一个目标,即便目标暂时被遮挡,重新出现后还能继续跟踪。

接入时最有用的配置是“识别结果置信度阈值”。系统默认阈值比较保守,测试时我用某款饮料包装做识别,总是识别成“未知物体”,调低阈值后就正常了。建议你根据自己业务对误报率的要求去调节,像商品识别这种场景,阈值设到0.5以下会明显提升识别率,但代价是偶尔会把形状相似的瓶子误判成同一款。

目标追踪控件更适合和“兴趣区域框选”配合。用户可以手动画框选中画面里的一个目标,然后控件持续跟踪。这里有一个细节:框选的起始目标太小,跟踪时会不稳定。实测经验是框选区域至少占画面10%以上,追踪效果才比较理想。如果你的业务还得支持小目标追踪,建议结合系统相机的高帧率模式使用。

4. 接入全流程:从工程创建到控件上屏

这里我用文档扫描功能举例,带你走一遍完整接入流程。整个过程大概需要半天时间,主要工作量集中在权限配置和页面参数调优,不需要写模型相关代码。

4.1 工程配置与依赖添加

首先创建一个HarmonyOS 7的工程,然后在module的oh-package.json5中添加视觉控件Kit的依赖。注意这里需要区分API版本,不同版本的Kit包名和接口会有差异,建议统一使用官方最新稳定版,避免后面遇到莫名其妙的编译问题。

当前你使用的API版本对应的依赖包版本号,可以在SDK的组件列表里查得到。我建议你直接查官方文档的版本映射表,不要盲目升级最新版本,有时候大版本间的接口变化不向下兼容,会让你被迫做额外的适配修改。加完依赖后,还需要在module.json5里声明相机权限和存储权限,否则运行时会闪退。

4.2 页面布局与控件初始化

依赖和权限搞定后,就可以开始写页面了。在ArkUI中放置一个DocumentScanComponent,设置好回调方法和扫描结果监听。性能测试里,控件在初始化时会额外启动相机预览流,如果你不做延迟加载,页面切换的首帧会有明显掉帧。建议把这个控件放在动态创建的分支里,等用户真正进入扫描页再创建。

初始化代码里有一个细节:如果在onPageShow中才拿到控件实例,这时相机的画面流已经启动了,但页面还没真正渲染出来,前置时间会有几帧黑屏。解决办法是在页面onReady之后,延迟100-200毫秒再执行startScan。这样用户看到的第一个画面就是稳定的取景器预览,体验更自然。

4.3 扫描结果获取与后续处理

扫描完成后,通过控件的回调方法拿到输出结果。返回的数据包括矫正后的图片数据和文档四角坐标。坐标非常重要,你可以根据坐标信息判断文档在原图里的实际位置,做二次裁剪。这里建议把角点坐标做一次空闲缓存,后续处理重试时可以直接用,省去再一次全流程识别。

识别结果我建议你做两级保存策略:先保存原始帧,再保存矫正后的图片。特别是发票、合同这类单据,一旦矫正算法出现极端情况导致内容畸变,原始帧至少能兜底。实测部分深色桌面加上白色纸张时,边缘检测偶尔会拿错参考边,输出画面出现轻微倾斜,这种场景用原始帧重走一遍流程就能修复。

4.4 后端接驳路径设计

单独把视觉结果展示在页面上还不够,产品化必须要跟后端数据打通。文档扫描结果拿到手之后,就要考虑怎么跟服务端对接了。建议你在业务层抽象一个视觉结果处理器,统一承接控件回调的各种结果数据,再转成后端接口的数据结构,这样后续如果要从文档扫描换成人脸识别,上层业务完全不用改。

如果要做实时性要求比较高的功能,比如直播目标追踪、人脸关键点实时贴纸,控件回调的数据流比较大。这时候建议在端侧做一层轻量的数据缓存,用帧间隔合并相同帧数据,保证回调数据尽量少,减少ArkTS层的调用开销。我在做贴纸功能时,就是通过合并处理回调的坐标数据,把界面的刷新频率降到了跟屏幕刷新率匹配的程度,有效避免了动画卡顿。

5. 系统级方案背后的三笔账

为什么我说这套方案值得认真关注,很大程度上是因为它在几个层面做了更聪明的取舍。站在工程、成本和体验三个维度来看,它的价值特别明显。

5.1 工程复杂度的账:复杂视觉功能的接入成本大幅降低

工程上最直观的变化就是接入成本的大幅下降。传统SDK接入视觉能力,要做模型初始化、环境配置、设备适配。换成系统级控件之后,你需要自己维护的只有业务逻辑和UI层,底层算法升级替换都交给系统。

从代码量上来说,以前做一个文档扫描功能,从相机预览、边缘检测、坐标回调、透视变换到结果存储,至少需要上千行代码。换成HarmonyOS这套控件后,核心代码降低到一两百行,而且没有多少复杂的几何算法需要考虑。系统的版本升级也会自动带到底层视觉能力的迭代,你不用定期去更新SDK,省力很多。

5.2 运行时性能的账:端侧算力效率的最大化

端侧AI最怕的就是算力浪费在无谓的模型调度和内存拷贝上。系统级控件的优势在于算力调度和内存管理都交给系统统一优化了,不同场景下的视觉AI运算可以共享系统级的资源池。测试时对比第三方SDK接入,内存占用有明显下降。

这套控件的另一个优势是资源回收非常及时。第三方SDK经常遇到的现象是模型驻留内存后进程退出也不释放,系统级控件则会在页面销毁时自动回收。我在连续切换页面、反复进入退出扫描场景的压测中,没有出现内存持续增长的情况,这点在稳定性上非常重要。

5.3 业务敏捷性的账:快速试错的成本被无限压低

从业务角度来说,这套控件带来的最大价值是“试错成本”几乎被压没了。产品经理提出“加一个人脸检测功能”“加一个拍照搜同款”,你不需要排期等模型训练,直接摆一个控件上去就能验证效果。业务可行性验证的时间从一个迭代周期缩短到一天以内。

我用控件做过一个原型验证:在产品页里放了一个商品识别控件,当天就打通了“拍照选商品”的完整链路,大概整个流程只花了几小时,包含UI调整。这在以前是不敢想象的,以前光是模型的选型测试就得花两三天。这种快速验证能力,对业务创新来说价值很大。

6. 这套方案的限制与边界

当然,系统级控件也不是万能的。在“便利”的背后,也要认清它的边界在哪里。

6.1 什么时候不建议用系统级控件

如果你的业务对视觉AI有极端定制化的需求,比如自研检测模型来做特定品类商品的精细识别,或者需要在特殊硬件上做端侧AI硬件部署,那系统级控件就不太合适。它提供的是“通用能力的最优解”,但不是“特定问题的最优解”。这种情况下,要下沉到算法能力集做二次开发,或者直接用端侧AI框架搭专有的推理链路。

另外,如果你需要实时把视觉分析结果上传云端做二次处理,用它也要多想一想。系统级控件为了隐私合规,在端侧做了很多数据保护,不必然支持裸数据上传。设计这类业务时,需要绕开系统的私有数据处理链路。这一点越早了解,越能避免后面返工。

6.2 性能参考:什么样的设备都能跑吗

我对三款不同档位的设备做了同一组测试:荣耀中端机型、旗舰机、还有一款平板设备,分别在它们上面跑人脸检测和OCR识别。人脸检测在旗舰机上能到30帧以上的流畅度,中端机也稳定在25帧左右;OCR识别则是所有设备上都保持在可接受的识别时延以内,打印体识别基本在1秒左右完成,手写体识别大约2到3秒。

如果你要支持更旧的设备,或者同时开多个视觉任务,需要自己做一下资源评估。实测同时开启人脸框定和OCR识别的场景下,CPU占用率会比单开一个任务高出不少,但系统会优先保证当前前台控件的资源供给,视觉结果可能会有短暂延迟。如果你的业务场景对时效性要求很高,建议限制并发控件数量,或者用系统提供的优先级接口做调度。

6.3 用控件时的性能监控建议

用系统级控件的时候,不要忽视性能监控。我建议你在接入后,使用系统自带的性能分析工具跑一遍主流程,重点看两个指标:扫描页从进入到首帧的时间(首帧时延),以及识别按钮点击到结果回调的时间差。把这两个指标记录在日志里,发布时作为健康度基准线,后续如果系统升级导致性能波动,你有基准可对比。

我还建议关注相机预览画面切换到分析画面的线程切换点。控件内部为了保证流畅性,会在分析时切换渲染线程,如果你的页面在那一瞬间有比较大的渲染开销,可能引起丢帧。解决方式是把与视觉无关的UI更新错峰到5帧之后再执行,实测这种错峰策略可以减少约20%的丢帧率。

7. 常见问题与排查技巧实录

接入过程中一定会踩坑。这里我把实际遇到的几个典型问题和排查思路整理成一份速查表,方便你在调试时少走弯路。

问题现象可能原因排查思路与解决建议
控件初始化后页面黑屏相机流未与页面渲染同步在页面onReady后延迟100-200ms启动扫描,不要立即startScan
同时开多个视觉控件后识别卡顿并发任务抢占系统算力只保留前台正在使用的控件,其余控件用stop接口挂起,等切回来再恢复
OCR识别结果忽好忽差相机自动对焦频繁触发锁定曝光参数、限制自动对焦区域,让测光区域聚焦在预览画面中心
文档边缘检测偶尔拿错边背景复杂、纸张与背景对比度低增加辅助照明,或在页面增加“手动调整边框”的兜底交互、用原始帧重跑流程
活体检测在暗光环境失败率升高环境光线不足接入系统亮度增强接口,开启补光提示,让用户靠近光源

黑屏问题的排查,我建议你从日志里找“preview_start”和“first_frame_rendered”两个标记,观看二者的间隔时间。正常情况下应小于300毫秒。如果超过这个值,大概率是相机初始化时被其它任务阻塞了,可以用异步方式让相机初始化让出主线程,页面渲染就不会被拖住。

识别精度问题是最常见的一类。如果你的应用日志出现大量“low confidence”的字段,说明当前模型对目标场景的置信度普遍偏低。这个不一定代表模型有问题,更可能是输入图像质量不行。可以优先检查相机采样分辨率是否过低,或者预览流是否采用了过高的压缩率。

最后是一条比较容易被忽略的经验:如果你开发的是多端部署的应用,同一套控件在手机和平板上的布局表现差异会很大。建议对平板的控件做尺寸自适应设置,特别是边框、图标和提示文案的间距。不然用户在平板上看到的是一个被拉伸变形的“巨型控件”,体验非常糟糕。

8. 从控件出发,重新思考端侧AI的代码组织方式

接入这套控件之后,我不只在业务页面上做了调整,还顺手重构了一遍项目里所有跟AI相关的代码组织方式。这个思路值得分享给你:把视觉能力当作基础组件来管理,而不是当作一个独立的“算法黑盒”。

我习惯把每个视觉业务场景封装成一个独立的ViewModel,View层只负责托管控件实例和渲染结果,业务逻辑全部放到数据层。比如文档扫描,View只有扫描页面和结果展示页,中间的逻辑都归ViewModel管。这样UI层就不依赖具体是哪个控件实现的,就算以后换一套识别底层,UI代码也基本不用动。

在这种模式下,视觉能力天然成为了“可插拔”的模块。产品说要做一个新功能,你就复制一个ViewModel,换一下控件配置,再调整一下结果处理逻辑,一个功能就好了。我在团队里同步了这个实践后,新同学做视觉功能的效率提升也很明显,因为整个操作模型统一了,遇到问题可以横向参考其他场景的实现。

另外我建议你在项目里提前建立一套视觉结果缓存的标准结构。不管控件返回的数据长什么样,落到缓存层统一用“图片路径+结果数据+时间戳”的结构存。后面如果要给用户做历史记录、做结果对比,这套标准结构直接就能复用,不用再做一次混乱的数据清洗。

9. 基于这套控件,还可以怎么扩展

系统级视觉控件能做的,不止是它内置的那几个场景。稍微动动脑筋,这背后的能力可以延伸到不少业务里。我分享几个我实际尝试过、以及觉得很有潜力的方向。

我在一个学习类App里,用OCR控件做了“拍题搜解析”的功能入口。用户拍下题目,OCR控件识别出文字,再转换成结构化数据去后台搜索题目。之前这个功能用的是云端OCR,网络一差就转圈圈。全换成端侧控件之后,识别速度和成功率都上来了,离线也能用。用户体验提升明显,同时也省下一笔云资源费用。

另一个值得尝试的方向是做“视觉辅助输入”。人脸关键点控件可以实时检测面部朝向,把用户的点头、摇头、张嘴变成输入指令。我给一个儿童识字App做过一个原型,孩子不用碰屏幕,张嘴说“开始”,摄像头识别人脸关键点变化触发录音,就完成了交互闭环。这种模式在无障碍场景、运动场景里有很大的想象空间。

还有一个数字化方向是利用“物体识别控件”做门店盘点和商品陈列分析。导购员拿平板对着货架扫一圈,系统就能识别出空位、缺品。虽然商品识别精度达不到那种专门训练模型的效果,但对常规品类的粗析已经够用了。这类场景用控件来做MVP验证,非常合适。

从长期看,系统级视觉能力会越来越像基础设施。手机系统都带摄像头,未来的应用形态里,视觉AI会和触控一样普遍,成为基础交互方式。现在花点时间把视觉能力和系统控件摸透,以后做新产品时,就能跑得更快。这个窗口期值得先占住。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 4:12:55

用AI搭建个人投资研究系统:信息到决策的完整链路

我直接从读者视角出发,写一篇关于用AI搭建个人投资研究系统的深度分享,把核心概念、完整框架、工具选型和实操过程都讲透,保证内容是落地、有借鉴价值的。1. 项目全景:AI投资实战营到底在解决什么问题先聊聊我为什么要碰这个项目。…

作者头像 李华
网站建设 2026/9/30 4:12:52

Hindsight实战:Chrome浏览器历史取证解析器指南

1. Hindsight 是什么,为什么取证圈都在聊它第一次听到 hindsight 这个名字,是在一次技术交流会上,一个做数字取证的同事提到"后见之明"这个词的时候,顺带说了一句:"浏览器取证现在就靠它了。"当时…

作者头像 李华
网站建设 2026/9/30 4:10:18

从零手写大语言模型:数据、训练、推理与部署全流程实战

这两个月我干了一件特别“找虐”的事:给自己定了个项目代号ai-engineering-from-scratch,目标是从零开始构建一个能跑通数据、模型、训练、推理、部署全流程的AI工程,而不是调用现成的 Transformers 工具包。这个项目本质上包含两条主线&…

作者头像 李华
网站建设 2026/9/30 4:08:57

防火墙技术从课件到实战:协议分层、体系结构与配置避坑指南

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

作者头像 李华
网站建设 2026/9/30 4:07:44

Luatools for macOS实战:LuatOS固件烧录与串口调试指南

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

作者头像 李华