前言
之前用WordPress的时候就用cloudflare检测友链的状态,现在换到hexo了,就想到用github Action来解决这一事情
效果

教程
首先就是添加links.js
文件,并且添加如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| const fs = require('fs'); const path = require('path');
hexo.extend.generator.register('links-api', function(locals) { const linksData = hexo.locals.get('data').links; if (!linksData) { return; }
const actualLinksData = linksData.links; if (!actualLinksData || !Array.isArray(actualLinksData)) { return; }
let xiaohuobanCategory = null; for (const category of actualLinksData) { if (category.class_name === '小伙伴') { xiaohuobanCategory = category; break; } }
if (!xiaohuobanCategory || !xiaohuobanCategory.link_list) { return; }
const friends = xiaohuobanCategory.link_list.map(link => [ link.name, link.link, link.avatar ]);
const apiData = { friends: friends };
const apiDir = path.join(hexo.public_dir, 'api'); if (!fs.existsSync(apiDir)) { fs.mkdirSync(apiDir, { recursive: true }); }
const filePath = path.join(apiDir, 'links.json'); fs.writeFileSync(filePath, JSON.stringify(apiData, null, 2), 'utf8');
return { path: '/links.json', data: JSON.stringify(apiData, null, 2) }; });
|
此代码的作用就是生成以小伙伴
分类为基础的友链json文件,你可以根据实际情况进行修改
然后就是到github中fork我的项目links-status到自己的仓库
点击编辑config.yml
中的内容就可以修改设置了。
找到Actions找到检测友链状态的脚本点击RUN workflow
就可以了
因为不会写代码,一切都是AI写的,所以在生成文件到page
分支的时候很慢,大约需要三分钟
构建好以后可以用vercel,edgeone pages等平台选择page
分支部署就可以了,然后将代码中的json文件地址替换成你自己的
如果你有更好的方法可以留言告诉我,一起进步!~
最后就是solitude主题怎么引入呢?
很简单,就是在source
文件夹的js
文件夹中添加一个links-status.js
的文件,并且放入代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| let retryCount = 0; const MAX_RETRIES = 3; const STATUS_URL = 'https://links.ityr.xyz/status.json';
function fetchLinkStatus() { return fetch(STATUS_URL) .then(response => { if (!response.ok) { throw new Error('网络请求失败'); } return response.json(); }); }
function updateLinkStatus(data) { if (data && data.link_status) { const statusMap = {}; data.link_status.forEach(link => { statusMap[link.name] = link; }); const statusElements = document.querySelectorAll('.site-card-status'); statusElements.forEach(el => { const linkName = el.getAttribute('data-name'); if (statusMap[linkName]) { const status = statusMap[linkName]; let statusClass = ''; let statusText = ''; if (!status.success || status.latency === -1) { statusClass = 'status-error'; const errorCount = status.error_count || 0; statusText = "异常[" + errorCount + "]"; } else { const latency = status.latency; if (latency <= 3) { statusClass = 'status-normal'; } else { statusClass = 'status-slow'; } statusText = latency + 's'; } el.className = 'site-card-status ' + statusClass; el.textContent = statusText; el.classList.remove('status-loading'); } }); } else { throw new Error('无效的状态数据'); } }
function handleError() { retryCount++; if (retryCount <= MAX_RETRIES) { setTimeout(fetchAndUpdateStatus, 2000 * retryCount); } else { document.querySelectorAll('.site-card-status.status-loading').forEach(el => { el.className = 'site-card-status status-error'; el.textContent = '获取失败'; }); } }
function fetchAndUpdateStatus() { fetchLinkStatus() .then(data => updateLinkStatus(data)) .catch(error => { console.error('获取友链状态失败:', error); handleError(); }); }
document.addEventListener('DOMContentLoaded', fetchAndUpdateStatus);
document.addEventListener('pjax:complete', fetchAndUpdateStatus);
|
再然后到_config.solitude.yml
文件的body
中引入该文件,并且在自定义CSS文件中添加代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| .site-card { position: relative }
.flink-list-item { position: relative }
.site-card-status { position: absolute; bottom: 0; right: 0; z-index: 10; padding: 3px 8px; border-radius: 8px 0 8px 0; font-size: 12px; font-weight: 500; color: #fff; background-color: rgba(0, 0, 0, 0.6); backdrop-filter: blur(4px); transition: all 0.3s ease }
.site-card-status.status-loading { background-color: rgba(100, 100, 100, 0.8); animation: pulse 1.5s infinite }
.site-card-status.status-normal { background-color: rgba(82, 196, 26, 0.9) }
.site-card-status.status-slow { background-color: rgba(250, 173, 20, 0.9) }
.site-card-status.status-error { background-color: rgba(255, 77, 79, 0.9) }
@keyframes pulse {
0%, 100% { opacity: 1 }
50% { opacity: 0.5 } }
[data-theme="dark"] .site-card-status { background-color: rgba(255, 255, 255, 0.1); color: #fff }
[data-theme="dark"] .site-card-status.status-loading { background-color: rgba(100, 100, 100, 0.8) }
[data-theme="dark"] .site-card-status.status-normal { background-color: rgba(82, 196, 26, 0.8) }
[data-theme="dark"] .site-card-status.status-slow { background-color: rgba(250, 173, 20, 0.8) }
[data-theme="dark"] .site-card-status.status-error { background-color: rgba(255, 77, 79, 0.8) }
.flink-templates { margin-top: 2rem; padding: 1.5rem; background: var(--efu-card-bg); border-radius: 12px; border: var(--style-border-always); box-shadow: var(--efu-shadow-border) }
.flink-templates h3 { margin-bottom: 1rem; font-size: 1.2rem; font-weight: 600; color: var(--efu-fontcolor) }
.template-buttons { display: flex; gap: 1rem; flex-wrap: wrap }
.template-btn { display: flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1.5rem; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.3s ease; background: var(--efu-theme); color: #fff }
.template-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) }
.template-btn i { font-size: 16px }
.template-btn.markdown-btn { background: #10b981 }
.template-btn.markdown-btn:hover { background: #059669 }
[data-theme="dark"] .flink-templates { background: var(--efu-card-bg); border-color: var(--efu-border) }
[data-theme="dark"] .template-btn { background: var(--efu-theme) }
[data-theme="dark"] .template-btn.markdown-btn { background: #10b981 }
|
最后就是一键三连即可看到效果了