UXR2.0开发环境搭建:从ROS 2、Python到仿真工具的完整指南
1. 项目概述为什么UXR2.0的开发环境值得你投入时间最近在和一些做机器人、无人机或者智能硬件开发的朋友聊天发现大家或多或少都接触过PX4、NCS、ESP32这些开源或嵌入式平台。搭建这些开发环境的过程往往伴随着各种依赖冲突、环境变量配置和编译报错堪称“从入门到放弃”的第一道坎。今天我想聊的“UXR2.0开发环境搭建”本质上也是这类工作但它指向的可能是更前沿、更集成的机器人或XR扩展现实应用开发平台。UXR这个缩写在不同语境下可能有不同含义比如“Unified XR Runtime”或者某个特定厂商的机器人开发套件。我们这里讨论的UXR2.0可以理解为一个集成了感知、规划、控制、仿真与交互的下一代机器人或XR应用开发框架。搭建它的开发环境不是简单地装个IDE集成开发环境或者编译器而是构建一个能支撑复杂算法验证、多传感器数据融合、实时控制与3D可视化仿真的完整工具链。这就像你要造一辆智能汽车需要的不是一个扳手而是一个配备齐全的现代化车间。对于开发者而言成功搭建UXR2.0环境意味着你拿到了进入这个领域的“入场券”。你能本地编译核心代码、运行单元测试、启动高保真仿真环境并最终将算法部署到实体硬件上。这个过程会强迫你理解整个系统的架构、模块间的依赖关系以及底层的通信机制。无论你是算法工程师、软件工程师还是系统集成工程师一个稳定、高效的开发环境都是生产力基石。我经历过无数次因为环境问题导致的调试僵局深知前期多花几个小时把环境搭得“干净”且“可复现”后期能省下几十个小时的排查时间。2. 环境搭建的核心思路与前置准备搭建一个像UXR2.0这样复杂的开发环境最忌讳的就是拿到脚本无脑运行。一旦报错面对满屏的日志你根本不知道从哪里开始排查。我的思路一直是“分而治之明确依赖”。整个环境可以看作由几个层次构成操作系统层、基础工具链层、核心依赖库层、框架本体层以及辅助工具层。我们需要逐层构建确保每一层都稳固。2.1 操作系统与基础环境选型首先面临的选择是操作系统。从相关热搜词如“ncs开发环境搭建windows”和“python win下开发环境 详细搭建”可以看出很多开发者习惯或不得不使用Windows。然而对于机器人、嵌入式开发这类重度依赖Linux生态如ROS、Gazebo的项目Windows并非首选可能会遇到库兼容性、性能开销通过WSL或实时性等问题。强烈建议在Ubuntu Linux原生环境下进行版本选择上Ubuntu 20.04 LTS或22.04 LTS是社区支持最广泛、最稳定的选择。它们提供了大多数依赖库的预编译版本能极大减少从源码编译的痛苦。如果你必须使用Windows那么Windows Subsystem for Linux 2 (WSL2) 是底线它能提供一个相对完整的Linux命令行环境。但需要注意WSL2在图形界面GUI应用支持、USB设备直连和实时性能上仍有局限对于需要运行3D仿真工具如Gazebo、Unity或直接调试硬件的场景可能会比较棘手。在准备系统后第一件事是更新软件源并安装一些基础工具这些是后续所有操作的“脚手架”sudo apt update sudo apt upgrade -y sudo apt install -y curl wget git build-essential cmake pkg-configbuild-essential包含了GCC、G、Make等编译套件是编译任何C/C代码的基础。cmakepkg-config现代C/C项目广泛使用CMake作为构建系统pkg-config则用于帮助查找库文件和头文件。curlwget网络下载工具。git版本控制用于克隆代码仓库。注意在服务器或纯净系统上务必先执行apt update更新软件包列表否则可能安装不到最新或指定的版本。2.2 关键依赖解析Python、ROS与中间件UXR2.0这类框架通常不是空中楼阁它建立在诸多成熟的开源项目之上。通过分析“px4开发环境搭建”、“esp32开发环境搭建”等热词我们可以发现一些共性依赖。1. Python环境管理Python是机器人领域的脚本语言之王用于工具脚本、测试、部分算法原型如机器学习等。直接使用系统Python容易引发版本冲突。绝对推荐使用Anaconda或Miniconda进行环境隔离呼应热词“搭建机器学习开发环境-anaconda”。这能让你为UXR2.0创建一个专属的、纯净的Python环境。# 假设已安装Miniconda conda create -n uxr2.0 python3.8 -y # 具体版本需参考UXR2.0官方要求 conda activate uxr2.0为什么是3.8这是一个在机器人领域库支持如PyTorch, TensorFlow, ROS方面兼容性较好的版本。当然最终需以UXR2.0官方文档为准。2. 机器人中间件ROS 2UXR2.0极有可能基于或兼容ROS 2 (Robot Operating System 2)。ROS 2提供了分布式通信、设备抽象、工具集等核心功能是机器人软件的事实标准。你需要安装ROS 2。以Ubuntu 22.04对应ROS 2 Humble Hawksbill为例# 设置locale sudo apt install locales sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALLen_US.UTF-8 LANGen_US.UTF-8 export LANGen_US.UTF-8 # 添加ROS 2仓库 sudo apt install software-properties-common sudo add-apt-repository universe sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release echo $UBUNTU_CODENAME) main | sudo tee /etc/apt/sources.list.d/ros2.list /dev/null # 安装ROS 2基础包 sudo apt update sudo apt install ros-humble-desktop python3-colcon-common-extensions -y # 配置环境变量建议写入~/.bashrc echo source /opt/ros/humble/setup.bash ~/.bashrc source ~/.bashrc安装ros-humble-desktop包含了ROS 2核心库、基础工具和图形化界面工具。colcon是ROS 2推荐的构建工具。3. 其他潜在核心依赖Eigen3线性代数库机器人运动学、滤波算法必备。sudo apt install libeigen3-devOpenCV计算机视觉库热词中也有提及。如果UXR涉及视觉感知则需要安装。建议从源码安装特定版本以获得完整功能如CUDA支持。Protocol Buffers / gRPC用于高效的进程间通信或网络通信。sudo apt install protobuf-compiler libprotobuf-dev libgrpc-dev实时内核可选但重要如果UXR2.0涉及硬实时控制可能需要为Ubuntu安装PREEMPT_RT实时补丁内核。这是一个进阶操作且可能影响系统稳定性初期仿真开发可暂缓。3. UXR2.0本体的获取与编译当基础环境就绪后我们就可以着手处理UXR2.0框架本身了。这部分最考验耐心和排查问题的能力。3.1 源码获取与工作空间组织首先需要找到UXR2.0的官方源码仓库。这通常是一个Git仓库可能托管在GitHub、GitLab或Gitee上。假设仓库地址为https://github.com/uxr-project/uxr2.0.git。# 创建一个专门的工作空间目录保持项目结构清晰 mkdir -p ~/uxr_ws/src cd ~/uxr_ws/src # 克隆UXR2.0主仓库 git clone https://github.com/uxr-project/uxr2.0.git # 很可能还需要克隆其他的依赖包通常以“vendor”、“third_party”或子模块形式存在 # 例如如果使用git子模块管理依赖 cd uxr2.0 git submodule init git submodule update工作空间结构是ROS/现代机器人项目的一个好习惯。uxr_ws是工作空间根目录src下存放所有源码包包括UXR2.0及其依赖。后续的编译、安装都会在这个工作空间内进行与环境隔离。3.2 依赖安装与编译配置在编译前项目通常会有声明依赖的文件如package.xmlROS格式或requirements.txtPython、CMakeLists.txtC。我们需要根据这些文件安装系统依赖。# 返回工作空间根目录 cd ~/uxr_ws # 使用rosdep工具自动安装系统依赖如果项目是ROS格式 sudo apt install python3-rosdep2 sudo rosdep init # 如果之前没初始化过 rosdep update rosdep install --from-paths src --ignore-src -r -yrosdep是一个神器它能解析package.xml文件自动安装列出的系统依赖包如libboost-dev,libpcl-dev等。--ignore-src表示忽略已经存在于src目录中的包-r表示忽略错误继续-y是自动确认。接下来是编译。对于基于CMake和colcon的项目ROS 2风格cd ~/uxr_ws colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPERelease--symlink-install使用符号链接而非拷贝文件到安装目录这样在src中修改源码后安装目录中的文件即时生效便于开发调试。--cmake-args传递参数给底层的CMake。-DCMAKE_BUILD_TYPERelease指定为发布模式优化性能。调试时可改为Debug。编译过程可能会很长取决于项目规模和电脑性能。首次编译请密切关注终端输出任何ERROR都需要立即处理。3.3 编译后的环境配置与验证编译成功后工作空间下会生成build、install、log目录。你需要“激活”或“source”这个工作空间的安装文件才能让系统找到你刚编译好的UXR2.0库和可执行文件。# 在每次打开新的终端进行开发时都需要执行 source ~/uxr_ws/install/setup.bash # 同样可以将这行命令添加到你的~/.bashrc中但建议在需要时手动source避免多个工作空间环境冲突。如何验证环境是否搭建成功通常有几个方法运行核心节点尝试启动UXR2.0框架的一个核心节点例如通信中间件守护进程或管理器。ros2 run uxr_core uxr_manager查看是否有错误输出或者使用ros2 node list查看节点是否成功启动。编译并运行示例程序查看项目examples或demos目录尝试编译并运行一个最简单的示例比如发布一个“Hello World”消息。启动仿真环境如果支持如果UXR2.0集成了Gazebo、Ignition或Webots仿真尝试启动一个预设的仿真世界看能否加载机器人模型并运行。4. 辅助工具链的集成与配置一个完整的开发环境不仅仅是能编译和运行核心框架还包括能高效编写代码、调试问题、可视化数据的一系列工具。4.1 集成开发环境IDE的选择与配置对于C/Python混合开发Visual Studio Code (VSCode)是目前非常流行的选择它轻量、插件丰富、对ROS 2支持好。安装VSCode从官网下载.deb包安装。安装核心插件C/C(Microsoft)提供C代码补全、调试、跳转。Python(Microsoft)Python语言支持。ROS(Microsoft)专门为ROS 1和ROS 2开发提供支持可以自动识别工作空间、提供launch文件支持、查看话题和服务等。CMake Tools增强CMake项目的配置、构建、调试体验。配置VSCode打开~/uxr_ws文件夹作为工作区。VSCode的ROS插件通常能自动检测到工作空间并配置相关路径。你需要在.vscode/c_cpp_properties.json中确保includePath和compileCommands正确指向你的install目录和系统ROS目录这通常由插件自动完成。对于追求更强大C重构和代码分析功能的开发者CLion也是一个优秀的商业选择它对CMake项目的支持是顶级的。4.2 调试与可视化工具命令行调试gdb(C) 和pdb(Python) 是基础。对于ROS 2节点可以使用ros2 run --prefix gdb -ex run --args package_name executable_nameROS 2可视化工具rqt一个基于Qt的图形化框架包含一系列插件如rqt_graph查看节点与话题拓扑图、rqt_console查看和过滤日志、rqt_plot绘制话题数据曲线。rviz23D可视化工具是机器人开发的“眼睛”可以显示传感器数据点云、图像、机器人模型URDF、地图、路径规划结果等。UXR2.0很可能会定义自己的RViz插件来显示特有数据类型。ros2 topic echo /topic_name在终端中实时查看某个话题上流动的数据是最简单的调试方式。系统监控工具htop监控CPU/内存nvtop监控NVIDIA GPU如果使用rostopic hz测量话题发布频率。4.3 仿真与测试环境如果UXR2.0涉及机器人控制一个高保真的仿真环境至关重要。Gazebo / Ignition Gazebo物理仿真引擎与ROS 2深度集成。需要单独安装并确保版本匹配。sudo apt install ros-humble-gazebo-ros-pkgs单元测试与集成测试使用colcon的测试功能。colcon test --packages-select your_uxr_package # 运行特定包的测试 colcon test-result --all --verbose # 查看所有测试结果良好的项目应该有完善的测试用例。在搭建环境后运行一遍基础测试是验证环境是否健全的好方法。5. 常见问题与避坑指南实录这里记录了我及同行在搭建类似复杂环境时踩过的坑希望能帮你绕开弯路。5.1 依赖冲突与版本地狱问题编译时最常见的就是Could NOT find XXX或XXX version mismatch。例如项目要求Eigen 3.3.7但系统安装的是3.3.4。解决思路优先使用包管理器apt search libeigen3-dev查看可用版本。如果版本不够新可以考虑添加PPA个人软件包归档源但需谨慎评估稳定性。源码安装到本地从官网下载所需版本源码在本地编译安装到/usr/local或自定义目录如~/libs。然后通过设置CMAKE_PREFIX_PATH环境变量或在CMakeLists.txt中指定find_package的路径来引导CMake找到它。# 示例本地安装Eigen cd /tmp wget https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz tar -xzf eigen-3.3.7.tar.gz cd eigen-3.3.7 mkdir build cd build cmake .. -DCMAKE_INSTALL_PREFIX/usr/local sudo make install利用虚拟环境/容器隔离对于Python包冲突Conda环境是救星。对于更复杂的系统级依赖冲突考虑使用Docker。官方或社区很可能提供了UXR2.0的Docker镜像这是保证环境一致性的终极方案。5.2 编译错误与链接错误问题编译过程中出现undefined reference to ...或multiple definition of ...。排查步骤仔细阅读错误信息错误信息通常会给出出错的源码文件和行号以及涉及的具体函数或变量。检查头文件与库文件路径确保#include路径正确并且链接器能找到对应的库文件.so或.a。在CMake中检查target_include_directories()和target_link_libraries()是否配置正确。清理后重新编译有时旧的编译产物会导致奇怪问题。彻底删除build、install、log目录然后重新执行colcon build。查看更详细的日志使用colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPERelease --event-handlers console_direct可以让编译输出更详细。5.3 运行时错误与环境变量问题编译成功但运行节点时提示error while loading shared libraries: libuxr_core.so: cannot open shared object file。原因与解决动态链接库找不到。这是因为你虽然编译安装了但系统的动态链接器缓存ldconfig没有更新或者你source的环境不对。确保你已经执行了source ~/uxr_ws/install/setup.bash。这个脚本会将该工作空间下install/lib目录添加到LD_LIBRARY_PATH环境变量中。可以手动检查echo $LD_LIBRARY_PATH看是否包含你的install/lib路径。如果问题依旧可以尝试手动刷新缓存sudo ldconfig谨慎使用确保你知道在做什么。5.4 网络问题与源码下载失败问题git clone或git submodule update失败尤其是涉及GitHub时。解决使用国内镜像源例如将github.com替换为hub.fastgit.org注意镜像的可用性会变化。配置Git代理如果你有合法合规的网络加速方式。对于特定的子模块或依赖如果实在无法下载可以尝试在项目社区或Issue中寻找已经下载好的压缩包但要注意版本一致性。一个重要的心得在开始搭建前花时间通读官方文档的“Getting Started”或“Build Instructions”部分即使它看起来有点过时。同时在GitHub/GitLab的Issue中搜索“build error”、“install”等关键词你遇到的问题很可能别人已经遇到并解决了。记录下你每一步的操作和遇到的错误及解决方案这不仅是给自己留档未来也能帮助其他社区成员。搭建环境的过程本身就是对项目架构最直接、最深刻的一次学习。

相关新闻

智能汽车双芯座舱架构:性能优化与成本控制实践

智能汽车双芯座舱架构:性能优化与成本控制实践

1. 双芯座舱架构的行业背景与核心价值在智能汽车座舱领域,算力需求正呈现爆发式增长。根据行业调研数据,2023年主流车型的座舱算力需求较2020年已增长近300%,而传统单芯片方案越来越难以满足多屏联动、语音交互、AR导航等场景的并发需求。问界…

2026/10/12 9:02:18 阅读更多 →
深入解析AM64x/AM243x I2C寄存器:从原理到驱动开发实战

深入解析AM64x/AM243x I2C寄存器:从原理到驱动开发实战

1. 项目概述与I2C总线核心价值在嵌入式系统开发中,I2C总线就像城市里的公交系统,它用两根线(SDA数据线和SCL时钟线)就能串联起处理器和多个外设“站点”,实现高效、有序的数据交换。这套协议之所以能成为行业标准&…

2026/10/13 3:22:45 阅读更多 →
计算机毕业设计之基于SpringBoot的老龄化社区服务管理系统的设计与实现

计算机毕业设计之基于SpringBoot的老龄化社区服务管理系统的设计与实现

随着人口老龄化进程加速,老龄化社区数量增多,社区内老年人口的服务需求日益复杂多样。传统社区服务管理模式多依赖人工,信息传递不及时、服务资源分配不合理、沟通渠道不畅通等问题凸显。老年人在就医、参与活动、寻求志愿服务等方面面临诸多…

2026/10/10 18:43:34 阅读更多 →

最新新闻

关系模型实战指南:从二维表到业务稳定性的底层逻辑

关系模型实战指南:从二维表到业务稳定性的底层逻辑

1. 这不是教科书里的“关系”,而是你每天都在用的数据组织逻辑“关系模型的基本概念”——看到这八个字,很多人第一反应是大学数据库课上那个被粉笔灰笼罩的下午,黑板上写着“实体、属性、域、键”,讲台下有人偷偷刷手机&#xff…

2026/10/13 12:22:17 阅读更多 →
Qt国际化翻译完整实践:从tr()到动态语言切换

Qt国际化翻译完整实践:从tr()到动态语言切换

做Qt开发这么多年,遇到最多的问题不是功能写不出来,而是功能做完以后客户说看不懂。于是QT国际化翻译就成了绕不开的环节。表面上看,这事只是把界面文字换成英文、日文,真正做起来却涉及源码扫描、翻译文件管理、运行时加载、动态…

2026/10/13 12:22:17 阅读更多 →
华为+红帽双赛道:2026网工转型的破局之道

华为+红帽双赛道:2026网工转型的破局之道

1. 为什么2026年网工转型,我建议你押注"华为红帽"双赛道最近不少朋友私信问我关于2026年转行网络工程师(网工)的事,大家的焦虑点很一致:AI工具越来越强,初中级网工的活是不是要被替代&#xff1f…

2026/10/13 12:22:17 阅读更多 →
Modern.js 服务端编译核心 @modern-js/server-utils:TypeScript 编译、别名解析与原生 ESM 支持的源码级解析

Modern.js 服务端编译核心 @modern-js/server-utils:TypeScript 编译、别名解析与原生 ESM 支持的源码级解析

前端后端Web框架 【免费下载链接】modern.js A progressive web framework based on React and Rsbuild. 项目地址: https://gitcode.com/gh_mirrors/mo/modern.js 点击查看 免费下载 本文围绕 packages/server/utils/CHANGELOG.md 记录的能力演进,结合…

2026/10/13 12:22:17 阅读更多 →
基于SpringBoot+Vue的派出所健康档案管理系统设计与实现

基于SpringBoot+Vue的派出所健康档案管理系统设计与实现

选题背景 社会对公共安全的重视,派出所民警的工作压力日益增大,其健康状况备受关注。早期的健康档案管理方式效率低下,难以实现信息的实时共享和动态更新。本系统采用 Spring Boot 框架,结合前端技术和数据库技术,构建…

2026/10/13 12:22:17 阅读更多 →
EmbeddingGemma 2本地多模态嵌入模型部署与向量检索实战

EmbeddingGemma 2本地多模态嵌入模型部署与向量检索实战

1. 这个模型到底是什么:先把它的定位弄清楚拿到"EmbeddingGemma 2"这个名字,第一反应就是:这是个嵌入模型,740M参数规模,多模态,而且主打本地推理。这几个关键词放在一起,意味着它并不…

2026/10/13 12:21:16 阅读更多 →

日新闻

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

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

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

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 阅读更多 →