artcraft 创作工具链实战:从滤镜链到批量处理与素材管理
1. 从“artcraft”这个名字说起一个被低估的创作工具链思路第一次看到“artcraft”这个标题的时候我脑子里蹦出来的第一反应是——这大概率不是一个单一工具而是一套围绕“艺术化创作”搭建起来的工作流或者工具集合。为什么这么说因为“art”和“craft”这两个词放在一起本身就带着一种很明确的指向性前者偏向审美表达、视觉呈现、创意输出后者偏向手工技艺、流程打磨、可复现的操作方法。把这两个词捏在一起基本上就是在说一件事——让创意落地的那套手艺。我在不同项目里见过太多类似命名的东西有的最后做成了一个图片处理的小脚本集合有的演变成了一个面向设计师的素材管理面板还有的干脆就是一套“从灵感记录到成品输出”的完整流水线。所以“artcraft”这个标题本身其实留了很大的解读空间但核心跑不出三个方向创作辅助、素材加工、流程编排。这三个方向对应的需求人群也不太一样前者面向内容创作者中者面向设计和开发后者面向需要批量处理素材的运营或工程角色。这篇文章我打算按照“一套完整的创作工具链”来拆解 artcraft 这个项目。原因很简单单纯把它当成一个脚本或者一个库来讲内容撑不起来也不符合这个命名本身透露出的野心。我会从整体设计思路、核心模块拆解、实操落地过程、常见问题排查这几个维度展开把我在类似项目里踩过的坑、总结出来的经验都揉进去。不管你是刚接触这类工具的新手还是已经做过几轮类似项目的从业者应该都能从中找到可以直接抄作业的部分。先给一个整体判断artcraft 这类项目的核心价值不在于某个单点功能有多强而在于它能不能把“灵感→素材→成品→归档”这条链路串起来。单点工具市面上太多了缺的是能把它们粘合在一起的胶水层。下面我就按这个逻辑往下拆。2. 整体架构设计artcraft 到底该怎么搭2.1 核心需求拆解与模块划分在动手之前我习惯先把需求拆成“输入、处理、输出、管理”四块。artcraft 这个项目按这个框架拆下来大致是这样的输入层接收原始素材可能是图片、文本描述、草图、配色方案甚至是语音备忘。这一层的关键是格式兼容性和元数据提取。处理层这是 artcraft 的核心包含风格迁移、滤镜链、排版引擎、批量裁剪、水印叠加等操作。处理层要解决的是“怎么把原始素材变成符合预期的中间产物”。输出层导出成品支持多种格式和分辨率同时保留可编辑的工程文件。这一层最容易被忽视但恰恰是决定工具好不好用的关键。管理层素材库、版本记录、标签系统、任务队列。没有这一层项目用两周就会变成一团乱麻。我见过不少类似项目一开始只做处理层结果用户用着用着就发现素材找不到、版本对不上、批量任务跑到一半崩了没法恢复。所以我的建议是管理层哪怕先做个最简版本也要在第一版就留出位置。2.2 技术选型背后的取舍逻辑技术选型这块我按不同角色给几套方案你可以根据自己的实际情况挑。如果你是个人开发者或者小团队我建议走 Python Pillow/OpenCV SQLite 这条线。理由很直接Python 生态里图像处理库成熟得不能再成熟SQLite 零配置单文件就能跑部署成本几乎为零。处理层用 Pillow 做基础操作OpenCV 做复杂变换管理层用 SQLite 存元数据输出层用 Pillow 的 save 方法配合参数控制质量。这套组合我实测下来处理几千张图片的批量任务完全扛得住。如果你是面向 Web 的场景那前端用 Canvas 或者 WebGL 做实时预览后端用 Node.js Sharp 做批量处理数据库换成 PostgreSQL 或者直接上对象存储加索引。Sharp 的性能比 Pillow 在 Node 环境下要好不少尤其是并发处理的时候。如果你是面向设计团队内部使用可以考虑 Electron 打包一个桌面应用底层还是那套处理逻辑但交互体验会好很多。不过 Electron 的打包体积和内存占用要有心理准备我见过一个类似项目打包出来 200 多兆启动要好几秒这个取舍要看你的用户能不能接受。提示不要一上来就追求“全平台支持”。我踩过这个坑为了同时支持 Windows、macOS、Linux光路径处理和字体渲染就折腾了一周多。先在一个平台上跑通再考虑移植。2.3 目录结构与工程组织一个清晰的目录结构能省掉后面无数麻烦。我推荐的结构是这样的artcraft/ ├── core/ # 核心处理逻辑 │ ├── filters/ # 滤镜链 │ ├── transforms/ # 几何变换 │ └── compositor/ # 合成引擎 ├── io/ # 输入输出 │ ├── readers/ # 格式读取 │ └── writers/ # 格式导出 ├── manage/ # 管理层 │ ├── library.py # 素材库 │ ├── version.py # 版本记录 │ └── queue.py # 任务队列 ├── config/ # 配置文件 ├── assets/ # 内置资源字体、预设 └── cli.py # 命令行入口这个结构的好处是职责边界清晰。core 只管处理io 只管读写manage 只管状态互相之间通过明确的接口通信。后面要加新功能往对应目录里塞就行不会牵一发动全身。3. 核心模块深度拆解从滤镜链到合成引擎3.1 滤镜链的设计与实现要点滤镜链是 artcraft 处理层最核心的部分。所谓滤镜链就是把多个滤镜按顺序串起来前一个的输出作为后一个的输入。听起来简单但实际做起来有几个关键决策点。第一个决策点是滤镜的粒度。粒度太粗灵活性差粒度太细链会变得很长性能损耗大。我的经验是按“原子操作”来划分亮度调整、对比度调整、饱和度调整、高斯模糊、锐化、色调分离每个都是一个独立滤镜。这样组合出来的效果最灵活而且每个滤镜的实现都很简单不容易出 bug。第二个决策点是参数传递方式。我推荐用字典或者 dataclass 来传参而不是位置参数。原因很实际位置参数一旦顺序改了所有调用点都要跟着改而字典方式只认键名扩展性好得多。from dataclasses import dataclass dataclass class FilterParams: brightness: float 1.0 contrast: float 1.0 saturation: float 1.0 blur_radius: float 0.0 def apply_filter_chain(image, chain): for filter_fn, params in chain: image filter_fn(image, params) return image第三个决策点是链的执行顺序。这个没有绝对标准但有一个经验法则先做几何变换再做颜色调整最后做锐化和降噪。因为几何变换会改变像素邻域关系如果先锐化再缩放锐化产生的边缘会被缩放模糊掉效果就白做了。注意滤镜链越长累积误差越大。尤其是涉及多次缩放和颜色空间转换的时候建议中间结果用高位深格式保存最后再降到 8 位输出。3.2 合成引擎的关键技术点合成引擎负责把多个图层按照一定规则叠加在一起。这块的技术点主要集中在混合模式和蒙版处理上。混合模式常见的有正常、正片叠底、滤色、叠加、柔光等。实现的时候核心是对每个像素做通道级的数学运算。以正片叠底为例公式是result base * blend / 255滤色是result 255 - (255 - base) * (255 - blend) / 255。这些公式看起来简单但要注意颜色空间的问题。如果在 sRGB 空间直接算结果会偏暗或者偏亮正确的做法是先转到线性空间算完再转回来。蒙版处理的关键是边缘羽化。硬边蒙版合成出来会有明显的锯齿尤其是缩放之后。我的做法是对蒙版先做一次高斯模糊半径根据输出分辨率来定一般取输出宽度的 0.5% 到 1% 之间。这个参数需要根据实际效果微调没有万能值。3.3 素材管理与版本记录素材管理这块我强烈建议从第一天就用数据库哪怕只是 SQLite。用文件夹加文件名来管理素材短期看没问题一旦素材超过几百个找起来就是灾难。数据库表的设计我推荐至少包含这几张表表名用途关键字段assets素材主表id, path, hash, type, created_atversions版本记录id, asset_id, parent_id, params, created_attags标签id, nameasset_tags关联表asset_id, tag_idtasks任务队列id, status, payload, result, created_athash 字段用来做去重这个很实用。我见过一个项目因为没做去重同一个素材被导入了十几次磁盘空间白白浪费。版本记录用 parent_id 做成树状结构这样可以追溯每一次修改的来源回滚的时候特别方便。4. 实操落地从零跑通一条完整链路4.1 环境准备与依赖安装先把环境搭起来。我以 Python 方案为例其他方案思路类似。python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install pillow opencv-python numpy sqlalchemy click这里解释一下每个依赖的作用Pillow 做基础图像读写和简单处理OpenCV 做复杂变换和性能敏感的操作numpy 做数组运算SQLAlchemy 做数据库 ORMclick 做命令行接口。这套组合我用了好几年稳定性没问题。提示OpenCV 的安装在不同平台上偶尔会有依赖问题如果 pip 装不上可以试试 conda 或者用 opencv-python-headless 版本后者不带 GUI 依赖体积小很多。4.2 核心处理流程的代码实现下面这段代码展示了一条完整的处理链路读取素材、应用滤镜链、合成水印、导出成品、记录版本。from PIL import Image, ImageEnhance, ImageFilter from pathlib import Path import hashlib from datetime import datetime def load_asset(path): img Image.open(path).convert(RGBA) return img def apply_brightness(img, factor): return ImageEnhance.Brightness(img).enhance(factor) def apply_contrast(img, factor): return ImageEnhance.Contrast(img).enhance(factor) def apply_blur(img, radius): return img.filter(ImageFilter.GaussianBlur(radius)) def compose_watermark(base, watermark, position, opacity): wm watermark.copy() alpha wm.split()[3] alpha alpha.point(lambda p: int(p * opacity)) wm.putalpha(alpha) result base.copy() result.paste(wm, position, wm) return result def process(input_path, output_path, watermark_pathNone): img load_asset(input_path) img apply_brightness(img, 1.1) img apply_contrast(img, 1.05) img apply_blur(img, 0.5) if watermark_path: wm load_asset(watermark_path) img compose_watermark(img, wm, (20, 20), 0.6) img.convert(RGB).save(output_path, quality92) return output_path这段代码看起来简单但里面有几个细节值得说。第一convert(RGBA)是为了统一格式避免后面处理时因为模式不一致报错。第二水印的透明度是通过修改 alpha 通道实现的比直接调整整体透明度更可控。第三导出时转成 RGB 再保存因为 JPEG 不支持 alpha 通道不转的话会报错。4.3 批量任务与队列管理单个文件处理跑通之后下一步就是批量。批量任务的核心是队列管理和错误恢复。import queue import threading from pathlib import Path class TaskQueue: def __init__(self, workers4): self.q queue.Queue() self.workers workers self.results [] self.errors [] def add(self, task): self.q.put(task) def worker(self): while True: task self.q.get() if task is None: break try: result process(**task) self.results.append(result) except Exception as e: self.errors.append((task, str(e))) finally: self.q.task_done() def run(self): threads [] for _ in range(self.workers): t threading.Thread(targetself.worker) t.start() threads.append(t) self.q.join() for _ in range(self.workers): self.q.put(None) for t in threads: t.join()worker 数量怎么定我的经验是CPU 核心数的一半到全部具体看任务是 IO 密集还是 CPU 密集。图像处理大部分是 CPU 密集所以设成核心数左右比较合适。设太多反而会因为上下文切换导致性能下降。错误处理这块我建议记录失败任务但不中断整个队列。我见过一个项目因为一张图片损坏导致整个批量任务崩掉几百张图白跑。正确的做法是把失败的任务和错误信息记下来跑完之后统一处理。4.4 输出质量控制与格式选择输出环节有几个参数直接影响成品质量我整理成表格方便对照格式适用场景关键参数建议值JPEG照片、网页quality88-95PNG需要透明、无损compress_level6-9WebP网页、体积敏感quality, method85, 4-6TIFF印刷、归档compressionlzwJPEG 的 quality 设太高体积会暴涨设太低会有明显块状伪影。我实测下来 92 是个比较平衡的值肉眼看不出损失体积也可控。PNG 的 compress_level 影响的是压缩时间和体积的权衡9 最省空间但最慢6 是折中点。注意如果处理链路里有多次保存和读取中间结果一定要用无损格式。我踩过这个坑中间用 JPEG 存了一次后面再处理的时候伪影被放大了好几倍最后成品质量惨不忍睹。5. 常见问题与排查技巧实录5.1 图像处理类问题速查这类问题在实际操作中出现频率最高我整理了一张速查表现象可能原因排查方法解决方案输出偏色颜色空间不一致检查输入输出 ICC 配置统一转 sRGB 再处理边缘锯齿缩放算法不当对比不同重采样方法缩小用 LANCZOS放大用 BICUBIC内存暴涨大图未分块处理监控处理峰值内存分块处理或降低分辨率处理速度慢滤镜链过长逐段计时合并可合并的滤镜透明区域变黑alpha 通道丢失检查中间格式中间结果用 PNG偏色这个问题我遇到过好几次最后发现都是颜色空间没统一。有的素材是 Adobe RGB有的是 sRGB直接混在一起处理输出必然偏。解决办法很简单读取的时候统一转成 sRGB处理完再按需转回去。5.2 性能瓶颈的定位与优化性能问题不要凭感觉猜一定要先测量再优化。我的做法是在每个关键节点加计时跑一批样本看时间花在哪里。import time def timed(fn): def wrapper(*args, **kwargs): start time.perf_counter() result fn(*args, **kwargs) elapsed time.perf_counter() - start print(f{fn.__name__}: {elapsed:.3f}s) return result return wrapper实测下来图像处理的时间分布通常是这样的读取占 10%处理占 70%写入占 20%。如果处理占了大头就去看是哪个滤镜慢如果读取慢可能是磁盘 IO 或者格式解码的问题如果写入慢多半是压缩参数设太高了。优化的优先级我建议是先换算法再调参数最后才考虑并行。很多人一上来就上多进程结果发现单张图处理本身就慢并行只是把慢分摊了总量没变。5.3 踩过的坑与独家避坑技巧说几个我实际踩过的坑都是文档里不会写的。第一个坑是字体渲染的平台差异。同样的字体文件在 Windows 和 Linux 上渲染出来的字重和间距可能不一样。如果你的项目涉及文字排版一定要在目标平台上做视觉验收不能只在开发机上看着没问题就发布。第二个坑是EXIF 方向信息。手机拍的图片经常带 EXIF 方向标记Pillow 读取的时候默认不旋转但显示的时候会旋转。如果不处理这个批量处理出来的图方向全是乱的。解决办法是读取之后立刻用ImageOps.exif_transpose处理一下。第三个坑是并发写入冲突。多个 worker 同时往同一个目录写文件如果文件名规则不够唯一会互相覆盖。我的做法是文件名里带上任务 ID 和时间戳确保唯一性。第四个坑是内存泄漏。Pillow 的 Image 对象如果不显式关闭在长时间运行的批量任务里会累积占用内存。虽然 Python 有垃圾回收但图像对象占的内存大回收不及时。建议处理完一张就img.close()或者用上下文管理器。6. 扩展方向与个人经验体会artcraft 这类项目跑通基础链路之后有几个方向可以继续深挖。一个是预设系统把常用的滤镜链和参数组合保存成预设一键套用这个对提升效率帮助很大。另一个是批处理模板针对特定场景比如电商主图、社交媒体配图预定义好整套处理流程用户只需要丢素材进去就行。还有一个方向是处理过程的可视化。把滤镜链的每一步结果都展示出来让用户能直观看到每个参数的影响。这个功能对新手特别友好我见过一个类似项目加了实时预览之后用户留存率明显提升。我个人在实际操作中的体会是这类工具的价值不在于功能多而在于流程顺。功能再多如果从素材导入到成品导出要经过七八个步骤用户用两次就放弃了。反过来功能少一点但每一步都顺畅用户反而愿意长期用。所以做这类项目我建议把精力优先花在流程打磨上而不是堆功能。最后分享一个小技巧处理链路的每一步都保留中间结果哪怕只是临时文件。这样出问题的时候可以快速定位是哪一步出的错不用从头重跑。等整个流程稳定了再考虑关掉中间结果的保存来节省磁盘空间。这个习惯帮我省了无数次重跑的时间。

