会话记录:sikaoa.com 博客迁移与上传工具开发
一、项目背景回顾
1.1 旧站架构
- 平台:WordPress
- 数据库:MySQL 5.5.42
- 备份:完整文件备份 + SQL 导出(约 102MB)
- 历史:站点成立于 2012 年
1.2 新站架构(Next.js 重建)
- 框架:Next.js 16 + App Router + TypeScript
- 样式:Tailwind CSS + 自定义 CSS 变量(支持亮/暗主题)
- 动效:Three.js / React Three Fiber(WebGL 粒子背景)
- CMS:已配置 Sanity 支持(示例文件存在,尚未完全接入)
- 数据:3573 篇文章从 WordPress 导出,存储为
src/data/posts.json
1.3 文章数据结构
interface Post {
id: number; // 文章唯一标识
date: string; // 发布时间,格式 "YYYY-MM-DD HH:mm:ss"
title: string; // 文章标题
slug: string; // URL 标识(中文标题直接作为 slug)
excerpt: string; // 摘要(纯文本,约 200 字)
content?: string; // 完整正文(Markdown 或 HTML)
}
二、需求:跨设备 Markdown 上传工具
场景:用户可能在任何一台联网的电脑上撰写 .md 文件,需要便捷地将文章导入博客。
最终交付两套方案:Web 上传 + 命令行上传。
三、方案 A:Web 上传页面
3.1 实现文件
| 文件 | 职责 |
|---|---|
src/lib/upload.ts | 核心逻辑:解析 Markdown frontmatter、生成 excerpt、读写 posts.json |
src/app/api/upload/route.ts | POST API 路由,接收文件名和内容,调用核心逻辑 |
src/app/upload/page.tsx | 上传页面:拖拽上传、批量选择、frontmatter 预览、token 验证 |
3.2 功能特性
- 拖拽上传:支持批量拖拽
.md文件到浏览器 - Frontmatter 解析:自动提取
title和date - 智能回退:无 frontmatter 时,从文件名或正文第一行
# 标题提取标题 - 重复检测:相同标题或 slug 自动拒绝,避免重复导入
- Token 验证:可选环境变量
UPLOAD_TOKEN,未配置时开放上传 - 实时预览:上传前显示解析出的标题、日期、摘要
3.3 启动方式
# 局域网访问(同一 WiFi 下的其他设备可访问)
npm run dev:lan
# 其他电脑打开浏览器访问
http://<服务器IP>:3000/upload/
3.4 公网访问(跨网络)
如需从手机流量、外地电脑上传,可使用 Cloudflare Tunnel:
brew install cloudflared
cloudflared tunnel --url http://localhost:3000
四、方案 B:命令行批量上传
4.1 实现文件
scripts/upload-md.js—— 纯 Node.js 脚本,零依赖package.json新增脚本"upload-md": "node scripts/upload-md.js"
4.2 用法
# 批量上传整个文件夹
cd <项目根目录>
npm run upload-md /path/to/markdown文件夹
# 上传单个文件
npm run upload-md /path/to/某篇文章.md
4.3 脚本行为
- 遍历指定路径下的所有
.md文件 - 解析 frontmatter → 提取 title、date
- 去除 Markdown 标记 → 生成 200 字摘要
- 生成唯一 ID(时间戳)和 slug
- 检查重复 → 跳过已存在文章
- 追加到
posts.json数组头部 - 输出汇总报告(新增数 / 跳过数 / 总数)
优势:无需启动服务,无需联网,纯本地文件操作,速度极快。
五、Markdown 格式建议
为获得最佳解析效果,建议文章采用以下格式:
---
title: 文章标题
date: 2026-05-04 18:00:00
---
正文内容,支持标准 Markdown 语法。
## 二级标题
- 列表项
- 列表项
**粗体** 和 *斜体*。
> 引用段落
title和date为可选字段,缺失时脚本会自动推断- 日期格式支持
YYYY-MM-DD HH:mm:ss或 ISO 8601
六、部署注意事项
| 场景 | 可行性 | 说明 |
|---|---|---|
本地开发 (npm run dev) | ✅ 完全支持 | Web + 命令行均可使用 |
局域网 (npm run dev:lan) | ✅ 完全支持 | 同 WiFi 设备通过 IP 访问 |
| 自托管服务器 | ✅ 完全支持 | 需 Node.js 运行时 |
| Vercel / Cloudflare Pages | ❌ 不支持写文件 | Serverless 环境为只读文件系统,需改用 Sanity CMS 或数据库 |
七、文件变更清单
new-blog/
├── package.json # + dev:lan / + upload-md 脚本
├── src/
│ ├── lib/
│ │ └── upload.ts # 新增:上传核心逻辑
│ ├── app/
│ │ ├── api/upload/
│ │ │ └── route.ts # 新增:上传 API
│ │ └── upload/
│ │ └── page.tsx # 新增:Web 上传页面
│ └── data/
│ └── posts.json # 被脚本读写(3573 → N 篇)
└── scripts/
└── upload-md.js # 新增:命令行批量上传