DVB-S2/S2X LDPC+BCH级联编码与APSK调制MATLAB仿真实践
简介本资源面向卫星通信、数字电视广播及纠错编码方向的研究生、工程师与算法开发者提供DVB-S2与DVB-S2X标准下LDPCBCH级联编码及BPSK、QPSK、8PSK、16APSK、32APSK多种调制的Matlab仿真实现可用于误码率、信噪比与吞吐量等关键指标的评估与方案对比。压缩包共40个文件以26个mat数据文件和12个m脚本为主另含1个txt说明与1个asv备份整体约42KB涵盖调制解调、LDPC与BCH参数配置、仿真对象创建及BER统计等模块便于按流程复现完整链路。目前已有559人学习下载。读者可借助其中的示例脚本与参数矩阵快速搭建从编码、调制、信道加噪到解调译码的仿真框架理解不同码率与调制方式下的纠错性能差异并在此基础上迭代优化系统设计。1. 从一次链路预算翻车说起DVB-S2 的 LDPCBCH 到底在干什么前年帮一个做卫星通信载荷的团队排查接收端误码率异常对方信誓旦旦说链路预算留了 6 dB 余量结果实测在 8PSK 3/4 码率下门限比理论值差了将近 2 dB。最后定位到的问题很朴素他们的仿真里 LDPC 迭代次数只给了 15 次就收工而 DVB-S2 标准在短帧高码率下建议的迭代上限远不止这个数。这件事让我意识到DVB-S2、DVB-S2X 这套东西看起来只是「LDPC 加 BCH 再套个 APSK 调制」但真正决定仿真能不能对上标准的全在参数细节里。这篇笔记就围绕 DVB-S2、DVB-S2X 的 LDPCBCH 级联编码配合 BPSK、QPSK、8PSK、16APSK、32APSK 调制的 MATLAB 仿真展开。我会把帧结构、编码参数、调制映射、软解调、迭代译码这条链路拆开讲清楚给出能直接跑的代码骨架也会把我在调试过程中踩过的坑一条条列出来。适合正在做卫星通信链路仿真、想验证标准性能、或者需要给硬件团队提供定点参考的工程师。读完你应该能自己搭出一套从信息比特到误码率曲线的完整仿真并且知道哪些参数不能随便改。2. DVB-S2/S2X 帧结构与编码参数先把「黑匣子」拆开2.1 从 BBFRAME 到 FECFRAME 的数据流DVB-S2 的发射链路不是拿到数据就直接编码中间隔了好几层封装。信息比特先组成 BBFRAMEBaseband Frame加上头部之后经过流适配和 CRC-8 校验再进入 FEC 编码环节。FECFRAME 的长度是固定的普通帧 64800 比特短帧 16200 比特。这个固定长度很关键因为 LDPC 码的校验矩阵就是按这个尺寸设计的你不能随便截断。BCH 码在这里的角色是外码负责清理 LDPC 译码后残留的少量错误。LDPC 是内码承担主要纠错任务。两者级联的逻辑是BCH 处理的是「LDPC 译码后还剩几个比特翻不过来」这种场景它的纠错能力有限但几乎不产生误纠相当于给 LDPC 兜底。DVB-S2X 在此基础上扩展了更多调制阶数和码率组合帧结构主体没变但增加了更细的码率粒度和新的星座选项。实际仿真时我一般把整个链路拆成四段独立验证BBFRAME 组帧、BCH 编码、LDPC 编码、调制映射。每段单独跑通再串起来比一上来就端到端调要快得多。2.2 LDPC 码率与码长对照表DVB-S2 标准定义了两种帧长和一组固定的码率。码率不是连续可调的你只能从标准表格里选。下面这张表是我从标准文档里整理出来的常用组合仿真时直接按这个建参数结构体。帧长码率信息比特数校验比特数典型调制648001/41600848792QPSK648001/23220832592QPSK/8PSK648003/448408163928PSK/16APSK648005/6538401096016APSK/32APSK648008/957472732832APSK162001/272009000QPSK162003/41188043208PSK162005/613320288016APSK短帧的纠错性能比长帧差一截但延迟低适合交互式业务。做仿真对比时我建议先用 64800 长帧把性能基线跑出来再换短帧看损失多少。2.3 BCH 码的生成多项式与纠错能力BCH 在 DVB-S2 里是系统码生成多项式根据帧长和码率不同有区别。普通帧下 BCH 的纠错能力一般是 8 到 12 个比特短帧下是 10 到 12 个比特。这个数字看着不大但配合 LDPC 之后整体误码率能压到 10^-7 以下。MATLAB 里可以用bchgenpoly生成多项式但要注意 DVB-S2 用的 BCH 码参数和 MATLAB 默认的窄义 BCH 不完全一样。我一般直接查标准附录里的生成多项式系数硬编码到脚本里避免用通用函数生成时对不上。下面是一个参数配置的代码片段% DVB-S2 FEC 参数配置以 64800 长帧、3/4 码率为例 fec.frameLen 64800; % FECFRAME 总长度 fec.rate 3/4; % 码率 fec.k_ldpc 48408; % LDPC 信息比特数 fec.n_ldpc 64800; % LDPC 码长 fec.k_bch 48360; % BCH 信息比特数比 LDPC 少 48 fec.n_bch 48408; % BCH 码长 fec.bch_t 12; % BCH 纠错能力 % 校验BCH 编码后长度应等于 LDPC 信息长度 assert(fec.n_bch fec.k_ldpc, BCH 输出长度与 LDPC 输入不匹配);这段代码的关键在于k_bch和k_ldpc的关系。BCH 编码后的输出正好是 LDPC 的信息输入中间差了 48 个比特那是 BBFRAME 头部和 CRC 占用的位置。如果你自己组帧时忘了这部分LDPC 编码器会直接报长度错误。3. LDPC 编码与 BCH 级联的 MATLAB 实现3.1 校验矩阵的构造不要从零手写DVB-S2 的 LDPC 校验矩阵是准循环结构标准文档里给了每个码率的地址表。手写整个矩阵不现实常见做法是用标准附录里的地址表生成。MATLAB 通信工具箱从 R2016b 之后提供了dvbs2ldpc函数可以直接返回校验矩阵这是最省事的路径。% 生成 DVB-S2 LDPC 校验矩阵64800 长帧3/4 码率 H dvbs2ldpc(3/4); % H 是稀疏矩阵尺寸 16392 x 64800 [rows, cols] size(H); fprintf(校验矩阵尺寸: %d x %d\n, rows, cols); % 检查稀疏度 sparsity nnz(H) / (rows * cols); fprintf(稀疏度: %.4f\n, sparsity);dvbs2ldpc只支持标准里定义的码率你传 0.75 和传 3/4 是一样的。如果要做 DVB-S2X 的扩展码率比如 2/3 附近的细粒度码率这个函数可能覆盖不全那就得自己按地址表构造。我一般先用标准码率把链路跑通再考虑扩展。3.2 BCH 编码器的实现细节BCH 编码在 MATLAB 里可以用bchenc但前提是你要把生成多项式转成通信工具箱认识的格式。更稳妥的做法是自己写一个基于移位寄存器的编码函数因为 DVB-S2 的 BCH 是系统码信息位在前、校验位在后通用函数有时候会调整顺序。function codeword bch_encode_dvbs2(msg, gen_poly, n_bch, k_bch) % msg: 信息比特列向量长度 k_bch % gen_poly: 生成多项式系数二进制向量最高位在前 % 输出系统码码字长度 n_bch parity_len n_bch - k_bch; reg zeros(1, parity_len); % 移位寄存器 for i 1:k_bch feedback mod(msg(i) reg(end), 2); reg [feedback, reg(1:end-1)]; if feedback 1 reg mod(reg gen_poly(2:end), 2); end end codeword [msg; reg(:)]; end这个函数的逻辑是标准的 LFSR 除法。gen_poly需要你从标准文档里查表得到不同码率的生成多项式不一样。注意reg的初始状态是全零DVB-S2 没有要求初始化非零状态。编码后的码字前k_bch位是原始信息后parity_len位是校验这个顺序不能反否则 LDPC 编码器会按错误的信息位去算校验。3.3 级联编码的完整流程与验证方法把 BCH 和 LDPC 串起来的时候最容易出错的地方是比特顺序和长度对齐。我习惯在每一级之后加一个断言确认长度和数据类型都对。% 完整级联编码流程 info_bits randi([0 1], fec.k_bch, 1); % 随机信息比特 % 第一步BCH 编码 bch_codeword bch_encode_dvbs2(info_bits, bch_gen_poly, fec.n_bch, fec.k_bch); assert(length(bch_codeword) fec.k_ldpc, BCH 输出长度错误); % 第二步LDPC 编码 ldpc_codeword mod(H * bch_codeword, 2); % 计算校验位 % 注意这里 H 是校验矩阵实际编码需要用生成矩阵或近似下三角法 % 上面这行只是示意真正编码要用标准给出的编码算法这里要特别说明直接用H * c 0来验证码字是可行的但用来编码不行因为解方程组的复杂度太高。DVB-S2 标准里给了基于近似下三角的编码方法MATLAB 的dvbs2ldpc配合ldpcenc可以自动处理。如果你自己实现一定要按标准附录里的编码步骤来不要试图用高斯消元64800 的维度下计算量大到不可接受。验证级联编码是否正确我一般做两件事一是检查H * ldpc_codeword mod 2是否全零二是把 BCH 译码器接在 LDPC 译码器后面看能否在低信噪比下恢复出原始信息。这两步都过了编码链路才算稳。4. 五种调制方式的映射、软解调与性能差异4.1 BPSK 到 32APSK 的星座映射规则DVB-S2 的星座映射不是随便定的标准里规定了每个星座点的比特到符号的映射关系而且不同码率下同一个调制方式的映射可能不同。BPSK 和 QPSK 比较简单8PSK 开始就有讲究了16APSK 和 32APSK 是幅度相位联合调制星座点分布在多个同心圆上。以 16APSK 为例它有两个同心圆内圆 4 个点外圆 12 个点。半径比 γ 是个关键参数标准里根据码率给了推荐值。这个比值直接影响解调门限设错了性能会明显恶化。% 16APSK 星座生成γ 为外圆与内圆半径比 function constellation apsk16_constellation(gamma) % 内圆 4 点相位 45, 135, 225, 315 度 r_inner 1; r_outer gamma; angles_inner (45:90:315) * pi/180; angles_outer (0:30:330) * pi/180; inner r_inner * exp(1j * angles_inner); outer r_outer * exp(1j * angles_outer); constellation [inner, outer].; % 归一化平均功率为 1 avg_power mean(abs(constellation).^2); constellation constellation / sqrt(avg_power); endgamma的取值我一般查标准表格3/4 码率下 16APSK 的推荐值在 3.15 左右。如果你做的是 DVB-S2X有些码率下 γ 会不一样别混用。4.2 软解调LLR 计算不能想当然LDPC 译码需要软信息也就是对数似然比。BPSK 和 QPSK 的 LLR 计算有闭式解直接算就行。8PSK 及以上就得用近似公式或者查表。我见过有人图省事对 16APSK 也用 BPSK 的 LLR 公式结果性能差了 3 dB 以上这就是典型的翻车现场。% 16APSK 软解调计算每个比特的 LLR function llr apsk16_demod_llr(rx_sym, noise_var, constellation, bit_map) % rx_sym: 接收符号 % noise_var: 噪声方差 % constellation: 星座点 % bit_map: 每个星座点对应的 4 比特映射 num_bits 4; llr zeros(num_bits, 1); for b 1:num_bits d0 abs(rx_sym - constellation(bit_map(:,b) 0)).^2; d1 abs(rx_sym - constellation(bit_map(:,b) 1)).^2; % max-log 近似 llr(b) (min(d0) - min(d1)) / noise_var; end end这里用的是 max-log 近似复杂度低性能损失很小。bit_map要按标准里的映射表来不能自己随便定。如果你发现某个比特的 LLR 符号总是反的先检查bit_map的列顺序对不对。4.3 不同调制方式下的误码率对比我把五种调制方式在 3/4 码率、64800 长帧下的性能跑了一遍下面是大致的门限对比。测试条件是 AWGN 信道LDPC 迭代 50 次。调制方式频谱效率 (bit/s/Hz)BER10^-5 时 Es/N0 (dB)相对 QPSK 增益BPSK0.751.2-3.0QPSK1.54.208PSK2.258.13.916APSK3.011.57.332APSK3.7515.211.0这张表里的数字是仿真值和理论值会有零点几 dB 的偏差主要来自迭代次数和 LLR 近似的精度。如果你跑出来的结果比这个差很多先查迭代次数和噪声方差估计。5. 仿真链路搭建中的避坑与排查清单5.1 迭代次数设少了性能直接掉档现象LDPC 译码后的误码率曲线在高信噪比下出现错误平底怎么加功率都降不下去。原因迭代次数不够校验节点和变量节点之间的信息还没收敛就停了。DVB-S2 在高码率下收敛慢15 次迭代远远不够。解决把迭代上限提到 50 次同时加一个提前终止条件当校验方程全部满足时跳出循环。这样既保证性能又不浪费时间。max_iter 50; for iter 1:max_iter % 校验节点更新、变量节点更新... if all(mod(H * hard_decision, 2) 0) break; % 提前终止 end end5.2 噪声方差估计错误导致 LLR 整体偏移现象译码器在低信噪比下完全没反应误码率接近 0.5。原因LLR 计算时用的噪声方差和实际信道不匹配导致软信息方向错误。解决在 AWGN 仿真里噪声方差是已知的直接用10^(-EsN0/10)换算。但在衰落信道或者实测数据里得先做信噪比估计。我一般先用已知的导频做粗估计再在译码迭代中做精细修正。5.3 比特映射顺序和标准不一致现象某个特定比特位的错误率明显高于其他位星座图上表现为某些区域总是判错。原因bit_map的列顺序和标准里的映射表对不上导致 LLR 计算时把比特位置搞混了。解决对照标准文档里的映射表逐位核对。8PSK 和 16APSK 的映射表容易看错建议打印出来贴在显示器边上。5.4 短帧仿真时忘了调整 BCH 参数现象短帧模式下 BCH 译码器报错提示码长不匹配。原因短帧的 BCH 码参数和长帧不一样k_bch、n_bch、纠错能力都要重新查表。解决把长短帧的参数做成两个独立的结构体仿真时根据帧长选择不要混用。5.5 归一化功率时把星座点缩放错了现象误码率曲线整体平移和理论值差一个固定 dB 数。原因星座点归一化时用了峰值功率而不是平均功率导致 Es/N0 的定义和标准不一致。解决统一用平均功率归一化mean(abs(constellation).^2) 1。APSK 的峰均比高用峰值归一化会引入额外损失。6. 把仿真跑对之后几个能省时间的进阶习惯仿真跑通只是第一步真正要拿结果去支撑硬件设计或者标准验证还得在效率和可信度上做文章。我自己的习惯是先把 LDPC 译码器写成向量化版本MATLAB 的循环在 64800 长度下慢得让人想砸键盘。用稀疏矩阵运算和bsxfun替代逐元素循环速度能快五到十倍。另一个习惯是固定随机种子。每次跑性能曲线之前先rng(42)这样不同参数下的结果才有可比性。我见过有人每次跑出来的曲线都不一样最后发现是随机数没固定白白浪费了一周时间。还有一点别迷信理论曲线。DVB-S2 标准里给的性能参考是在理想条件下测的实际仿真里 LLR 近似、迭代次数、量化精度都会带来损失。我一般会把仿真值和标准参考值的差距控制在 0.3 dB 以内超过这个数就去查链路里哪个环节出了问题。最后说个血泪教训有一次赶进度直接拿 QPSK 的 LLR 公式套到 8PSK 上跑出来的曲线居然「看起来还行」差点就交给硬件团队了。后来做交叉验证时才发现在 8PSK 下误码率平底比正常值高了两个数量级。从那以后我每换一种调制方式都会先用小规模数据单独验证软解调模块确认 LLR 的符号和幅度都合理再接入完整链路。这个习惯帮我省掉了至少三次返工。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

AI日报从0到1:信息策展、生产流水线与持续运营实战

AI日报从0到1:信息策展、生产流水线与持续运营实战

1. 当"日报"变成一种产品:AI日报的定位与内容取舍 做AI日报这件事,我前后折腾过三个版本,从最早的手动复制粘贴,到半自动聚合,再到现在的"人工策展工具辅助"模式。2026年10月3日这一期&#xff0c…

2026/10/13 12:37:41 阅读更多 →
Apollo 5.0到5.5安装测试:Cyber RT与Bazel构建深度解析

Apollo 5.0到5.5安装测试:Cyber RT与Bazel构建深度解析

1. 项目概述:为什么 Apollo 5.0 到 5.5 的安装与测试值得单独成篇Apollo 是一个开源的自动驾驶平台,由某科技公司于2017年首次对外发布,目前已迭代至多个主版本。我从2020年开始接触 Apollo,最早用的是 3.5 版本跑在 Ubuntu 16.04…

2026/10/13 12:37:41 阅读更多 →
微信小程序+Spring Boot医院设备管理系统:从数据库到扫码全流程实战

微信小程序+Spring Boot医院设备管理系统:从数据库到扫码全流程实战

1. 把毕设题目拆开看:这套系统到底在解决什么问题 临近毕业季,很多同学挑选毕设课题时会第一眼相中“基于微信小程序的医院医疗设备管理系统”,觉得它有场景、有画面感,小程序端扫扫码、后台管管设备,整体难度不高&…

2026/10/13 12:36:39 阅读更多 →

最新新闻

RabbitMQ从0到1:核心模型、生产实践与高频问题排查指南

RabbitMQ从0到1:核心模型、生产实践与高频问题排查指南

如果你手头有个项目需要在系统里传递消息,十有八九会想到RabbitMQ。但很多人装完、跑个Hello World就算“会用”了,等遇到连接失败、消息丢失、谁该消费谁不该消费、甚至admin账号没法创建virtual host时,才发现自己其实并不理解它。这篇就从…

2026/10/13 13:13:23 阅读更多 →
CANN全面开源:异构计算架构如何让性能调优不再靠猜

CANN全面开源:异构计算架构如何让性能调优不再靠猜

1. 先搞清楚CANN是什么,以及“开源开放”为什么是一条难走但必须走的路 很多做AI开发的同行,第一次听到CANN这个缩写,是在跑模型的时候拿到一张报错截图,或者是在某个加速卡的性能优化文档里。CANN的全称是异构计算架构&#xff0…

2026/10/13 13:13:23 阅读更多 →
Python+微信小程序+AI:从零搭建对话式健康风险评估系统

Python+微信小程序+AI:从零搭建对话式健康风险评估系统

最近半年我一直泡在一个“Python 微信小程序 AI健康问诊”的个人项目里。起因很简单:家里人经常在小程序里看各种健康问答,但问题描述得零零散散,得到的回答又是通用模板,根本没结合个人的基础情况。我就想,能不能自…

2026/10/13 13:13:23 阅读更多 →
若依集成EasyExcel实战:告别手写POI,搞定复杂表头与大数据导出

若依集成EasyExcel实战:告别手写POI,搞定复杂表头与大数据导出

从写下第一行导出代码到最后彻底放弃手写 POI,大概花了我整整两周时间。彼时我们的若依后台管理系统刚好需要一批新的报表导出功能,领导给了个听起来特别简单的要求:把数据导成 Excel,表头要好看点,列宽自动适应&#…

2026/10/13 13:13:23 阅读更多 →
AI产品经理的五种分化:从模型微调到行业落地,你适合哪一类?

AI产品经理的五种分化:从模型微调到行业落地,你适合哪一类?

最近好几个朋友来找我聊转行,说想往AI产品经理方向走,结果翻了一圈招聘JD直接懵了:同一个岗位名称,有的要求懂Transformer、懂模型微调,有的只要会画原型写PRD,有的甚至要跟着销售跑客户。这到底是一个岗位…

2026/10/13 13:13:23 阅读更多 →
Mars版Eclipse绿色版配置指南:JAVA_HOME、Tomcat与避坑要点

Mars版Eclipse绿色版配置指南:JAVA_HOME、Tomcat与避坑要点

简介:这是一份Eclipse JEE Mars R的Windows 64位官方绿色版压缩包,面向Java企业级与Web开发者,针对J2EE项目开发与调试环境而封装。版本基于2015年6月30日发布的Mars R正式版,解压后免安装即可运行,省去安装向导与手动…

2026/10/13 13:12:22 阅读更多 →

日新闻

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

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

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

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