从零搭建代码评审自动化流水线:open-code-review 实战指南
1. 从零搭建一套代码评审自动化流水线我为什么盯上了 open-code-review第一次听到 open-code-review 这个词是在一个做后端的朋友群里。有人吐槽说团队里代码评审全靠人肉盯一个 PR 挂三天没人理合并之后线上炸了才发现问题。当时我就想代码评审这件事本质上是一个流程 工具 习惯三件套的问题光靠喊口号没用得有一套能落地的自动化机制。open-code-review 这个方向说白了就是把代码评审从靠人自觉变成靠系统驱动让每一次提交都经过一套可配置、可追溯、可度量的检查流程。我自己在几个项目里折腾过不同形态的评审方案从最早的纯人工 review到后来接入静态扫描、再到自己写脚本做增量检查踩过的坑不算少。open-code-review 吸引我的地方在于它不是一个具体的商业产品而是一类开放式的代码评审工程实践——你可以用开源工具拼装也可以自己写规则引擎核心是把评审这件事拆解成可自动化的环节。它解决的核心问题是评审标准不统一、评审过程不可追溯、评审效率随团队规模下降。适合谁来参考我觉得三类人最需要一是中小团队的技术负责人想用最低成本建立评审规范二是独立开发者一个人维护多个仓库需要自动化兜底三是刚接触工程化的开发者想理解一套评审流水线到底是怎么跑起来的。这篇文章我会把 open-code-review 这套东西从设计思路到落地细节完整拆一遍包括我实际用过的工具组合、参数配置、踩坑记录以及那些文档里不会写的经验。你不需要有很深的 DevOps 背景只要会基本的 Git 操作和一点点脚本能力就能跟着搭起来。2. 整体设计思路评审流水线到底该怎么拆2.1 为什么不能只靠人工评审先说一个我观察到的现实大部分团队的代码评审实际执行下来就是看两眼、点个 approve。不是大家不负责而是人工评审有几个天然瓶颈。第一是注意力有限一个 PR 改了 800 行评审人看到第 200 行就开始走神了第二是标准漂移今天 A 评审人觉得命名要驼峰明天 B 评审人觉得下划线也行同一个仓库风格越来越乱第三是不可度量你没法回答我们这个月评审发现了多少问题这种问题因为根本没记录。open-code-review 的思路是把评审拆成三层机器能查的交给机器机器查不了的交给清单清单之外的才靠人。这个分层很关键它决定了你后面所有工具选型和流程设计。我见过太多团队一上来就想搞全自动 AI 评审结果规则误报一堆最后大家直接把检查关掉了。分层的好处是每一层职责清晰出问题也好定位。2.2 三层评审模型的具体划分我把这三层具体说一下方便你对照自己的项目。第一层确定性检查机器全自动。这一层处理的是有明确对错的问题比如代码格式、语法错误、明显的空指针风险、依赖漏洞、敏感信息硬编码。这些用静态扫描工具就能搞定不需要人参与检查不通过直接卡住合并。这一层的核心指标是零误报因为一旦误报开发者就会失去信任。第二层规范性检查清单驱动。这一层处理的是有约定但需要判断的问题比如函数是否过长、注释是否完整、提交信息是否符合规范、测试覆盖率是否达标。这些可以用规则引擎配置阈值超了就提示但不一定卡死。这一层的关键是阈值可调不同项目阶段标准不一样。第三层逻辑性评审人工 辅助。这一层处理的是业务逻辑对不对、设计合不合理的问题机器很难判断。但 open-code-review 的价值在于它能把前两层的结果汇总成一份评审清单让评审人带着机器已经查过这些了你重点看逻辑的心态去 review效率会高很多。2.3 工具选型的取舍逻辑工具选型这块我踩过最大的坑就是贪多。一开始我恨不得把市面上所有扫描工具都接进去结果 CI 跑一次要十几分钟开发者怨声载道。后来我总结了一个原则每个环节只选一个主力工具能合并的检查合并到一个工具里。具体来说格式和基础语法检查用语言自带的 linter 就够了不用额外引入安全扫描选一个覆盖面广的就行不用同时上三个依赖检查用语言生态里的标准工具。我实测下来一个中等规模的项目评审流水线从触发到出结果控制在 3 分钟以内是比较舒服的超过 5 分钟开发者就会开始绕过它。提示工具选型时优先考虑能否输出机器可读的结果比如 JSON 或 SARIF 格式。这决定了你后面能不能把多个工具的结果汇总成一份统一报告否则每个工具一个输出格式汇总起来会非常痛苦。2.4 流水线触发的时机设计触发时机这个细节很多人忽略但它直接影响体验。我的建议是分两级触发提交时做轻量检查合并前做完整检查。提交时只跑格式和语法这种秒级检查给开发者即时反馈合并前跑完整的安全扫描和覆盖率检查作为合并门禁。这样既保证了反馈速度又保证了合并质量。还有一个细节是增量检查。全量扫描一个老仓库可能要几分钟但只扫描本次改动涉及的文件通常几秒钟就够。open-code-review 的实践中增量检查是提升体验的关键手段后面我会讲具体怎么实现。3. 核心细节解析每个环节的关键参数与实操要点3.1 静态扫描规则的配置要点静态扫描是评审流水线的地基但配置不好就是灾难。我见过一个项目扫描规则开了 500 多条每次提交报 200 个 warning开发者直接麻木了。我的经验是新项目从 20 条核心规则起步老项目先只开 error 级别。核心规则怎么选我一般按这个优先级来空指针/未定义引用、资源未释放、明显的逻辑错误比如恒真恒假条件、安全漏洞注入类、硬编码密钥。这几类问题是真正会导致线上故障的必须卡死。至于命名规范、代码风格这类放到第二层用清单提示就行不要卡合并。参数配置上有个关键点严重级别要分级。我通常分三档——blocker必须修否则不能合并、warning提示允许合并但记录、info仅记录。这个分级要写进配置文件里而不是靠工具默认。下面是一个配置结构的示例rules: - id: null-pointer-check level: blocker paths: [src/**/*.java] - id: unused-import level: warning paths: [src/**/*.java] - id: naming-convention level: info paths: [src/**/*.java]这个结构的好处是规则、级别、作用路径一目了然后面要调整直接改配置不用动代码。3.2 评审清单的模板设计第二层的评审清单我建议用 Markdown 模板 自动填充的方式来做。模板里固定几个维度变更概述、影响范围、测试情况、风险点、回滚方案。每次提 PR 时系统自动把静态扫描结果填进去开发者补充人工部分。这里有个实操技巧清单不要超过 8 项。我试过 15 项的清单结果大家填的时候全是无已测试形同虚设。8 项以内每项都是真正需要思考的填写质量会高很多。我常用的清单长这样检查项填写要求是否必填变更目的一句话说明为什么改是影响模块列出受影响的模块是测试方式说明如何验证是风险点可能出问题的地方是回滚方案出问题怎么退是关联需求关联的需求编号否性能影响是否有性能变化否兼容性是否影响老接口否3.3 增量检查的实现原理增量检查是提升评审体验的核心。原理其实不复杂拿到本次提交的 diff提取出改动的文件列表和行号范围只对这些范围跑检查。难点在于如何准确提取改动范围以及如何处理跨文件的依赖。提取改动范围用 Git 命令就能做到git diff --name-only HEAD~1 HEAD git diff --unified0 HEAD~1 HEAD第一条拿到改动的文件列表第二条拿到具体的改动行。然后把这些信息传给扫描工具只扫描这些文件。跨文件依赖的处理要谨慎比如你改了一个接口定义调用方可能没改这种问题增量检查发现不了。我的做法是增量检查用于快速反馈全量检查作为合并前的最终门禁两者结合。注意增量检查有个坑就是重命名文件。Git 有时会把重命名识别成删除 新增导致检查范围出错。建议在 diff 命令里加上--find-renames参数让 Git 正确识别重命名。3.4 评审结果的汇总与展示多个工具跑完结果怎么汇总我的方案是统一转成一种中间格式再渲染成报告。SARIF 是个不错的选择很多扫描工具都支持输出这个格式。汇总之后报告要分三块展示必须修复的问题、建议修复的问题、仅记录的问题。这样评审人一眼就能看到重点。报告展示的位置也有讲究。我一般放两个地方一是 PR 的评论里自动贴一份摘要二是流水线的产物里存一份完整报告。摘要要短只列 blocker 和 warning 的数量及前几条完整报告给需要深挖的人看。这个设计能兼顾快速浏览和深入排查两种需求。4. 实操过程从零搭一套可运行的评审流水线4.1 环境准备与仓库初始化假设你有一个 Git 仓库现在要给它加上评审流水线。第一步是准备环境。我用的是一台普通的 Linux 服务器装了 Git、Docker 和基本的构建工具。Docker 是为了跑扫描工具避免污染宿主机环境。仓库初始化这块我建议在根目录建一个.review目录专门放评审相关的配置mkdir -p .review/rules mkdir -p .review/templates touch .review/config.yaml.review/config.yaml是主配置.review/rules放规则文件.review/templates放清单模板。这个结构清晰后面维护起来方便。初始化完之后先别急着接工具把配置文件的骨架写好。4.2 配置静态扫描工具接下来配置静态扫描。我以 Java 项目为例用语言生态里的标准扫描工具。安装方式用 Docker 拉镜像避免版本问题docker pull scanner-image:latest然后写一个扫描脚本.review/scan.sh核心逻辑是接收改动文件列表只扫描这些文件#!/bin/bash CHANGED_FILES$(git diff --name-only HEAD~1 HEAD -- *.java) if [ -z $CHANGED_FILES ]; then echo no java files changed exit 0 fi docker run --rm -v $(pwd):/src scanner-image:latest \ --rules /src/.review/rules \ --files $CHANGED_FILES \ --output /src/.review/report.json这个脚本的关键点是--files参数只传改动文件实现增量扫描。实测下来一个 5000 行的项目全量扫描要 40 秒增量扫描只要 3 秒。4.3 接入提交钩子与流水线扫描脚本写好了接下来要让它自动触发。我分两个入口本地提交钩子和服务端流水线。本地钩子用 Git 的 pre-push 钩子推送前跑一次轻量检查给开发者即时反馈#!/bin/bash # .git/hooks/pre-push bash .review/scan.sh if [ $? -ne 0 ]; then echo 扫描未通过请修复后再推送 exit 1 fi服务端流水线用 CI 工具配置在合并请求创建时触发完整检查。这里要注意服务端的检查结果要回写到 PR 评论里否则开发者看不到。回写的方式各 CI 工具不同一般是调用 API 发评论。4.4 评审清单的自动填充清单自动填充这块我写了一个小脚本在 PR 创建时把扫描结果填进模板import json with open(.review/report.json) as f: report json.load(f) blockers [r for r in report[results] if r[level] blocker] warnings [r for r in report[results] if r[level] warning] template f ## 变更概述 请补充 ## 自动检查结果 - 必须修复{len(blockers)} 项 - 建议修复{len(warnings)} 项 ## 影响模块 请补充 ## 测试方式 请补充 print(template)这个脚本输出的内容直接作为 PR 描述的初始内容。开发者在此基础上补充人工部分省去了手动整理扫描结果的麻烦。4.5 完整流程的串联与验证所有环节准备好之后串起来跑一遍。流程是这样的开发者本地提交 → pre-push 钩子跑轻量扫描 → 推送成功 → 创建 PR → CI 触发完整扫描 → 结果回写 PR 评论 → 清单自动填充 → 评审人 review → 合并。验证的时候我建议故意制造几个问题看看流水线能不能抓到。比如故意留一个未使用的变量、故意硬编码一个密钥、故意让测试覆盖率下降。实测下来这套流程能抓到 80% 以上的常见问题剩下的 20% 靠人工评审兜底。提示第一次跑完整流程时建议把 blocker 级别的规则先设成 warning观察一周误报情况确认没问题再改成 blocker。直接上 blocker 容易因为误报导致流程被绕过。5. 常见问题与排查技巧实录5.1 扫描速度慢怎么办扫描速度慢是最常见的问题。我排查下来原因通常有三个一是全量扫描没做增量二是扫描工具本身太重三是并发度不够。对应的解决办法增量扫描前面讲过了工具太重的话换轻量级的替代品或者只开核心规则并发度不够的话把多个扫描任务并行跑。我实测过一个优化案例原来串行跑三个扫描工具要 90 秒改成并行之后降到 35 秒。并行的实现方式在 CI 里配置多个 job 同时跑最后汇总结果。5.2 误报太多导致流程被绕过误报是评审流水线的头号杀手。我见过最夸张的一个项目扫描出 300 个 warning开发者直接无视。解决误报我的经验是三步走先降级、再排除、后调优。先降级是把误报的规则从 blocker 降到 warning再排除是把确认无问题的文件或规则加入白名单后调优是调整规则的参数让它更贴合项目实际。白名单的配置要谨慎不能随便加否则等于把规则关了。我的做法是白名单必须写理由并且定期 review看看能不能去掉。5.3 评审清单流于形式清单流于形式根本原因是填写成本高于收益。解决办法有两个一是自动填充能自动的部分减少人工填写量二是把清单和实际评审挂钩比如评审人必须逐项确认才能 approve。我试过在 PR 模板里加一个 checkbox 列表评审人必须全部勾选才能合并效果比纯文字清单好很多。5.4 常见问题速查表问题现象可能原因排查方向解决办法扫描超时全量扫描或工具过重看扫描日志的文件数改增量扫描换轻量工具误报过多规则太严或不适配统计误报规则分布降级、白名单、调参流程被绕过检查太慢或误报多看开发者反馈优化速度减少误报清单没人填填写成本高看 PR 描述质量自动填充加必填校验结果看不到回写失败看 CI 日志检查 API 权限和格式5.5 几个文档里不会写的避坑经验第一个坑不要在 pre-commit 钩子里跑重检查。pre-commit 是每次提交都触发跑重检查会让提交变得极慢开发者会直接--no-verify绕过。重检查放 pre-push 或 CI。第二个坑扫描工具的版本要锁定。我有一次没锁版本工具升级后规则变了一夜之间多出 50 个 warning团队以为代码出了大问题。后来所有工具都用固定版本号。第三个坑报告要存档。评审结果不只是给当前 PR 看的后面复盘、审计都要用。我一般把报告存到对象存储里按日期和 PR 编号归档。第四个坑规则要定期 review。项目在演进半年前合适的规则现在可能不合适了。我一般每季度 review 一次规则该加的加该删的删。6. 评审流水线的度量与持续优化6.1 该度量哪些指标流水线跑起来之后得知道它到底有没有用。我一般盯四个指标拦截率扫描发现的问题占总问题的比例、误报率误报数占总报警数的比例、平均评审时长从 PR 创建到合并的时间、绕过率开发者绕过检查的比例。这四个指标能反映流水线的健康度。拦截率高说明规则有效误报率低说明规则精准评审时长短说明流程顺畅绕过率低说明开发者认可。我一般把拦截率目标定在 60% 以上误报率控制在 10% 以内绕过率控制在 5% 以内。6.2 根据数据调整规则数据出来之后要针对性调整。误报率高的规则要么调参要么删拦截率低的规则看看是不是太宽松评审时长突然变长看看是不是某个环节卡住了。我一般每月做一次数据分析每季度做一次规则大调整。调整的时候要注意不要一次改太多。一次改十几条规则出了问题很难定位是哪条引起的。我一般一次改 3 到 5 条观察一周再改下一批。6.3 让评审文化真正落地工具只是手段最终还是要落到文化上。我的经验是让开发者感受到评审是在帮他们而不是在卡他们。具体做法扫描发现的问题给出明确的修复建议而不是只报错评审通过的 PR给个正向反馈定期分享评审发现的典型案例让大家知道这套东西真的在防问题。我在实际项目里推这套流程的时候最开始阻力很大大家觉得是额外负担。后来我把扫描速度优化到 3 秒以内误报降到 5% 以下慢慢就没人抱怨了。再后来有开发者主动说这个检查帮我抓到一个空指针不然上线就炸了这时候流程才算真正落地。最后再分享一个小技巧把评审流水线的配置也纳入版本管理。规则、模板、脚本都放在仓库里谁改了什么一目了然。这样既方便追溯也方便新项目直接复用。我现在的做法是新项目初始化时直接把老项目的.review目录拷过去改改路径就能用省了大量重复配置的时间。

相关新闻

ERP委外入库按大单位录入:计量单位组与换算率配置全解析

ERP委外入库按大单位录入:计量单位组与换算率配置全解析

1. 问题背景:为什么大单位录入会让很多人卡壳 先说下我遇到的场景。某次做项目支持的时候,生产部门提了个问题:委外加工回来的产成品,仓管员入库时想按“箱”录入,但系统里死活只能按基本单位“件”填数。比如一张委外…

2026/10/12 11:20:16 阅读更多 →
联邦学习如何赋能端侧唤醒词识别:从模型设计到工程落地

联邦学习如何赋能端侧唤醒词识别:从模型设计到工程落地

1. 唤醒词识别与联邦学习是怎么凑到一起的如果你的手机语音助手一直在本地监听“唤醒词”,那么从某种意义上说,全球用户每天都在产生海量敏感语音数据,只不过这些数据的绝大部分都沉睡在各自设备里。唤醒词识别(Keyword Spotting&…

2026/10/12 11:19:15 阅读更多 →
QOwnNotes Homepage 书签建议 API 接入指南:为 Homepage 搜索框提供本地书签联想

QOwnNotes Homepage 书签建议 API 接入指南:为 Homepage 搜索框提供本地书签联想

桌面应用 【免费下载链接】QOwnNotes QOwnNotes is a plain-text file notepad and todo-list manager with Markdown support and Nextcloud / ownCloud integration. 项目地址: https://gitcode.com/gh_mirrors/qo/QOwnNotes 点击查看 免费下载 QOwnNotes 内置了…

2026/10/12 11:19:15 阅读更多 →

最新新闻

机器学习最小可行知识链:从公式到可调试代码的完整实践

机器学习最小可行知识链:从公式到可调试代码的完整实践

简介:本资源是邹博主讲的《机器学习全方位解析:从基础到实践》配套教学包,面向零基础入门者与希望系统夯实理论与工程能力的学习者,解决机器学习概念抽象、代码实践脱节、算法调优无从下手等核心痛点。压缩包共613个文件&#xff…

2026/10/12 13:00:09 阅读更多 →
Harbor v2.13.1 ARM64离线部署实战:内网镜像仓库搭建与避坑指南

Harbor v2.13.1 ARM64离线部署实战:内网镜像仓库搭建与避坑指南

简介:本资源为 Harbor 最新 v2.13.1 的 ARM64 架构离线安装包,面向在 ARM64 服务器或 Kubernetes 集群上部署私有镜像仓库的运维与开发人员,解决国产化平台、信创环境及边缘节点无法直接拉取官方 x86 安装包的问题。压缩包共 6 个文件&#x…

2026/10/12 13:00:09 阅读更多 →
物联网平台二次开发选型指南:架构边界、扩展点与实战避坑

物联网平台二次开发选型指南:架构边界、扩展点与实战避坑

1. 为什么“适合二开”才是物联网平台选型的硬指标做物联网平台选型这件事,我踩过不少坑。早年做某智慧园区项目,技术评审时大家盯着功能清单看——设备接入、规则引擎、数据大屏、告警中心,列表很丰满,厂商演示也很流畅。结果签完…

2026/10/12 13:00:09 阅读更多 →
批处理驱动Matlab实现参数自动扫描:原理、传参与排错指南

批处理驱动Matlab实现参数自动扫描:原理、传参与排错指南

说实话,用批处理去反复跑Matlab这事儿,我最早是在一次大规模参数寻优中被逼出来的。那时候手里有一堆实验数据要拟合,模型参数有四五种组合方式,每组参数跑一遍得几十秒,加起来几百个组合,手动改一个跑一个…

2026/10/12 13:00:08 阅读更多 →
PyTorch新手必学:ResNet18从原理到手写实现详解

PyTorch新手必学:ResNet18从原理到手写实现详解

1. 项目概述:为什么ResNet18是PyTorch新手绕不开的“第一座桥”如果你刚打开Jupyter Notebook,敲下import torch,接着想跑一个真正能分类图像的模型——不是MNIST手写数字那种玩具级任务,而是能在CIFAR-10上稳定达到92%准确率、结…

2026/10/12 13:00:08 阅读更多 →
LCA最近公共祖先算法详解:倍增法、Tarjan与树链剖分

LCA最近公共祖先算法详解:倍增法、Tarjan与树链剖分

1. 从一道面试题说起:为什么LCA值得花时间搞透第一次接触LCA是在刷题的时候,题目很直白:给一棵树,多次询问两个节点的最近公共祖先。当时我的第一反应是暴力——两个节点分别往上走,标记走过的路径,第一个相…

2026/10/12 12:59:08 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →