diagram-design:从结构化数据到代码化渲染的架构图画图方法论
画图这件事看起来是最没有技术含量的工作但真正想画出一张让所有人一眼就懂的架构图、流程图、时序图难度真不亚于写一份清晰的技术方案。diagram-design 就是我在反复踩坑之后总结出来的一套画图方法论加配套小工具它把画图的流程拆解为结构设计、布局规划、视觉规范、代码化定义、自动渲染几个环节让每一张图都有据可依而不是纯凭手感发挥。这个项目适合谁两类人最需要。第一类是经常给团队、客户、评审会画图的开发者、架构师、技术文档写作者图是你的表达工具图的质量直接影响别人对你方案的理解程度。第二类是正在组建文档体系、想把“画图”这件事标准化的小伙伴这里面的思路和模板可以直接抄走。如果你只是想找一个软件赶紧出图这篇文章也能帮你搞清楚“好图到底好在哪”之后再去选工具方向会明确很多。1. 项目概述diagram-design 到底在解决什么问题1.1 一张烂图消耗的是所有人的时间先说我观察到的高频痛点。很多图不是画不出来而是画完没人看得懂。节点摆放随意线条交叉得密密麻麻颜色用了七八种却没有语义字号忽大忽小箭头方向全凭个人习惯。这些问题单独看都不严重叠在一起就是灾难看图的同事要反复问你“这个框代表什么”“这条线为什么是虚线”一场原本十分钟能讲清楚的方案评审硬生生变成了一场图例解释大会。更隐蔽的问题是图与代码、文档脱节。代码里改了模块拆分架构图还是旧版本流程里新增了一个异常分支流程图没跟上。时间一长团队里没人信图了遇到事情直接去看代码图变成了一堆装饰性图片。diagram-design 这个项目最初就是冲着这两个痛点去的让图有统一的结构规则、让图的产生过程可以像代码一样被管理和复用。1.2 把“画图”重构为“设计图”我做这个项目之前画图基本靠鼠标拖拽一张图改五六遍是常事。后来我意识到画图慢、乱、难维护本质上是因为缺少一个“设计层”我们直接跳到了表达层脑子里还没想清楚这张图要强调什么、分几层、哪些是核心节点手已经开始动了。diagram-design 的核心转变是把工作流改成下面这样先定信息结构这张图要传达几个信息块块与块之间是什么关系。再定视觉层级哪些是主节点哪些是辅助说明用什么方式区分。然后用结构化数据描述图节点、连线、分组、标注全部用数据表达。最后交给渲染层自动生成成品。这个顺序看起来多了一步实际用起来反而快。因为结构定清楚之后视觉表达是水到渠成的事而如果一开始就沉迷于拖框拉线改布局就要半小时改结构更是伤筋动骨。1.3 代码化带来的三个意外红利把图用数据来表达除了好修改还带来了三个我一开始没想到的好处。第一个是可复用。同样的一个模块节点在架构图里出现过一次下次画部署图、时序图时可以直接复用同样的定义。第二个是可校验。数据化之后我可以写脚本检查这张图有没有孤立节点、有没有悬空的连线、有没有该连却漏连的关系比人眼检查靠谱得多。第三个是可演进。图跟着代码仓库一起走代码评审的时候顺便评审图图和代码再也不会各说各话。2. 整体设计思路与方案选型2.1 为什么我放弃了“所见即所得”最早做这个项目的时候我用的是所见即所得的绘图软件拖拽、缩放、对齐都挺顺手。但用了半年我发现了几个绕不开的问题图层一多就容易误操作对齐全靠肉眼批量修改节点样式要一个一个点版本管理几乎等于没有。后来我转向了代码化方案也就是用文本定义图形。一开始不适应总觉得“看不到东西心里没底”但用了两周之后就回不去了。文本定义有三个优势是鼠标拖拽给不了的第一可以 diff图改了哪里在版本管理里看得一清二楚第二可以批量几十个节点想统一换颜色改一个公共变量就行第三可以生成定义图的数据结构可以来自代码扫描、来自数据库元数据图不再是手工产物。2.2 声明式定义的选型考量在定义图的方式上我对比过命令式和声明式两条路线。命令式就是“先画一个矩形再画一条线把它移到某个位置”每一步都指定具体操作。声明式则是“这张图有哪些节点、哪些连线它们的属性是什么”具体怎么排布、怎么画由引擎去解决。我最后选了声明式原因是它更接近“设计意图”。画图的人真正想表达的是“支付服务和订单服务之间有调用关系”而不是“从坐标 100,100 到坐标 300,200 画一条带箭头的线”。声明式把注意力拉回到内容上布局这种事交给算法这是从根上解决“布局乱”的思路。2.3 项目目录与基础设施设计整个项目的文件组织非常朴素我按照“定义、样式、模板、输出”四个维度拆分diagram-design/ ├── schema/ # 图的数据结构定义 ├── styles/ # 视觉规范颜色、线型、字体 ├── templates/ # 常用图的模板架构图、流程图、时序图 ├── diagrams/ # 实际绘制的图定义文件 └── render.py # 渲染入口脚本这里面的核心是 schema 层。我在 schema 里定义了节点、连线、分组、标注四种基本元素所有图都是这四种元素的组合。这个设计有点像给画图建立了一门“最小语言”语法越简单使用门槛越低出错的概率也越小。3. 核心细节解析与实操要点3.1 四种基本元素节点、连线、分组、标注一张技术图再复杂拆到底也就是这四种元素。节点表示事物连线表示关系分组表示归属或层级标注表示补充信息。我在项目里给这四种元素分别定了规范元素作用常见误区我的建议节点表达实体、步骤、状态框内文字太多信息过载节点文字控制在 6 个字以内细节放到标注里连线表达关系、流向、依赖线型混乱箭头方向歧义一个图里最多用两种线型实线表示强关系虚线表示弱关系分组表达系统边界、模块归属分组随意边界交叉分组之间不要嵌套超过两层边界用圆角矩形标注表达补充说明、约束、注解标注过多喧宾夺主标注统一靠右下角字色比正文浅一级有个细节很多人忽略节点框的形状是有语义的。矩形适合表达服务、组件、状态菱形适合表达判断平行四边形适合表达数据圆角矩形适合表达人的行为或外部系统。如果这些形状混用看图的人会下意识地去找形状里的隐含意义找不到就会困惑。3.2 布局规则为什么“自顶向下”永远最稳布局这件事早期我用自动布局算法发现算法排出来的图虽然交叉少但语义常常不对。后来我定了三条硬规则所有图的布局都优先遵守它们方向统一绝大多数图使用自顶向下的流向只有时间线类图才用自左向右。层级对齐属于同一逻辑层级的所有节点放在同一水平线上一眼就能看出分层。连线最短连线尽量走“直角最短路径”少用斜线更不要绕路。这三条规则看着简单实际执行之后图的清晰度提升非常明显。我做过一个小实验用同一组数据画同一张调用关系图随意布局的平均理解时间大约 40 秒按层级对齐布局的平均理解时间只需要 12 秒。差距就是这么悬殊。3.3 配色体系颜色是信息不是装饰很多图的问题是“每个模块一个颜色”结果整张图像个彩虹看完只记得“五颜六色”不知道重点在哪。diagram-design 里我把颜色严格分成四个职能主色核心业务模块全图只允许出现一次色相的强调。辅助色周边支撑模块使用主色的邻近色。中性色基础设施、通用组件用灰色系。语义色表示成功、告警、失败等状态只在状态类图中使用。我建议把颜色配置集中放在一个样式文件里而不是散落在每个图的定义中。这样调整视觉风格时只需要改一个文件全项目的图都会跟着变。这也是代码化方案对比手工绘图的一大优势。3.4 文字标注规范越少越好越短越好图里的文字是高频毁图因素。文字太多节点会变大布局会变拥挤文字太随意术语不统一看图的人会怀疑是不是两个不同的东西。我定了几条实操规范节点文字用短语而不是句子动词开头的保持一致比如“创建订单”“调用支付”不要一会儿名词一会儿动词。标注信息放到图的底部统一说明不要零零散散放在图的各个角落。术语必须和代码、文档里的术语完全一致宁可让文字长一点也不要为了短而发明新叫法。4. 实操过程与核心环节实现4.1 第一步先画一张“丑图”理清结构很多人一上来就直接开画这是最大的误区。我在实际项目里总结了一个“丑图先行”的方法拿一张白纸或者白板不追求美观只把信息结构画出来。这个阶段只回答三个问题有哪些关键实体实体之间是什么关系哪些实体属于同一个系统边界这张丑图不需要给别人看它是给自己理思路用的。通常画完丑图之后你会发现原来以为很清楚的结构其实有一两个模糊的地方比如某个模块到底是属于业务层还是支撑层某条依赖关系是单向还是双向。这些模糊点如果在草稿阶段不解决画到正式图里会加倍放大。4.2 第二步用结构化数据定义图结构理清之后就可以用数据来定义图了。这是 diagram-design 项目的核心环节。我通常先用一个轻量的格式来描述比如下面这个支付流程的简单示意diagram: title: 支付流程 type: flowchart nodes: - id: start label: 发起支付 shape: rounded - id: gateway label: 调用支付网关 shape: rect - id: check label: 校验签名 shape: diamond - id: save label: 保存记录 shape: rect - id: notify label: 发送通知 shape: rounded edges: - from: start to: gateway label: 请求 - from: gateway to: check label: 响应 - from: check to: save label: 通过 - from: check to: start label: 失败重试 - from: save to: notify groups: - id: external label: 外部系统 nodes: [gateway]这段数据里没有任何坐标信息只有纯粹的“内容”。我把这些问题想清楚了节点有哪些节点类型是什么连线从哪里到哪里分组包含哪些节点。剩下的布局、颜色、字体全部交给渲染层处理。4.3 第三步渲染与人工微调渲染这一步我封装了一个入口脚本把上面这种结构化定义翻译成绘图引擎的调用指令。整个过程不需要打开图形界面直接命令行跑一下就会在当前目录生成对应的图表文件。# render.py 的核心逻辑伪代码 def load_diagram(path): 读取图定义文件解析成内部数据结构 raw read_yaml(path) return parse_schema(raw) def layout(diagram): 基于层级规则计算节点坐标和连线路径 assign_layers(diagram.nodes, diagram.edges) generate_edge_paths(diagram.edges) detect_overlaps(diagram) def render(diagram, output_format): 按样式规范绘制并导出 apply_style(diagram, load_style(styles/base.yaml)) export(diagram, output_format) if __name__ __main__: path sys.argv[1] d load_diagram(path) layout(d) render(d, output_formatsvg)这个脚本本身很简单但有一个设计我花了不少心思布局完成之后会做一轮“重叠检测”。如果两个节点的文字区域发生重叠脚本会提示但不会自动改因为自动调整常常越调越乱。这时候需要人工介入给某个节点加一条“拖后一点”的提示或者干脆调整一下分组结构。实际经验是九成的情况不是因为缺一个拖拽功能而是前面的结构没定义好。4.4 一个完整的架构图示例我用一个常见的系统架构图来说明完整效果。假设要画一个订单系统的简化架构按照流程我先在草稿上明确了分层接入层、业务层、数据层、基础设施。然后定义节点和连线diagram: title: 订单系统架构 type: architecture groups: - id: gateway_layer label: 接入层 nodes: [api, auth] - id: biz_layer label: 业务层 nodes: [order_svc, payment_svc, stock_svc] - id: data_layer label: 数据层 nodes: [order_db, payment_db] - id: infra label: 基础设施 nodes: [mq, monitor] nodes: - id: api label: 网关 color: primary - id: auth label: 鉴权 color: primary - id: order_svc label: 订单服务 color: accent - id: payment_svc label: 支付服务 color: accent - id: stock_svc label: 库存服务 color: accent - id: order_db label: 订单库 color: neutral - id: payment_db label: 支付库 color: neutral - id: mq label: 消息队列 color: neutral - id: monitor label: 监控 color: neutral edges: - from: api to: order_svc - from: api to: auth - from: order_svc to: payment_svc - from: order_svc to: stock_svc - from: order_svc to: order_db - from: payment_svc to: payment_db - from: order_svc to: mq这张图的亮点在于“接入层”“业务层”这些分组本身就是信息不需要额外用文字解释主模块用主色支撑模块用中性色视觉顺序和业务流程一致。生成之后基本不需要手动调整。5. 常见问题与排查技巧实录5.1 布局乱成一团怎么办布局是最容易出问题的地方我见过的最典型情况是两层之间有十几条连线渲染出来交叉成蜘蛛网。排查思路分两步走。第一步检查连线的方向是否都是同向的如果有反向连线优先处理。反向连线常常意味着这个模块的依赖方向是反的值得警惕。第二步检查分组之间的连接跨组连线超过一定数量就要考虑是不是缺了一个中间层。如果这两个都没问题布局还是乱那多半是节点数量太多了。我有一条经验线单层节点数超过 7 个或者全图节点超过 25 个这张图就该拆了不要硬塞进一张图里。拆的思路不是简单分成多张图而是抽出一个“核心链路图”和若干“局部放大图”用一张总览图把它们串起来。注意拆分图不是偷懒是保护读者注意力。一张图超过 25 个节点不管布局多精致认知负担都会急剧上升。5.2 中文文字显示异常代码化方案渲染中文时最常遇到的问题就是文字变成方块或者乱码。这是因为渲染引擎默认字体里没有中文字形。解决方式很直接在样式配置里显式指定一个系统里存在的中文字体而不是依赖默认值。我习惯把字体配置也写进样式文件和颜色、线型放在一起style: font: family: Noto Sans CJK SC size: 14 code_size: 12这里有个容易踩的坑字体名字有时候需要写英文名有时候需要写系统中识别的本地化名称不同环境写法不一样。我的经验是先在命令行里去查一下系统当前可用的字体列表确认名字之后再去配置不要凭记忆填。改完字体别忘了重新生成一次有时候渲染进程有缓存需要先清理再跑。5.3 导出图片模糊不清图是要放到文档、PPT、网页里的导出格式选不对就会出现“放大就糊”的问题。我的建议非常明确只要是放到屏幕上看的图一律导出矢量格式只有需要打印或者给外部系统投递时才考虑位图格式。我在项目里把导出流程做成了双轨制默认导出矢量格式用于屏幕展示和后续编辑同时生成一份位图用于快速预览和发送。位图的分辨率建议至少 2 倍图也就是 2x 缩放否则在高清屏上就会出现边缘锯齿。5.4 多人协作时的图形冲突代码化方案的版本管理优势在多人协作时也会带来一个副产品合并冲突。两个人同时改同一张图的定义文件很容易出现节点 id 冲突、连线重复定义等问题。我的经验是两条第一节点 id 的命名要带模块前缀不要用 a、b、c 这种无意义的名字例如订单服务的节点就叫 order_svc一看就知道属于哪个模块。第二每个图文件保持单一职责一个人负责一个文件减少两个人同时编辑同一文件的概率。如果冲突真的发生了不要慌因为文本冲突是最好解决的。看一眼冲突标记保留正确的节点定义删掉重复的连线即可。这比两个人在可视化工具里同时编辑一个文件后保存的人把先保存的人全部改动覆盖掉要安全得多。5.5 图的“过期问题”如何根治最后说一个最容易被忽视的问题图会过期。代码改了图没改是团队文档里最常见的事故。diagram-design 给了我一个根治的思路把图定义和代码放在同一个仓库把图的更新纳入代码评审流程。谁改了模块结构谁就负责同步修改对应的图定义。更进一步对于某些可以自动生成的图比如模块依赖图、数据表关系图我直接用脚本扫描代码自动生成完全消灭手工维护。这个做法带来的收益非常大图和代码永远同步评审的人看到图就能校对代码结构代码的改动能直观地体现在图上。6. 实操心得与扩展方向这套 diagram-design 的方法我用到现在最深的体会是画图的瓶颈从来不是手而是脑子。结构想清楚了图就成功了一半。如果你之前画图总是觉得累、觉得乱不妨试试先把工具放一边拿张纸把信息结构理清楚再用结构化数据把它表达出来。你会发现以前半小时画一张图现在可能十分钟就搞定而且画完自己都挑不出毛病。最后分享一个小技巧不要追求“每张图都不同”。恰恰相反你应该追求“所有图都长得像”。统一的视觉风格、布局方向、配色体系会让团队里的所有图看起来像一个体系的产品读者看图时不需要重新学习理解速度会快很多。后续如果还想扩展可以考虑给这套方案加上一个“图级校验”环节在渲染前自动检查孤立节点、重复连线、未定义的引用把低级错误直接拦截在生成之前。这个方向我已经在实验了实测下来对团队协作的帮助非常明显。

