做了这么多年的移动端自动化身边经常有人问Appium、Accessibility、uiautomator 都已经能测手机了为什么谷歌还要做一个叫 ARTEMIS 的东西同样是操作手机脚本“点哪里”和 AI“看懂屏幕再决定点哪里”完全不是一回事。ARTEMIS 这个开源项目真正吸引我的地方也正是这个差异——它不再靠坐标和控件 ID 硬编码而是让 AI 助手像人一样去看、去想、去操作手机界面。这篇文章我准备从 ARTEMIS 的核心机制拆起聊一聊它和传统移动端自动化的本质差别然后带大家看看这个框架的模块构成、环境准备方法以及哪些场景真正适合用它。如果你正在研究 AI Agent、想找一套能落地的移动端多模态交互方案或者做自动化测试想往前多走一步这篇内容应该值得你花几分钟看完。1. ARTEMIS 不是普通自动化脚本而是一个会用眼睛看手机的 Agent先说一个很多人刚接触 ARTEMIS 时的误解看到“移动端自动化框架”几个字下意识就会把它和 Appium、Selenium 混为一谈。但 ARTEMIS 的定位完全不同。它的源头其实是谷歌的一篇研究论文《ARTEMIS: Towards Language-Enhanced GUI Understanding》论文里关注的问题就是“AI 怎样才能像人一样操作手机”。也就是说它天生就是一个 AI Agent 研究项目只不过以开源代码的形式放了出来。导航我用一个类比来说明 ARTEMIS 和传统自动化脚本的区别。传统自动化是“录好的钢琴曲”——你提前把每一个音符、按键的时间都编排好曲子听起来是对的但一旦钢琴换了一台或者乐谱换了版本演奏就荒腔走板。而 ARTEMIS 更像一个“即兴演奏的乐手”——你告诉它“弹一首适合下午茶时间的曲子”它先看看周围再决定节奏和和弦弹错了还能在下一段纠正回来。细化到技术层面这个差异体现在三个核心特征上。第一它不是靠控件层级找元素而是靠“看”。传统自动化依赖 uiautomator dump 出来的控件树或者通过 AccessibilityService 拿到界面节点这要求界面元素暴露了稳定的 resource-id 和文本。ARTEMIS 走的是多模态路线它会把手机屏幕的图像转换成一段自然语言描述然后在这个描述上面做决策。界面长什么样不重要重要的是模型理解的语义。第二它不是顺序执行而是有个感知—规划—行动循环。ARTEMIS 每走一步都会先观察当前屏幕状态再规划下一个动作执行之后重新观察形成一个闭环。这就意味着它有纠错能力上一个点击没生效再试一次别的路径就好。第三它不依赖选定的 App 内操作而是可以跨应用完成多步骤任务。论文里给的标准案例就包括“帮我在聊天应用里找到一个联系人把某个地址分享给他”这种需要跨多个 App、多个页面完成的任务。ARTEMIS 还有个反直觉的地方它用的不是当时最顶级的超大语言模型。论文里反复强调一个观点——精巧设计优于庞大模型。它使用的是轻量级的 FLAN-T5-XXL通过 Ception 模块把复杂截图“压缩”成简洁文本再用语言模型做计划。这种做法大幅降低了推理资源消耗整个系统可以在控制台研究环境中跑起来。这一点我印象很深因为 AI Agent 行业里普遍存在“模型越大越好”的思路但 ARTEMIS 的实际效果告诉我们理解屏幕内容与规划动作之间的连接设计可能比模型本身的规模更关键。2. 值得玩味的架构Ception 把像素翻译成语言环境层负责执行和反馈如果说有一条主线贯穿了 ARTEMIS 的全部设计那就是“让语言模型能读(读)懂手机屏幕”。为了做到这件事ARTEMIS 把系统分成了几个功能分工明确的模块。2.1 CeptionAI 的“眼睛”Ception 是 ARTEMIS 里最核心的组件负责把 GUI 像素转换成文字描述。为什么需要这一步因为纯视觉信息对语言模型来说太“闷”了一个高分辨率截图包含的信息量很大但模型真正关心的可能只是“屏幕上有没有一个加号按钮”“顶部标题写的是什么”“当前列表里哪个选项高亮”。Ception 做的事情就是从这个毫无结构的像素中提取出结构化的语义输出类似“当前屏幕显示聊天列表第一项是联系人张三底部有一个输入框和一个发送按钮”的自然语言。这个设计思路和人类操作手机倒是很像人也不可能“眼观六路”地处理每一个像素你瞟一眼屏幕注意到的就是几个关键信息点。Ception 相当于把“看一眼”的过程模块化并让这个输出的信息量刚好足够语言模型做出下一步决策。2.2 TheEnvironmentAI 的“手”有了眼睛还得有手。TheEnvironment 这个模块在 ARTEMIS 里负责两件事一是行动执行二是状态反馈。代码仓库里能看到它和 ControlSuiteApi、Android 模拟器的交互逻辑——TheEnvironment 会向 Android 系统发出点击、滑动、输入文本等动作指令然后接收执行后的新屏幕状态。这里有个细节值得一提ARTEMIS 的行动集不是随意定义的它有一套“抽象状态表示”机制。系统会把截图转成 GUI 状态然后用深度Q网络给这些状态打分。这个打分的意义在于Agent 可以知道“走到这一步距离完成任务还有多远”。有了评估指标系统就能在多个可选动作里选择回报预期更高的那个而不是机械地按模板走。2.3 系统状态机把零散动作串成一条合理的任务路径如果只看 Ception 和环境层ARTEMIS 还停留在“一帧一决策”的水平容易被单个动作卡住。真正让它显得“像人”的是系统状态机这个中间层。状态机会把任务拆成一系列可管理的小步骤然后为每个步骤维护不同的候选动作。论文里提到了用 Dijkstra 最短路径搜索来优化任务完成路径——换句话说它不是每次只在当前屏幕“摸个奖”而是会结合任务历史和状态评分选择一条成功率最高的执行路线。我举个例子假设任务是“打开日历应用创建一个明天上午10点的日程并把日程详情发送到某个聊天会话”。如果只靠“看一眼就点击”agent 很容易在“添加到日历”和“分享日程”之间反复横跳。但有了状态机系统知道当前处于哪个阶段也知道从一个阶段跳到下一个阶段需要完成哪些动作执行时的稳定性就强了很多。2.4 轻量级模型又在同领域里多跑赢一步ARTEMIS 使用 FLAN-T5-XXL 作为大脑而不是 GPT 级别的庞然大物。背后的逻辑在于GUI 操作任务和开放式聊天不一样它需要的不是广博的知识量而是对界面语义的精准理解、对操作顺序的合理规划。Ception 已经把屏幕信息“预处理”成文本了语言模型只要在这个文本上完成推理即可并不需要多强的“世界知识”。从工程角度看这个选择也带来了部署上的优势FLAN-T5-XXL 这类模型体积可控在提供足够推理能力的条件下对 GPU 的需求远低于动辄百亿参数的大模型。对于一个想跑在模拟器环境里的研究框架这是很务实的取舍。网络热词里有“ai测试开发”“接口自动化测试框架pytest”这类词说明有不少人正在往 AI 测试方向靠拢。ARTEMIS 的这个设计值得这类团队参考不是所有代码都要上大模型先做信息压缩再用小模型做决策往往性价比更高。3. 从开源仓库看 ARTEMIS 的具体构成模块、权限与集成难点上一节聊了 ARTEMIS 的设计思想这一节我们来“翻代码”看看仓库里到底有些什么。ARTEMIS 开源在 GitHub 的 articulate-mobile/android-artemis 仓库采用 GPL-3.0 许可证。关心商用授权的同学要先注意这一点GPL 协议意味着衍生作品需要开源对纯研究或者个人学习问题不大商业产品集成就需要谨慎评估了。3.1 主要模块与职责拆分从仓库代码来看ARTEMIS 按功能大致分成以下几块模块职责关键交互对象CeptionApi生成 GUI 文本摘要把屏幕像素转为自然语言Android 模拟器截图、语言模型ControlSuiteApi提供信号与动作接口执行点击、滑动、文本输入等Android 模拟器TheEnvironment负责环境反馈与状态管理CeptionApi、ControlSuiteApi、状态机TaskManager任务协调负责记录任务进度、调用模型做规划上层 Agent 逻辑、状态机MemPlanner/Planner 类长期记忆与行动规划数据库、历史状态这个拆分其实很有讲究。它把“理解屏幕”Ception和“操作用户界面”ControlSuite彻底解耦上层 Agent 可以只依赖 TheEnvironment 这一层抽象不用关心底层是模拟器还是真机。这带来的直接好处是便于扩展——如果你想把行动层从 Android 模拟器换成自己的真机测试平台理论上只需要替换 ControlSuiteApi 的具体实现。3.2 权限与辅助功能一个容易忽略的集成难点做移动端自动化的人都有经验操作第三方 App 时最麻烦的不是找不到元素而是权限弹窗和无障碍服务的开启。ARTEMIS 在 Android 系统上运行同样绕不开这个问题。从仓库的说明和论文的评估环境看ARTEMIS 需要开启 Android 的“无障碍服务”AccessibilityService。这也是它能够读取屏幕内容并模拟点击动作的基础。集成时需要注意Android 13 的严格权限管理、不可关闭的弹窗、以及某些应用的控(控)制手段都可能导致自动化中断。我建议在上手阶段就把测试目标固定在模拟器环境内先把框架跑通再考虑真机适配。3.3 与外部应用的集成度Mattermost 是一个典型的“陪练”ARTEMIS 的论文里反复出现一个叫 Mattermost 的应用。它本质是一个消息协作平台之所以出现在 ARTEMIS 里是因为论文任务场景需要 AI 在“日历—聊天—地图”等不同应用间完成跨应用操作。Mattermost 充当了对话消息载体的角色用来验证 agent 能否在聊天界面中发送信息、接收指令。这个选型对跑通整个流程很有参考价值。Mattermost 是一个开源软件部署门槛低也没有太多的商业化 App 设防非常适合作为 AI Agent 的验证环境。你自己做实验时可以用它也可以换成 Telegram Bot API 或者开源的即时聊天应用。关键是环境本身要稳定可控不要让反自动化机制干扰了对 agent 本身的评估。4. 动手实操前的环境准备ARTEMIS 需要什么样的运行环境聊完了框架结构来说说实操。ARTEMIS 目前不是一个“下个 APK 就能装进手机跑”的落地产品它更多是研究版的试验环境。从官方仓库和论文中的说明来看筹备运行环境大概要准备这几块内容。4.1 软件依赖清单我按照官方推荐路线和社区里的实践整理了一份依赖清单Linux 操作系统推荐 Ubuntu 系的发行版驱动和虚拟化组件最省事Docker 与 Docker Compose用于拉起配套服务PostgreSQL 数据库存储任务状态和历史记录Redis用于缓存和消息队列MinIO 对象存储保存屏幕截图、模型输出等文件Mattermost 桌面端或服务器端作为聊天交互环境Android 13 x86_64 系统镜像的 Android 模拟器ControlSuite Api 服务负责与 Android 模拟器交互语言模型推理环境例如 FLAN-T5-XXL 的部署服务独立的 HTTP API从热词“artemis教程”也能看出很多人卡在环境搭建这一步。这套依赖确实比一般工具链重很多但它不是故意添堵——ARTEMIS 需要在接近真实的 Android 用户界面环境中运行得有模拟器需要验证跨应用任务得有聊天软件需要持久化任务状态和截图就离不开数据库和对象存储。理解了这一层再去对照着搭环境会顺手很多。4.2 部署步骤概要具体部署的步骤大致如下用 Docker Compose 启动 Mattermost以及配套的 PostgreSQL。Mattermost 的初始配置向导里需要设置管理员账号后续 ARTEMIS 的对话任务就在这里进行。启动 MinIO 和 Redis 服务确认它们的端口能被其他服务访问。MinIO 的 API 端口和 Web 控制台端口默认不同注意别配混了。部署 ControlSuite Api 服务这个服务负责和 Android 模拟器通信。官方仓库里有单独的控制套件代码仓库需要编译后运行并且要配置好模拟器的 adb 连接地址。创建并启动 Android 13 x86_64 模拟器安装好需要测试的目标应用。构建并部署语言模型服务确保 Ception 能通过 HTTP 调用到模型接口。官方仓库建议了不同规格的 GPU 配置消费级显卡能跑小模型但体验流畅度会打折。启动 ARTEMIS 主进程连接好模拟器、模型服务、Mattermost然后通过它的任务管理界面或命令行下发一个任务。首次跑通整个链路我估计需要一到两天时间。大多数人会卡在 ControlSuite Api 与模拟器的连接上常见的错误是 adb 端口没配对、模拟器没有开启无障碍服务、或者模型服务返回格式不匹配。排错时建议从底层往上查先确认 adb shell 能连上模拟器再确认控制套件能执行最简单的点击操作然后再启动 ARTEMIS 主进程。4.3 硬件建议ARTEMIS 对硬件的要求主要体现在两块一是 Android 模拟器本身需要开启硬件加速没有 KVM 支持的话模拟器会慢到难用二是模型推理需要 GPU。官方仓库对两种规格10GB VRAM 和 40GB VRAM做了说明小规格适合轻量模型和简单任务大规格适合跑更复杂的功能评估。个人开发者如果手头只有一台集显笔记本建议先放在云服务器上跑模拟器本地只做代码浏览和远程调试。5. 应用场景与真实局限什么时候值得用 ARTEMIS什么时候别用任何一个框架都有自己的适用边界ARTEMIS 也不例外。我接触过一些团队把 ARTEMIS 简化理解成“能用 AI 测手机”然后直接拿来对付生产级 App 的回归测试结果发现效果并不理想。这其实不是框架的问题是对它的定位理解偏了。5.1 真正适合 ARTEMIS 的场景从论文和开源仓库的设计目标看ARTEMIS 的优势场景是那些需要“理解界面语义并做决策”的任务。跨应用任务编排例如“查看明天日程把日程通过聊天发给某个人”“帮我在地图应用里找到最近的咖啡店并把地址分享出去”。这类任务单个动作不难难的是跨应用时的页面切换和状态跟踪。Agent 能力评估与训练如果你想评估一个多模态模型的 GUI 理解能力或者训练一个手机操作智能体ARTEMIS 提供了一套完整的环境和评估流程。行为自动化策略研究比如动态规划、错误恢复、任务拆解这些方向ARTEMIS 的系统状态机和环境反馈机制是很好的研究载体。5.2 不太适合直接套用的场景高频重复性操作比如每天每小时的 App 冒烟测试ARTEMIS 的反应速度不如成熟的控件级自动化框架而且它的推理链条较长中间任一环节出错都会增加执行时间。对真机硬件能力有强依赖的场景如果你需要测手机摄像头、传感器、蓝牙连接ARTEMIS 和 Android 模拟器的组合就不合适。对安全性有严格要求的商业产品集成GPL-3.0 许可证限制在这里加上框架本身还处在研究期生产环境的风险偏高。5.3 和传统自动化框架的定位差异我整理了一个对比表格方便大家快速理解 ARTEMIS 和现有工具的边界对比维度传统自动化Appium/Playwright等ARTEMIS元素定位依据控件ID、Accessibility节点、坐标屏幕截图的语言化语义跨页面/跨App能力依赖脚本内显式跳转逻辑依赖模型的动态规划出错恢复能力通常需要预先写重试逻辑通过环境反馈动态调整行动执行速度快适合大量回归相对较慢适合探索性任务模型依赖无FLAN-T5-XXL 等语言模型适用场景企业级 App 回归测试AI Agent 研究与复杂交互任务表里没有谁好谁坏的意思因为这两类工具的出发点就不一样。传统自动化解决的是“已知路径的稳定复现”ARTEMIS 想解决的是“未知路径的智能探索”。在企业团队里两者完全可以互补回归测试跑传统脚本探索性测试和 AI Agent 相关能力验证交给 ARTEMIS。6. 关于 ARTEMIS 的几点体会与可扩展思路最后聊一点我的个人感受。研究 ARTEMIS 这段时间给我最大启发的并不是它用了某个多先进的模型而是它把“GUI 自动化”和“语言模型决策”之间的连接点找得特别准。Ception 的设计就像给语言模型配了一副合适的眼镜它不需要看密密麻麻的像素只需要一份精要的“屏幕摘要”。这个思路放到任何 AI Agent 项目里都适用——信息入口的信息质量往往决定了整个系统的决策上限。网络热词里有一串和“ai agent”“ai测试开发”“ai编程提示词”相关的词条说明这个方向确实热。如果你想在 ARTEMIS 基础上做一些扩展我提三个思路供参考第一替换模型层。FLAN-T5-XXL 是论文时代的选型现在完全可以接回到本地部署的更轻量模型甚至通过开源框架接入实时更新的多模态大模型观察 Ception 的文本摘要质量对最终成功率的影响。这是最温和的改进路线改动范围集中在语言模型服务这一层。第二增强长期记忆。ARTEMIS 目前的任务状态是依赖外部数据库存储的但缺乏跨会话的“经验沉淀”。你可以把每次任务成功执行的状态序列缓存下来作为新任务的参考轨迹这其实就是最简单的记忆增强 Agent。第三扩展到真实设备测试平台。控制套件 API 只依赖 adb 和 UI 操作接口替换成真机测试平台并不是不可能。如果你的团队有一批测试真机并且有能统管设备的平台把 ARTEMIS 挂上去做混合测试理论上能覆盖更多真实场景。这也是我觉得这个项目后续最值得期待的应用方向。对我来说ARTEMIS 最有价值的身份不是“又一个自动化框架”而是“一个研究 AI 如何操作手机的开源试验场”。它把整套系统的感知、规划、执行、反馈全部开放了出来任何人都有机会在它上面做实验去验证自己对多模态 Agent 的理解。后续如果你的目标是做移动端 AI 应用或者探索让 AI 真正替人操作手机的产品方向ARTEMIS 绝对是一个值得长久关注的项目。
企业数字化 ERP 产品动态
相关推荐
TencentDB Agent Memory 源码解析与 Codex 接入实战 1. 从一次真实的踩坑说起:为什么我要去翻 TencentDB Agent Memory 的源码事情的起因很简单。我在做一个基于 Codex 的本地 Agent 项目,想让它在多轮对话里记住用户之前说过的偏好,比如“我习惯用 Python 而不是 Node”“数据库统一走 Postgre… · 2026/11/3 8:34:26
光伏投资智能测算工具iSolarBP的核心功能与应用 1. 光伏投资决策的痛点与解决方案 光伏行业近年来发展迅猛,但投资决策过程中存在诸多痛点。传统的光伏收益测算往往依赖Excel表格,需要手动输入大量参数,计算过程繁琐且容易出错。不同地区的辐照数据、电价政策、组件衰减率等变量相互影响&am… · 2026/11/3 8:34:26
磁性直接驱动器:音圈、线性与力矩电机的精密运动控制选型指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:01:47
基于MAX14431BAEE+与PIC18F85J50的SPI隔离通信设计 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:01:47
STM32 SPI隔离设计复盘:MAX14431BAEE+消除地环路干扰 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:01:47
工业级隔离SPI设计:MAX14431与STM32L081实战指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:01:47
STM32与数字隔离器SPI方案:地环路干扰与共模噪声实战解决 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:01:47
STM32L4A6RG与MAX14431BAEE+的SPI隔离通信方案设计与实现 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:00:46
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46