flytotmoon 博客后台管理系统介绍

flytotmoon 博客后台管理系统介绍

为 Hexo + AnZhiYu 博客「飞向月球」量身打造的在线内容管理系统(CMS)。 一个界面,两种模式:本机 Node 服务 与 GitHub 云端,覆盖博客全部内容板块,保存即自动发布。


一、一句话概括

以前写博客要开电脑、改 Markdown、跑命令、部署;现在打开浏览器就能管理整个博客——写文章、发说说、传照片、更新友链、改自我介绍,点「保存」,约 2~5 分钟后自动上线。


二、核心亮点

亮点 说明
🌐 在线化 后台页面随博客发布到 /admin/,任何设备、任何浏览器都能管理,无需安装任何软件
☁️ 零服务器成本 GitHub 云端模式直接调用 GitHub 仓库 API,配合 Actions 自动构建,不需要租服务器
💾 保存即发布 每次保存自动提交 → 自动触发 GitHub Actions 构建 → 自动部署到博客,全程无需手动操作
🖥️ 本地也能用 保留本机模式:一个零依赖的 Node 服务,直接读写本地文件,构建日志 SSE 实时推送
✍️ Typora 风格写作 源码 / 双栏 / 预览三种模式、大纲侧栏、状态栏、Typora 式排版与编辑习惯
🖼️ PicGo 风格图床 三种图床一键切换、拖拽与 Ctrl+V 粘贴上传、云端相册自动翻页读取全部图片
🧩 全板块覆盖 文章、草稿、说说、相册、自我介绍、友链、装备、创意、媒体库、配置、构建,一站式管理
🛡️ 安全设计 细粒度令牌仅存浏览器本地;路径校验防穿越;删除入回收站;配置修改自动备份
🧪 质量保障 101 项回归测试全通过(含真跑前端 Markdown 渲染器);解析器与图床模块双端共用,读写往返无损

三、双模式架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌─────────────────────────────┐        ┌──────────────────────────────┐
│ 本机模式 │ │ GitHub 云端模式 │
│ 浏览器 http://127.0.0.1:4321│ │ 浏览器 blog.flytotmoon.cn/ │
│ │ │ │ admin/ │
│ ▼ │ │ │ │
│ Node 服务(admin/server.js)│ │ 直接调用 GitHub REST API │
│ 零第三方依赖 · scrypt口令 │ │ (Contents / Actions) │
│ HMAC 令牌 · 登录限流 │ │ │ │
│ │ │ │ ▼ │
│ ▼ │ │ flytotmoon/flytotmoon. │
│ 本地文件 source/_posts… │ │ github.io 仓库 source 分支 │
│ hexo generate / deploy │ │ │ │
│ (SSE 实时日志) │ │ ▼ │
└─────────────────────────────┘ │ GitHub Actions 自动构建 │
│ 产物推送 master(Pages) │
└──────────────────────────────┘

自动发布链路(云端):

1
2
3
保存 → 提交到 source 分支 → push 事件触发 Actions
→ npm ci → 安装 pandoc → hexo clean && generate
→ 产物推送 master 分支 → GitHub Pages 更新(约 2~5 分钟)

四、功能全景

📝 文章管理

  • 新建 / 编辑 / 删除(本机模式入回收站,云端模式可经 Git 历史找回)
  • 完整 Front-matter 支持:标题、日期、分类、标签、封面、摘要、置顶、数学公式、评论开关
  • 搜索、分类/标签筛选、分页;标题改名自动重命名文件

📄 草稿箱

  • 草稿独立管理(_drafts,不会被发布);一键「发布」转为正式文章

✍️ Markdown 编辑器(Typora 风格)

  • 三种写作模式(记忆上次选择):源码(居中单栏纯 Markdown)、双栏(源码 + 实时预览)、预览(整洁排版的阅读/校对视图)
  • 大纲侧栏:自动列出各级标题并按层级缩进(自动跳过代码块里的 #),点击即跳到源码对应行并滚动预览
  • 状态栏:字数 / 字符 / 行数 / 光标行列 + 「已保存 / 未保存」;右下角可折叠「文章属性」与「大纲」
  • Typora 式排版:标题下边框、引用左侧细线、行内代码粉底、代码块带语言标签与复制按钮、表格斑马纹、图片居中带阴影、任务列表真实复选框
  • Typora 式编辑习惯:Tab / Shift+Tab 整段缩进、回车自动续写 - 1. > - [ ](空条目回车即退出列表)、Ctrl+B/I/K/E、Ctrl+S 保存
  • 工具栏分组:H1~H3 · 加粗/斜体/删除线/行内代码 · 引用/列表/任务/代码块/表格/分割线 · 链接/图片/上传
  • 布局细节:编辑器占满可视区,属性栏、大纲、写作区各自内部滚动,鼠标滚动不会带动整页

💬 千言万语(即刻短文)

  • YAML 编辑 + 博客同款卡片实时预览 + 保存前格式检查
  • 新条目插入到列表最前面(主题按文件顺序渲染,最新的自然排在最上面,且不受 limit 截断);插入后自动选中占位文字,直接改写即可

🖼️ 相册集

  • 相册分组管理(瀑布流/画廊两种模式),封面与照片缩略图预览,一键新建相册模板

👤 自我介绍

  • 关于页 20 个板块(头像技能/书本/人格/座右铭/游戏/读书/打赏等)的分区概览编辑

🔗 友链管理

  • 分组 + 三种卡片样式(flexcard/telescopic/anzhiyu)+ 推荐/标签徽标预览

🎒 我的装备

  • 分类 → 好物 → 设备三级结构的卡片预览编辑

⭐ 创意技能

  • 音乐墙图标网格预览编辑

📁 媒体库(PicGo 风格云图库)

  • 拖拽 / 点击 / Ctrl+V 粘贴三种上传方式,多选上传带进度条,上传后可自动复制 Markdown 引用
  • 三种图床一键切换:
    • GitHub 仓库:存 source/img/upload/,零配置随站发布
    • 阿里云 OSS:AccessKey + Bucket + Endpoint,可绑自定义域名 / CDN,浏览器直传
    • 自定义接口:Chevereto / EasyImages / 自建服务,支持自定义字段名、请求头与 URL 提取正则
  • 云相册:直接列出当前图床的图片。OSS 走 ListObjects 并自动翻页读取目录下全部图片(默认上限 2000 张),支持文件名搜索、分批渲染「显示更多」、悬停复制 Markdown / 复制链接 / 预览 / 删除
    • 读取范围由「存储目录前缀」决定:填 img 就读取 img/ 下所有图片(上传也放进去),留空读整个 Bucket
    • 「上传时按月建子目录」可关闭,让新图与已有的 img/xxx.jpg 保持同一层
  • 一键测试上传:用一张 1×1 测试图验证图床配置;「最近上传记录」保存在浏览器,自定义图床也能找回地址
  • 容错与诊断:Endpoint 只填地域名会自动补全、误带 https:// 或 Bucket 前缀会自动纠正;AccessKey 里的空格换行自动清洗并校验长度;出错时给出完整可复制的诊断面板(本机签名串 / OSS 期望签名串 / RequestId)

⚙️ 站点设置

  • 可视化修改站点信息;高级模式直接编辑 _config.yml / _config.anzhiyu.yml(自动备份 / Git 历史即备份)
  • 本机模式支持修改后台密码

🚀 构建发布

  • 本机模式:hexo clean / generate / deploy 一键执行,SSE 实时日志流,可取消
  • 云端模式:触发 GitHub Actions,状态自动轮询(构建结束自动停止轮询,节省 API 配额)

📊 仪表盘

  • 文章/草稿/分类/标签/字数统计、分类分布条、标签云、最近文章、快捷操作

五、快速上手

本机模式

1
npm run admin          # 启动,浏览器打开 http://127.0.0.1:4321/

默认账号 admin / admin123(登录后请立即修改密码)。

GitHub 云端模式

  1. 源码推送至仓库 source 分支(master 留给构建产物)
  2. 创建 GitHub 细粒度令牌:Contents: Read and write + Workflows: Read and write,仅授权该仓库
  3. 打开 https://blog.flytotmoon.cn/admin/ → 「GitHub 云端」→ 填令牌与仓库 → 连接测试 → 进入后台

配置阿里云 OSS 图床(可选)

  1. 「媒体库」→「图床设置」→ 选 阿里云 OSS,填 AccessKey ID、AccessKey Secret、Bucket、Endpoint(如 oss-cn-beijing.aliyuncs.com)
  2. 「存储目录前缀」填图片所在目录,例如 img —— 既决定上传位置,也决定云相册的读取范围
  3. 「上传时按月建子目录」按需开关:想让新图和已有的 img/xxx.jpg 放在同一层就关掉
  4. 云端模式还需给 Bucket 配置跨域规则(CORS):来源填 https://blog.flytotmoon.cn,允许方法勾全 PUT/POST/GET/HEAD/DELETE,允许 Headers 填 *;本机模式由服务端代签名,无需 CORS
  5. 点「测试上传」验证;通过后拖拽或 Ctrl+V 粘贴图片即可,上传完 Markdown 自动进剪贴板

建议使用 RAM 子账号,只授予该 Bucket 的 oss:PutObject、oss:GetObject、oss:ListObjects、oss:DeleteObject 权限;密钥只保存在本机配置或浏览器本地,不会写入仓库。


六、技术特点

  • 零第三方依赖:本机服务仅用 Node 内置模块(http / crypto / fs / child_process),单文件可运行
  • 双端共用解析器:fm.js 同时运行在 Node 服务端与浏览器端,front-matter 解析/回写完全一致,读写往返无损(含无缩进列表等非标写法)
  • 双端共用图床模块:storage.js 同样一套代码跑两端(浏览器用 WebCrypto、Node 用 crypto),内置阿里云 OSS V1 签名直传、自定义接口上传与云相册列举
  • 浏览器直传 OSS 的签名方案:浏览器的 fetch 禁止脚本设置 Date 请求头(会被静默丢弃),因此改用 OSS 支持的 x-oss-date;并且签名约定(哪些子资源参与签名、值是否编码、x-oss-date 是否计入签名头)由 OSS 返回的「期望签名串」自动学习并在后续请求中复用
  • 前端 Markdown 渲染器自带测试:预览渲染器在单元测试里被放入沙箱真跑,任务列表、代码块、转义、表格等行为都有断言保护
  • 视图容器隔离:每次切换视图都换一个全新的 #page-container,旧容器隐藏保留片刻——迟到的异步渲染落在旧容器里,既不报错也不会串到新页面
  • 登录安全:scrypt 口令哈希 + HMAC 签名令牌(7 天有效期)+ 登录失败限流
  • 细粒度令牌:云端模式令牌只保存在浏览器 localStorage,页面公开但无令牌无法操作
  • 防限流优化:目录树缓存 120s、统计缓存 60s、构建完成自动停止轮询、限流错误中文提示
  • 防缓存策略:资源带版本号(?v=x.y.z)+ 登录页版本标识,避免旧版缓存困扰
  • 格式安全:YAML 类数据页保存前做解析检查,格式错误时二次确认,防止博客构建失败
  • 回归测试:node admin/test-api.js 覆盖 101 项断言,含 OSS 签名向量、分页、二进制解码、前端渲染器等

七、版本演进

版本 内容
v1.0.0 本机模式:认证、文章/草稿、媒体、设置、构建(SSE 日志),33 项 API 测试
v1.2.0 GitHub 云端模式上线:/admin 在线后台、Actions 自动构建部署
v1.3.0 资源版本号防缓存 + 版本标识
v1.4.0 UI 全新重设计(深空分屏登录、渐变侧边栏)+ 修复 hexo 主题布局污染(skip_render)
v1.4.1 API 调用频率优化 + 限流中文提示
v1.4.2 保存即自动发布的提示文案修正
v1.5.0 千言万语集成
v1.5.1 相册集集成
v1.5.2 自我介绍集成
v1.6.0 友链 / 装备 / 创意技能全部集成(45 项 API 测试全通过)
v1.6.x 交互细节打磨(编辑器焦点、置顶优先级、媒体删除缓存等)
v1.7.0 媒体库升级为 PicGo 风格云图库:三种图床切换(GitHub / 阿里云 OSS / 自定义接口)、拖拽与 Ctrl+V 粘贴上传、云相册浏览、自动复制 Markdown(63 项 API 测试全通过)
v1.7.1 修复云端模式删除图片报 URI malformed(二进制文件被当成文本解码,删除静默失败)
v1.7.2 千言万语「添加新条目」改为插入到列表最前面,并自动选中占位文字
v1.7.3 OSS Endpoint 自动纠错(只填地域名 / 多带协议或 Bucket 前缀),上传失败给出可排查的中文提示
v1.7.4 OSS 改用 x-oss-date 签名,修复浏览器直传 403 requires a valid Date
v1.7.5 OSS 密钥自动清洗(空格/换行/引号)与长度校验;签名不匹配时给出完整诊断信息
v1.8.0 云相册自动翻页读取 OSS 目录下全部图片(默认 2000 张);前缀按目录语义、上传目录可平铺;相册分批渲染
v1.8.1 OSS 签名约定自适应:用 OSS 返回的期望签名串重签重放并学习,错误改为完整可复制的诊断面板
v1.8.2 修复快速切换视图时迟到异步渲染报 querySelectorAll of null(每个视图使用独立容器)
v1.9.0 文章编辑器改造为 Typora 风格:三种写作模式、大纲侧栏、状态栏、Typora 式排版与编辑习惯
v1.9.1 修复编辑器中滚动时「文章属性 / 大纲」跟着整页滚动(三栏各自内部滚动)

八、踩坑记(浏览器直传对象存储)

把「图床」做进纯前端后台,踩了一串坑,记下来给以后的自己:

  1. 跨域(CORS):浏览器直传 OSS 前,必须给 Bucket 配置跨域规则:来源填站点域名、允许方法 PUT/POST/GET/HEAD/DELETE、允许 Headers 填 *。没配时前端只能看到 Failed to fetch,看不出原因——所以「把网络错误翻译成人话」很有必要。
  2. Date 请求头被浏览器禁止:JS 通过 fetch 设置的 Date 属于 forbidden header,会被静默丢弃,OSS 于是回 403 AccessDenied: OSS authentication requires a valid Date。解法是改用 x-oss-date(它同时作为签名串里的时间戳并计入 CanonicalizedOSSHeaders)。
  3. 签名串的细节差异:即使算法和官方 SDK 逐字符一致,不同实现/区域对「哪些子资源参与签名、值用原文还是 URL 编码」仍可能不同,表现为 SignatureDoesNotMatch。最终的稳妥做法是:OSS 会在错误响应里原样返回它期望的签名串,直接用它重签一次即可,同时从中反推约定供后续请求复用。
  4. Endpoint 与密钥的手滑:oss-cn-beijing 少了 .aliyuncs.com、密钥复制多一个空格或换行、误把 AccessKey ID 当 Secret——这几种错误都会表现为「签名不匹配」,所以在保存时做归一化与长度校验,比事后排查省事得多。
  5. 列举要翻页:ListObjects 单次最多 1000 个对象,且 V1 在不带 delimiter 时不返回 NextMarker,要用本页最后一个 Key 当下一页的 marker。
  6. 别把二进制当文本读:云端删除图片时若先读文件内容拿 sha,用 decodeURIComponent(escape(atob(...))) 解码图片会抛 URI malformed,删除请求根本发不出去。
  7. 列表缓存与「删不掉」的错觉:写入后必须让目录树缓存失效,前端再做一次乐观移除,否则界面看起来「删了还在」。
  8. GitHub Pages 的缓存:推送成功但线上还是旧版,除了资源加 ?v=x.y.z,也可能是 Pages 没有重建——推一个空提交触发一次即可。
  9. 异步渲染与切换视图:视图都是 async 的,await 期间用户切走后,旧代码继续操作已被替换的 DOM 就会报 null;让每个视图持有独立容器、旧容器隐藏保留片刻,问题从根上消失。

九、目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
admin/
├── server.js # 本机模式后端服务(零依赖,单文件)
├── config.json # 本机凭据(自动生成,已 gitignore)
├── test-api.js # 回归测试(101 项)
├── backups/ trash/ # 本机模式备份与回收站
└── README.md # 完整使用文档

source/admin/ # 后台前端(随博客发布到 /admin/)
├── index.html app.js style.css fm.js
└── storage.js # 图床模块(OSS 直传签名 / 自定义接口 / 云相册)

.github/workflows/
└── auto-deploy.yml # GitHub Actions 自动构建部署

十、安全说明

  • 本机模式默认仅监听 127.0.0.1;密码 scrypt 加盐哈希;令牌 HMAC 签名
  • 云端模式:令牌仅存浏览器本地;请使用细粒度令牌并只授权本仓库,定期更换
  • 所有文件操作均做路径校验(防目录穿越);删除仅入回收站 / Git 历史可找回
  • 修改配置文件自动备份(本机)或依赖 Git 历史(云端)