TIP修改前必读:
- 本帖基于
Astro框架的Fuwari主题进行修改方案编写,因此请读者优先掌握 Astro Docs 的内容后再来进行魔改。- 由于修改内容较多,以及可能会导致意料之外的事情,推荐使用
Github配合VSCode进行修改,方便随时备份恢复
前言
之前在用 Hexo 的 anzhiyu 主题时,就搞过一次友链状态显示的功能(详见安知鱼主题实现友链状态前端显示),当时用的是 LiuShen 大佬 的 check-flink 方案,效果还不错。
后来博客迁移到了 Astro 框架的 Fuwari 主题,之前那些 Hexo 的东西自然是用不了了。一直惦记着这个功能,趁着有空就把它给搞上了。
实现来自:LiuShen 大佬的友链状态检测方案
解析
先简单说一下这个功能的原理,其实和之前 anzhiyu 主题那篇是一样的套路:
- 后端检测:通过 GitHub Action 定时运行 Python 脚本,访问所有友链站点,记录延迟和可达性
- 生成结果:检测结果输出到一个
result.json文件,部署在 Vercel / Zeabur 等平台 - 前端渲染:页面加载时 fetch 这个 JSON,根据延迟数据在友链卡片上显示彩色状态标签
状态颜色分级如下:
- 绿色(延迟 < 1s):站点响应很快
- 黄色(延迟 1s ~ 2s):正常速度
- 橙色(延迟 >= 2s):有点慢
- 红色(超时 / 不可达):站点可能挂了
修改
后端配置
后端检测部分直接使用 LiuShen 大佬的 check-flink 项目,具体部署教程可以参考他的文章,这里就不重复了。你需要做的就是:
- Fork 他的仓库
- 配置 GitHub Action
- 部署到 Vercel / Zeabur,拿到一个可以访问
result.json的 URL
拿到 URL 后,记下来,后面要用。
友链页改造
首先需要修改 src/pages/link.astro,给每个友链卡片加上 data-url 属性和状态标签的容器。
<div class="grid grid-cols-1 md:grid-cols-2 gap-4"> {friends.map((friend) => ( <a href={friend.url} target="_blank" class="friend-card"> <a href={friend.url} target="_blank" class="friend-card" data-url={friend.url}> <span class="friend-status"></span> <div class="flex items-center gap-2">然后在 <style> 部分添加状态标签的样式。注意 .friend-card 需要加上 relative 定位,这样状态标签才能相对卡片定位。
// src/pages/link.astro <style> .friend-card { @apply flex flex-col gap-1 p-4 rounded-lg bg-[var(--card-bg)] border border-black/10 dark:border-white/10 hover:border-black/20 dark:hover:border-white/20 hover:bg-black/5 dark:hover:bg-white/5; @apply relative flex flex-col gap-1 p-4 rounded-lg bg-[var(--card-bg)] border border-black/10 dark:border-white/10 hover:border-black/20 dark:hover:border-white/20 hover:bg-black/5 dark:hover:bg-white/5; transition-property: background-color, border-color, scale; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 0.15s; transform: translateZ(0); }
.friend-status { position: absolute; top: 8px; right: 8px; font-size: 0.7rem; padding: 2px 6px; border-radius: 4px; color: #fff; line-height: 1.2; white-space: nowrap; display: none; }
.friend-card:active {渲染逻辑
最关键的一步,在 src/layouts/Layout.astro 的 </style> 标签后面添加内联脚本。这里用 is:inline 让脚本直接在客户端执行,不经过 Astro 的打包处理。
</style>
<script is:inline>function renderLinkStatus() { if (!document.querySelector(".friend-status")) return; fetch("https://check-flink.mcxiaochen.top/result.json") // 改成你自己的 URL .then(res => res.json()) .then(data => { if (!data.link_status) return; const statusMap = {}; data.link_status.forEach(item => { statusMap[item.link] = item; }); document.querySelectorAll(".friend-status").forEach(el => { const card = el.closest("[data-url]"); if (!card) return; const url = card.getAttribute("data-url"); const info = statusMap[url]; if (!info) return; el.style.display = "inline-block"; if (info.latency === -1) { el.style.backgroundColor = "#ef4444"; el.textContent = "超时"; } else if (info.latency < 1) { el.style.backgroundColor = "#22c55e"; el.textContent = info.latency + "s"; } else if (info.latency < 2) { el.style.backgroundColor = "#f59e0b"; el.textContent = info.latency + "s"; } else { el.style.backgroundColor = "#f97316"; el.textContent = info.latency + "s"; } }); }) .catch(err => console.error("friend link status error:", err));}
function setupLinkStatus() { renderLinkStatus(); if (window.swup) { window.swup.hooks.on("page:view", renderLinkStatus); }}
if (window?.swup?.hooks) { setupLinkStatus();} else { document.addEventListener("swup:enable", setupLinkStatus);}</script>
<script>这里有一个小细节:Fuwari 主题使用了 swup 做页面过渡动画,所以需要监听 swup 的 page:view 事件,在页面切换后重新渲染状态标签。如果不做这个处理,在友链页和其他页面之间切换时,状态标签就不会刷新。
顺便修的一个小 Bug
在改的过程中发现 src/layouts/Layout.astro 里的 keywords meta 标签有个小问题 —— 当 siteConfig.keywords 是数组时,直接塞进 content 属性会变成逗号分隔的奇怪字符串。顺手修了一下:
<meta name="keywords" content={siteConfig.keywords}> <meta name="keywords" content={Array.isArray(siteConfig.keywords) ? siteConfig.keywords.join(', ') : siteConfig.keywords}>写在最后
到这里就大功告成了,效果就是在友链卡片的右上角会显示一个小标签,颜色根据延迟自动变化。
好处:
- 一目了然:打开友链页就能看到哪些站点正常、哪些挂了
- 自动更新:后端 GitHub Action 定时检测,前端实时拉取,不用手动维护
- 视觉友好:颜色分级直观,绿色放心、红色警惕
代码是 AI 辅助修改的,如果有问题欢迎评论区指出~
参考资料(排名不分先后)
文章修订历史 (1 次)
查看变更记录
chore(config): add WebFetch domains and refactor git history data