Files
blog/.spec/specs/archive/2026-10-24_migrate-blog-content/spec.md
wait4xandGLM-5.3 aea21c8694 feat(migrate): Halo 全量内容迁移(压缩版)——6文/21图/1瞬间 URL 1:1
- 正文源=线上渲染页(Halo 快照层 patch 残迹:泥潭/赎罪仅 2 字符),
  pandoc html→gfm + tags API 显示名换算后分类:5 书评(五档情绪色)+1 技术
- 图库 21 张:长边 2400/q86 压缩入仓(原图 196M→9.5M——公开仓历史膨胀
  与 nginx 100M 推送上限双杀;原图在 Phase 0 备份 tar 中永久留档)
- 瞬间 1 条;URL 1:1(6 slug 全等,零 301)
- 本提交由 7 个本地提交重写而成(清除已进历史的 196M blob,未推送过);
  因 reset --soft 暂存竞态,一并包含 spec 归档文件
  (.spec/specs/archive/2026-10-24_migrate-blog-content/)

验证: check_urls.py 6==6;astro build 11 页 exit 0(8.67s);
      EXIF 管线跑通;staging 更新;halo healthy+200 全程未动

Co-authored-by: GLM-5.3
2026-10-25 00:39:08 +08:00

3.9 KiB
Raw Permalink Blame History

Phase 2:Halo 内容迁移(6文/21图/1瞬间,URL 1:1)- 项目范围

1. 问题定义

  • 项目目标:把 Halo 生产内容(6 篇文章 + 21 张图库照片 + 1 条瞬间)迁入 Astro 集合,URL 与旧站 1:1,生产 Halo 全程只读不动
  • 目标用户:站长(迁移完成后新站具备真实全量内容,具备上线条件)
  • 核心价值:内容资产零丢失转移;SEO 无损(同 slug)

2. 假设与待确认

2.1 已确认事实

  • Halo 公共 API 可匿名读:posts 列表含 status.content(HTML);photos 插件 /apis/api.photo.halo.run;moments /apis/api.moment.halo.run
  • 现有 slugs:deng-dai-ge-duo/hai-feng-zhong-shi-luo-de-xie-se-kui-zeng/mian-sha/shu-zui/ni-tan/cs-ge-lei-pei-zhi(首查实测,其中技术文旧 slug 为 csge-lei-pei-zhi 需在迁移时核对)
  • pandoc 可用(~/.local/bin)
  • Phase 1 集合 schema:posts(category/tags/mood)/photos(json sidecar+jpg)/moments

2.2 关键假设

  • Halo 正文内嵌图片走 /upload/ 相对路径,可经 127.0.0.1:18090 直下
  • 引文(blockquote)经 pandoc 转 md 后结构保留,无需人工重排

2.3 待确认问题

  • 文章内嵌图与图库照片是否同一批(书评封面 vs 独立照片)→ 结论:正文零内嵌图,封面图独立未迁(原站亦独立),已记 spot-check 人工项

2.4 可选解释与取舍

  • pandoc + python 后处理 > 纯手写解析器:覆盖面与可维护性 -> 选 pandoc
  • 迁移中间产物(导出 JSON/原始 HTML)不入库(.migration/ gitignore),脚本与最终内容入库

2.5 已证伪路径

  • 无

3. 功能范围

3.1 核心功能(MVP)

  • T1 Halo 全量导出脚本(posts/photos/moments/附件,中间产物 .migration/)
  • T2 文章 HTML→MD 转换 + frontmatter 组装 + 图片本地化
  • T3 图库 21 张迁移(下载+sidecar+EXIF+分组)
  • T4 瞬间迁移
  • T5 URL 1:1 断言脚本(旧 slug 集 == 新 slug 集)
  • T6 全站构建 + staging 更新 + 抽检清单

3.2 扩展功能

  • 无

3.3 不在范围内

  • 双语翻译(Phase 3)、上线切换(Phase 4)、Halo 停用(Phase 5)、旧站评论(数为 0)

4. 最小实现路径

  • 最简单可行方案:导出/转换/断言脚本入 scripts/migrate/,一次性中间产物 .migration/(gitignore);真实内容直接覆盖同 slug 样例文件
  • 暂不引入:评论迁移(存量为 0)、双语分流(Phase 3)、封面图 frontmatter 扩展
  • 不做的抽象/配置化:不写通用 CMS 迁移框架,只服务本次 Halo 一次性迁移

5. 技术决策

  • 技术栈:python3 + pandoc + curl
  • 证据协议:evidence: runs
  • 本轮允许改动:scripts/migrate/、content/、.gitignore、.spec/、src/(仅消费侧微调如分组枚举)
  • 本轮不应触碰:~/docker_apps/halo 运行实例与 postgres、nginx、其它 infra
  • Git integration branch:spec/2026-10-24_migrate-blog-content

5.1 验证策略

  • 范围级别:package
  • 变更对象:content/ 三集合、scripts/migrate/ 脚本、.gitignore
  • 快速检查:pnpm astro build
  • 集成检查:URL 1:1 断言 + 全量路由产物存在(6 文章页)
  • 全项目检查:staging 更新 + rollback-dryrun 仍绿;仅在内容 schema 或构建链变更时升级范围重跑
  • 升级触发:只有改动集合 schema、构建链或部署脚本时,才升级验证范围并记录理由

6. 成功标准与验证方式

  • 6 篇文章新站路由全存在且 slug 与旧站一致 -> verify: task_0005
  • 图库 21 张全量呈现(EXIF 提取成功数记录) -> verify: task_0003
  • 瞬间 1 条迁移 -> verify: task_0004
  • 生产 Halo 状态未变(healthy + 200) -> verify: task_0006

7. 风险与约束

  • Halo HTML 含编辑器私有结构(嵌入块)→ pandoc 后人工抽检点写入 T6 清单 -> 抽检覆盖
  • 附件 URL 形态不一(相对/绝对)→ 下载器双形态兼容