惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recorded Future
Recorded Future
C
Cyber Attacks, Cyber Crime and Cyber Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Scott Helme
Scott Helme
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Palo Alto Networks Blog
Google Online Security Blog
Google Online Security Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
WordPress大学
WordPress大学
博客园 - 聂微东
L
LINUX DO - 最新话题
月光博客
月光博客
小众软件
小众软件
T
Troy Hunt's Blog
A
Arctic Wolf
量子位
I
Intezer
大猫的无限游戏
大猫的无限游戏
T
Tailwind CSS Blog
S
Schneier on Security
Schneier on Security
Schneier on Security
NISL@THU
NISL@THU
T
Threat Research - Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园_首页
有赞技术团队
有赞技术团队
N
News and Events Feed by Topic
美团技术团队
The Cloudflare Blog
P
Privacy International News Feed
S
Security Affairs
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
GRAHAM CLULEY
N
News | PayPal Newsroom
Apple Machine Learning Research
Apple Machine Learning Research
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LINUX DO - 热门话题
V
Vulnerabilities – Threatpost
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
CXSECURITY Database RSS Feed - CXSecurity.com
宝玉的分享
宝玉的分享
Application and Cybersecurity Blog
Application and Cybersecurity Blog
IT之家
IT之家
Hacker News: Ask HN
Hacker News: Ask HN
雷峰网
雷峰网

辰渊尘站

713解锁节来辣!小米17全系,k90pm又能解bl了 - 辰渊尘站 服务器面板迁移:从宝塔到 1Panel - 辰渊尘站 Subconverter 太臃肿?PHP 版轻量化替代来了! - 辰渊尘站 Astro框架Fuwari主题侧边栏添加Umami访问统计 免费领取网易云音乐7天会员 小米MiMo Token Plan免费送辣! Astro框架Fuwari主题实现仿hexo-abbrlink功能 观《鬼灭之刃:无限城篇 第一章 猗窝座再袭》首映有感 为你anzhiyu主题的Twikoo评论系统恢复预览按钮 山东泰安泰山游记:煌煌泰山景,谦谦君子风 安知鱼主题:修复背景图修改引发的深色模式可读性问题 安知鱼主题实现友链状态前端显示 我敲!优选DNS牛大了 安知鱼主题侧边栏添加无聊湾 从零开始使用Hexo框架搭建属于你的博客(一)环境准备篇 记录下Hexo博客从本地构建迁移到Netlify,AI API Key 泄露问题与解决方案记录 云服务器宝塔部署Twikoo博客评论系统 手把手教你在Linux系统下部署MCSManager并搭建一个MC服务器 为你的Twikoo添加酷安表情包 记录一次博客评论迁移过程 记一次花嫁联名借记卡申领过程 为使用anzhiyu主题的博客加上十年之约进度条 有关建站一个月以来的一点点感想和后续计划 这可能是iOS自签的版本答案,二合一LiveContainer教程来辣! iOS侧载新选择!SideStore+LiveContainer,纯净无广,无限安装软件!!! 从零开始使用Hexo框架搭建属于你的博客(零)准备篇 Arch Linux+Hyprland从安装到使用只需这一篇(保姆级喂饭超全教程) - 辰渊尘站 恭喜你找到了本站的第一篇文档 - 辰渊尘站
为Fuwari框架适配友链状态显示
辰渊尘 · 2026-05-08 · via 辰渊尘站
TIP

修改前必读:

  • 本帖基于 Astro框架Fuwari主题 进行修改方案编写,因此请读者优先掌握 Astro Docs 的内容后再来进行魔改。
  • 由于修改内容较多,以及可能会导致意料之外的事情,推荐使用 Github 配合 VSCode 进行修改,方便随时备份恢复

前言#

之前在用 Hexo 的 anzhiyu 主题时,就搞过一次友链状态显示的功能(详见安知鱼主题实现友链状态前端显示),当时用的是 LiuShen大佬check-flink 方案,效果还不错。

后来博客迁移到了 Astro 框架的 Fuwari 主题,之前那些 Hexo 的东西自然是用不了了。一直惦记着这个功能,趁着有空就把它给搞上了。

实现来自:LiuShen大佬的友链状态检测方案

解析#

先简单说一下这个功能的原理,其实和之前 anzhiyu 主题那篇是一样的套路:

  1. 后端检测:通过 GitHub Action 定时运行 Python 脚本,访问所有友链站点,记录延迟和可达性
  2. 生成结果:检测结果输出到一个 result.json 文件,部署在 Vercel/Zeabur 等平台
  3. 前端渲染:页面加载时 fetch 这个 JSON,根据延迟数据在友链卡片上显示彩色状态标签

状态颜色分级如下:

  • 绿色(延迟 < 1s):站点响应很快
  • 黄色(延迟 1s ~ 2s):正常速度
  • 橙色(延迟 >= 2s):有点慢
  • 红色(超时 / 不可达):站点可能挂了

修改#

后端配置#

后端检测部分直接使用 LiuShen 大佬的 check-flink 项目,具体部署教程可以参考他的文章,这里就不重复了。你需要做的就是:

  1. Fork 他的仓库
  2. 配置 GitHub Action
  3. 部署到 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}>

写在最后#

到这里就大功告成了,效果就是在友链卡片的右上角会显示一个小标签,颜色根据延迟自动变化。

好处:

  1. 一目了然:打开友链页就能看到哪些站点正常、哪些挂了
  2. 自动更新:后端 GitHub Action 定时检测,前端实时拉取,不用手动维护
  3. 视觉友好:颜色分级直观,绿色放心、红色警惕

代码是 AI 辅助修改的,如果有问题欢迎评论区指出~

参考资料(排名不分先后)#