uniapp小程序AppSecret泄漏排查与修复:从拒审到过审的完整实战
提交审核被拒这种事做过小程序的人多少都经历过几回。但如果你收到的拒审理由是“代码中存在AppSecret敏感信息存在泄漏风险”那问题就比样式错位、功能不达标严重多了——这属于安全合规类问题不彻底处理干净你改十次也是白改。我这次的项目是一个基于uniapp开发的微信小程序平时开发、预览、真机调试一切正常结果一到提审就被打回来拒审意见原话大意就是检测到AppSecret存在泄漏的安全风险。一开始我还以为是误报结果把代码翻了个底朝天冷汗直接下来了——AppSecret确实就明晃晃地躺在请求封装的配置文件里等于把自家大门的钥匙挂在了门口公告栏上。这篇文章把整个排查、修复、再提审的完整过程梳理一遍包括uniapp项目里AppSecret最常见的藏身位置、背后的泄漏机制、根治方案和避坑清单给同样被这个问题卡住的开发者一份能直接抄作业的参考。1. 先搞清楚AppSecret到底是什么为什么小程序代码里不能有它1.1 用银行卡来理解AppSecret的权限范围AppSecret是微信小程序应用体系里的核心凭证。AppID是公开的相当于银行卡号AppSecret则是取款密码。微信小程序后台在生成AppID时会同步生成一个AppSecret它专门用于调用那些需要身份验证的“服务端接口”。这些接口中最为关键的就是获取access_token的接口GET https://api.weixin.qq.com/cgi-bin/token?grant_typeclient_credentialappidAPPIDsecretAPPSECRETaccess_token是一个有效期为2小时的全局唯一调用凭证。有了它就可以调用一系列高权限操作给用户发送订阅消息、换取用户手机号、生成小程序码、管理用户身份数据等等。换句话说一旦AppSecret泄漏别人就能替你的小程序执行这些敏感操作。如果小程序接入了付费能力比如短信发送、订单状态通知、个人敏感数据交换那损失就是直接且现实的。这里要额外敲一个重点access_token是“全局唯一”的意味着同一个小程序在同一时间只能存在一个有效access_token。别人用你的AppSecret抢先获取了access_token你的后端再去获取时微信会直接把旧的token作废导致你正在跑的定时任务、消息推送、数据同步全部“静默失败”。这种故障最难排查因为代码本身没有问题问题出在密钥已经被别人拿走了。1.2 小程序前端是一个“透明盒子”很多有跨端开发经验的程序员容易下意识地把后端Web项目的习惯带进来。Web项目的服务端代码部署在私有服务器上密钥只要不提交进代码仓库就能保守秘密。但微信小程序完全不一样它最终打包出来的代码包是原封不动运行在用户手机上的。不管你是用uniapp还是原生小程序写的不管你有没有做压缩混淆用户只要把代码包抓下来用逆向工具解包里面的JS逻辑、静态资源、配置文件全都看得一清二楚。更不用说微信审核系统本身就能直接读取你的代码包做静态扫描。所以任何写在小程序前端代码里的AppSecret本质上就是公开的不存在“藏得深就没人发现”这种侥幸。1.3 审核系统是怎么发现AppSecret的从我的亲历和观察来看微信审核对AppSecret的检测至少分两层第一层是自动化的静态扫描。审核系统会扫描整个代码包匹配常见密钥形态特征。比如32位十六进制字符串、以secret或appsecret命名的变量、请求URL里带有secret参数。如果你把AppSecret赋值给一个名叫appSecret的变量基本必中。第二层是人工复核。如果你的小程序调用了敏感接口例如获取用户手机号、发送订阅消息审核人员会进一步检查代码流程确认这些操作是否真正由服务端发起。如果发现前端直接请求微信API的痕迹那就不只是密钥泄漏的问题还会附加一个“不合规调用”的判定。需要特别注意的是检测范围不只覆盖JS代码也包括上传的所有静态文件、页面里存放的JSON配置、甚至被注释掉的老代码。那些觉得“我写成注释应该没事”的可以醒醒了整个包都会被扫到。2. 逐个排查uniapp项目里AppSecret最容易“漏”在哪2.1 藏在全局配置文件里的重灾区uniapp项目的目录结构里人最容易图省事的就是全局配置文件。我这次项目里的泄漏点就在utils/config.js代码大概是这个样子export default { baseUrl: https://api.example.com, appId: wx1234..., appSecret: a1b2c3d4e5f6... }写的时候逻辑很顺全局配置放一份后面任何模块引用都方便。但问题在于小程序前端代码不存在“编译时剥离”的说法config.js最终会被原样打包进小程序代码包里。类似的坑还包括写在App.vue的globalData里写在main.js的process.env里注意uniapp的process.env最终是以纯文本形式嵌入到前端源码的并不是你认为的“运行环境变量”写在公共样式环绕的doc注释里虽然不是可运行代码但打包后依然存在写在manifest.json的扩展配置里那个文件同样会被打包2.2 请求封装里的“一键带参”另一个高发场景是请求库封装。uniapp开发里大家习惯把uni.request二次封装统一加header、统一处理状态码。有些开发者图省事在公共请求方法里直接把appSecret拼到header或query里觉得“每次请求走统一入口后端验签方便”。uni.request({ url: this.baseUrl /api/data, header: { X-App-Secret: a1b2c3d4... } })这种做法在小程序审核看来是典型的高危特征。且不说安全性从设计上讲给普通业务请求无条件附带AppSecret本身就是架构偷懒的表现。正确的验签应放在自己的服务端前端只使用后端签发、可定期轮换的业务token就够了。2.3 容易被忽略的角落注释、老代码、静态资源和调试脚本这是我自己踩过的第二道坑翻查代码时发现老版本的项目里曾在某个页面脚本中为了快速联调把完整带AppSecret的URL写在注释里。后来功能重写代码删了注释没删。提审时扫描器照样识别到了这个字符串。还有几种情况你最好也自查一遍static目录下的json、txt文件。有人为了方便把接口文档直接存进小程序包文档里截了AppSecret全量值。测试阶段的临时脚本。比如云函数测试代码、mock工具里写死的密钥。从别人项目拷贝来的公共模块可能带着别人的AppSecret。Git历史分支。这个不在小程序包内但如果团队协同平台检测到历史提交里有明文密钥也会触发安全警报甚至影响关联账号的整体信誉度。2.4 开发版、体验版与审核版都能查到很多人有个错误认知只有正式版才会被检查开发版和体验版里藏着密钥没事反正是内部用。但微信审核的逻辑是你点击“提交审核”时系统基于你上传到微信服务器的那个版本做代码质量分析。如果你为了方便把带密钥的版本上传成体验版再从这个体验版“提交审核”检测结果就是一样的。反过来说有人会担心“我项目里没写AppSecret但调用了微信的某个接口会不会被误伤”。这里要理清问题不在于你是否调用微信接口而在于代码包中是否出现了明文密钥。服务端调用微信接口是再正常不过的事情前端代码里只有业务逻辑就不会触发检测。3. 根治方案把AppSecret彻底移出前端代码3.1 思路内核后端中转是唯一正确姿势要把AppSecret从前端代码中移除核心原则只有一句话凡是需要AppSecret的操作必须在一个不受小程序用户控制的环节执行。这个环节可以是自己的服务器、第三方云函数也可以是小程序云开发环境。前端唯一允许保留的是AppID——这本来就是公开标识。所有以AppSecret为凭据的微信服务端接口调用都应该由服务端完成。这也是我在文档中反复强调的微信小程序的代码中不应存在appsecret敏感信息不是“尽量不写”而是“一处都不能写”。3.2 方案一自建后端中转如果你已经有一台自己的后端服务器这是最自然的选择。改造思路分两步。第一步新增登录接口。前端在小程序里执行uni.login拿到临时code把code发给自己的后端// 前端uniapp代码 uni.login({ provider: weixin, success: function(loginRes) { uni.request({ url: https://api.example.com/api/wx/login, method: POST, data: { code: loginRes.code }, success: function(res) { uni.setStorageSync(token, res.data.token) } }) } })第二步后端拿着code和AppSecret去微信换session_key与openid// 后端服务代码示例Node.js const https require(https) function code2Session(code) { const url https://api.weixin.qq.com/sns/jscode2session?appid${APPID}secret${APPSECRET}js_code${code}grant_typeauthorization_code return new Promise((resolve, reject) { https.get(url, res { let data res.on(data, chunk (data chunk)) res.on(end, () resolve(JSON.parse(data))) }).on(error, reject) }) }AppSecret存放后端的环境变量或密钥管理服务中Git仓库里只留一个占位符。这样前端代码包里就再也没有任何密钥痕迹了。还有个细节后端获取access_token同样要注意缓存。微信的access_token有效期是2小时而且有调用频率限制建议在后端做内存缓存或Redis缓存临近过期再刷新。如果每次都临时请求既慢又容易触发限流。3.3 方案二uniCloud云函数uniapp项目如果不想自建服务器可以直接用uniCloud。云函数天然运行在服务端把AppSecret存在云函数的环境变量里前端调用云函数由云函数去请求微信接口。// uniCloud云函数内读取环境变量 const appSecret process.env.WX_APPSECRET // 云函数请求微信接口获取session_key const res await uniCloud.httpclient.request( https://api.weixin.qq.com/sns/jscode2session, { method: GET, data: { appid: process.env.WX_APPID, secret: appSecret, js_code: code, grant_type: authorization_code }, dataType: json } )用uniCloud的好处在于云函数调用api.weixin.qq.com不经过小程序的request域名白名单体系省掉了自建服务器必须的HTTPS域名配置和备案流程。前端只需要uniCloud.callFunction链路非常短。3.4 方案三微信云开发如果团队希望把整个后端都部署在微信生态内可以选用微信云开发。它自带云函数、云数据库、云存储在云函数中配置AppSecret同样可以安全地代前端完成所有敏感调用。这个方案的优点是与小程序鉴权体系天然打通缺点是它和uniapp是两套体系需要在uniapp代码里配合wx.cloud初始化跨框架时有少量适配成本。3.5 三个方案怎么选维度自建后端uniCloud微信云开发适用团队已有服务端团队uniapp前端团队想用微信生态全家桶域名要求需要HTTPS合法域名不需要不需要AppSecret存放服务器环境变量云函数环境变量云函数环境变量运维成本较高较低较低与uniapp集成度一般最高中需要注意的点密钥管理依赖自身云函数代码同样不能提交密钥云函数代码提交时也要扫描无论选哪套方案最终目标一致小程序代码包里不再出现AppSecret所有敏感操作都发生在服务端。4. 实操全记录从定位泄漏点到修复再提审的完整流程4.1 第一步全局扫描把所有泄漏点揪出来修复前先做一次全项目扫描把AppSecret的所有藏身位置都找出来不要补了一个漏了三个。我这里的做法是三步走。第一步文本搜索。在HBuilderX里用全项目搜索功能关键词至少包括appSecret、appsecret、client_secret、apisecret。同时把你AppSecret字符串的前8位拿出来搜一遍比如a1b2c3d4。这两步不重复字符串搜索能抓住变量名和赋值位置密钥片段搜索能抓住那些写死但没有统一命名的位置。第二步静态资源排查。检查static目录下所有非代码文件。把json、txt、md这类文件全部打开过一遍有密钥的直接删除或替换。这一步很费时间但非常值得因为扫描器对静态资源一样不放过。第三步Git历史检查。如果项目已经用Git管理AppSecret曾经出现在历史提交记录里就要特别小心。即使当前代码删掉了老版本仍然可能被恢复。有条件的话对仓库做一次彻底的历史清理或者直接重置密钥。4.2 第二步代码改造删除、替换、外移找到泄漏点之后改造原则是“删除、替换、外移”三连删除把前端代码里直接出现的AppSecret字符串全部删掉。替换如果业务上确实需要前端做身份识别换成后端签发的业务token比如JWT或简单的随机token。外移AppSecret只出现在服务端的环境变量中前端不保留任何副本。改造完用一个很土但很有效的自查方法在编辑器里全局搜索AppSecret的完整值结果必须为0。如果还能搜到哪怕一个字符说明仍有泄漏点。4.3 第三步后端接口设计与联调如果选择自建后端方案后端至少需要提供两个接口接口一登录换token。入参是code内部用AppSecret调微信code2session接口换取openid再生成自己的登录态返回给前端。接口二业务接口统一走token鉴权。前端每次请求带上后端签发的token后端自行校验不在前端放任何与微信密钥相关的东西。联调时有一个细节需要记住本地开发阶段微信开发者工具可以勾选“不校验合法域名”但真机预览和提审阶段域名必须已经配置且完成备案。如果使用第三方测试环境也会遇到同样的问题。这里还有一个小坑联调成功并不代表提审一定能过。如果后端接口没有对来源请求做合理限制审核人员在人工复核阶段发现前端存在异常的解密逻辑或过度暴露的数据接口同样可能要求进一步整改。所以改造不只是删密钥更是借此机会梳理一整条安全链路。4.4 第四步重置AppSecret更新服务端重新提审代码改完后一定要去微信公众平台的开发设置里把原来的AppSecret重置一遍。这一步不是走形式而是基于一个实际考虑既然旧密钥已经在代码里暴露过你无法确认它是否已被第三方抓取使用。重置后旧密钥立即失效所有基于旧密钥获取的access_token也全部作废。重置完记得同步更新服务端配置。这里最容易出的尴尬情况是前端代码清干净了后端也改完了结果忘了在服务端更新新密钥导致正式环境登录接口全部报错。建议按这个顺序操作先在公众平台重置立刻更新服务端配置再验证一遍登录和业务接口最后才提交代码审核。重新提交审核时建议在审核备注里简单说明一句已按安全要求将AppSecret迁移至服务端前端代码中不再存储任何敏感信息。审核系统虽然主要靠自动检测但这句话能减少部分人工复核环节的来回拉锯。5. 问题排查与避坑技巧速查5.1 改完代码还是被拒先检查这几处如果已经按上面的方式清理干净再次提审仍然提示AppSecret泄漏别急着怀疑审核误判按顺序排查提审版本没更新。本地改完了但“提交审核”时选中的还是上一次上传的旧版本。一定要在开发者工具中重新上传新版本再用新版本号提审。静态资源遗漏。static目录下可能还有你没翻到的json、txt文件把密钥包了进去。最保险的做法是把代码包下载解压人工再搜一遍。第三方组件或插件残留。项目引入了第三方组件组件内部可能自带密钥。全局搜索时范围要包含整个项目以及已安装的依赖包有时候泄漏点不在自己写的代码里。多端条件编译误带。uniapp项目经常同时编译为小程序、App、H5。H5端配置了密钥本身不影响小程序审核但如果被条件编译误带进小程序包就会被一起扫到。5.2 AppID和AppSecret别再搞混新手最容易混淆这两个概念。AppID是公开的而且必须写在代码里它是小程序的唯一标识微信后台靠它区分你的小程序。AppSecret则完全不同权限大得多只应该存在于服务端。一个比较生活化的类比AppID是门牌号可以印在名片上AppSecret是你家防盗门的钥匙只能放在自己口袋里。门牌号被大家知道没什么钥匙被复制了意味着别人随时能开门进来。5.3 预防机制让敏感信息在源头就断掉最后分享几条团队规范层面的预防建议尤其适合正在带项目的新人团队建立环境变量模板。项目根目录放一份.env.example里面用占位符代替真实密钥。真实密钥只存在于本地或服务端配置中该文件必须加入.gitignore。启用代码提交防护。在Git钩子或CI流程中加一条检查脚本一旦提交内容匹配到密钥特征字符串直接阻塞提交。这比靠人记忆靠谱太多。定期轮换密钥。微信公众平台的AppSecret支持重置建议每隔半年或每逢团队中有成员离职主动重置一次。使用密钥管理工具。团队规模稍大一些就不要把密钥放在明文环境变量里了云厂商的密钥管理服务或内部Vault都是正规做法。写进提审排查清单。每次提审前清单里固定增加一项“全局搜索AppSecret”。这个动作只要十秒钟但能省下数周审核等待的代价。5.4 最后再分享一个多端项目的小技巧uniapp项目往往同时维护多端代码同一套业务逻辑会编译成微信小程序、支付宝小程序、H5甚至App。正因为如此敏感信息泄漏的排查范围会比原生开发更大。你以为只改了微信小程序端的代码其实其他端分支里的注释、配置也可能会在条件编译时混进包内。所以在做uniapp的多端项目时我建议把AppSecret扫描做成一个持续性的习惯每次发版前都扫一遍而不是等审核打回再来处理。安全这件事前置永远比补救省心。你要是现在项目里还躺着明文密钥别犹豫今天就把“不吃”的代码翻出来尽早清理干净。

相关新闻

计算机中的数学笔记#MCS #Mathematics #Maths #Yibo #翊博 #翊博在这里 #菲尔兹奖 #yibohere

计算机中的数学笔记#MCS #Mathematics #Maths #Yibo #翊博 #翊博在这里 #菲尔兹奖 #yibohere

#MCS #Mathematics #Maths #Yibo #翊博 #翊博在这里 #菲尔兹奖 #yibohere高等数学/线性代数概率论 精简笔记一、排列组合A排列:有序,调换两个元素算不同方案 $$A_n^m\frac{n!}{(n-m)!}n(n-1)\dots(n-m1)$$C组合:无序,调换两个元素…

2026/10/18 7:40:06 阅读更多 →
南京二手房数据采集与清洗实战指南

南京二手房数据采集与清洗实战指南

简介:本资源是一套面向本科毕业设计、课程设计及期末大作业的Python数据项目实战方案,聚焦南京地区二手房市场,完整覆盖数据采集、清洗、分析与可视化全流程,特别适合编程基础尚浅但需交付高质量项目的计算机或信息管理类学生。压…

2026/10/18 7:40:06 阅读更多 →
AI违规识别系统如何将安防响应时间从分钟级压缩到秒级

AI违规识别系统如何将安防响应时间从分钟级压缩到秒级

