VS2019 下编译 KDDockWidgets 动态库:从源码到 Qt 工程集成指南
简介KDDockWidgets是Qt生态中功能完善的可停靠窗口Docking组件这套资源为基于VS2019与Qt5.15.264位预编译的动态库和完整源码面向需要在Qt Quick或Widgets应用中实现灵活窗口停靠布局的开发者。整个压缩包为RAR格式共956个文件约51.56MB其中包含279个头文件、139个C源文件、12个DLL动态库及配套LIB/EXE产物还有QML界面资源、JSON配置、CMake脚本与PDF说明文档等便于按需查阅和二次开发。需要特别留意动态库严格区分为Quick和QWidget两种版本对应include头文件不能混用并且仅支持64位编译环境32位工程不可使用。资源内附带两个演示demo每个demo均包含KDDockWidgets工程文件夹开发者可直接将KDDockWidgets.pri引入自己的项目省去复杂配置也能对照示例快速掌握集成方法与布局效果。目前已有789人学习下载配合作者博客中的讲解可更深入地理解停靠窗口的集成细节和常见问题。1. VS2019 编译 KDDockWidgets 这件事卡住过很多人在 Windows 桌面端做多窗口应用绕不开“停靠布局”这套交互侧边栏可以拖出来、贴回去、Tab 合并外观像 Visual Studio 自己的面板。自己写一套能商用的停靠框架少说两到三个月而且拖拽、吸附、布局保存这些细节特别容易烂尾。KDDockWidgets 就是专门解决这个问题的开源库底层基于 Qt性能与交互都贴近生产级。但这个库不直接给 VS 用户发编译好的二进制官方默认只给 QMake/CMake 的源码工程导致大量开发者卡在“源码在手编不出 dll”这一步——Qt 版本不对、CMake 找不到 Qt、编译器工具集不匹配任何一个环节都能让编译失败。这篇笔记的目标就一个把 KDDockWidgets 在 VS2019 下的编译链路、动态库产物和集成步骤一次讲透照着能产出 KDDockWidgets.dll并能被自己的 Qt 工程正常加载。2. KDDockWidgets 是什么为什么值得先花半小时理解它的源码结构2.1 停靠框架要解决的核心问题停靠框架Docking System做的事情是把一个窗口区域抽象成可停靠的 DockWidget用户可以拖动它到主窗口的上下左右边缘也可以让它浮动成独立窗口还可以多个 DockWidget 叠成 Tab 页。KDDockWidgets 的核心卖点是“用 Qt 标准控件实现不依赖第三方重量级组件”而且它把 MainWindow、DropArea、DockWidget 这几个类拆得很清楚改行为比 QMdiArea 和 QDockWidget 默认形态灵活得多。选 KDDockWidgets 而不是 QDockWidget主要是因为 QDockWidget 的浮动窗口和布局恢复能力比较弱拖动反馈也粗糙。KDDockWidgets 支持多窗口间互相拖拽停靠这在 Qt 原生控件里是做不到的。另外它的 License 是 LGPL动态链接的情况下可以闭源商用这也是很多团队选它的关键原因。2.2 源码目录里藏着的“三件套”core、dockwidget、multisplitter从 GitHub 拉下来的 KDDockWidgets 源码顶层目录基本是 examples、src、tests 这三个。src 下面要盯住几个子目录Core 是核心逻辑拖拽、状态管理DockWidget 是各个 Dock 组件MultiSplitter 是停靠区域的布局算法。编译之前最好先把 MultiSplitter 这个目录翻一下里面是窗口分割的几何计算后续你要是想改“最小停靠宽度”“浮动窗口透明度”这类行为改的就是这里。源码根目录的 CMakeLists.txt 是整个工程的入口它通过add_subdirectory把 Core、DockWidget 等模块组装起来。VS2019 编译走 CMake 是最稳的路径因为 KDDockWidgets 对 qmake 的支持虽然还在但新特性基本都优先落在 CMake 上。2.3 动态库与静态库的选择不是越多越好编译 KDDockWidgets 时CMake 会产出一组库文件包括核心库 KDDockWidgets或带 Qt 主版本后缀的 KDDockWidgets_Qt6、KDDockWidgets_Qt5如果你打开的是多窗口示例还会编出 KDDockWidgets 的 examples 可执行文件。选择动态库而不是静态库最直接的好处是主程序体积小KDDockWidgets 的 bug 修复后只要替换 dll 就能生效不用重新链接整个 exe。动态库的代价是部署时要多带一个 dll还要保证 Qt 的运行库Qt6Core.dll、Qt6Gui.dll、Qt6Widgets.dll路径能被找到。你要是图省事选静态库编译时间会更长而且链接时经常遇到“符号重定义”之类的问题反而更难排查。所以我的建议是项目发布用动态库调试阶段也保持动态库保持开发与生产环境一致。3. 从源码到 dll用 CMake 在 VS2019 下产出 KDDockWidgets 动态库3.1 环境准备确认三样东西缺一不可开始编译前先把环境清单过一遍。第一是 Visual Studio 2019必须安装“使用 C 的桌面开发”工作负载里面包含 MSVC v142 工具集和 Windows SDK。第二是 CMakeVS2019 自带 CMake 组件也可以用 cmake.org 的独立安装包版本建议 3.16 以上。第三是 QtKDDockWidgets 依赖 Qt5 或 Qt6编译前必须用 Qt 官方安装器装好对应版本的 MSVC 2019 64-bit 组件。特别要注意 Qt 的编译器必须与 VS2019 匹配VS2019 对应 MSVC v142Qt 安装器里要选 “MSVC 2019 64-bit” 那一套不能选 MinGW 版本。我见过不少人在这一步翻车Qt 装的是 MinGW结果 VS2019 的 CMake 配置阶段就报 “Could NOT find Qt6”因为两者的 ABI 完全不兼容。3.2 CMake 配置核心命令与参数清单打开“x64 Native Tools Command Prompt for VS2019”开始菜单里搜这个名字先确认 CMake 和 Qt 的环境变量。然后进入源码目录执行以下命令mkdir build-vs2019 cd build-vs2019 cmake .. -G Visual Studio 16 2019 -A x64 ^ -DCMAKE_PREFIX_PATHC:/Qt/6.5.3/msvc2019_64 ^ -DCMAKE_BUILD_TYPERelease ^ -DCMAKE_INSTALL_PREFIXC:/kddockwidgets-install ^ -DKDDockWidgets_EXAMPLESON这里-G Visual Studio 16 2019指定生成 VS2019 工程-A x64指定 64 位架构如果你的目标平台是 x86可以改成 Win32但不建议Qt 官方发布的预编译库基本都是 64 位为主。CMAKE_PREFIX_PATH指向 Qt 的安装目录CMake 会在这里找 Qt6Config.cmake 之类的配置文件。KDDockWidgets_EXAMPLES打开示例工程建议第一次编译时打开编译完可以直接跑 examples 验证动态库是否正常。如果 CMake 报错找不到 Qt不要急着怀疑路径先检查C:/Qt/6.5.3/msvc2019_64/lib/cmake目录是否存在再确认 CMAKE_PREFIX_PATH 写的是否是这个路径的父目录。另外CMake 缓存会记住第一次配置的结果改路径后需要删掉 build 目录重来否则会继续用旧缓存报同样的错。3.3 编译与产物检查三个关键文件配置成功后执行编译命令。用 CMake 生成 VS 工程后也可以用 Visual Studio 直接打开 build-vs2019 目录下的 KDDockWidgets.sln在“解决方案配置”里切到 Release/x64右键 KDDockWidgets 项目选择“生成”。命令行方式更可控cmake --build . --config Release --parallel 8--config Release指定 Release 配置--parallel 8表示 8 线程并行编译第一次编译会比较久耐心等它跑完。编译完成后去build-vs2019/src/Release目录检查产物正常会有 KDDockWidgets.dll 和 KDDockWidgets.lib如果你用的是 Qt6还会见到 KDDockWidgets_Qt6.dll 这样带版本尾巴的库名。同时 examples/Release 下会有多个示例 exe随便挑一个运行比如最简单的 HelloWorld能看到窗口出现并且能拖动侧边栏就说明动态库本身没有问题。3.4 安装到本地省去手动拷 dll 的麻烦cmake --install . --config Release这条命令会把头文件、dll、lib、cmake 配置文件统一安装到 CMAKE_INSTALL_PREFIX 指定的目录。安装后的目录结构大概是这样include/KDDockWidgets 下是头文件bin 下是 dlllib 下是导入库lib/cmake 下是 KDDockWidgetsConfig.cmake。你后续自己的工程只要通过 find_package(KDDockWidgets) 就能接上不用再手动配置头文件路径和库路径。4. 把动态库接进你自己的 VS2019 Qt 工程两种链接方式4.1 隐式链接最常规的做法假设你自己有一个 Qt Widgets 工程工程文件是 .vcxproj。在项目属性里需要设置几个地方C/C → 常规 → 附加包含目录加上C:/kddockwidgets-install/include链接器 → 常规 → 附加库目录加上C:/kddockwidgets-install/lib链接器 → 输入 → 附加依赖项写上KDDockWidgets.libQt6 对应 KDDockWidgets_Qt6.lib。如果你用 CMake 管理自己的工程代码里只需要三行find_package(KDDockWidgets REQUIRED) target_link_libraries(your_app PRIVATE KDDockWidgets::kddockwidgets)这是最省心的方式KDDockWidgets 安装时已经导出了 CMake 的 package 配置find_package会把头文件目录、导入库、依赖的 Qt 模块一次性带全。注意你的工程里的 Qt 版本要和编译 KDDockWidgets 时用的一致混用 Qt5 编译的库和 Qt6 工程链接时会出现一堆 “unresolved external symbol”。4.2 使用 KDDockWidgets 的 API最小可运行代码动态库链接成功后写一段最小代码验证#include QApplication #include KDDockWidgets/MainWindow.h #include KDDockWidgets/DockWidget.h int main(int argc, char** argv) { QApplication app(argc, argv); KDDockWidgets::MainWindow window; window.resize(1024, 768); auto* dock new KDDockWidgets::DockWidget(Sidebar); dock-setWidget(new QTextEdit(window)); window.addDockWidgetAsTab(dock); window.show(); return app.exec(); }这段代码创建了一个主窗口把一个 DockWidget 以 Tab 页的形式加进去。addDockWidgetAsTab是最简单的停靠方式适合做第一个验证程序KDDockWidgets 还提供addDockWidgetAsSidePanel让面板停靠在侧边以及多个 DockWidget 之间的位置管理接口但先跑通这个最小例子比一上来就搞复杂布局稳妥得多。4.3 运行时找不到 dll 的排查顺序程序编译通过但运行时报 “无法启动此程序因为计算机中丢失 KDDockWidgets.dll”这是最常见的问题。排查顺序是第一把 KDDockWidgets.dll 拷贝到 exe 同目录第二确认 Qt 的 dllQt6Core.dll 等也在 exe 同目录或系统 PATH 里第三如果还报错用 Dependency Walker 或 Visual Studio 的“调试 → 窗口 → 模块”看具体缺哪个依赖。补充一点Qt 的插件如 platforms/qwindows.dll也要能被找到。如果你的 exe 目录下没有 platforms 文件夹Qt 程序启动时会直接崩溃这个和 KDDockWidgets 本身无关但经常被误认为是动态库有问题。用 windeployqt 工具可以自动把 Qt 运行库和插件拷贝到 exe 目录省去手工搬运。5. 动态库与源码的避坑清单五条血泪经验5.1 Debug 与 Release 混用导致的内存崩溃现象用 Release 版 KDDockWidgets.dll 链接 Debug 版自己的工程程序运行时随机崩溃有时是中文乱码有时是 QByteArray 内部断言失败。原因Qt 的 Debug 和 Release 使用不同的内存分配器和数据结构布局两个版本的 Qt 核心库混在一起时对象在 Release 库中创建、在 Debug 库中释放直接踩到堆损坏。解决KDDockWidgets 的库版本必须和你的工程一致。你的工程是 Debug 配置就必须用cmake --build . --config Debug编出来的 KDDockWidgetsd.dll注意名字里的 d。链接库也要对应Debug 工程链接 KDDockWidgetsd.libRelease 工程链接 KDDockWidgets.lib。5.2 源码更新后 dll 没重新编译界面出现“新接口找不到”现象刚拉取最新源码编译的 dll 替换到部署目录后程序启动报错找不到某个符号或者点击某功能时直接崩溃。原因KDDockWidgets 的源码更新频繁接口或类布局可能有变动旧 exe 链接的是旧版动态库导入表里的符号地址已经失效。解决本地源码更新后不要只编译 dll 替换要把自己工程的 exe 也重新编译一遍。如果你用隐式链接exe 和 dll 必须同时更新这是 Windows 动态链接的常识但在快速迭代时最容易疏忽。5.3 CMake 找不到 Qt但 Qt 明明装了现象CMake 配置时输出Could NOT find Qt6检查 Qt 路径确实存在。原因CMAKE_PREFIX_PATH 只给到了 Qt 的安装根目录但 CMake 需要的是C:/Qt/6.5.3/msvc2019_64这个包含 lib/cmake 的目录或者把 Qt 安装成了 MinGW 版本MSVC 的 CMake 工程找不到对应的配置。解决确认路径指向 Qt 对应编译器版本的根目录同时打开C:/Qt/6.5.3/msvc2019_64/lib/cmake看是否存在 Qt6Config.cmake 这一类文件。如果存在但 CMake 仍报错在 build 目录里删掉 CMakeCache.txt 重新配置不要复用旧缓存。5.4 编译成功但示例程序启动白屏现象KDDockWidgets 的 examples 编译通过运行后主窗口出现了但内容是空白的或者所有 DockWidget 都不显示。原因最常见的不是 KDDockWidgets 的问题而是 Qt 插件目录没有被识别。exe 在 build 目录下运行时Qt 找不到 platforms 插件。解决在 Qt 安装目录下找到C:/Qt/6.5.3/msvc2019_64/plugins/platforms把它整个拷贝到 exe 同目录下或者用 windeployqt 工具自动部署。之后再运行窗口内容就正常了。5.5 动态库文件拷贝不全部署到别的机器报错现象把 exe 和 KDDockWidgets.dll 拷到一台没装 Qt 的电脑上运行双击没反应事件查看器里显示找不到 Qt6Core.dll。原因KDDockWidgets.dll 依赖 Qt 运行库Qt 运行库又依赖 C 运行库单纯拷贝一个 dll 是不够的。解决不要手动挑 dll 拷贝用 Qt 自带的 windeployqt 命令。在 VS2019 的开发者命令行里执行windeployqt your_app.exe它会自动把 Qt 的 dll、插件、翻译文件全部拷到 exe 目录基本不会漏。6. 进阶用 KDDockWidgets 的调试日志验证动态库是否真的工作这个技巧对排查“dll 编好了但拖拽行为异常”特别有效。KDDockWidgets 内部预留了日志开关不需要改源码在程序启动前设置一个环境变量就能打开详细输出set KDDOCKWIDGETS_LOG_LEVELdebug然后在你的程序里加上一段代码把日志打印到控制台#include QDebug #include spdlog/spdlog.h int main(int argc, char** argv) { qputenv(KDDOCKWIDGETS_LOG_LEVEL, debug); spdlog::set_level(spdlog::level::debug); // 你的业务代码 }设置这个环境变量后KDDockWidgets 会输出拖拽事件、布局计算、窗口停靠的详细信息。比如拖一个 DockWidget 到边缘时日志里会显示DropArea::onDrop这样的关键字如果某次停靠失败日志里通常能看到Invalid drop position一类的提示。这个日志对确认“到底是动态库行为异常还是我的业务代码传参有误”非常有用。我自己的习惯是每次更新 KDDockWidgets 源码重新编译后先用 examples 跑一遍再打开日志跑一遍自己的工程最后才替换到正式分支。这样虽然多花几分钟但能提前过滤掉大部分“编译成功但运行行为不对”的坑。KDDockWidgets 这个库整体质量不错只要 Qt 版本、MSVC 工具集和 Debug/Release 这三组参数对齐VS2019 下编出可用的动态库并不难希望这些经验能帮你少走几步弯路。本文还有配套的精品资源点击获取

相关新闻

给论文做一次“AI含量体检”,把重复率和机写味一起降下来

给论文做一次“AI含量体检”,把重复率和机写味一起降下来

交论文之前,很多学校现在都要过两道“安检”:一道是查重,看你的文字和别人撞了多少;一道是查AI,看你这段话是不是机器生成的。 很多同学只盯着重复率,改到绿了才松一口气,结果AI检测那边又亮起红…

2026/10/13 14:59:30 阅读更多 →
惠构思AI:期刊论文的数据和模型,为什么不能只是“截图”

惠构思AI:期刊论文的数据和模型,为什么不能只是“截图”

投过期刊的人都知道一个尴尬时刻。 审稿人问:"你这个结果的数据能不能提供一下?“你翻遍电脑,发现当初跑分析的原始文件已经找不到了,只剩下论文里那张图。你只能回复"数据已按要求处理”,心里清楚这个回答不…

2026/10/13 14:59:30 阅读更多 →
惠构思AI:期刊论文被拒,可能不是因为你写得不好,而是因为“对不上”

惠构思AI:期刊论文被拒,可能不是因为你写得不好,而是因为“对不上”

大家好。 今天聊一个投稿被拒的隐蔽原因。 很多作者收到拒稿信,第一反应是"我写得不够好"。但审稿人真正在意的,往往不是文笔,而是你的论文内部对不对得上。摘要里承诺的贡献,引言里有没有铺垫清楚?方法部分…

2026/10/13 14:59:30 阅读更多 →

最新新闻

金字塔原理:职场沟通结构化表达的四个原则与实战技巧

金字塔原理:职场沟通结构化表达的四个原则与实战技巧

废话不多说,这可能是你在职场沟通中最值得补的一课。我见过太多人,明明业务能力很强,可一开口就败下阵来:汇报讲了十分钟,领导眉头越皱越紧;邮件写了几百字,对方回复“所以你想表达什么”&#…

2026/10/13 17:10:09 阅读更多 →
实时数据采集架构设计:从需求量化到全链路调优

实时数据采集架构设计:从需求量化到全链路调优

直接开讲。实时数据采集架构设计这件事,我前前后后做了三年多,从最早只会写脚本定时拉数据,到后来能独立设计一套覆盖采集、缓冲、计算、落库全链路的实时方案,中间踩过不少坑。很多人一听到“实时数据采集”这几个字,…

2026/10/13 17:10:09 阅读更多 →
专科生AI论文写作平台实测:8个靠谱工具全解析

专科生AI论文写作平台实测:8个靠谱工具全解析

实话实说,专科生写毕业论文,难度不比本科生低,甚至更难。难在哪?时间紧、任务重,还有相当一部分同学是第一次接触完整的学术写作流程。我自己当年在专科阶段写毕业设计报告时,光是“怎么开头”“怎么把一段…

2026/10/13 17:10:09 阅读更多 →
Docker部署Ceph实现RBD镜像创建与挂载全流程

Docker部署Ceph实现RBD镜像创建与挂载全流程

1. 为什么非得用 Docker 部署 Ceph?——从“三台物理机起步”到“单机快速验证”的真实动因很多人看到“Docker 部署 Ceph”第一反应是皱眉:“Ceph 不是分布式存储系统吗?跑在容器里靠谱?”这问题我当年在某高校实验室带学生做存储…

2026/10/13 17:10:09 阅读更多 →
Python机器学习入侵检测系统实战:从NSL-KDD到Flask部署

Python机器学习入侵检测系统实战:从NSL-KDD到Flask部署

简介:这是一份基于Python机器学习的入侵检测系统项目源码,面向希望入门或进阶网络安全与机器学习方向的学习者,可作为毕业设计、课程设计、大作业或工程实训的参考方案。项目围绕网络流量嗅探与异常检测展开,包含数据预处理、特征…

2026/10/13 17:10:09 阅读更多 →
荷兰耕地遥感语义分割:从数据标注到模型训练全流程实战

荷兰耕地遥感语义分割:从数据标注到模型训练全流程实战

简介:这份荷兰耕地语义分割遥感影像数据集面向遥感图像处理、计算机视觉与农业监测方向的研究者和开发者,用于训练和验证耕地识别与像素级分割模型。资源包共2000个文件,以xml标注文件为主要类型,对应每张遥感影像的像素级类别标签…

2026/10/13 17:09:08 阅读更多 →

日新闻

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

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

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

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/13 16:22:04 阅读更多 →
影刀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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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 阅读更多 →