相关新闻

基于MP2642GR-Z与PIC18F86J10的两串电池主动均衡方案设计与实操

基于MP2642GR-Z与PIC18F86J10的两串电池主动均衡方案设计与实操

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

2026/10/17 3:53:58 阅读更多 →
大语言模型核心原理与工程实战:从Transformer到RAG与Agent

大语言模型核心原理与工程实战:从Transformer到RAG与Agent

1. 核心架构:为什么Transformer成了大模型的地基聊大语言模型,绕不开Transformer。现在市面上你能叫得上名字的大模型,底座基本都是它。很多朋友一开始接触这个概念会觉得抽象,我换个说法:Transformer本质上是一个“词…

2026/10/17 3:53:58 阅读更多 →
SQL Server CONVERT日期转换全解析:从style参数到性能优化

SQL Server CONVERT日期转换全解析:从style参数到性能优化

做 SQL Server 开发的人,几乎没有不跟 CONVERT 打交道的。尤其是日期转换,“CONVERT(varchar, GETDATE(), 23)”这种写法在公司的存储过程、日常查询、数据导出脚本里到处都是。可说实话,真正能把这个函数讲清楚、用明白的人并不多。大多数情…

2026/10/17 3:53:58 阅读更多 →

最新新闻

金融数据服务中台架构实战:从多源聚合到实时推送全解析