相关新闻

如何用DiarizationLM-Gemma-4-E4B-v1批量修正ASR转写的说话人错标:端到端工作流详解

如何用DiarizationLM-Gemma-4-E4B-v1批量修正ASR转写的说话人错标:端到端工作流详解

人工智能大模型语音微调模型量化 【免费下载链接】DiarizationLM-Gemma-4-E4B-v1 项目地址: https://ai.gitcode.com/hf_mirrors/google/DiarizationLM-Gemma-4-E4B-v1 点击查看 免费下载 做完 ASR(自动语音识别) 说话人分离后,转…

2026/10/19 6:48:00 阅读更多 →
STM32单片机 定时器 编码器接口

STM32单片机 定时器 编码器接口

编码器接口测速,用于电机控制Encoder Interface 编码器接口编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度每…

2026/10/19 6:46:59 阅读更多 →
PWMI模式测频率占空比

PWMI模式测频率占空比

开启时钟GPIO时基单元输入捕获初始化部分配置两个IC通道同时捕获同一个引脚的模式//快捷将电路配置成PWMI标准的标准结构,只支持通道1、2不支持3、4 //只需要传入一个通道的函数,此函数同时会把另一个通道配置为相反的配置,实现PWMI模式 TIM_…

2026/10/19 6:46:58 阅读更多 →

最新新闻

H3-Base衍生方案深度解析:VDN-H3、FastH3、QuantFunc如何选

H3-Base衍生方案深度解析:VDN-H3、FastH3、QuantFunc如何选

1. H3-Base开源带来的机会:三个衍生方案到底解决了什么问题1.1 从"看得见"到"用得起":开源底座和衍生方案的关系先把这个话题梳理清楚。MiniMax H3-Base开源之后,视频生成圈子里最大的变化不是"又出了一个模型"…

2026/10/20 9:03:41 阅读更多 →
大模型微调实战:从数据准备到LoRA调参避坑指南

大模型微调实战:从数据准备到LoRA调参避坑指南

最近有个朋友问我,想做一个专门解读自家行业文档的AI助手,是不是得把某个开源模型从头训练一遍。他想得挺认真,连训练数据要攒多少、GPU要租几台都开始打听了。我赶紧拦了一句:你先停一下,你要的东西大概率不是“从头训…

2026/10/20 9:03:41 阅读更多 →
Arduino新手入门完全指南:从选型到第一个项目避坑实战

Arduino新手入门完全指南:从选型到第一个项目避坑实战

想认真把Arduino新手入门走通,光靠看示例代码是不够的。很多人第一次接触Arduino,都是先刷到一段灯光闪烁的视频,觉得“这也不难嘛”,结果板子到手,配好环境、插好线、点下上传,灯就是不亮,最后…

2026/10/20 9:03:41 阅读更多 →
大模型情感智能实战:从认知科学到提示词工程与评估体系

大模型情感智能实战:从认知科学到提示词工程与评估体系

大型语言模型中的情感智能:从认知科学到技术实践的深度探索这两年做大模型应用,最让我感慨的一个变化是:大家不再满足于让模型“说话正确”,而是开始要求它“说人话、懂人心”。所谓懂人心,指的就是情感智能&#xff0…

2026/10/20 9:03:40 阅读更多 →
Python数据脱敏实战:学生信息保护的完整方案

Python数据脱敏实战:学生信息保护的完整方案

说个我最近遇到的事。帮朋友整理一批学生模拟数据时,打开表格差点没愣住——身份证号、手机号、家庭住址、成绩,哪个字段拿出来都是能直接定位到个人的敏感信息。对方还很随意地说了句“反正就内部用用,没事”。结果没过几天,这份…

2026/10/20 9:03:40 阅读更多 →
CODE V数码相机镜头设计:从规格约束到公差分析全流程

CODE V数码相机镜头设计:从规格约束到公差分析全流程

简介:资源围绕CODE V软件设计数码相机镜头的完整流程展开,面向光学设计入门者及需要了解镜头规格、优化指标的工程师。文档从一台定焦VGA数码相机的设计规格出发,详细讲解了像面尺寸、像素大小、焦距、视场角等关键参数,并说明如何…

2026/10/20 9:02:37 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →