储能参与调峰的配置方案与经济性分析复现思路
做储能配置与经济性分析这个方向最怕的不是建模算不出来而是拿到一篇论文标题后发现根本没给代码。标题写着“EI复现”点进去一看正文是空的关键词和摘要也全空。这种情况我碰到太多次了尤其是“参与调峰的储能系统配置方案及经济性分析”这类题目——它本质上是一个典型的双层优化问题外层决定储能配多大容量、多大功率内层决定储能怎么充放电最后还要把全生命周期的经济账算清楚。这篇我就把整个复现思路拆开讲从调峰建模的数学逻辑到容量功率的参数设计再到经济性口径、Matlab求解框架最后是大家最容易踩的五个坑。1. 先把调峰问题翻译成数学语言储能参与调峰的建模逻辑1.1 调峰的本质是削减峰谷差电网的负荷曲线一天之内变化很大。早上八九点到中午、傍晚六七点往往是高峰后半夜是低谷。发电侧为了满足峰段需求得随时准备开更多的机组而低谷时段机组又不能完全停机否则再启动成本很高。储能参与调峰本质上就是“削峰填谷”负荷低谷时给储能充电负荷高峰时储能放电把原来波峰波谷明显的净负荷曲线尽量拉平。这里必须先分清概念储能调峰和储能套利不是一回事。调峰的收益来源是“让电网少调用高成本机组”或者“削峰填谷后的市场补偿”套利的收益来源是峰谷电价差。实际工程项目里两者经常同时发生但建模目标不一样。像这个标题里的“参与调峰”更常见的目标是在满足削峰需求的前提下让储能配置的全生命周期总成本最小或者让综合收益最大。生活里可以这么理解你办公室里中午用电高峰空调全开配了一个大充电宝在凌晨自动充满午后放电撑住电压月底看电费单省了一笔。这个充电宝该买多大容量、功率就是你每天充放电策略叠加出来的结果——但要买多大得先把“每天怎么充放”定下来这就是双层优化的雏形。1.2 目标函数和约束一个完整的调峰优化模型怎么搭调峰优化模型的目标函数可以写成最小化削峰后的净负荷峰谷差[ \min ; \max_{t} \left[ P_{load}(t) P_{ch}(t) - P_{dis}(t) \right] - \min_{t} \left[ P_{load}(t) P_{ch}(t) - P_{dis}(t) \right] ]其中 (P_{load}(t)) 是预测负荷(P_{ch}(t)) 是充电功率(P_{dis}(t)) 是放电功率。净负荷就是原始负荷叠加储能动作后的曲线峰谷差越小调峰效果越好。也可以写成总成本最小化的形式[ \min ; C_{inv} C_{om} C_{buy} - R_{peak_shaving} ]也就是“投资成本 运维成本 购电成本 - 调峰收益”最小这样配置方案和经济性分析就自然地结合在了一起。约束条件里有几个是必须写的一个都不能省功率平衡每个时段的净负荷等于原始负荷加储能充电减储能放电这是最底层的物理约束SOC递推(SOC(t1) SOC(t) (\eta_c P_{ch}(t) - \frac{P_{dis}(t)}{\eta_d})\Delta t / E)充电效率系数 (\eta_c) 和放电效率系数 (\eta_d) 都要显式建进去不然储能好像“凭空消失能量”充放电功率限幅(0 \le P_{ch}(t) \le P_{rate})(0 \le P_{dis}(t) \le P_{rate})充放电互斥同一时段不能既充又放引入0-1变量SOC边界与初末值SOC不能越界一个调度周期结束时的SOC一般要求回到初始水平否则会白白“借”能量。如果你在论文里看到的模型没有SOC递推公式或者说充放电互斥约束是空的那大概率是为了凑版面简化掉的复现时不要照着抄要补回来。因为SOC递推直接决定了储能的容量能不能真正支撑你设计的充放电策略漏掉它等于整个配置方案是空算。2. 容量功率不是拍脑袋配置参数设计与初值求取2.1 从负荷曲线出发反推储能规模和功率很多人拿到题目就先找优化算法其实第一步应该是看数据。储能配置方案的核心决策变量是两个额定功率 (P_{rate}) 和额定容量 (E_{rate})。它们不能盲目枚举需要有初值。经验做法是先画负荷曲线看峰谷差 (\Delta P P_{load,max} - P_{load,min})。储能功率初值一般取峰谷差的 15% 到 30%然后容量按“可持续参与调峰的时长”来定。市场上常见的调峰储能是 2 小时、4 小时、6 小时配置。比如某地区典型日负荷曲线峰谷差是 20MW那你先取 (P_0 4\text{MW} \sim 6\text{MW})容量 (E_0 4\text{MW} \times 4\text{h} 16\text{MWh}) 或者 6 小时版本的 24MWh作为枚举搜索的中心。为什么要这样反推因为配置方案它不是一个孤立变量是和日充放电策略强耦合的。你让一个 1MWh 的小电池去削 10MW 的峰一天充放电再多次物理上也削不动。反过来你配一个 100MWh 的巨型储能却只削 1MW 的峰利用率太低经济性必挂。所以外层枚举配置内层跑调度策略两层迭代才能得到靠谱的方案。2.2 经济性参数的工程取值区间这个题目最关键的是“经济性分析”而所有经济性分析都建立在参数假设上。参数不同结论天差地别。表里我给出一组我在复现类似题目时常用的工程估值区间供参考参数取值区间说明储能系统单位造价1200–1800 元/kWh含电池、PCS、BMS、集装箱、安装不含土建PCS功率单元350–600 元/kW双向变流器与容量分开计运维费率初始投资的2%–5%/年含人工、备件、定期巡检调峰补偿或峰谷价差0.5–1.5 元/kWh视当地市场规则而定贴现率6%–8%一般取8%偏保守计算期10–15 年储能设计寿命常见10年可延保至15年注意上面这些值是工程可研和行业报价的常见区间不是哪个特定项目的数据。你在不同论文里看到的参数可能差几倍那不是别人算错而是假设条件不同。复现时务必先把自己手里的场景参数对齐再去调整配置变量。还有一个很容易忽略的电池衰减。锂电池不是“第一年多大以后永远多大”到寿命末期容量可能衰减到初始的80%左右。严肃一点的经济性分析会按寿命期内逐年容量衰减曲线做修正简单一点的做法是取全周期平均可用容量折算。如果论文里完全没提衰减那经济性结果必然是偏乐观的。3. 算经济账的三层口径从静态回收期到全生命周期NPV3.1 静态回收期为什么只能用来“初筛”静态回收期的公式很简单投资总额除以年净收益。假设一套 5MW/20MWh 的储能系统总投资 3000 万元年净收益 400 万元静态回收期就是 7.5 年。这个数字看上去很直观但它没有考虑资金时间价值也没有考虑项目后期运维费用上涨、电池容量衰减导致的收益递减。实际工程里静态回收期只适合用来快速比较几个候选方案。两个项目一个回收期 6 年、一个 7.5 年大概率 6 年那个更值得优先做。但如果你要在 7 年和 8 年之间做精确决策必须上动态经济性评价。3.2 净现值计算里最容易错的三处地方动态经济性分析的标尺是净现值NPV公式是[ NPV \sum_{t0}^{T} \frac{CF_t}{(1r)^t} ]其中 (CF_t) 是第 t 年的净现金流(r) 是贴现率(T) 是计算周期。现金流以为正收入、投资为负支出NPV 0 说明项目可行。这里有两个极容易出错的地方。第一是“计算期”和“寿命期”搞混。储能使用 10 年就衰减到报废你非要按 15 年计算后 5 年的收益假设根本不成立。第二是对“年净收益”的构成理解不统一。参与调峰的收益可能包含调峰补偿和峰谷套利两部分但有些复现代码把储能充电时的购电成本漏算了相当于只算卖电收入不算买电支出结果自然漂亮得吓人。我按 5MW/20MWh、总投资 3000 万元、每天净收益 1.2 万元、年运行 330 天、年运维费 90 万元、贴现率 8%、寿命 10 年算了一笔账年收益(1.2 \times 330 396) 万元年运维费(3000 \times 3% 90) 万元年净现金流(396 - 90 306) 万元10 年年金现值系数((1 - 1.08^{-10}) / 0.08 \approx 6.71)NPV(306 \times 6.71 - 3000 \approx -946) 万元这个结果是负的说明按这笔参数项目收益率达不到 8%经济性不过关。这不是配置错了而是这套参数下储能造价还是偏高、或收益被低估。复现经济性分析时得到负NPV是很正常的重要的是能解释为什么负、哪个参数主导了结论。3.3 残值与税收可别小看最后那一笔经济性分析的最后一个口径是残值。寿命期末电池虽然衰减了但还有回收价值——正极材料回收、结构件回收一般取初始投资的 3% 到 8%。不能说“寿命到了就全归零”也不能夸大残值因为回收成本会吃掉相当大一部分。另外如果项目进入电力市场参与交易还要考虑增值税、所得税这些在粗略的研究中可以简化但在可研级项目中必须列明。复现论文时先看原文有没有残值和税费项再看它用的是税前还是税后现金流这样你算出来的内部收益率才能跟论文对得上。4. Matlab落地求解器选型、程序结构与核心代码骨架4.1 外层配置搜索和内层优化调度的模块划分Matlab代码实现该怎么组织我建议主程序分三段参数初始化段读入负荷曲线、电价或调峰补偿曲线、储能技术参数效率、SOC上下限、经济性参数造价、贴现率、寿命配置与调度迭代段外层遍历候选功率容量组合内层构建目标函数和约束调用求解器返回每个配置下的调度结果经济性后处理段把每个配置的充放电曲线换算成年度收益、投资成本、NPV、回收期输出对比表。内层调度模型建议用标准混合整数线性规划。为什么必须用MILP而不是启发式算法因为充放电互斥约束引入了0-1变量同时目标函数里含有max/min非线性项但可以用辅助变量线性化。线性化之后的模型商业求解器能保证收敛到全局最优。启发式算法只能给“一个可行解”无法证明它是最优配置。4.2 变量维度估算与求解器适配假设全天 24 个时段储能候选 20 组容量、20 组功率内层单次求解的决策变量包括24 个时段的充电功率 24 个放电功率共 48 个连续变量24 个充电状态 24 个放电状态共 48 个0-1变量加SOC递推所需的25个连续变量。单次求解量级在100多个变量对任何开源或商业求解器都是小意思。外层20×20400次内层求解每次不到1秒整个程序跑完几分钟内搞定。所以不要一上来就套遗传算法先把精确模型跑通再谈加速。如果负荷数据是 8760 小时逐时曲线直接建模型变量会到上万个轻则求解变慢重则内存爆掉。这时才需要做典型日选择或者场景削减一般取 4 个季节典型日、每个典型日 24 时段。4.3 可直接参考的Matlab代码骨架下面的代码是调峰优化模型的核心骨架重点是SOC约束和充放电互斥约束的写法% 参数 T 24; % 时段数 dt 1; % 时间间隔小时 P_load [...] % 预测负荷曲线1xT E_rated 20; % 储能额定容量MWh P_rated 5; % 储能额定功率MW eta_c 0.95; % 充电效率 eta_d 0.95; % 放电效率 soc_min 0.1; soc_max 0.9; % SOC边界 soc_0 0.2; % 初始SOC占总容量比例 % 变量 P_ch sdpvar(1, T); % 充电功率 P_dis sdpvar(1, T); % 放电功率 u_ch binvar(1, T); % 充电状态 u_dis binvar(1, T); % 放电状态 soc sdpvar(1, T1); % SOC含初值 % 目标最小化净负荷峰谷差 P_net P_load P_ch - P_dis; obj max(P_net) - min(P_net); % 约束 cons []; % SOC递推 for t 1:T cons [cons, soc(t1) soc(t) ... (eta_c * P_ch(t) - P_dis(t) / eta_d) * dt / E_rated]; end % SOC边界与初值 cons [cons, soc(1) soc_0]; cons [cons, soc(T1) soc_0]; % 周期末回到初值 cons [cons, soc_min soc soc_max]; % 功率限幅 cons [cons, 0 P_ch P_rated]; cons [cons, 0 P_dis P_rated]; % 充放电互斥 cons [cons, P_ch 1e6 * u_ch]; % 大M约束 cons [cons, P_dis 1e6 * u_dis]; cons [cons, u_ch u_dis 1]; % 求解 ops sdpsettings(solver, gurobi, verbose, 0); optimize(cons, obj, ops);注意目标函数里的max(P_net) - min(P_net)严格来说不是线性表达式实际写成MILP时要用辅助变量替换引入 (M_{max})、(M_{min})让 (M_{max} \ge P_{net}(t))、(M_{min} \le P_{net}(t))目标改成 (M_{max} - M_{min})。上面骨架里用sdpvar的max/min写法在建模层会自动转化但如果你手写约束流派一定要记得线性化这一步。还要补充两点大M的取值不是越大越好。你写1e6只是示意实际用P_rated P_load_max 1就够太大容易造成数值病态。另外SOC的单位要统一有的论文用百分比有的用MWhsoc如果定义成0到1的比例那么在递推公式里要除以 (E_{rated})如果你定义成MWh就不要除。单位不统一是复现结果对不上的头号原因。5. 复现过程中最容易翻车的五个问题5.1 SOC初值决定结果“假优”还是“真优”这个坑我踩过不止一次。如果SOC初始值设成0.2周期末不约束回到0.2那么储能相当于多了一块免费充入的能量调度结果必然虚高。解决办法很简单首尾SOC一致。但在某个具体项目的复现里原文写的是“调度周期内SOC保持合理范围”并没有明确首尾一致这时你就要根据原文的投资逻辑去判断——如果原文目标函数只算调峰收益不算储能充放电的购电成本那它大概率没有考虑能量守恒结果参考价值有限。复现时按首尾一致来处理才是工程上能落地的方案。5.2 时间分辨率太粗导致“假削峰”24点曲线是一小时一个点对于慢变化的调峰场景勉强够用但要小心如果负荷曲线在某小时内有一个短时尖峰一小时平均后尖峰被抹平了你的储能配置就会偏小。反过来如果负荷曲线原始数据本身就是5分钟级而你强行聚合成1小时也会把短时负荷峰值抹掉。复现时我建议先看数据源的时间粒度再决定优化模型的分辨率。如果两者不匹配至少要做一个敏感性分析用24点算一版、用96点算一版对比配置结果的变化幅度。5.3 双层迭代的一致性校验外层枚举配置内层求解调度听起来简单实际运行时经常出现“内层返回的是上一轮配置的缓存结果”。原因很隐蔽在主循环里用了eval或assign没有清空变量导致不同配置下用的还是旧的目标函数系数。排查方法是在每次内层求解后打印一组已知最优解的判断变量例如某个时段的放电功率看看是否随配置变化而合理变化。如果一排功率完全不变那一定是变量覆盖出了bug。5.4 峰谷时段定义直接改变收益同一个负荷曲线“高峰期”定义成8点到12点还是18点到22点对应的储能放电时段完全不同。有的论文用的是固定分时电价峰谷时段有的用的是基于净负荷曲线动态划分峰谷段。复现时如果只看“收益”不看“时段划分逻辑”很容易得到数字上对不上的结果。正确的做法是先从论文的文字描述里提取出时段划分规则再在代码中把这条规则显式写成参数配置而不是靠读负荷曲线猜。5.5 论文结果核对的顺序问题拿到一篇论文不要急着跑图表先按下面三步核对单位核对kW、MW、kWh、MWh、万元、亿元差1000倍很常见参数核对把论文正文和附录里出现的所有经济性参数列成一张表逐个与代码里的常量比对场景核对论文用的负荷曲线是哪类行业负荷、哪个季节、抽样天数决定了它结果不可直接迁移到你自己的场景。走完这三步再跑程序你会发现很多“复现不出来”根本不是代码问题而是参数抄错了。复现这类“EI题目”做多了我的体感是真正卡人的地方从来不在算法本身而在参数口径和模型细节。你拿到一个储能配置题目先花一个小时把原文的场景参数表格化、把目标函数和约束条件按自己习惯重写一遍再动手写Matlab后面会顺畅得多。代码只是把模型“翻译”成机器能算的形式模型本身如果理解不透换什么求解器都白搭。

相关新闻

游戏Agent实践:从LLM规划到评估体系的9月工程复盘

游戏Agent实践:从LLM规划到评估体系的9月工程复盘

9月这段时间,游戏Agent方向算是我们团队今年投入最密集的一个月。月初我们还在为"Agent能不能在一个复杂环境里稳定完成三步以上的任务"争论,月底的时候,内部的沙盒环境里已经能跑出一套可复现的评测数据了。这篇文章想把9月这个阶…

2026/10/13 11:29:57 阅读更多 →
华为DHCP中继配置原理与排错实战

华为DHCP中继配置原理与排错实战

1. 项目概述:为什么DHCP relay不是“配个IP那么简单”“华为DHCP relay(中继)”这六个字,乍看是网络工程师日常配置里最不起眼的一行命令,但真正在某高校数据中心做网络割接时,我亲眼见过它让整栋实验楼的2…

2026/10/13 11:29:57 阅读更多 →
如何让AI记住团队工作方式?Agent Skills实战解析

如何让AI记住团队工作方式?Agent Skills实战解析

从今年年初开始,我越来越频繁地听到身边同事抱怨同一个问题:AI工具明明很聪明,但每次都得重新教一遍“我们团队是怎么做事的”。比如团队约定周报必须按“本周目标—进展—风险—下周计划”四段式来写,头一天晚上刚给AI讲清楚&…

2026/10/13 11:28:53 阅读更多 →

最新新闻

写作工具越简单越好?我在纯文本里找回了专注与效率

写作工具越简单越好?我在纯文本里找回了专注与效率

1. 从“不要赶路”到“还在赶路”:一轮纯文本工具带来的节奏反思写下这个标题的时候,我刚结束一趟长途自驾。回来之后,我打开一个新建的纯文本文件,把所有碎碎念倒进去,然后盯着光标发呆——这和出发前计划好的“路上写…

2026/10/13 22:53:12 阅读更多 →
Spring AI Alibaba Flow编排与A2A远程调用实战:客服子智能体流水线拆解

Spring AI Alibaba Flow编排与A2A远程调用实战:客服子智能体流水线拆解

Spring AI Alibaba 的 flow 编排和 A2A 远程调用,我是在把一个客服系统硬生生拆成五个子智能体、再拼装成流水线时才真正看懂的。之前文档翻了好几遍,总觉得 flow 就是个状态机封装,A2A 也就是互相发个消息。直到自己动手把意图识别、订单查询…

2026/10/13 22:53:12 阅读更多 →
Spring Boot 3.x连接Redis失败排错指南:从Unable to connect到ACL权限

Spring Boot 3.x连接Redis失败排错指南:从Unable to connect到ACL权限

如果你也在某个Spring Boot 3.x项目里看到过这么一行日志,而且网上搜到的配置教程试了一圈还是连不上,那这篇文章应该能帮到你。先说背景:我这边一个内部系统最近从Spring Boot 2.7升级到3.2,启动看着一切正常,结果第一…

2026/10/13 22:53:12 阅读更多 →
OkHttp3 POST请求400 Bad Request原因分析与排查清单

OkHttp3 POST请求400 Bad Request原因分析与排查清单

做了十几年接口自动化,说实话,最怕的不是 500,也不是超时,而是那种“看起来一切正常,却偏偏给你个 400”的请求。400 Bad Request 这个状态码,在自动化测试里就是一颗定时炸弹——500 起码能证明请求打到了…

2026/10/13 22:53:12 阅读更多 →
平台误判AI生成内容:申诉策略与降低误判概率的实操指南

平台误判AI生成内容:申诉策略与降低误判概率的实操指南

1. 平台误判“AI生成”这件事,到底卡在哪个环节内容被平台打上“AI生成”标签,然后流量断崖式下跌、推荐池被踢出、甚至直接屏蔽,这套流程我在过去一年里被问过不下几十次。问的人里有做图文长文的,有做短视频口播的,也…

2026/10/13 22:53:12 阅读更多 →
多Agent工作流实战:并行、协调与评估的完整设计指南

多Agent工作流实战:并行、协调与评估的完整设计指南

最近接了一个内部工具的改造任务,核心诉求很简单:让十几个负责不同环节的Agent能够并行处理任务,同时又不乱套。说实话,单Agent跑流水线大家都会,一旦上升到复杂Agent工作流,并行、协调、评估这三件事要是没…

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

日新闻

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

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

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

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/13 22:01:27 阅读更多 →
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 阅读更多 →