金融数据服务中台架构实战:从多源聚合到实时推送全解析

先交代下背景。我最近在负责一个代号叫financial-services的内部项目,说白了就是一套面向金融场景的数据服务中台:上游接行情源、资讯源、账户流水,下游对接移动端、Web 和量化脚本。这个项目名字看起来很简单,但真正落地的时候牵…

2026/10/17 4:42:13 阅读更多 →
CLI-Anything:命令行的可观测性操作系统

CLI-Anything:命令行的可观测性操作系统

1. CLI-Anything 不是又一个命令行包装器,它是 CLI 生态的“操作系统级抽象层”你有没有试过在终端里敲下git commit -m "fix: typo",却突然意识到——这行命令背后其实调用了至少 4 层抽象:Shell 解析器 → Git 二进制入口 → lib…

2026/10/17 4:42:13 阅读更多 →
从51万行泄露代码看大模型AI工程架构与安全底线

从51万行泄露代码看大模型AI工程架构与安全底线

这两天 AI 圈最热闹的事,莫过于某头部 AI 实验室的代码库被曝大规模泄露,媒体标题一个比一个刺激:“51万行代码”“底裤被扒干净”。吃瓜群众盯着“翻车”两个字看热闹,但作为一个常年泡在模型训练和工程基建里的人,我…

2026/10/17 4:42:13 阅读更多 →
自动驾驶产业链全景图谱:从传感器到商业运营的关键逻辑

自动驾驶产业链全景图谱:从传感器到商业运营的关键逻辑

聊到自动驾驶,很多人第一时间想到的是无人驾驶出租车,或者是某款新车宣传片里的自动变道。但真正在产业链里跑过一圈的人都知道,自动驾驶根本不是“一辆车”的事情,它是一条从芯片、传感器、底盘,到系统集成、运营调度…

2026/10/17 4:42:13 阅读更多 →
Unity伤害数字系统实战:对象池与飘字动画优化方案

Unity伤害数字系统实战:对象池与飘字动画优化方案

1. 为什么一个伤害数字值得单独拿出来做做Unity项目的人,尤其是做动作类、RPG类或者塔防类玩法的,几乎都会碰到同一个需求:角色挨打或者打出伤害时,屏幕上要飘出一个数字,告诉玩家这一下打了多少。听起来特别简单&…

2026/10/17 4:42:13 阅读更多 →
云原生功能测试实践:容器与微服务特性适配关键点

云原生功能测试实践:容器与微服务特性适配关键点

1. 项目背景与测试定位:容器化之后,功能测试到底测什么做云原生应用测试,最怕的就是一上来就扎进细节里。我接手这份“云原生应用软件功能测试报告:容器与微服务特性适配”的时候,第一反应不是急着列用例,而…

2026/10/17 4:41:13 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →