ThinkPHP6网盘系统源码实战:分片上传与文件管理后端搭建
简介这份源码资源面向PHP Web开发初学者与进阶学习者提供一套基于ThinkPHP6框架构建的网盘系统完整实现可用于理解文件上传、下载、管理等核心业务逻辑也适合作为教育平台的教学案例或课程设计参考。压缩包共633个文件约7.53MB以JavaScript、PHP、HTML、CSS为主涵盖前端交互、后端控制器与模型、页面结构与样式另含Nginx配置、环境变量文件、Composer依赖清单及ThinkPHP命令行工具等工程化文件目录组织清晰便于按模块研读。已有566人学习下载说明其在同类资源中具备一定参考价值。读者可从中掌握ThinkPHP6的控制器、模型、视图分层写法理解Ajax异步通信与文件拖放上传、进度显示等前端协作模式并借助Nginx与.env配置了解部署与环境隔离思路是串联前后端开发流程的实践素材。1. 基于ThinkPHP6的网盘系统设计源码从零搭一套能跑的文件管理后端很多人第一次接触“网盘系统”这个词脑子里浮现的是大厂那种分布式对象存储集群觉得离自己很远。但如果你手里只有一台普通云服务器想给团队内部做一个文件上传、目录管理、分享链接的后端基于ThinkPHP6的网盘系统设计源码其实是一个非常务实的起点。它解决的核心问题不是海量并发而是把文件元数据、物理存储、权限校验这三件事用一套清晰的 MVC 结构串起来。适合谁适合已经会写 PHP、用过 Composer、想拿一个完整项目练手或直接改造成内部工具的后端开发者。这篇文章不讲空泛的架构图只讲怎么把源码跑起来、每个模块为什么这么设计、参数在哪里改、以及我踩过的那些坑。2. 环境搭建与源码结构把项目在本地跑通的最小路径2.1 ThinkPHP6 的运行前提与依赖安装ThinkPHP6 对运行环境有明确要求这不是玄学是框架底层用了 PHP 7.1 以上的语法特性。我一般会先把版本卡死避免后面出现“在我机器上能跑”的翻车现场。常见做法是 PHP 7.4 或 8.0搭配 Composer 2.x。数据库方面网盘系统的元数据表关系不复杂MySQL 5.7 或 8.0 都行但要注意 8.0 默认的字符集和认证插件可能让老代码连接失败。先确认环境php -v composer -V mysql --version如果 PHP 版本低于 7.1后面的步骤不用看了先升级。接下来进入项目根目录安装依赖。ThinkPHP6 的依赖通过 Composer 管理源码包里通常已经带了composer.json你只需要执行composer install --no-dev这里加--no-dev是因为生产环境不需要 phpunit 这类开发依赖能减少自动加载的扫描量。如果你要改代码就去掉这个参数。安装完成后检查vendor目录是否生成think命令行文件是否存在。2.2 目录结构与核心文件职责ThinkPHP6 是标准的单应用模式网盘系统的源码一般会按下面这种方式组织。我把它拆成表格方便你对照手里的包目录/文件职责你重点要看的地方app/controller接收 HTTP 请求参数校验File.php、Share.phpapp/model数据库模型关联查询FileModel.phpapp/service业务逻辑如分片合并UploadService.phpconfig/database.php数据库连接配置主机、库名、密码route/app.php路由定义文件上传、下载、分享接口public/storage物理文件存储根目录权限必须可写.env环境变量数据库、缓存、存储路径很多新手会直接把文件存到public下然后用 URL 直接访问。这在内部测试没问题但一旦对外等于把整个存储目录暴露了。常见做法是把物理文件放在public之外通过控制器读取后输出或者用 Nginx 的X-Accel-Redirect做内部跳转。源码里如果已经做了后者你就要去 Nginx 配置里加一段internal的 location。2.3 数据库初始化与配置文件修改拿到源码后第一件事是建库建表。源码包里通常会有一个install.sql或者 migration 文件。我一般用命令行导入避免 phpMyAdmin 的超时问题mysql -u root -p netdisk install.sql然后修改.env文件。ThinkPHP6 优先读取.env没有才读config目录。注意.env里的变量名要和config/database.php里的env(database.hostname, 127.0.0.1)对应上。一个常见的坑是.env文件里写了DATABASE_HOSTNAME但配置文件里读的是database.hostname大小写和下划线不一致导致一直连默认的 127.0.0.1。APP_DEBUG true [DATABASE] TYPE mysql HOSTNAME 127.0.0.1 DATABASE netdisk USERNAME root PASSWORD your_password HOSTPORT 3306 CHARSET utf8mb4 DEBUG true [STORAGE] ROOT_PATH /www/wwwroot/netdisk/storageROOT_PATH这个自定义配置是我强烈建议加的。不要硬编码存储路径否则迁移服务器时你会想把代码重写一遍。改完配置后访问public/index.php对应的入口如果看到 ThinkPHP 的欢迎页或者登录页说明框架层通了。3. 文件上传与分片处理大文件不超时的实现细节3.1 为什么网盘系统必须做分片上传直接上传一个 2GB 的文件浏览器会先卡死PHP 的upload_max_filesize和post_max_size也会拦你。就算你把这两个值调到 2GNginx 的client_max_body_size默认是 1M请求根本到不了 PHP。分片上传的本质是把一个大文件切成固定大小的块逐块上传最后在服务端合并。这样每个请求都很小超时风险低还能做断点续传。分片大小怎么定我一般用 2MB 到 5MB。太小了请求次数多元数据写入频繁太大了又失去了分片的意义。源码里如果写死了 1MB你可以改但要注意前端也要同步改否则合并时偏移量对不上。3.2 分片上传的接口设计与参数说明一个典型的分片上传流程分三步初始化上传任务、上传分片、合并分片。对应的路由和控制器方法如下// route/app.php Route::post(upload/init, Upload/init); Route::post(upload/chunk, Upload/chunk); Route::post(upload/merge, Upload/merge);初始化接口接收文件名、文件总大小、分片总数返回一个唯一的upload_id。这个 ID 用来关联所有分片通常用md5(文件名用户ID时间戳)生成。// app/controller/Upload.php public function init() { $filename input(post.filename); $totalSize input(post.total_size); $chunkTotal input(post.chunk_total); $userId $this-request-userId; // 从中间件获取 // 生成唯一上传ID $uploadId md5($filename . $userId . microtime(true)); // 写入上传任务表 UploadModel::create([ upload_id $uploadId, filename $filename, total_size $totalSize, chunk_total $chunkTotal, user_id $userId, status 0, // 0进行中 1已完成 ]); return json([code 0, upload_id $uploadId]); }分片上传接口接收upload_id、分片序号chunk_index、分片二进制数据。这里要注意ThinkPHP6 接收文件用$this-request-file(chunk)不要用$_FILES。分片文件先存到临时目录命名规则是upload_id . _ . chunk_index。public function chunk() { $uploadId input(post.upload_id); $chunkIndex input(post.chunk_index); $file $this-request-file(chunk); // 校验上传任务是否存在 $task UploadModel::where(upload_id, $uploadId)-find(); if (!$task) { return json([code 1, msg 上传任务不存在]); } // 临时分片目录 $tmpDir runtime_path() . chunks . DIRECTORY_SEPARATOR . $uploadId; if (!is_dir($tmpDir)) { mkdir($tmpDir, 0755, true); } // 移动分片文件 $chunkFile $tmpDir . DIRECTORY_SEPARATOR . $chunkIndex; $file-move($tmpDir, $chunkIndex); return json([code 0, msg 分片上传成功]); }合并接口按顺序读取所有分片追加写入最终文件。这里有个血泪经验不要用file_put_contents循环追加大文件会内存溢出。用流式写入public function merge() { $uploadId input(post.upload_id); $task UploadModel::where(upload_id, $uploadId)-find(); $tmpDir runtime_path() . chunks . DIRECTORY_SEPARATOR . $uploadId; $finalFile config(storage.root_path) . DIRECTORY_SEPARATOR . $task[filename]; $fp fopen($finalFile, wb); for ($i 0; $i $task[chunk_total]; $i) { $chunkFile $tmpDir . DIRECTORY_SEPARATOR . $i; if (!file_exists($chunkFile)) { fclose($fp); return json([code 1, msg 分片 {$i} 缺失]); } fwrite($fp, file_get_contents($chunkFile)); unlink($chunkFile); // 删除已合并分片 } fclose($fp); // 更新任务状态 UploadModel::where(upload_id, $uploadId)-update([status 1]); return json([code 0, msg 合并完成]); }参数说明chunk_total必须和初始化时一致否则合并会漏片。storage.root_path要确保 PHP 进程有写权限否则fopen返回 false但不会报错你会得到一个空文件。3.3 断点续传的校验逻辑断点续传不是必须的但做了体验会好很多。实现方式很简单前端在上传前先请求一个check接口传入文件 hash 和upload_id服务端返回已经上传了哪些分片。前端跳过这些分片即可。服务端只需要扫描临时目录下的文件名返回索引数组。public function check() { $uploadId input(post.upload_id); $tmpDir runtime_path() . chunks . DIRECTORY_SEPARATOR . $uploadId; $uploaded []; if (is_dir($tmpDir)) { $files scandir($tmpDir); foreach ($files as $f) { if ($f ! . $f ! ..) { $uploaded[] (int)$f; } } } return json([code 0, uploaded $uploaded]); }注意临时目录的清理很重要。如果用户上传到一半放弃了分片会一直占着磁盘。我一般会加一个定时任务清理runtime/chunks下超过 24 小时的目录。4. 文件存储与权限控制物理路径与数据库的映射4.1 存储路径的分目录策略所有文件都堆在一个目录里文件数量上万后ls都会卡。常见做法是按日期或用户 ID 做二级目录。比如storage/2025/01/15/或者storage/user_123/。源码里如果用的是扁平存储建议你改成哈希分片取文件 MD5 的前两位作为一级目录前四位作为二级目录。$md5 md5_file($finalFile); $subDir substr($md5, 0, 2) . / . substr($md5, 2, 2); $targetDir config(storage.root_path) . / . $subDir; if (!is_dir($targetDir)) { mkdir($targetDir, 0755, true); } rename($finalFile, $targetDir . / . $md5);这样同一个目录下的文件数量可控而且天然支持秒传上传前先算 MD5查数据库有没有相同 MD5 的记录有就直接引用不用再传一遍。4.2 下载时的权限校验与 X-Accel-Redirect文件不能直接暴露 URL否则任何人拿到链接就能下载。下载接口要先校验用户身份和文件归属然后输出文件流。但 PHP 输出大文件很占进程更好的做法是用 Nginx 的X-Accel-Redirect。public function download() { $fileId input(get.file_id); $userId $this-request-userId; $file FileModel::where(id, $fileId) -where(user_id, $userId) -find(); if (!$file) { return json([code 1, msg 文件不存在或无权限]); } $realPath config(storage.root_path) . / . $file[path]; // 告诉 Nginx 内部跳转 return response(, 200, [ X-Accel-Redirect /internal_storage/ . $file[path], Content-Disposition attachment; filename . $file[filename] . , ]); }Nginx 配置里加location /internal_storage/ { internal; alias /www/wwwroot/netdisk/storage/; }这样 PHP 只负责鉴权文件传输由 Nginx 处理并发能力提升一个量级。注意alias后面的路径结尾斜杠要和X-Accel-Redirect的路径拼接后正确。4.3 分享链接的生成与过期控制分享功能是网盘的核心。设计上一般用一张share表记录分享码、文件 ID、过期时间、提取密码。分享码用随机字符串不要用自增 ID否则容易被遍历。$shareCode bin2hex(random_bytes(8)); // 16位随机码 ShareModel::create([ share_code $shareCode, file_id $fileId, user_id $userId, expire_at date(Y-m-d H:i:s, strtotime(7 days)), password $password ? password_hash($password, PASSWORD_DEFAULT) : , ]);访问分享链接时先查share_code再判断expire_at是否过期最后校验提取密码。这里有个坑password_hash每次生成的盐不同不能用md5比对必须用password_verify。5. 避坑与常见问题那些让我加班到凌晨的细节5.1 上传大文件时 Nginx 返回 413现象前端上传到一半控制台报 413 Request Entity Too LargePHP 日志里什么都没有。原因请求根本没到 PHP被 Nginx 的client_max_body_size拦了。默认值是 1M分片如果设成 2M 就会触发。解决在 Nginx 的http、server或location块里加client_max_body_size 10m;然后nginx -s reload。注意如果用了 CDN 或反向代理每一层都要改。5.2 合并后的文件比原文件大现象上传一个 10MB 的文件合并后变成 10.5MB打开损坏。原因分片上传时ThinkPHP 的move方法可能会在文件末尾追加换行或 BOM或者前端把分片数据做了 base64 编码但服务端没解码。解决检查前端FormData是否直接 append 的Blob不要转 base64。服务端接收后用file_get_contents读取原始二进制不要做任何字符串处理。合并时用fwrite而不是file_put_contents追加。5.3 下载文件时中文名乱码现象下载下来的文件名是%E6%B5%8B%E8%AF%95.pdf或者乱码。原因Content-Disposition头里的文件名没有做 URL 编码或者编码方式不对。解决用rawurlencode处理文件名并且加上filename*参数$filename rawurlencode($file[filename]); header(Content-Disposition: attachment; filename . $filename . ; filename*UTF-8\\ . $filename);5.4 并发上传同一文件导致覆盖现象两个用户同时上传同名文件后上传的覆盖了先上传的。原因存储路径只用了文件名没有加唯一标识。解决存储路径用 MD5 或upload_id做目录数据库里记录原始文件名和物理路径的映射。物理文件名不要用用户上传的名字用哈希值。5.5 临时分片目录权限不足现象分片上传接口返回成功但合并时提示分片缺失。原因runtime/chunks目录权限不对PHP 进程写不进去但move方法返回了 trueThinkPHP 的坑实际文件没生成。解决确保runtime目录对 PHP 运行用户可写。在 Linux 下用chown -R www:www runtime不要用chmod 777那是在给自己挖坑。6. 进阶技巧用命令行脚本做存储清理与秒传校验6.1 写一个 ThinkPHP 命令行脚本清理过期分片ThinkPHP6 支持自定义命令行比写 crontab 调 URL 更可控。先创建命令类php think make:command CleanChunks然后在app/command/CleanChunks.php里写逻辑namespace app\command; use think\console\Command; use think\console\Input; use think\console\Output; class CleanChunks extends Command { protected function configure() { $this-setName(clean:chunks) -setDescription(清理超过24小时的临时分片); } protected function execute(Input $input, Output $output) { $chunkRoot runtime_path() . chunks; if (!is_dir($chunkRoot)) { $output-writeln(分片目录不存在); return; } $now time(); $dirs scandir($chunkRoot); $count 0; foreach ($dirs as $dir) { if ($dir . || $dir ..) continue; $fullPath $chunkRoot . DIRECTORY_SEPARATOR . $dir; if (is_dir($fullPath) ($now - filemtime($fullPath)) 86400) { $this-delDir($fullPath); $count; } } $output-writeln(已清理 {$count} 个过期分片目录); } private function delDir($path) { $files scandir($path); foreach ($files as $f) { if ($f ! . $f ! ..) { $p $path . DIRECTORY_SEPARATOR . $f; is_dir($p) ? $this-delDir($p) : unlink($p); } } rmdir($path); } }注册到config/console.phpreturn [ commands [ clean:chunks app\command\CleanChunks, ], ];然后加 crontab0 3 * * * cd /www/wwwroot/netdisk php think clean:chunks。这样每天凌晨三点自动清理不用手动干预。6.2 秒传的实现与 MD5 校验的边界秒传的核心是上传前先算文件 MD5服务端查库如果存在相同 MD5 且文件大小一致直接返回文件 ID不再上传。但这里有个边界MD5 碰撞虽然概率极低但理论上存在。更稳妥的做法是 MD5 文件大小双重校验。public function fastUpload() { $md5 input(post.md5); $size input(post.size); $userId $this-request-userId; $exist FileModel::where(md5, $md5) -where(size, $size) -where(status, 1) -find(); if ($exist) { // 直接建立用户与文件的关联 UserFileModel::create([ user_id $userId, file_id $exist[id], filename input(post.filename), ]); return json([code 0, file_id $exist[id], fast 1]); } return json([code 0, fast 0]); }注意秒传只对已完成的文件生效status必须是 1。如果用户上传到一半MD5 还没算出来不能走秒传。6.3 用中间件统一处理用户鉴权网盘系统的所有接口都需要登录态。不要在每個控制器里重复写if (!$userId) return ...用中间件。namespace app\middleware; use think\facade\Request; class Auth { public function handle($request, \Closure $next) { $token $request-header(Authorization); if (!$token) { return json([code 401, msg 未登录]); } // 解析 token获取用户ID $userId $this-parseToken($token); if (!$userId) { return json([code 401, msg 登录已过期]); } $request-userId $userId; return $next($request); } private function parseToken($token) { // 实际项目里用 JWT 或 Redis 存储 $data cache(token_ . $token); return $data ? $data[user_id] : 0; } }然后在路由分组里挂载Route::group(function () { Route::post(upload/init, Upload/init); Route::post(upload/chunk, Upload/chunk); Route::post(upload/merge, Upload/merge); Route::get(file/download, File/download); })-middleware(\app\middleware\Auth::class);这样鉴权逻辑只写一次后面加接口不会漏。我见过太多项目因为某个接口忘了加鉴权导致文件被越权下载这种后悔药没地方买。6.4 一个我坚持了很久的习惯每次改完存储相关的代码我一定会做两件事第一用php think clean:chunks跑一遍确认没有残留第二手动上传一个 100MB 以上的文件走完分片、合并、下载全流程。不要只测小文件小文件掩盖了所有分片和超时问题。这个习惯帮我省下了至少三次线上事故。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

卫士盾V2.5.0:轻量级EXE网络验证中间件

卫士盾V2.5.0:轻量级EXE网络验证中间件

简介:本资源是一套面向EXE软件开发者的轻量化网络验证与加密管理解决方案,专为解决传统机器码绑定模式安全性低、部署复杂等痛点而设计,适用于教育培训类工具、共享软件及商业桌面应用的版权保护场景。压缩包共122个文件,含14个可…

2026/10/9 15:02:35 阅读更多 →
dnSpy-net472实战:反编译、调试与修改.NET程序集的完整指南

dnSpy-net472实战:反编译、调试与修改.NET程序集的完整指南

简介:dnSpy-net472 是一款面向 .NET 开发者的开源反编译与调试工具,特别适合需要逆向分析 C# 程序、阅读第三方库或调试无源代码场景的工程师。它基于 .NET Framework 4.7.2 构建,集 IL 到 C#/VB.NET 反编译、断点调试、调用堆栈查看、变量监…

2026/10/9 15:02:35 阅读更多 →
ManagedSpy for .NET 4.5:运行时诊断工具深度解析

ManagedSpy for .NET 4.5:运行时诊断工具深度解析

简介:ManagedSpy for .NET 4.5 是一款专为 .NET Framework 4.5 环境设计的轻量级托管代码动态分析工具,面向中高级 .NET 开发者,尤其适用于需在不重启、不重编译、不附加进程的前提下,实时探查运行时对象状态、方法调用链、内存分…

2026/10/9 15:02:35 阅读更多 →

最新新闻

Android智能求职招聘系统开发:匹配链路与推荐算法实战

Android智能求职招聘系统开发:匹配链路与推荐算法实战

简介:面向高校毕业设计与课程设计的安卓智能求职招聘系统完整工程包,以移动端加服务端整体方案覆盖职位浏览、搜索、简历投递、职位发布与面试安排等核心流程。客户端基于安卓与Java开发,服务端采用MVC模式、JSP与MySQL构建,通过H…

2026/10/9 15:38:22 阅读更多 →
MySQL数据库系统维护实战:权限、日志、备份与性能巡检

MySQL数据库系统维护实战:权限、日志、备份与性能巡检

简介:这份资源是国家开放大学MySQL基础课程的实验训练4配套文档,面向正在学习数据库系统维护的在校学生与自学者,帮助完成用户管理、权限控制、备份恢复及数据导入导出等核心实验任务。包内为1个docx文档,大小约3.59MB&#xff0c…

2026/10/9 15:38:22 阅读更多 →
AI编程助手从零搭建宠物生命周期管理App实战

AI编程助手从零搭建宠物生命周期管理App实战

1. 为什么我决定用 AI 编程助手从零搭一个宠物生命周期管理 App先说说这个项目的来龙去脉。我手上一直有个想法:做一个宠物生命周期管理 App,覆盖从领养/购买、疫苗接种、驱虫、体检、发情/绝育、配种/繁育、日常喂养记录,到老年护理、临终关…

2026/10/9 15:38:21 阅读更多 →
RxJava异步编程实战:从设计原理到背压与线程调度

RxJava异步编程实战:从设计原理到背压与线程调度

1. 为什么值得花时间系统梳理RxJava刚接触RxJava那会儿,我踩过一个很典型的坑:在项目里看到别人用Observable串了一长串操作符,觉得挺优雅,照猫画虎写了一段,结果线程切换没搞对,网络请求跑在主线程上&…

2026/10/9 15:38:21 阅读更多 →
Vue生命周期与computed核心原理及Nuxt实战解析

Vue生命周期与computed核心原理及Nuxt实战解析

先说句实话:每次面试前端候选人时,我最喜欢问的问题就是生命周期和computed。不是因为这俩多难,而是它们最能看出一个人是“会用Vue”还是“真懂Vue”。很多写了两年Vue的人,能背出create、mounted、updated,但一问“为…

2026/10/9 15:38:21 阅读更多 →
445万块耕地贴上了二维码,种地的人能得到什么?

445万块耕地贴上了二维码,种地的人能得到什么?

2026年10月9日(周五) 覆盖时段:10月8日午后 — 10月9日清晨。 📑 本文目录 开场:一块地,凭什么要有一份档案这两天,有两份文件在说同一件事为什么按地块算,比按户算更准给一块地贴码…

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

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 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/8 21:13:17 阅读更多 →
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/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练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/9 6:17:20 阅读更多 →