监控装了几年,录像也存了几个月,可一旦真出了安全事故,大家第一反应还是那句老话:“去调监控看看。”这句话背后藏着传统安防系统的核心痛点——事后追责难、响应时间长、证据链断裂。我在最近做的一个园区安防改造项目里&#xf…

2026/10/18 7:40:06 阅读更多 →

最新新闻

Vibe Coding 优缺点全解析:用 TaoToken 统一 Key 实测 AI 编程体验

Vibe Coding 优缺点全解析:用 TaoToken 统一 Key 实测 AI 编程体验

/* 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 16:46:42 阅读更多 →
玄武CLI vs Ollama:国产算力本地大模型部署选型与调优指南

玄武CLI vs Ollama:国产算力本地大模型部署选型与调优指南

1. 从一条命令行说起:为什么本地跑大模型这件事,值得重新审视如果你最近半年在折腾本地大模型部署,大概率绕不开一个名字:Ollama。它把"下载模型、拉起服务、暴露接口"这三件事压缩成了一条命令,确实让很多人…

2026/10/18 16:46:42 阅读更多 →
矩阵不是堆账号,而是织一张AI看得见的信任网

矩阵不是堆账号,而是织一张AI看得见的信任网

做矩阵这几年,我见过太多人把“矩阵”做成了“养号流水线”:弄几十台旧手机,注册一批账号,批量发布相似内容,指望哪条命中了就赚哪条。这种玩法在前几年确实能捞到一些流量,但放到今天,基本上是…

2026/10/18 16:46:42 阅读更多 →
小学生Python入门:用Turtle图形库实现编程启蒙的极度舒适

小学生Python入门:用Turtle图形库实现编程启蒙的极度舒适

简介:这是一份专为零基础小学生设计的Python编程入门教程PDF,以轻松易懂、节奏舒缓的方式系统讲解编程核心概念,解决初学者畏难、不知从何学起的问题。教程覆盖Python交互环境启动、print与input函数使用、整数/浮点数/字符串/布尔值等基本数…

2026/10/18 16:46:42 阅读更多 →
Java Web停车场管理系统:毕设课设可用的业务闭环实战方案

Java Web停车场管理系统:毕设课设可用的业务闭环实战方案

简介:本资源是一套完整的Java Web停车场管理系统毕业设计项目,面向计算机专业本科生及Java初学者,解决校园或中小型商业场景下车位管理、车主信息登记与停车流程数字化等实际问题。压缩包共含源码、数据库脚本、开题报告论文文档及操作视频说…

2026/10/18 16:46:42 阅读更多 →
AirLLM:单张显卡也能跑70B大模型的分层推理显存优化方案

AirLLM:单张显卡也能跑70B大模型的分层推理显存优化方案

1. AirLLM 到底是什么:一个把“大模型塞进小显存”的暴力优雅方案QLoRA、GPTQ、GGUF,这些名字想必大家都不陌生。这几年为了在消费级显卡上跑大模型,各路方案层出不穷,核心思路无非两种:量化压缩模型权重,或…

2026/10/18 16:45:42 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

2026/10/18 0:00:55 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 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/18 0:55:02 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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 阅读更多 →