Skip to content

增加后台控制面板 - #642

Open
fengyiqianhun wants to merge 1 commit into
CuteLeaf:masterfrom
fengyiqianhun:feature/admin
Open

fengyiqianhun wants to merge 1 commit into
CuteLeaf:masterfrom
fengyiqianhun:feature/admin

Conversation

@fengyiqianhun

Copy link
Copy Markdown

Firefly 管理后台 · 更改记录

本文档记录「Firefly 图形化管理后台」开发过程中的全部仓库变更:新增文件、修改文件、核心机制、Bug 修复与验证结果。使用说明见 admin/README.md。

📌 变更概述

本次开发为 Firefly 主题新增了一个与站点完全解耦的图形化管理后台(Node + Hono + 原生 ESM 前端),实现了:

  1. 账号密码登录:账号密码只能通过 admin/admin.config.ts 修改(网页无改密入口),带会话签名、登录防爆破与 CSRF 防护;
  2. 文章管理:新建 / 编辑 / 草稿 / 发布 / 下架 / 删除(回收站),中文标题自动转拼音 URL,正文改动自动写 updated,Markdown 实时预览,封面图可从媒体库选择;
  3. 个性化设置:以 Schema 驱动的动态表单覆盖 src/config/ 全部 26 个配置模块,支持保存与一键恢复默认;
  4. 模块化:服务端模块注册表 + 前端视图注册表 + Schema 片段机制,三步即可扩展新功能。

同时打通了「后台图形化配置」与「站点源码配置」的桥接:后台只写 src/config/user-config.json 覆盖层,24 个配置模块在导出前经 mergeUserConfig() 做形状守卫深合并,与手写配置互不冲突、可随时恢复默认、模板升级不受影响。


🆕 新增文件

1. 后台应用 admin/(新增整个目录)

文件 说明
admin/admin.config.ts 账号密码 / 端口 / 目录 / 构建开关的唯一配置文件
admin/README.md 后台使用文档(快速开始、功能指南、架构、二次开发、FAQ)
admin/tsconfig.json 后台 TypeScript 类型检查配置(pnpm admin:check)
admin/env.d.ts 补充 import.meta.env 类型声明(后台以 Node 运行并静态导入站点配置模块)

服务端 admin/server/

文件 说明
index.ts 入口:模块注册表 + 认证中间件 + SPA 静态托管 + /vendor/marked.js + /schemas/:name
lib/auth.ts 会话令牌(HMAC 签名)、明文/scrypt 密码校验、按 IP 防爆破、CSRF 请求头校验、admin/.secret 密钥持久化
lib/config-manifest.ts 26 个配置模块的唯一登记表(key / 标题 / 分组 / 默认值 / Schema 文件)
lib/user-config.ts 覆盖层读写、差异计算 computeOverlay、形状守卫合并 mergeOverlay
lib/schemas.ts ajv 校验器(加载 fragments、错误中文化)
lib/paths.ts 仓库根解析与目录穿越防护
lib/fs.ts 原子写入、深比较、JSON 读写
modules/auth.ts 登录 / 登出 / 会话接口
modules/dashboard.ts 仪表盘汇总数据
modules/posts.ts 文章 CRUD(gray-matter 解析、拼音 slug、回收站)
modules/configs.ts 配置模块的读取 / 保存(差异剥离)/ 恢复默认
modules/media.ts 图片/音频上传(multipart)、浏览、删除
modules/site.ts 站点状态、一键 pnpm build、SSE 实时构建日志

前端 admin/ui/(无构建步骤的原生 ESM)

文件 说明
index.html / favicon.svg SPA 壳与图标
css/admin.css 全套后台样式(深色侧栏 + 卡片 + 表格 + 表单 + 开关等)
js/api.js fetch 封装(自动携带 CSRF 头、401 处理)
js/router.js hash 路由器 + 视图渲染包装(401 → 登录页)
js/app.js 会话检测、前端视图注册表、导航高亮、退出登录
js/components/ui.js toast / 确认弹窗 / 弹窗 / 图标库 / 工具函数
js/components/schema-form.js 通用 Schema 表单渲染器(对象分组、数组增删排序、标签输入、枚举下拉、布尔开关、单值/多值切换、JSON 编辑器、x-if 条件显示)
js/components/markdown.js Markdown 预览(复用项目已有依赖 marked)
js/views/ 7 个视图:login / dashboard / posts / post-edit / settings / media / site

Schema 与脚本 admin/schemas/、admin/scripts/

文件 说明
schemas/post.schema.json 文章 Frontmatter 表单 Schema(19 个字段,对应 content 集合)
schemas/fragments/*.schema.json 26 个配置模块的表单 Schema 片段:site profile navbar sidebar backgroundWallpaper announcement gallery sponsor friends friendsPage booknav booknavPage dynamic coverImage comment musicPlayer sakura live2dWidget spineModel displaySettings analytics expressiveCode mermaid plantuml font license
scripts/hash-password.mjs 生成 scrypt 密码哈希(pnpm admin:hash-password -- 密码)
scripts/check-schemas.ts Schema 字段名与配置真实默认值的交叉校验(防字段漂移)
scripts/e2e-test.mjs headless Chrome 端到端冒烟测试(含开关布局回归检测)

2. 覆盖层机制 src/config/

文件 说明
src/config/user-config.ts mergeUserConfig():形状守卫深合并(对象递归 / 数组整体替换 / 类型不匹配忽略 / 未知字段忽略,支持数组根分区)
src/config/user-config.json 覆盖层数据文件(提交进仓库;后台只保存与默认值不同的差异,含 "//" 说明键)

✏️ 修改文件

src/config/(24 个配置模块,均做最小化包装)

所有配置模块统一改为「默认值 + 合并导出」模式,站点行为完全不变:

import { mergeUserConfig } from "./user-config";

export const xxxDefaults: XxxConfig = { /* 原默认值,原样保留 */ };

export const xxxConfig: XxxConfig = mergeUserConfig("xxx", xxxDefaults);
文件 分区键 备注
siteConfig.ts site —
profileConfig.ts profile —
commentConfig.ts comment —
announcementConfig.ts announcement —
sidebarConfig.ts sidebar —
navBarConfig.ts navbar 额外导出 getDynamicNavBarConfig() 供后台读取生成后的默认值
backgroundWallpaper.ts backgroundWallpaper —
musicConfig.ts musicPlayer —
effectsConfig.ts sakura —
pioConfig.ts live2dWidget / spineModel 两个导出分别合并
booknavConfig.ts booknav / booknavPage 两个导出分别合并
galleryConfig.ts gallery —
sponsorConfig.ts sponsor —
friendsConfig.ts friends / friendsPage 友链列表为数组根分区
analyticsConfig.ts analytics —
displaySettingsConfig.ts displaySettings 合并发生在 resolveDisplaySettingsConfig 之前,保留环境变量/总开关语义;额外导出原始默认值
dynamicConfig.ts dynamic —
coverImageConfig.ts coverImage —
expressiveCodeConfig.ts expressiveCode —
mermaidConfig.ts mermaid —
plantumlConfig.ts plantuml —
fontConfig.ts font fontsList 为代码层定义,不参与表单编辑
licenseConfig.ts license —

未纳入图形化编辑的导出:LinkPresets、getEnabledFriends、fontsList、navBarSearchConfig(TS 数字枚举)等代码级/派生值,仍以手写为准。

工程文件

文件 变更
package.json 新增脚本 admin / admin:check / admin:hash-password;新增依赖 hono、@hono/node-server、ajv;新增 devDependency @types/node
pnpm-lock.yaml 随依赖更新(并重建 node_modules,修复了原安装源自 Linux 路径导致的 store 失效问题)
pnpm-workspace.yaml pnpm 供应链策略自动补充 minimumReleaseAgeExclude(hono)
.gitignore 新增忽略 .pnpm-store/、admin/.secret、admin/trash/
README.md 「快速开始」新增「🖥️ 图形化管理后台」小节

🐛 修复的问题(含开发过程中发现并修复)

问题 修复
开关组件布局重叠(用户反馈):.field > label 特异性高于 .switch,把开关的 inline-flex 覆盖成 block,轨道旋钮压住文字 CSS 选择器改为 .field > label:not(.switch);并在 E2E 中加入计算样式回归断言(修复前 display=block, weight=600 → 修复后 inline-flex, track=36px, weight=400)
数组根分区(友链 friends、书签 booknav)的覆盖层被 mergeUserConfig 直接忽略 增加数组根处理:整体替换返回
Schema 片段字段与配置默认值可能漂移 编写 admin/scripts/check-schemas.ts 双向交叉校验(Schema 路径 ↔ 真实默认值),全部 26 模块校验通过(14 条提示均为类型中合法的可选字段)
通用表单渲染器边界问题 JSON 编辑器被事件委托覆盖、字符串列表删除未写回 state、缺失路径下数组操作失效等,均已修复

🧪 验证结果

检查项 结果
pnpm check(astro check) ✅ 260 个文件,0 错误 / 0 警告
pnpm type-check ✅ 通过
pnpm build(完整生产构建:LQIP → VNDB → Astro → 裁剪 → 字体 → Pagefind) ✅ 成功,0 错误
pnpm admin:check ✅ 通过
npx tsx admin/scripts/check-schemas.ts ✅ 26/26 模块,无硬错误
node admin/scripts/e2e-test.mjs(headless Chrome) ✅ 10 步全通过:登录 → 仪表盘 → 文章列表/筛选 → 开关布局 → 配置保存/恢复默认 → 条件显示 → 数组增删 → 新建草稿 → 发布 → 列表可见 → 媒体库 → 构建页 → 清理
API 冒烟测试(curl) ✅ 认证 / 防爆破 / CSRF / 配置读写与站点侧合并 / 文章 CRUD 与自动 updated / 媒体上传与路径穿越防护 / SSE 构建日志

🚀 快速使用

pnpm admin        # 启动后台 → http://localhost:4001(默认 admin / admin123)
pnpm dev          # 另一终端启动站点 → http://localhost:4321(保存配置自动热更新)
  • 修改账号密码:编辑 admin/admin.config.ts 的 adminAuth(唯一入口,网页不可改);
  • 常用命令:pnpm admin:check(类型检查)、pnpm admin:hash-password -- <密码>(生成哈希)、npx tsx admin/scripts/check-schemas.ts(Schema 校验)、node admin/scripts/e2e-test.mjs(浏览器回归测试);
  • 详细的架构说明、三步扩展指南与 FAQ 见 admin/README.md。

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @fengyiqianhun, your pull request is larger than the review limit of 150,000 diff characters

@netlify

netlify Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for demo-firefly ready!

Name Link
🔨 Latest commit 395ecf8
🔍 Latest deploy log https://app.netlify.com/projects/demo-firefly/deploys/6aa9496d2ba14400095eae0d
😎 Deploy Preview https://deploy-preview-642--demo-firefly.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant