Firefly魔改总结

2026年8月21日星期五·3433 字·17 分钟·
-浏览量
学习文档博客二开firefly
AI 摘要- DeepSeek

记录 Firefly 博客主题的二次开发,涵盖 Astro 内容系统、Svelte 交互、首页动效、音乐可视化、标签图谱、留言板和 Cloudflare 集成。

Firefly魔改总结 - 封面图
提示

本文记录基于 Firefly 主题进行二次开发的实现取舍,覆盖首页动效、音乐可视化、标签图谱、留言板、Cloudflare 集成和部署流程。项目目标是保留 Astro 内容系统,同时将交互功能拆分为可独立维护的模块。

选型背景#

项目最初定位为个人主页,后续增加了文章、评论、搜索和统计能力,因此选择继续在 Astro 内容系统上演进。没有迁移到 Fuwari 的主要原因是现有文章、组件和部署配置已经围绕 Astro 组织,迁移成本高于继续维护。

截至本文发布时,项目本地构建时间约为 24 s;性能结果取决于图片数量、网络环境和部署平台,不能直接作为所有环境的基准。后续重构的主要成本来自交互组件、Swup 生命周期和外部服务配置之间的耦合。

项目地址

https://github.com/MmzMing/my-blog

项目属于二次开发,代码和配置以仓库当前版本为准。

一、重点#

1、首页#

  1. Hero 区域采用 Galgame 风格
  2. 站点地图一览
  3. 作品展示和博客主要方向
技术栈版本作用
GSAP3.15.0处理进入动画、碎片拼合和数字过渡
GSAP ScrollTrigger3.15.0根据滚动位置驱动首页 Hero 与展示层动画
SVG Filter浏览器原生 API提供首页标题的轻量熔化文字效果
Canvas 2D API浏览器原生 API绘制首页雨滴等轻量动态效果
@swup/astro1.8.0提供页面缓存、预加载和页面切换;切换后重新初始化动态组件
Tailwind CSS4.2.4提供通用布局、排版和响应式样式

2、音乐#

3D棋盘可视化音乐。

该功能参考并复刻了开源音乐地图项目的交互思路。

实现参考了 sonic-topography,并根据本站布局和数据结构进行了改造。复用代码或素材前应确认原项目许可证和署名要求。

技术栈版本作用
HTMLAudioElement浏览器原生 API控制播放、暂停、进度和音量
Three.js0.184.0构建音乐可视化的 3D 场景、相机与实例化网格
WebGL浏览器原生 API渲染音乐可视化的 3D 画面
Web Audio API浏览器原生 API使用 AudioContext 与分析节点读取频谱数据并驱动可视化

3、分类标签#

分类页现在只保留标签关系图谱:标签是节点,同一篇文章中同时出现的标签会连成边,边越粗表示共现次数越多。

技术栈版本作用
Astro Content Collections6.4.6在构建时校验文章元数据并生成归档、分类和标签数据
Markdown FrontmatterMarkdown 标准能力维护 categorytags 和发布日期
URLSearchParams浏览器原生 API读取标签和分类筛选参数
(核心)D3.js7.9.0使用 d3-force 计算力导向布局,使用 d3-zoom 处理缩放与拖拽
Canvas 2D API浏览器原生 API绘制节点、连线、标签和悬停高亮,避免大量 SVG 节点带来的渲染压力
ResizeObserver、IntersectionObserver、MutationObserver浏览器原生 API在容器尺寸、可见性和主题变化时分别调整图谱尺寸、暂停动画和刷新配色

实现上,构建阶段会遍历所有文章的 tags:每个标签生成一个节点,并记录它关联的文章;同一篇文章内的任意两个标签生成一条共现边,边的权重就是它们共同出现的次数。客户端按连通关系给节点分组,再交给 D3 力导向模拟进行排布;Canvas 根据模拟结果逐帧绘制图谱。节点大小由文章数量决定,边的透明度和粗细由共现权重决定。用户可以缩放、拖拽节点、悬停查看关联文章,点击或按回车跳转到对应标签页;同时支持键盘选择、减少动态效果偏好和亮暗主题切换。

4、留言#

转变UI为聊天室,并复用 Waline 的登录、审核、表情和访问量能力。原本做了个翻卡牌的,因为这个在KV上面天天给我报警告,后面就取消了。

技术栈版本作用
Waline Client3.15.2初始化普通文章评论区与访问量统计
(核心)@waline/api1.1.2调用留言读取、登录、发布、编辑和删除接口
Lucide Svelte0.468.0提供刷新、状态和操作图标
Fetch API、Web Storage API浏览器原生 API校验登录回调 Token,并保存草稿、资料和登录状态

Waline 服务独立部署,博客只保存服务地址和客户端配置;项目 Worker 不保存评论内容,也不维护留言数据库或登录系统。

留言板调用的接口如下。读取接口每 30 s 轮询一次;页面不可见或浏览器离线时停止发起无效请求。

管理员 Token 仅保存到 sessionStorage;普通用户根据”记住登录”选项保存到 sessionStoragelocalStorage。任何读取、发布、修改或删除请求返回鉴权错误时,页面都会清除本地 Token 并要求重新登录。

4.1 接口列表#

以下为 @waline/api 中留言板实际调用的 CRUD 接口。

// GET /api/comment?path=...&pageSize=...&page=...&lang=...&sortBy=...
// Headers: (token 存在时) Authorization: Bearer <token>
// 读取留言列表(分页,首次加载 + 轮询 + 加载历史)
getComment({
serverURL: string, // Waline 服务端地址
lang: string, // 语言
path: string, // 页面路径(留言板固定为 /guestbook/)
page: number, // 页码,从 1 开始
pageSize: number, // 每页条数
sortBy: string, // 排序方式(如 "insertedAt_desc")
token?: string, // 登录令牌(可选,管理员可看到待审核留言)
signal?: AbortSignal, // 取消请求信号
})
// Response: { count: number, page: number, pageSize: number, totalPages: number, data: WalineRootComment[] }
// --------------------------------------------------------------------------
// POST /api/comment?lang=<string>
// Headers: Content-Type: application/json
// (token 存在时) Authorization: Bearer <token>
// Body: { nick, mail?, link?, comment, ua, url, pid?, rid?, at? }
// 发布留言
addComment({
serverURL: string,
lang: string,
token?: string, // 登录令牌(登录用户可选,匿名时不需要)
comment: { // WalineCommentData
nick: string, // 昵称
mail?: string, // 邮箱
link?: string, // 网站地址
comment: string, // 留言内容(含回复标记 HTML 注释)
ua: string, // User Agent
url: string, // 页面路径
pid?: number, // 父评论 ID(回复时)
rid?: number, // 根评论 ID(回复时)
at?: string, // @用户 ID(回复时)
},
})
// Response: { errno: number, errmsg?: string, data?: WalineComment }
// --------------------------------------------------------------------------
// PUT /api/comment/<objectId>?lang=<string>
// Headers: Content-Type: application/json
// Authorization: Bearer <token>
// Body: { comment?, status?, sticky?, like? }
// 编辑留言(仅本人或管理员可编辑)
updateComment({
serverURL: string,
lang: string,
token: string, // 登录令牌(必需)
objectId: number, // 留言 objectId
comment?: { // UpdateWalineCommentData
comment?: string, // 修改后的内容
status?: "approved" | "waiting" | "spam", // 审核状态(管理员)
sticky?: 0 | 1, // 置顶状态(管理员)
like?: boolean, // 点赞/取消点赞
},
})
// Response: { errno: number, errmsg?: string, data: WalineComment }
// --------------------------------------------------------------------------
// DELETE /api/comment/<objectId>?lang=<string>
// Headers: Authorization: Bearer <token>
// 删除留言(仅本人或管理员可删除)
deleteComment({
serverURL: string,
lang: string,
token: string, // 登录令牌(必需)
objectId: number, // 留言 objectId
})
// Response: { errno: number, errmsg: string, data: "" }
// --------------------------------------------------------------------------
// GET /api/token?lang=<string>
// Headers: Authorization: Bearer <token>
// 登录回调 Token 校验(Waline OAuth 重定向回博客后验证身份)
fetch(`${serverURL}/api/token?lang=${lang}`, {
headers: { Authorization: `Bearer ${token}` },
})
// Response: { errno: number, errmsg?: string, data?: UserInfo }

4.2 登录流程#

浏览器窗口Waline 服务端博客页面用户浏览器窗口Waline 服务端博客页面用户桌面端:弹窗 + postMessagealt[验证成功][验证失败]移动端:跳转 + token 回传alt[验证成功][验证失败]存储策略alt[管理员][普通用户 + 勾选"记住登录"][普通用户 + 未勾选"记住登录"]点击"登录"打开登录弹窗 (window.open)用户完成 OAuth 认证postMessage ({ type: "userInfo", data: UserInfo })验证 UserInfo 合法性进入存储策略清除 Token,提示重新登录点击"登录"location.href 跳转到登录页用户完成 OAuth 认证302 重定向回博客 (?token=...)GET /api/token (Authorization: Bearer <token>)返回用户信息进入存储策略返回错误清除 Token,提示重新登录存入 sessionStorage存入 localStorage存入 sessionStorage刷新留言列表
浏览器窗口Waline 服务端博客页面用户浏览器窗口Waline 服务端博客页面用户桌面端:弹窗 + postMessagealt[验证成功][验证失败]移动端:跳转 + token 回传alt[验证成功][验证失败]存储策略alt[管理员][普通用户 + 勾选"记住登录"][普通用户 + 未勾选"记住登录"]点击"登录"打开登录弹窗 (window.open)用户完成 OAuth 认证postMessage ({ type: "userInfo", data: UserInfo })验证 UserInfo 合法性进入存储策略清除 Token,提示重新登录点击"登录"location.href 跳转到登录页用户完成 OAuth 认证302 重定向回博客 (?token=...)GET /api/token (Authorization: Bearer <token>)返回用户信息进入存储策略返回错误清除 Token,提示重新登录存入 sessionStorage存入 localStorage存入 sessionStorage刷新留言列表

5、关于#

关于页内容使用 MDX 编写,正文里直接内嵌 Astro 组件(资料卡、技术栈卡片、时间线、社交链接和聊天气泡),排版交给框架的 Markdown 渲染管线,无需手动处理换行。页面底部附带一张更新日志图谱:构建时解析 log.md 的变更记录,生成按类型着色的日志卡片,并用 SVG 连线标注条目之间的关联页面。

技术栈版本作用
MDXMarkdown 标准能力 + 组件语法维护个人资料文本并内嵌交互组件,内容更新不需要修改页面逻辑
Astro 组件6.4.6资料卡、技术栈、时间线、社交链接等区块均为 .astro 组件,构建时静态渲染
SVG浏览器标准绘制更新日志图谱中条目之间的关联连线与箭头
Pointer Events浏览器原生 API处理日志卡片的悬停高亮与展开交互
Tailwind CSS4.2.4提供排版和响应式样式
TypeScript5.9.2约束日志解析工具和组件 Props 的类型

6、日历#

日历以全局小组件形式提供,聚合文章发布日期、法定节假日、内置节日和生日/纪念日,在固定的 6 × 7 月视图中展示公历和农历信息,并提供近期事件与当天详情。

技术栈版本作用
lunar-typescript1.8.6将公历与农历日期互转,生成农历日期和农历生日、节日事件
Fetch API浏览器原生 API日历小组件在浏览器端获取文章元数据和节假日静态 JSON 数据
CSS Grid浏览器标准使用 6 × 7 网格稳定渲染每月 42 个日期单元格

6.1 接口列表#

以下两个内部 API 在构建时预渲染为静态 JSON;日历小组件在浏览器端运行时 fetch 这两份数据。其中 /api/holidays.json 在构建时会调用第三方节假日 API 获取数据。

// --------------------------------------------------------------------------
// GET /api/allPostMeta.json
// Headers: 无
// 调用方:日历小组件客户端脚本(浏览器运行时 fetch)
// 构建时由 Astro Content Collections 生成并预渲染为静态 JSON,包含所有文章的元数据
fetch("/api/allPostMeta.json")
// Response: Array<{ id: string, title: string, published: number, category?: string, password?: boolean }>
// --------------------------------------------------------------------------
// GET /api/holidays.json
// Headers: 无
// 调用方:日历小组件客户端脚本(浏览器运行时 fetch)
// 构建时内部调用第三方 API 获取节假日数据后合并内置节日,预渲染为静态 JSON
fetch("/api/holidays.json")
// Response: Array<{ date: string, name: string, isOfficial?: boolean, isWorkday?: boolean, icon?: string, source: "api" | "builtin", rest?: number }>
// --------------------------------------------------------------------------
// GET https://timor.tech/api/holiday/year/<year>
// Headers: Accept: application/json
// 调用方:/api/holidays.json 内部(构建时由 holidayApi 配置驱动)
// 获取中国法定节假日、调休补班日
// 配置路径:src/config/calendarConfig.ts → holidayApi.url
fetch("https://timor.tech/api/holiday/year/2026")
// Response: { code: number, holiday: Record<string, { holiday: boolean, name: string, rest?: number }> }

两个内部 API 只在 astro build 时执行并输出为静态 JSON,生产环境由静态资源直接返回,浏览器端 fetch 到的是静态文件。文章或节假日更新后需要重新构建才能反映到日历上。

7、归档#

归档页按年、月和文章组织时间线,支持分类和标签筛选,并显示年度文章进度。文章列表与统计在构建时根据文章元数据生成;由于静态构建无法读取查询参数,分类和标签筛选在客户端执行,不依赖额外的动态接口。

技术栈版本作用
Intl.DateTimeFormat浏览器原生 API构建时按站点时区归组年月,用于年度/月度文章统计
URLSearchParams浏览器原生 API客户端读取 ?tag / ?category / ?uncategorized 筛选参数
Svelte5.55.5统计卡片组件,配合 requestAnimationFrame 做数字过渡动画(尊重减少动态效果偏好)

8、其他#

  1. 取消了侧边栏,首页和文章页将主要导航集中到顶部与移动端 Dock。
  2. 修改了整体 UI 风格,保留亮色与暗色两种主题,不再维护背景图和多套背景配置。
  3. 添加了日历功能,按文章发布日期展示内容;节假日数据在构建时从第三方 API 拉取并合并内置节日,运行时只读静态 JSON。
  4. 删除了追番功能,避免相关数据请求和资源处理进入构建流程。
  5. 使用 Pagefind 1.5.2 构建本地全文索引,并在构建期生成 LLM Wiki 的 JSON / Markdown 机器入口。
  6. 站点完全静态生成,可直接部署到 Cloudflare Pages、Vercel、Netlify 或其他静态托管平台;评论和统计使用各自的外部服务。

二、用到的AI模型#

  • MIMO V2.5/PRO(送的百亿补贴)
  • claude opus 4.64.74.8fable 5
  • GPT 5.5/5.6
  • antigravity的gemini 3.1/3.5
  • TRAE上的 GLM/豆包/KIMI/QWEN/DeepSeek(都是拿来测试性能好在工作上确定是否实用)

本次试用成本约为 30 元。不同平台的模型、上下文管理和工具链存在差异,不能仅凭一次试用归因于模型或平台。实际接入时应使用小任务验证代码质量,并通过测试和审查控制回归风险。

三、优点与UI复制#

纯静态,部署快,维护简单,成本低(只需要域名的费用)。

外部 UI 参考可以加速原型制作,但接入前需要统一交互规范、无障碍要求和许可证边界,避免把不兼容的组件直接拼接到站点中。

MmzMing
/
my-blog
Waiting for api.github.com...
00K
0K
0K
Waiting...
Firefly魔改总结
https://dwancc.cn/posts/others-blog-firefly-mod/
作者
DWanCc
发布于
2026-08-21
许可协议
CC BY-NC-SA 4.0

评论区

公告
重构大版本更新

一口气全面统一博客样式,移除部分冗余导航页面,更专注内容展示。

优化稳定性修复一批

统一Swup生命周期(BUG更少了、牺牲了首屏部分性能)、升级astro 7(构建速度翻倍)、文章封面图片加载(更流畅)、更换音乐播放器 API(更稳定)等多个问题,站点更稳了。

友链互换友链

欢迎各位大佬互换友链,要求内容原创、稳定更新。申请前请先看友链页的说明,期待和你交换链接。

查看详情
欢迎关于我的介绍

欢迎来到我的博客,我是深耕java、python和agent技术开发。热爱技术、持续学习,欢迎同好交流探讨。

查看详情
音乐
封面

音乐

暂未播放

0:00
0:00
暂无歌词

日历

正在加载日历...

--

    最近节日

    正在加载日历...
    ----

    最近生日/纪念日

    正在加载日历...
    ----
    距月底--
    距年底--
    logo

    隐私政策

    更新日期: 2026 年 7 月 15 日
    生效日期: 2026 年 7 月 15 日

    适用范围#

    本政策适用于 DWanCc 的博客(以下简称“本站”)。本站是个人博客,用于发布和分享内容;不提供账户注册、支付、定位或广告投放服务。访问本站、发表文章评论或在留言板留言前,请阅读本政策。

    信息收集与使用#

    本站只在提供内容、评论和留言功能,以及维护站点安全所需的范围内处理信息。

    • 访问与统计信息:访问页面时,统计服务可能处理访问时间、页面地址、来源页、浏览器和设备相关信息,用于了解内容访问情况、排查故障和改进站点。
    • 评论信息:使用文章评论功能时,Waline 可能处理您主动提交的昵称、邮箱、站点链接和评论内容;还可能处理 IP 地址等必要信息,用于防止垃圾评论、滥用和维护服务安全。评论内容、昵称和站点链接(如填写)可能公开展示在文章下方;邮箱不会公开展示。
    • 留言信息:留言板使用 Waline /guestbook/ 频道。Waline 可能处理您主动提交的昵称、可选邮箱、站点链接、留言内容和图片,以及浏览器、操作系统、IP 地址等必要的反滥用信息。默认情况下,留言图片以内嵌数据随留言提交;如站点维护者配置了远程图片上传接口,图片会先发送至该接口并在留言中保存返回的图片地址。留言内容、昵称、图片和站点链接(如填写)可能公开展示;邮箱和 IP 地址不会在留言板公开展示。

    请不要在评论或留言中提交身份证件、银行卡、住址、密码或其他不必要的敏感个人信息。

    第三方服务#

    为实现本站功能,以下第三方会在各自服务范围内处理相关数据:

    • Umami:用于匿名化的网站访问统计和出站链接点击统计,帮助我了解本站的使用情况。
    • Waline:用于文章评论、留言板及访问量统计。服务会按照其自身规则处理您在评论或留言时提交的信息及必要的反滥用信息。
    • Cloudflare:可为本站提供静态资源分发和域名基础设施。
    • unpkg:用于加载 Waline 的前端脚本、样式和表情资源;请求这些资源时,您的浏览器会与该服务建立连接。

    第三方服务可能有独立的隐私政策和数据保存规则。请在使用相关功能前查阅其规则;本站无法控制其独立的数据处理活动。

    本站主要使用浏览器本地存储(Local Storage 或 Session Storage)保存使用偏好,例如主题颜色、明暗模式、文章列表视图和音乐播放设置。留言板会在本地保存匿名资料、未发送草稿和登录状态,以便恢复输入与会话;管理员登录状态仅保存在当前会话。

    本站不主动设置用于广告定向的第一方 Cookie。评论、统计或资源服务可能按照其自身规则使用 Cookie 或类似技术。您可以通过浏览器设置查看、删除或限制 Cookie 和本地存储;清除后,部分偏好或互动状态可能会恢复为默认值,评论功能也可能受到影响。

    信息公开、保存与安全#

    评论和留言属于公开互动内容,提交后可能被搜索引擎收录、被他人引用或在缓存中短暂保留。请谨慎决定发布内容。除非您提出删除请求、内容违反规则或法律法规另有要求,公开内容会持续保留以维持讨论上下文。

    本站会采取合理措施保护数据安全,包括使用 HTTPS、输入校验、内容转义和访问频率限制。但互联网传输和第三方服务均无法保证绝对安全,请理解并自行承担公开发布信息的相应风险。

    你的权利#

    你可以通过 784774835@qq.com 联系我,申请查询、更正或删除由本站直接保存的评论、留言或相关公开内容。为保护他人权益,请在请求中提供足以定位内容的信息,并说明你与该内容的关系;必要时可能需要进行合理核验。

    对于由 Waline、Umami、Cloudflare 或 unpkg 独立处理的数据,你也可以直接向对应服务提供方行使相关权利。删除公开评论或留言后,第三方缓存、搜索引擎索引或他人转载的副本可能无法立即同步删除。

    未成年人条款#

    未满 14 周岁的未成年人应在监护人同意和指导下使用本站的评论、留言等互动功能。监护人如发现未成年人未经同意提交了个人信息,可通过上述联系方式与我联系,我会在合理范围内协助处理。

    政策更新与联系#

    我可能因本站功能或适用规则变化更新本政策,更新后的版本将在本站公布并标明日期。继续使用相关功能即表示你已阅读并理解更新后的政策。

    如对本政策或数据处理有疑问,请联系 784774835@qq.com

    用户协议

    更新日期: 2026 年 5 月 19 日
    生效日期: 2026 年 5 月 19 日

    适用范围#

    本协议适用于你访问 DWanCc 的博客,以及使用文章评论、留言板等互动功能的行为。继续浏览本站或提交评论、留言,即表示你已阅读、理解并同意遵守本协议及本站的隐私政策。

    评论及留言规则#

    请在交流中保持友善、理性和尊重。你不得利用本站发布、传播或实施以下行为:

    • 发布任何违反中华人民共和国法律法规的内容。
    • 发布任何侵犯他人合法权益的内容,包括但不限于隐私、名誉、肖像、著作权、商标权和其他知识产权。
    • 恶意攻击、辱骂、骚扰、威胁、歧视其他用户或任何第三方。
    • 发布垃圾广告、恶意推广、刷屏、灌水,或与讨论主题明显无关的重复内容。
    • 利用本站进行网络诈骗、钓鱼、传播恶意软件,或发布可能危害网络和信息安全的内容。
    • 绕越或试图绕越本站的审核、限流、封禁等管理措施。
    • 冒充他人、伪造身份,或收集、公开他人的个人信息。

    内容与访问管理#

    你应对自己发布的评论和留言负责,并保证拥有发布该等内容所需的合法权利。论坛管理员有权在不另行通知的情况下删除违规内容、限制或封禁违规账号,或限制其继续使用本站互动功能。

    如发现涉嫌违法犯罪、严重侵权或危及本站安全的内容,本站可保留相关记录,并在法律法规要求或必要时向有关部门提供协助。对管理措施有疑问时,可通过文末联系方式说明情况;本站会结合实际情况处理,但不承诺恢复已删除内容或访问权限。

    知识产权与内容授权#

    本站原创文章、页面设计和其他受保护内容的权利归作者或权利人所有。未经授权,请勿复制、转载、镜像或用于商业用途;法律法规允许的合理使用除外。

    你发布评论或留言时,授予本站为展示、存储、备份、审核、删除和维护互动功能所必需的非独占、免费的使用许可。该许可不改变你对原创内容依法享有的权利。

    免责声明#

    本站内容仅用于个人记录、学习交流和一般信息参考,不构成任何专业意见、承诺或担保。你应结合自身情况独立判断,并对据此采取的行动负责。

    评论、留言和外部链接中的内容由其发布者或运营者负责,不代表本站立场。本站会在合理范围内处理明显违规内容,但不保证所有内容均及时发现,也不对第三方网站的可用性、内容、安全性或隐私实践承担责任。

    因网络故障、不可抗力、第三方服务异常、维护升级或超出合理控制范围的原因导致本站暂时无法访问、内容延迟或数据丢失的,本站会尽力恢复,但不承担由此产生的间接损失。

    未成年人条款#

    未满 14 周岁的未成年人应在监护人同意和指导下使用评论、留言等互动功能。监护人应协助未成年人理解本协议,并对其使用行为进行必要的引导。

    其他条款#

    我可以根据本站功能、管理需要或法律法规变化更新本协议,更新后的版本将在本站公布并标明日期。继续使用本站即视为接受更新后的协议。

    本协议的订立、执行和解释适用中华人民共和国法律。因本协议或使用本站产生争议时,双方应先友好协商;协商不成的,依法向有管辖权的人民法院解决。

    如对本协议或内容管理有疑问,请联系 784774835@qq.com

    复制成功,转载请标注本文地址