Firefly 魔改:每日一言侧边栏组件

Firefly 魔改:每日一言侧边栏组件

侧边栏每日一句名言,以日期为种子的伪随机算法确保同一天显示相同内容。
AI 迁移提示

本文由 AI 协助从旧站迁移,尚未完成逐篇人工审校;内容如有疏漏,将在复核后修订。

> 本文部分内容由 AI 辅助整理,已结合实际操作进行校验,请根据自身环境谨慎使用。

在侧边栏展示一句名言,每天刷新。如何做到"同一天显示相同的名言,且不需要数据库"?答案是用日期作为随机种子。

一、设计思路

今日一言效果图

名言数据存储在 content/ziyuan/quote.md 中,构建时读取。每次页面加载时通过日期字符串计算出伪随机索引,确保:

  • 同一天 → 显示同一条名言
  • 不同天 → 自动切换
  • 无需数据库 → 纯静态,构建时确定

二、核心实现

日期种子算法

组件完整源码:

为什么会这样工作?

toISOString().split("T")[0] 返回 "YYYY-MM-DD" 格式字符串。将其每个字符的 charCode 累加,得到的数字在不同日期不同,同一天完全一致。再取模就得到了"每日固定的随机"索引。

数据源

名言存放在资源集合 src/content/ziyuan/quote.md 的 frontmatter 中:

yaml
---
title: 名言集
quotes:
  - text: 知行合一
    author: 王阳明
  - text: 学而不思则罔,思而不学则殆
    author: 孔子
---

三、注册组件

src/components/layout/SideBar.astro 中导入:

js
import Advertisement from "@/components/widget/Advertisement.astro";
import Announcement from "@/components/widget/Announcement.astro";
import Calendar from "@/components/widget/Calendar.astro";
import Categories from "@/components/widget/Categories.astro";
import Dynamic from "@/components/widget/Dynamic.astro";
import GitHubHeatmap from "@/components/widget/GitHubHeatmap.astro";
import Music from "@/components/widget/Music.astro";
import Profile from "@/components/widget/Profile.astro";
import QuoteOfTheDay from "@/components/widget/QuoteOfTheDay.astro";
import Schedule from "@/components/widget/Schedule.astro";
import SidebarTOC from "@/components/widget/SidebarTOC.astro";
import SiteInfo from "@/components/widget/SiteInfo.astro";
import SiteStats from "@/components/widget/SiteStats.astro";
import Tags from "@/components/widget/Tags.astro";
import TimeGreeting from "@/components/widget/TimeGreeting.astro";

同时在 componentMap 中注册:

js
const componentMap = {
    profile: Profile,
    announcement: Announcement,
    categories: Categories,
    tags: Tags,
    sidebarToc: SidebarTOC,
    advertisement: Advertisement,
    stats: SiteStats,
    calendar: Calendar,
    music: Music,
    siteInfo: SiteInfo,
    githubHeatmap: GitHubHeatmap,
    timeGreeting: TimeGreeting,
    dynamic: Dynamic,
    schedule: Schedule,
    quoteOfTheDay: QuoteOfTheDay,
};

四、注册类型

src/types/sidebarConfig.ts 的类型联合中添加组件名:

typescript
export type WidgetComponentType =
    | "githubHeatmap"
    | "timeGreeting"
    | "dynamic"
    | "schedule"
    | "quoteOfTheDay";

五、配置方式

sidebarConfig.ts 中配置:

typescript
{
  type: "quoteOfTheDay",
  enable: true,
  position: "top",
  showOnPostPage: false,
}

添加新名言只需编辑 src/content/ziyuan/quote.md 中的数组即可。

六、外部 API 方式(可选)

如果不想维护本地名言库,也可以用客户端脚本在页面加载后实时拉取外部 API。在组件末尾添加 <script> 块:

astro
<script>
  (async () => {
    try {
      const res = await fetch("https://v1.hitokoto.cn/");
      const data = await res.json();
      const text = document.querySelector(".quote-text");
      const author = document.querySelector(".quote-author");
      if (text) text.textContent = `"${data.hitokoto}"`;
      if (author) author.textContent = `—— ${data.from || ""}`;
    } catch {
      // 保留构建时渲染的默认名言
    }
  })();
</script>

这样每次页面加载都会从一言 API 实时获取句子,覆盖组件原本渲染的本地名言。优点是名言库无限大,缺点是无法保持"同一天同内容"的确定性。

如果想保留每日确定性,也可以封装一个服务端 API 代理(类似 src/pages/api/dynamic.json.ts),在构建时缓存每日结果。

七、相关文件

组件:/src/components/widget/QuoteOfTheDay.astro

数据源:/src/content/ziyuan/quote.md

相关源码:olinll/firefly-blog

🔗 最后

这个组件的巧妙之处在于用最简单的算法实现了"每日刷新"的效果,零运行时依赖。名言数据源和展示逻辑完全分离,你只需要维护名言列表即可。

Firefly 魔改:时间进度与节假日倒计时组件
Jenkins 部署 Vue+Java 完整指南

评论区

评论加载中...