光伏阵列Boost与MPPT扰动观察法及储能控制Simulink仿真实践
最近在做光伏发电系统的仿真验证时我重新把“光伏阵列Boost电路MPPT控制储能单元”这套组合完整搭建了一遍。这个项目模型的核心是扰动观察法PO实现最大功率点跟踪MPPT同时叠加了储能控制策略并使用负载突变来验证系统在动态工况下的响应能力。整体基于MATLAB/Simulink搭建兼容性方面覆盖了从R2016a到R2023b的多个版本。这篇博文不打算泛泛地介绍原理而是把这次从建模思路、控制策略设计、仿真验证到版本迁移过程中遇到的实际问题和处理方式都整理出来。特别是扰动观察法在Simulink里的实现细节以及储能单元在负载突变时如何稳定直流母线电压这两个点是最容易出问题的地方也是这个模型的精髓所在。1. 模型整体架构光伏、变换器与储能单元的协同逻辑在动手搭建Simulink模型之前先理清整个系统的拓扑结构是很有必要的。很多初学者一上来就急着拖模块结果仿真发散或者波形不对往往就是因为在顶层设计时没有想清楚能量流动的方向和控制对象之间的关系。这个项目采用的结构是经典的两级式架构光伏阵列首先连接到Boost升压变换器Boost的输出端并联蓄电池储能单元最后共同构成直流母线向后端负载供电。之所以选择Boost拓扑是因为光伏组件的输出电压通常较低比如单块组件最大功率点电压在30V到40V左右而直流母线需要稳定在更高的电压等级比如400V或者48V取决于负载需求Boost电路正好承担了升压和MPPT调节的双重职责。1.1 光伏阵列的建模方式选择光伏阵列的建模在MATLAB里有三种常见路径直接用Simscape Electrical库中的Solar Cell模块、用Simulink标准库搭建基于单二极管模型的数学表达式、或者利用MATLAB的PV Array模块需要Simscape Electrical许可证。我这次选用的是基于单二极管五参数模型的数学建模方式理由很实际它不依赖额外的工具箱授权公式透明便于修改参数而且在纯Simulink环境下就能稳定运行。温度25°C、辐照度1000W/m²条件下的标准参数分别是开路电压Voc44.5V短路电流Isc8.5A最大功率点电压Vmp36V最大功率点电流Imp8A。将这些参数代入五参数模型的输出方程再通过S函数或MATLAB Function模块封装成子系统就能得到一个可复用的光伏阵列封装模块。提示如果你手头有Simscape Electrical许可证直接使用PV Array模块会省很多事。但如果是给学生做毕业设计或者团队合作需要分享模型数学建模方式的可移植性明显更好打开就能跑不存在工具箱缺失的报错问题。1.2 Boost变换器与MPPT的耦合关系Boost电路在这里不仅是电压变换器更是MPPT算法的执行机构。通过调节MOSFET的占空比D可以改变光伏阵列端口的等效负载阻抗从而牵引工作点向最大功率点移动。占空比与输入输出电压的关系满足Von Vpv × (1/(1-D))这个公式是整个控制回路的物理基础。建模时Boost电路的参数选择很关键。电感L的取值要保证电流连续导通模式CCM按照L Von × D / (2 × fsw × Icrit)估算。这里开关频率设为10kHz母线电压400V最大占空比约0.6临界电流取1A计算出来的电感值约为8mH左右实际选了6mH留有裕量。电容C1光伏侧主要起到抑制电压纹波的作用取200μF母线电容C2取1000μF用于平衡负载突变时的瞬时功率缺口。2. 扰动观察法的Simulink实现细节与参数整定逻辑扰动观察法PO是目前工程上应用最广泛的MPPT算法核心思想很朴素对工作电压施加一个小的扰动然后观测功率变化的方向如果功率增加就继续沿同一方向扰动如果功率减少就反向扰动。这个逻辑用流程图表达很简单但放到Simulink离散控制环境里实现时有几个细节决定了算法是否真正可用。2.1 实现方式从流程图到可运行的状态逻辑我选择用MATLAB Function模块来实现PO算法主体这样最灵活也便于后续调整步长策略。核心代码如下function D_ref PNO_MPPT(Vpv, Ipv, D_prev, P_prev, step_size) % 输入光伏电压Vpv光伏电流Ipv上一时刻占空比D_prev上一时刻功率P_prev扰动步长 % 输出当前时刻参考占空比D_ref P_now Vpv * Ipv; delta_P P_now - P_prev; delta_V Vpv - Vpv_prev; % 需要借助Unit Delay保存上一时刻电压 if delta_P 0 if delta_V 0 D_ref D_prev step_size; else D_ref D_prev - step_size; end else if delta_V 0 D_ref D_prev - step_size; else D_ref D_prev step_size; end end % 占空比限幅 if D_ref 0.9 D_ref 0.9; elseif D_ref 0.1 D_ref 0.1; end这里有个容易出问题的地方delta_P是当前功率与上一时刻功率的差值但delta_V是当前电压与上一时刻电压的差值这两个“上一时刻”必须是同一个采样点否则逻辑会混乱。因此需要在MATLAB Function外部用Unit Delay模块同时保存上一周期的电压值Vpv_prev和功率值P_prev。2.2 采样周期与扰动步长的配合经验PO算法的性能高度依赖采样周期Ts和扰动步长ΔD的配合。如果Ts太小变换器尚未达到稳态就采集了功率值算法会把动态响应误判为扰动结果造成振荡甚至误判如果Ts太大动态响应变慢光照快速变化时会丢失最大功率点。我实测下来对于开关频率10kHz的Boost电路MPPT采样周期取0.01s到0.05s之间是合理的区间。0.01s意味着十个开关周期后读取一次功率值此时电感电流和电容电压基本进入稳态。扰动步长方面固定步长0.005到0.01比较稳妥对于250W左右的光伏阵列0.01的占空比扰动引起的功率变化在几瓦级别容易分辨且不会造成明显振荡。如果希望进一步提高稳态精度可以考虑变步长策略当|delta_P|较大时用大步长加速追踪靠近最大功率点时自动切换为小步长。不过这会增加代码复杂度对于基础仿真验证来说固定步长已经可以满足要求了。2.3 为什么没有选电导增量法这里有必要说明一下算法选型的逻辑。电导增量法INC在光照快速变化时的追踪精度理论上优于PO但实现上需要精确计算dP/dV对采样噪声更敏感而且代码量更大。对于这个项目——重点是验证储能控制策略和负载突变响应——PO的简单性和工程实用性反而是优势。实际测试中只要步长和采样周期配合得当PO在稳态时的功率波动可以控制在最大功率的2%以内完全够用。3. 储能控制策略设计母线电压稳定与充放电管理的两难平衡储能单元是这项目的另一个核心。设计储能控制策略之前先要明确一个问题光伏系统的能量流动不是单向的光照充足时储能吸收多余能量光照不足或负载增大时储能释放能量补足缺口。因此储能控制策略必须同时考虑能量管理层面和电压控制层面。3.1 双层控制结构外环电压、内环电流我采用的是经典的双闭环控制结构。外环是直流母线电压环将母线电压采样值与参考值400V比较经过PI控制器得到蓄电池的充放电电流指令内环是电流环控制双向DC/DC变换器Buck/Boost的实际电流跟踪指令值。母线电压误差经过PI控制器后输出的电流指令正负号决定了蓄电池的工作模式。当母线电压高于参考值说明光伏输出大于负载需求指令电流为负——蓄电池进入充电状态Buck模式当母线电压低于参考值指令电流为正——蓄电池放电Boost模式。这个“电压误差转电流指令”的思路本质上是用蓄电池去吸收或补充母线上的不平衡功率。3.2 PI参数整定的实用方法与验证标准外环电压环的PI参数我按照经典二阶系统整定思路来调试。控制器传递函数为Gc(s) Kp Ki/s被控对象是母线电容和等效负载。初始值Kp取2Ki取20然后逐步增大Kp直到系统出现轻微振荡再回调至60%-70%的临界值。最终整定结果为Kp8.5Ki50实测母线电压在负载突变时能恢复到400V±1.5%的范围内。内环电流环的响应速度必须快于外环否则会出现环间耦合振荡。电流环PI参数Kp取0.5Ki15采样周期用1e-5s与开关周期同步确保电流环带宽远高于电压环。注意蓄电池模型我用了Simscape Electrical库的Battery模块标称电压240V、额定容量100Ah。这个模型包含了SOC、内阻和温度的影响比理想电压源真实得多。如果用理想电压源替代储能控制策略的验证结果会失真——尤其是SOC边界效应会在长时间仿真中体现出来。3.3 SOC限制与充放电切换逻辑蓄电池最怕过充和过放。我在控制策略中加入了SOC保护窗口当SOC大于95%时强制将充电电流指令降低至零当SOC小于20%时禁止放电状态激活。具体的状态切换逻辑我放在了一个Stateflow图表里但如果你不想引入Stateflow也可以用MATLAB Function配合逻辑判断来实现同样的效果。SOC下限保护在Simulink中的实现代码如下if SOC 20 I_ref 0 I_ref 0; % 禁止放电 elseif SOC 95 I_ref 0 I_ref 0; % 禁止充电 end这里还需要注意一个问题SOC变化速率很慢而负载突变是瞬态的。如果SOC刚好在边界附近可能会出现保护动作和负载响应之间的矛盾。我在实际测试中遇到过一次SOC在21%时负载突然加大母线电压跌落到390V以下但SOC保护逻辑禁止了放电导致电压持续跌落。最后通过降低SOC下限阈值到15%并加入两秒延时确认机制解决了问题——确实是“两难平衡”的典型写照。4. 负载突变验证场景从仿真波形到系统稳定性判断搭建完整个模型后最关键的验证环节就是负载突变。负载突变测试的目的是检验系统在外部条件突然变化时能否维持母线电压稳定、储能能否快速响应、MPPT是否还能锁定最大功率点。4.1 测试场景设计与参数设置我设计了三个典型工况。第一个是光照骤降场景辐照度在第2秒从1000W/m²瞬间降到400W/m²观察MPPT追踪行为和母线电压变化。第二个是负载突增场景在第3秒负载从2kW并联增加至4kW相当于瞬间将等效负载电阻减半检验储能单元的放电响应速度。第三个是光照恢复场景在第5秒辐照度回到1000W/m²此时储能可能还在放电状态需要观察控制环能否平滑切换回充电模式。负载突增这个场景最有价值。因为光伏阵列的最大功率是固定的250W×组串数如果负载需求突然超过光伏供给能力母线电压必然会跌落此时唯一能支撑母线电压的就是蓄电池放电。系统能否在几百毫秒内将母线电压拉回400V直接反映了储能控制的动态性能。4.2 波形判读什么样的响应算是合格测试得到的理想波形应该是这样的特征负载突变瞬间母线电压会有一个短暂的跌落通常有10V到20V的瞬时跌落取决于母线电容大小和负载变化幅度随后在200ms到500ms内恢复至400V±1%。蓄电池电流方向迅速反转从充电状态切换为放电状态电流幅值大致等于负载增量减去光伏功率缺额。如果波形出现以下问题就要回头排查参数了。母线电压长时间无法恢复说明电压环PI参数太保守或者蓄电池电流限幅设置过低母线电压出现持续振荡波动幅度超过5V且不衰减说明电压环与电流环带宽过于接近产生了谐振蓄电池电流频繁在充放电之间切换说明滞环策略缺失或者电压环参考值存在小幅偏移。4.3 负载突变仿真中常见的振荡问题及解决我在第一次完整联调时遇到了母线电压在负载突变后有约15Hz的低频振荡持续时间超过两秒。排查过程是这样的首先排除了MPPT环节——因为光照恒定PO算法输出稳定占空比几乎不变接着检查了储能电流环——将电流环PI参数从Kp0.5降低到0.2后振荡频率发生明显变化由此确定问题出在电压环与电流环的动态匹配上。最终的解决方案是重新整定电压环PI参数并额外增加了一个一阶低通滤波器时间常数0.02s对电压采样值进行滤波削弱了功率开关器件带来的开关纹波对电压环的干扰。这个处理之后负载突变时母线电压的恢复时间从800ms缩短到了300ms左右效果非常明显。5. MATLAB版本兼容性处理与模型落地经验这个模型从开发到现在经历了多个MATLAB版本遇到过不少兼容性问题。现在很多用户手里有R2016a也有R2023b大家打开同一个模型时尽可能保证“打开即跑”不弹出大量报错这是版本兼容处理的意义所在。5.1 版本差异的主要风险点从我实测的情况来看以下几个地方最容易出现版本兼容性问题。第一个是Simscape Electrical库的模块名称和端口定义不同版本对Battery、MOSFET等模块的参数设置界面有差异模型文件升级后部分模块会被替换成新版本需要手动确认端口顺序。第二个是MATLAB Function内部的代码语法兼容性新版本支持的一些语法在老版本中无法解析反之亦然。三是求解器设置不同版本对定步长求解器的默认选项有细微差别可能影响仿真收敛。5.2 兼容性处理的具体操作方式建议的开发模型方式在相对较老的环境如R2016a或R2018a中搭建模型主体避免使用较新版本才引入的专属模块在模型文件中尽量使用通用的积分器、常数、Unit Delay等标准库模块涉及S函数的尽量改用MATLAB Function这样可移植性更强。另外文件保存时建议保存为.slx格式并选择“保存为旧版本兼容格式”Save as previous version如果目标环境版本很老干脆使用.slx兼容模式或保留一份.mdl格式副本。演示交付给别人之前用各个目标版本的MATLAB各仿真一遍再打包发出这是最保险的做法。5.3 模型交付时建议附带的说明文档我在最终交付模型时除了.slx文件外总会附上一份简短的README里面说明清楚四件事模型的适用版本区间、需要哪些工具箱Simulink、Simscape Electrical、主仿真参数的存放位置MATLAB脚本文件、以及三组典型仿真场景对应的模型配置。这样别人拿到模型后不需要反向猜你的参数设置思路上手效率会高很多。6. 仿真模型的扩展方向与精细化改进建议模型跑通、负载突变验证完成只是第一步。从课程设计到真正可用于科研或工程初步验证这个模型还有不少可以精细打磨的地方。6.1 从单峰值到部分遮阴算法升级的岔路口标准的PO算法在均匀光照下工作良好但光伏组件被云层或建筑物部分遮挡时P-V曲线会呈现多峰特性PO很容易陷入局部最大功率点。这种情况下把算法升级为全局扫描局部PO的组合策略是更务实的路径每隔数十秒执行一次全局扫描确定当前全局最大功率点的大致范围然后用PO在该区间内精细追踪。这个改进在Simulink里实现并不复杂只需要增加一个扫描状态和一个切换使能信号。6.2 储能SOC均衡与多储能单元扩展如果系统包含多组储能单元需要考虑SOC均衡问题。否则容量大的电池组承担更多的充放电任务长期运行会导致电池老化不均衡。在控制层面可以在电流指令分配时根据各电池组的SOC比例进行加权分配SOC偏高的单元少充电、SOC偏低的单元多充电。这在Simulink里实现也不困难一个MATLAB Function模块即可搞定。6.3 与外部硬件在环测试的对接如果你有实时仿真设备这个模型还可以进一步改造为快速控制原型或硬件在环测试的载体。核心工作包括调整模型步长配置以适应实时仿真的计算约束、用真实的采样和PWM输出模块替换虚拟控制信号、以及增加输入输出信号的标定和诊断环节。这部分回头如果大家感兴趣我可以再单独整理一篇HIL联调的记录。在实际操作中我的体会是光伏系统的仿真验证不是一个“跑出波形就结束”的过程模型的可靠性取决于你在每个环节是否想清楚了参数从哪里来、边界在哪里、异常情况下系统会怎么表现。把扰动观察法、储能控制和负载突变这三块拧在一起做仿真本质上是在模拟一个微电网的核心能量调度逻辑先把这条主链路搞清楚、调稳了后续无论是做并网控制、模式切换还是能量管理策略都会顺利很多。

相关新闻

提示系统集成测试全攻略:从DSL版本兼容到预发环境落地

提示系统集成测试全攻略:从DSL版本兼容到预发环境落地

做提示词(Prompt)工程的都知道,单写一条高质量的提示词不难,难的是把一整套提示系统稳定地集成进业务里。我在大厂这几年,带过不下二十个提示系统的集成测试项目,见过太多“开发环境跑得好好的,…

2026/10/7 4:40:36 阅读更多 →
Node伪请求服务实战:解决前后端联调等待难题

Node伪请求服务实战:解决前后端联调等待难题

搞服务器运维搞到第四十三篇,今天想聊聊一个看起来不起眼、但在联调阶段能省下大量时间的活儿——用 Node 搭一个“伪请求”(pseudo http)服务。我们内部有个后台系统叫“东方仙盟”,前后端小团队联调时最烦的就是后端接口还没就绪…

2026/10/7 4:40:36 阅读更多 →
华为交换机路由器配置实例:从初始化到VLAN、路由与DHCP排障

华为交换机路由器配置实例:从初始化到VLAN、路由与DHCP排障

简介:这份华为交换机和路由器配置实例文档,面向企业网络管理员与运维工程师,系统梳理了多个主流系列交换机的端口限速配置场景,帮助读者根据设备型号选择合适的限速命令与参数。文档为单个电子文档文件,大小仅98KB&…

2026/10/7 4:39:36 阅读更多 →

最新新闻

Trae 深度实战:AI 原生 IDE 的 Agent 工作流与 VS Code 迁移指南

Trae 深度实战:AI 原生 IDE 的 Agent 工作流与 VS Code 迁移指南

1. 为什么我最终把主力编辑器换成了 Trae先说结论:我不是那种看到新工具就立刻迁移的人。VS Code 我用了快七年,插件配置、快捷键、代码片段、调试配置全都滚瓜烂熟,换编辑器的迁移成本我心里非常清楚。但用了 Trae 大概三周之后,…

2026/10/7 5:11:53 阅读更多 →
JavaScript 自增自减运算符完全指南:从表达式语义到踩坑排查

JavaScript 自增自减运算符完全指南:从表达式语义到踩坑排查

先给结论:let x 5; let y x;这行代码跑完,y是 5,x是 6。这不是什么高深的东西,但你要问一句“为什么y拿到的是 5 而不是 6”,能当场说清楚的人,其实没那么多。我见过太多人把和--背成“先加再用、先用再加…

2026/10/7 5:11:53 阅读更多 →
华为ENSP网络实验:18个练习题串讲数通考点,从VLAN到OSPF实战

华为ENSP网络实验:18个练习题串讲数通考点,从VLAN到OSPF实战

简介:这是一份面向华为网络设备配置学习的ENSP实验操作练习PDF,适合华为认证备考者、网络工程师及高校网络专业学生,用来在仿真环境中系统训练基础配置与排错能力。全书按实验模块组织,依次覆盖交换机基本配置、VLAN划分与单臂路由…

2026/10/7 5:11:53 阅读更多 →
Trae AI原生IDE深度实战:从配置调优到日常编码的完整工作流

Trae AI原生IDE深度实战:从配置调优到日常编码的完整工作流

AI 原生 IDE 这个概念,从 2024 年下半年开始被反复提起,但真正把它当成主力开发环境用下来的人其实不多。大部分人装了、试了、觉得"和 VS Code 差不多",然后就放着了。我从 Trae 早期版本开始用它写项目,中间经历过插件…

2026/10/7 5:11:53 阅读更多 →
潘多拉并非幻想:阿凡达设定的科学验证与硬核拆解

潘多拉并非幻想:阿凡达设定的科学验证与硬核拆解

开头前100字含核心关键词,说明是什么能做什么适合谁。用硬核影迷身份切入,拆解潘多拉存在的科学逻辑、电影设定对照、物理可行性算法,适配阿凡达影迷和科幻爱好者,用“洗白”报告的口吻挑战“科幻只是幻想”的定论。1. 为什么我说…

2026/10/7 5:11:53 阅读更多 →
CountDownLatch从入门到源码:Java并发等待机制详解

CountDownLatch从入门到源码:Java并发等待机制详解

Java 并发编程里头有一个工具,名字取得特别形象:CountDownLatch,中文一般翻译成“倒计时门闩”。你可以直接把它理解成一扇门:一开始门闩插得死死的,所有想进门的线程都被挡在外面,谁也过不去;等…

2026/10/7 5:10:53 阅读更多 →

日新闻

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

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

2026/10/7 1:01:58 阅读更多 →
用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

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

2026/10/7 1:02:00 阅读更多 →
芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

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

2026/10/7 1:02:00 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/6 7:15:40 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/6 5:29:09 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/6 6:26:51 阅读更多 →

月新闻

我发现了一个新思路:用 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/6 8:21:32 阅读更多 →
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/6 4:21:51 阅读更多 →
黑夜航拍船只数据集训练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/6 1:18:13 阅读更多 →