思考啊SIKAOA
11 分钟阅读幻灯片

会话记录:sikaoa.com 博客迁移与上传工具开发

会话记录: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.tsPOST API 路由,接收文件名和内容,调用核心逻辑
src/app/upload/page.tsx上传页面:拖拽上传、批量选择、frontmatter 预览、token 验证

3.2 功能特性

  • 拖拽上传:支持批量拖拽 .md 文件到浏览器
  • Frontmatter 解析:自动提取 titledate
  • 智能回退:无 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 脚本行为

  1. 遍历指定路径下的所有 .md 文件
  2. 解析 frontmatter → 提取 title、date
  3. 去除 Markdown 标记 → 生成 200 字摘要
  4. 生成唯一 ID(时间戳)和 slug
  5. 检查重复 → 跳过已存在文章
  6. 追加到 posts.json 数组头部
  7. 输出汇总报告(新增数 / 跳过数 / 总数)

优势:无需启动服务,无需联网,纯本地文件操作,速度极快。


五、Markdown 格式建议

为获得最佳解析效果,建议文章采用以下格式:

---
title: 文章标题
date: 2026-05-04 18:00:00
---

正文内容,支持标准 Markdown 语法。

## 二级标题

- 列表项
- 列表项

**粗体** 和 *斜体*。

> 引用段落
  • titledate 为可选字段,缺失时脚本会自动推断
  • 日期格式支持 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                  # 新增:命令行批量上传