优化一下GitHub action 输出

This commit is contained in:
zqlit committed 2026-05-20 14:42:30 +08:00
1 parent 427b17d7a0
commit 91a55bc10f
5 files changed
+3 -1567

No files matched your search

+2 -1
View File
@@ -23,7 +23,8 @@
"Bash(curl -s http://127.0.0.1:1316/ -o \".tmp-index.html\")",
"Bash(curl -s \"http://127.0.0.1:1316/js/bundle.min.ca22314448750e3cd87573167443c4f61447dd8c77fdb2a8ecf962e6e770a7b7.js\" -o \".tmp-bundle.js\")",
"Bash([ ! -x \"$CHROME\" ])",
"Bash(powershell -c \"\\(Get-Command chrome.exe\\).Source\")"
"Bash(powershell -c \"\\(Get-Command chrome.exe\\).Source\")",
"Bash(node scripts/generate_notification_report.js)"
],
"additionalDirectories": [
"E:\\GitHub\\Another-Blog"
+1 -8
View File
@@ -34,10 +34,7 @@ jobs:
- name: Run Pre-Build Scripts
shell: pwsh
run: |
# 1. 自动生成友链 JSON (即使本地漏提交也能保证是最新的)
./scripts/update_link_lite_json.ps1
# 2. 自动处理隐藏文章 (防止 status: hidden 的文章意外泄露)
# 自动处理隐藏文章 (防止 status: hidden 的文章意外泄露)
./scripts/add_draft_to_hidden.ps1
- name: Setup Node
@@ -76,10 +73,6 @@ jobs:
fi
- name: Generate Friend Circle Data
continue-on-error: true
run: node scripts/generate_circle_data.js
- name: Check Link Status
continue-on-error: true
run: node scripts/check_links.js
-969
View File
@@ -1,969 +0,0 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1316&amp;path=livereload" data-no-instant defer></script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>友圈</title>
<meta name="description" content="" />
<link rel="canonical" href="http://localhost:1316/circles.html" /><meta name="keywords" content="大学,教程,blog,优世界,优设计,博客,大学生博客,生活,文案" />
<meta property="og:title" content="友圈" />
<meta property="og:description" content="" />
<meta property="og:type" content="article" />
<meta property="og:url" content="http://localhost:1316/circles.html" />
<meta property="og:site_name" content="优世界" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="友圈" />
<meta name="twitter:description" content="" />
<link rel="alternate" type="application/rss+xml" title="优世界" href="/rss.xml">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<script async src="https://019e3dec-3312-7873-862a-3f56ac99ea83.spst2.com/ustat.js"></script>
<script>
(function () {
try {
var theme = localStorage.getItem('theme');
if (!theme) {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
theme = 'dark';
} else {
theme = 'light';
}
}
document.documentElement.setAttribute('data-theme', theme);
if (window.matchMedia) {
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
if (!localStorage.getItem('theme')) {
var newTheme = event.matches ? "dark" : "light";
document.documentElement.setAttribute('data-theme', newTheme);
}
});
}
} catch (e) {}
})();
</script>
<link rel="preload" href="/font/zql-v2.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/font/remixicon.woff2" as="font" type="font/woff2" crossorigin>
<script>
window.siteConfig = {
artalk: {
server: "https:\/\/artalk.usj.cc",
site: "优世界",
emoticons: "http:\/\/localhost:1316\/emotion\/OwO.json",
gravatar: "https:\/\/cravatar.cn\/avatar\/"
},
author: {
avatar: "\/image\/avatar\/tx7.jpg",
description: "不以物喜,不以己悲"
},
barrage: {
enableHitokoto: true ,
hitokotoUrl: "https:\/\/v1.hitokoto.cn?c=a\u0026c=b\u0026c=c\u0026c=d\u0026c=i"
}
};
</script>
<link rel="stylesheet" href="/css/style.min.7201c0e9ef7fa574d6fbab1efcb309790f11bbf063b86f0d8d36527afe7d209b.css">
<link rel="stylesheet" href="/css/libs/Artalk.min.c18a4adffe1319c3471e50565ff505ca8ca75eaf46d5661085de4918f94d6b4c.css"><style>
body, [data-theme="dark"] body {
background-image: url('/image/background/deno.webp') !important;
background-size: contain !important;
background-repeat: round !important;
background-position: center !important;
background-attachment: fixed !important;
}
</style><style>
@media only screen and (max-width: 768px) {
.items {
grid-template-columns: repeat(1, 1fr) !important;
grid-gap: 10px;
}
.link-des,.link-name{
right: 13px;
}
}
.items {
width: 100%;
height: 100%;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 10px;
justify-content: space-between;
}
.item-box {
background-color: white;
border-radius: 5px;
padding: 8px;
height: 300px;
box-shadow: rgba(14, 63, 126, 0.04) 0px 0px 0px 1px, rgba(42, 51, 69, 0.04) 0px 1px 1px -0.5px, rgba(42, 51, 70, 0.04) 0px 3px 3px -1.5px, rgba(42, 51, 70, 0.04) 0px 6px 6px -3px, rgba(14, 63, 126, 0.04) 0px 12px 12px -6px, rgba(14, 63, 126, 0.04) 0px 24px 24px -12px;
}
.website-img {
margin: 0 auto;
width: 90%;
}
.website-img img {
width: 100%;
height: 150px;
object-fit: contain;
}
.website-go-button {
margin: 0 auto;
width: 95%;
border-radius: 5px;
font-size: 14px;
padding: 5px;
text-align: center;
background-color: black;
color: white;
}
.link-info {
padding: 8px;
width: 100%;
height: 90px;
display: flex;
justify-content: center;
align-items: center;
}
.link-avatar {
width: 40%;
display: flex;
align-items: center;
}
.link-avatar img {
position: relative;
left: 5px;
width: 50px;
height: 50px;
}
.link-text-main {
width: 55%;
display: flex;
flex-direction: column;
}
.link-name {
position: relative;
right: 10px;
bottom: 5px;
width: 100%;
height: 50%;
font-weight: 600;
}
.link-des {
position: relative;
right: 10px;
top: 1px;
width: 100%;
height: 50%;
}
</style>
<script src="/js/instantpage.min.js" type="module" defer></script>
<script>console.log("\n %c Amigo Theme %c https://usj.cc \n", "color: #fadfa3; background: #030307; padding:3px; font-size:12px;", "color: #ffffff;background: #16171a; padding: 3px; font-size: 12px;");</script>
<meta name="template" content="Amigo" />
</head>
</head>
<body>
<script>
window.barrageConfig = {
enableHitokoto: true ,
hitokotoUrl: "https:\/\/v1.hitokoto.cn?c=a\u0026c=b\u0026c=c\u0026c=d\u0026c=i",
hitokotoAvatar: "\/image\/avatar\/tx7.jpg"
};
</script>
<div class="barrager"></div>
<div class="main">
<div class="container">
<div class="header">
<div class="header-top">
<div class="header-avatar load-memos-editor" id="theme-toggle-avatar">
<img src="/image/avatar/tx7.jpg" class="blog-img" width="80" height="80" alt="优世界" decoding="async" fetchpriority="high" />
<div class="avatar-theme-tip">
点击头像切换昼夜
</div>
</div>
<div class="header-info">
<div class="header-social ">
<a href="https://github.com/zqlit" title="GitHub" target="_blank"><i class="ri-github-fill"></i></a>
<a href="#" title="我的主页" target="_blank"><i class="ri-at-line"></i></a>
<a href="/rss.xml" title="Rss订阅" target="_blank"><i class="ri-rss-fill"></i></a>
</div>
<div class="header-bio ">不以物喜,不以己悲</div>
</div>
</div>
<nav class="header-menu">
<ul class="flat">
<li class="active "><a href="/">首页</a></li>
<li class="active "><a href="/about.html">关于</a></li>
<li class="active "><a href="/circles.html">友圈</a></li>
<li class="active "><a href="/comment.html">留言</a></li>
<li class="active "><a href="/archives.html">归档</a></li>
<li class="active "><a href="/links.html">友链</a></li>
</ul>
</nav>
</div>
<div id="pjax-wrapper" style="position: relative; min-height: 50vh;">
<div id="pjax-container">
<div class="post-content" itemprop="articleBody">
<div id="friend-circle-container" class="friend-circle-list">
<div class="loading-container">
<div class="loading-spinner"></div>
<p>正在探索朋友们的新动态...</p>
</div>
</div>
</div>
<style>
.friend-circle-list {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
margin-top: 20px;
padding: 0;
width: 100%;
}
@media (max-width: 768px) {
.friend-circle-list {
grid-template-columns: 1fr;
gap: 10px;
}
}
.fc-item {
display: flex;
flex-direction: column;
padding: 20px;
border-radius: 10px;
position: relative;
height: 160px;
justify-content: space-between;
background: rgba(255, 255, 255, 0.4);
backdrop-filter: blur(12px) saturate(120%);
-webkit-backdrop-filter: blur(12px) saturate(120%);
border: 1px solid #111827;
box-shadow: none;
transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1), box-shadow 0.3s ease, background-color 0.3s ease, border-color 0.3s ease;
will-change: transform;
text-decoration: none;
transform: translateZ(0);
overflow: hidden;
}
@media (max-width: 767px) {
.fc-item {
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
background: rgba(255, 255, 255, 0.8);
}
[data-theme="dark"] .fc-item {
background: rgba(30, 30, 30, 0.8);
}
}
.friend-circle-list a {
text-decoration: none;
}
:root {
--fc-text: #333;
--fc-meta-bg: rgba(0, 0, 0, 0.05);
}
[data-theme="dark"] {
--fc-text: #fff;
--fc-meta-bg: rgba(255, 255, 255, 0.1);
}
.fc-item:hover {
transform: translateY(-6px) scale(1.015);
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(0, 0, 0, 0.06);
background: rgba(255, 255, 255, 0.7);
border-color: #1a1a1a;
z-index: 10;
cursor: pointer;
}
.fc-item:active {
transform: translateY(-3px) scale(1.005);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
transition: all 0.15s ease;
}
.fc-title {
font-size: 18px;
font-weight: 700;
color: var(--fc-text);
text-decoration: none;
line-height: 1.4;
z-index: 2;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
margin-right: 60px;
}
.fc-item:hover .fc-title {
color: #000000;
}
.fc-bg-image {
position: absolute;
right: -20px;
bottom: -20px;
width: 140px;
height: 140px;
border-radius: 50%;
object-fit: cover;
opacity: 0.15;
transition: all 0.5s ease;
z-index: 0;
pointer-events: none;
filter: grayscale(20%);
}
.fc-item:hover .fc-bg-image {
opacity: 0.3;
transform: scale(1.1) rotate(deg);
filter: grayscale(0%);
}
.fc-bottom {
display: flex;
justify-content: space-between;
align-items: flex-end;
z-index: 2;
}
.fc-author-pill {
display: flex;
align-items: center;
background: var(--fc-meta-bg);
padding: 4px 10px 4px 4px;
border-radius: 20px;
transition: background 0.3s;
}
.fc-item:hover .fc-author-pill {
background: rgba(52, 152, 219, 0.1);
}
.fc-avatar {
width: 28px;
height: 28px;
border-radius: 50%;
object-fit: cover;
margin-right: 8px;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.fc-author-name {
font-size: 13px;
font-weight: 600;
color: var(--fc-text);
opacity: 0.9;
}
.fc-date {
font-size: 12px;
color: var(--fc-text);
opacity: 0.6;
display: flex;
align-items: center;
}
.fc-date i {
margin-right: 4px;
font-size: 11px;
}
.fc-icon-calendar::before {
content: "\f133";
font-family: "Font Awesome 5 Free", "FontAwesome";
font-weight: 900;
}
.loading-container {
grid-column: 1 / -1;
display: flex;
flex-direction: column;
align-items: center;
padding: 60px;
color: #888;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(127, 127, 127, 0.2);
border-radius: 50%;
border-top-color: #3498db;
animation: spin 1s ease-in-out infinite;
margin-bottom: 15px;
}
[data-theme="dark"] .fc-item {
background: rgba(35, 35, 35, 0.65);
box-shadow: none;
border: 1px solid rgba(255, 255, 255, 0.1);
}
[data-theme="dark"] .fc-author-pill {
background: #1a1a1a;
border: 1px solid #333;
}
[data-theme="dark"] .fc-bg-image {
opacity: 0.2;
}
[data-theme="dark"] .fc-item:hover {
background: rgba(60, 60, 60, 0.85);
border-color: rgba(255, 255, 255, 0.3);
}
[data-theme="dark"] .fc-item:hover .fc-title {
color: #ffffff;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.fc-load-more-btn {
grid-column: 1 / -1;
padding: 5px 30px;
margin: 30px auto 10px;
background: #000;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 30px;
color: #fff;
cursor: pointer;
font-size: 14px;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.fc-load-more-btn:hover {
background: #333;
color: #fff;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
[data-theme="dark"] .fc-load-more-btn {
background: #000;
border-color: rgba(255, 255, 255, 0.2);
}
[data-theme="dark"] .fc-load-more-btn:hover {
background: #222;
}
[data-theme="dark"] .artalk .atk-main-editor {
border: 1px solid rgba(255, 255, 255, 0.1) !important;
}
.fc-tooltip {
position: fixed;
z-index: 9999;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 12px;
padding: 16px;
width: 300px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
pointer-events: none;
opacity: 0;
transform: scale(0.95) translateY(10px);
transition: opacity 0.2s ease, transform 0.2s ease;
font-size: 14px;
line-height: 1.6;
color: #333;
display: none;
}
.fc-tooltip.is-visible {
opacity: 1;
transform: scale(1) translateY(0);
display: block;
}
.fc-tooltip-title {
font-weight: 700;
margin-bottom: 8px;
font-size: 15px;
color: #000;
border-bottom: 1px solid rgba(0,0,0,0.05);
padding-bottom: 6px;
}
.fc-tooltip-content {
color: #555;
text-align: justify;
display: -webkit-box;
-webkit-line-clamp: 6;
-webkit-box-orient: vertical;
overflow: hidden;
}
[data-theme="dark"] .fc-tooltip {
background: rgba(35, 35, 35, 0.95);
border: 1px solid rgba(255, 255, 255, 0.1);
color: #eee;
}
[data-theme="dark"] .fc-tooltip-title {
color: #fff;
border-bottom-color: rgba(255,255,255,0.1);
}
[data-theme="dark"] .fc-tooltip-content {
color: #ccc;
}
</style>
<div id="fc-tooltip" class="fc-tooltip">
<div class="fc-tooltip-title"></div>
<div class="fc-tooltip-content"></div>
</div>
<script>
window.FriendCircle = {
allPosts: [],
currentIndex: 0,
BATCH_SIZE: 10,
CACHE_KEY: 'friend-circle-v1',
CACHE_OPTIONS: {
version: 2,
softTtl: 5 * 60 * 1000,
hardTtl: 60 * 60 * 1000,
validate: function(data) {
return !!data && Array.isArray(data.posts);
}
},
timeAgo: function (dateStr) {
const date = new Date(dateStr);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return year + "-" + month + "-" + day;
},
renderPosts: function (posts) {
const container = document.getElementById("friend-circle-container");
if (!container) return;
const existingBtn = document.getElementById("fc-load-more-btn");
if (existingBtn) existingBtn.remove();
let html = "";
posts.forEach((post, index) => {
const dateStr = this.timeAgo(post.date);
const bgImageSrc = post.avatar;
const description = post.description ? post.description.replace(/"/g, '&quot;') : '';
const delay = index * 100;
html += '<a href="' + post.link + '" target="_blank" class="fc-item" data-desc="' + description + '" data-title="' + post.title + '" uk-scrollspy="cls: uk-animation-slide-bottom-small; delay: ' + delay + '">'
+ '<div class="fc-title" title="' + post.title + '">' + post.title + '</div>'
+ '<img src="' + bgImageSrc + '" class="fc-bg-image" onerror="this.style.opacity=0">'
+ '<div class="fc-bottom">'
+ '<div class="fc-author-pill">'
+ '<img src="' + post.avatar + '" class="fc-avatar" onerror="this.src=\'https://cravatar.cn/avatar/default?s=50\'">'
+ '<span class="fc-author-name">' + post.author + '</span>'
+ '</div>'
+ '<div class="fc-date"><i class="ri-calendar-line"></i> ' + dateStr + '</div>'
+ '</div>'
+ '</a>';
});
container.insertAdjacentHTML("beforeend", html);
if (this.currentIndex < this.allPosts.length) {
const btn = document.createElement("button");
btn.id = "fc-load-more-btn";
btn.className = "fc-load-more-btn";
btn.innerText = "加载更多";
btn.onclick = function() { window.FriendCircle.loadMore(); };
container.appendChild(btn);
} else {
if (window.fcUpdateTime) {
const footer = document.createElement("div");
footer.style.cssText = "grid-column: 1 / -1; text-align: center; margin-top: 20px; font-size: 12px; color: #999; opacity: 0.6;";
footer.innerText = "最近更新: " + window.fcUpdateTime;
container.appendChild(footer);
}
}
},
loadMore: function () {
const nextBatch = this.allPosts.slice(
this.currentIndex,
this.currentIndex + this.BATCH_SIZE
);
this.currentIndex += this.BATCH_SIZE;
requestAnimationFrame(function() {
window.FriendCircle.renderPosts(nextBatch);
});
},
renderEmpty: function () {
const container = document.getElementById("friend-circle-container");
if (!container) return;
container.innerHTML = '<div class="empty" style="grid-column: 1/-1; text-align:center; padding:20px;">暂无动态</div>';
},
renderError: function () {
const container = document.getElementById("friend-circle-container");
if (!container) return;
container.innerHTML = '<div class="error" style="grid-column: 1/-1; text-align:center; padding:20px; color:#d9534f;">加载失败,请稍后刷新重试</div>';
},
applyData: function (data) {
const container = document.getElementById("friend-circle-container");
if (!container) return;
if (!data.posts || data.posts.length === 0) {
this.renderEmpty();
return;
}
window.FriendCircle.allPosts = data.posts;
window.fcUpdateTime = new Date(data.updated).toLocaleString();
window.FriendCircle.currentIndex = 0;
container.innerHTML = "";
window.FriendCircle.loadMore();
},
fetchData: function () {
if (window.BrowserCache && typeof window.BrowserCache.log === 'function') {
window.BrowserCache.log('[FriendCircleCache][fetch]', {
key: window.BrowserCache ? window.BrowserCache.buildKey(window.FriendCircle.CACHE_KEY) : window.FriendCircle.CACHE_KEY,
softTtl: window.BrowserCache ? window.BrowserCache.formatDuration(window.FriendCircle.CACHE_OPTIONS.softTtl) : window.FriendCircle.CACHE_OPTIONS.softTtl,
hardTtl: window.BrowserCache ? window.BrowserCache.formatDuration(window.FriendCircle.CACHE_OPTIONS.hardTtl) : window.FriendCircle.CACHE_OPTIONS.hardTtl
});
}
return fetch("https://rssapi.usj.cc/api/articles?limit=50")
.then(function(res) {
if (!res.ok) throw new Error("Network response was not ok");
return res.json();
})
.then(function(apiData) {
const posts = (apiData.articles || []).map(function(a) {
return {
title: a.title || '',
link: a.link || '',
date: a.pubDate || '',
author: a.feedName || a.author || '',
avatar: a.favicon || '',
blogUrl: a.siteUrl || '',
image: null,
description: ''
};
});
const data = {
posts: posts,
updated: apiData.timestamp || new Date().toISOString()
};
if (window.BrowserCache) {
window.BrowserCache.write(window.FriendCircle.CACHE_KEY, window.FriendCircle.CACHE_OPTIONS, data);
}
return data;
});
},
initTooltip: function() {
if (this.tooltipInitialized) return;
this.tooltipInitialized = true;
const tooltip = document.getElementById('fc-tooltip');
const titleEl = tooltip.querySelector('.fc-tooltip-title');
const contentEl = tooltip.querySelector('.fc-tooltip-content');
const container = document.getElementById('friend-circle-container');
if (!tooltip || !container) return;
if (tooltip.parentNode !== document.body) {
document.body.appendChild(tooltip);
}
const cleanup = function() {
if (tooltip && tooltip.parentNode === document.body) {
tooltip.remove();
}
document.removeEventListener('pjax:send', cleanup);
};
document.addEventListener('pjax:send', cleanup);
const updateTooltip = function(e) {
if (window.innerWidth <= 768) return;
const item = e.target.closest('.fc-item');
if (item) {
const desc = item.getAttribute('data-desc');
const title = item.getAttribute('data-title');
if (desc) {
titleEl.innerText = title;
contentEl.innerText = desc;
tooltip.classList.add('is-visible');
const tooltipWidth = tooltip.offsetWidth;
const tooltipHeight = tooltip.offsetHeight;
const winWidth = window.innerWidth;
const winHeight = window.innerHeight;
const gap = 15;
let left = e.clientX + gap;
let top = e.clientY + gap;
if (left + tooltipWidth > winWidth - gap) {
left = e.clientX - tooltipWidth - gap;
if (left < gap) left = gap;
}
if (top + tooltipHeight > winHeight - gap) {
top = e.clientY - tooltipHeight - gap;
if (top < gap) top = gap;
}
tooltip.style.left = left + 'px';
tooltip.style.top = top + 'px';
} else {
tooltip.classList.remove('is-visible');
}
} else {
tooltip.classList.remove('is-visible');
}
};
container.addEventListener('mousemove', updateTooltip);
container.addEventListener('mouseleave', function() {
tooltip.classList.remove('is-visible');
});
},
init: function () {
const container = document.getElementById("friend-circle-container");
if (!container) return;
this.initTooltip();
if (this.isFetching) return;
this.isFetching = true;
const cached = window.BrowserCache && window.BrowserCache.read(this.CACHE_KEY, this.CACHE_OPTIONS);
if (cached) {
if (window.BrowserCache && typeof window.BrowserCache.log === 'function') {
window.BrowserCache.log('[FriendCircleCache][render]', {
key: cached.key,
age: cached.ageText,
isFresh: cached.isFresh,
softTtl: cached.softTtlText,
hardTtl: cached.hardTtlText
});
}
this.applyData(cached.data);
if (cached.isFresh) {
this.isFetching = false;
return;
}
}
this.fetchData()
.then(function(data) {
window.FriendCircle.applyData(data);
})
.catch(function(err) {
if (window.BrowserCache && window.BrowserCache.isDebug && window.BrowserCache.isDebug()) {
console.error("Friend Circle Error:", err);
}
if (!cached) {
window.FriendCircle.renderError();
}
})
.finally(function() {
window.FriendCircle.isFetching = false;
});
}
};
function initFriendCirclePage() {
if (window.FriendCircle && typeof window.FriendCircle.init === 'function') {
window.FriendCircle.init();
}
}
document.addEventListener('pjax:complete', initFriendCirclePage);
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initFriendCirclePage);
} else {
initFriendCirclePage();
}
</script>
</div>
</div>
<div class="footer">
<nav class="nav" style="clear: both;">
© 2019 - 2026
<br>
<a href="https://beian.miit.gov.cn/" target="_blank"><span style="color:#999999;">鄂ICP备2022015735号-1</span></a>
<br>
本站由<a href="https://www.upyun.com/?utm_source=lianmeng&utm_medium=referral" target="blank" title="又拍云"
style="display:inline-block;text-decoration:none;height:20px;line-height:20px;">
<span style="color: var(--contentColor);font-weight: 700;">又拍云CDN</span>
</a>提供CDN加速服务
<br>
</nav>
</div>
</div>
</div>
<div class="floating-tools">
<a href="javascript:;" id="search-btn" title="搜索文章">
<i class="ri-search-line"></i>
</a>
<a href="javascript:;" id="theme-toggle" title="切换主题">
<i class="ri-sun-line"></i>
</a>
<a href="#Comments" id="to-comments" title="跳转评论">
<i class="ri-chat-2-line"></i>
</a>
<a href="#" id="back-to-top" title="返回顶部">
<i class="ri-arrow-up-line"></i>
</a>
</div>
<div id="search-modal" class="search-modal">
<div class="search-modal-content">
<div class="search-header">
<h3>搜索文章</h3>
<span class="close-search">&times;</span>
</div>
<div class="search-body">
<div class="search-input-wrapper">
<input type="text" id="search-input" placeholder="输入关键词搜索..." autocomplete="off">
<button id="search-submit"><i class="ri-search-line"></i></button>
</div>
<div id="search-results" class="search-results">
<p class="search-tip">输入关键词并回车进行搜索</p>
</div>
</div>
</div>
</div>
<script defer src="/js/bundle.min.ca22314448750e3cd87573167443c4f61447dd8c77fdb2a8ecf962e6e770a7b7.js"></script>
<script>
window.enableInfiniteScroll = false ;
</script>
<script async src="/js/bsz.js"></script>
</body>
</html>
-536
View File
@@ -1,536 +0,0 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1316&amp;path=livereload" data-no-instant defer></script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>友链</title>
<meta name="description" content="" />
<link rel="canonical" href="http://localhost:1316/links.html" /><meta name="keywords" content="大学,教程,blog,优世界,优设计,博客,大学生博客,生活,文案" />
<meta property="og:title" content="友链" />
<meta property="og:description" content="" />
<meta property="og:type" content="article" />
<meta property="og:url" content="http://localhost:1316/links.html" />
<meta property="og:site_name" content="优世界" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="友链" />
<meta name="twitter:description" content="" />
<link rel="alternate" type="application/rss+xml" title="优世界" href="/rss.xml">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<script async src="https://019e3dec-3312-7873-862a-3f56ac99ea83.spst2.com/ustat.js"></script>
<script>
(function () {
try {
var theme = localStorage.getItem('theme');
if (!theme) {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
theme = 'dark';
} else {
theme = 'light';
}
}
document.documentElement.setAttribute('data-theme', theme);
if (window.matchMedia) {
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
if (!localStorage.getItem('theme')) {
var newTheme = event.matches ? "dark" : "light";
document.documentElement.setAttribute('data-theme', newTheme);
}
});
}
} catch (e) {}
})();
</script>
<link rel="preload" href="/font/zql-v2.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/font/remixicon.woff2" as="font" type="font/woff2" crossorigin>
<script>
window.siteConfig = {
artalk: {
server: "https:\/\/artalk.usj.cc",
site: "优世界",
emoticons: "http:\/\/localhost:1316\/emotion\/OwO.json",
gravatar: "https:\/\/cravatar.cn\/avatar\/"
},
author: {
avatar: "\/image\/avatar\/tx7.jpg",
description: "不以物喜,不以己悲"
},
barrage: {
enableHitokoto: true ,
hitokotoUrl: "https:\/\/v1.hitokoto.cn?c=a\u0026c=b\u0026c=c\u0026c=d\u0026c=i"
}
};
</script>
<link rel="stylesheet" href="/css/style.min.7201c0e9ef7fa574d6fbab1efcb309790f11bbf063b86f0d8d36527afe7d209b.css">
<link rel="stylesheet" href="/css/libs/Artalk.min.c18a4adffe1319c3471e50565ff505ca8ca75eaf46d5661085de4918f94d6b4c.css"><style>
body, [data-theme="dark"] body {
background-image: url('/image/background/deno.webp') !important;
background-size: contain !important;
background-repeat: round !important;
background-position: center !important;
background-attachment: fixed !important;
}
</style><style>
@media only screen and (max-width: 768px) {
.items {
grid-template-columns: repeat(1, 1fr) !important;
grid-gap: 10px;
}
.link-des,.link-name{
right: 13px;
}
}
.items {
width: 100%;
height: 100%;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 10px;
justify-content: space-between;
}
.item-box {
background-color: white;
border-radius: 5px;
padding: 8px;
height: 300px;
box-shadow: rgba(14, 63, 126, 0.04) 0px 0px 0px 1px, rgba(42, 51, 69, 0.04) 0px 1px 1px -0.5px, rgba(42, 51, 70, 0.04) 0px 3px 3px -1.5px, rgba(42, 51, 70, 0.04) 0px 6px 6px -3px, rgba(14, 63, 126, 0.04) 0px 12px 12px -6px, rgba(14, 63, 126, 0.04) 0px 24px 24px -12px;
}
.website-img {
margin: 0 auto;
width: 90%;
}
.website-img img {
width: 100%;
height: 150px;
object-fit: contain;
}
.website-go-button {
margin: 0 auto;
width: 95%;
border-radius: 5px;
font-size: 14px;
padding: 5px;
text-align: center;
background-color: black;
color: white;
}
.link-info {
padding: 8px;
width: 100%;
height: 90px;
display: flex;
justify-content: center;
align-items: center;
}
.link-avatar {
width: 40%;
display: flex;
align-items: center;
}
.link-avatar img {
position: relative;
left: 5px;
width: 50px;
height: 50px;
}
.link-text-main {
width: 55%;
display: flex;
flex-direction: column;
}
.link-name {
position: relative;
right: 10px;
bottom: 5px;
width: 100%;
height: 50%;
font-weight: 600;
}
.link-des {
position: relative;
right: 10px;
top: 1px;
width: 100%;
height: 50%;
}
</style>
<script src="/js/instantpage.min.js" type="module" defer></script>
<script>console.log("\n %c Amigo Theme %c https://usj.cc \n", "color: #fadfa3; background: #030307; padding:3px; font-size:12px;", "color: #ffffff;background: #16171a; padding: 3px; font-size: 12px;");</script>
<meta name="template" content="Amigo" />
</head>
</head>
<body>
<script>
window.barrageConfig = {
enableHitokoto: true ,
hitokotoUrl: "https:\/\/v1.hitokoto.cn?c=a\u0026c=b\u0026c=c\u0026c=d\u0026c=i",
hitokotoAvatar: "\/image\/avatar\/tx7.jpg"
};
</script>
<div class="barrager"></div>
<div class="main">
<div class="container">
<div class="header">
<div class="header-top">
<div class="header-avatar load-memos-editor" id="theme-toggle-avatar">
<img src="/image/avatar/tx7.jpg" class="blog-img" width="80" height="80" alt="优世界" decoding="async" fetchpriority="high" />
<div class="avatar-theme-tip">
点击头像切换昼夜
</div>
</div>
<div class="header-info">
<div class="header-social ">
<a href="https://github.com/zqlit" title="GitHub" target="_blank"><i class="ri-github-fill"></i></a>
<a href="#" title="我的主页" target="_blank"><i class="ri-at-line"></i></a>
<a href="/rss.xml" title="Rss订阅" target="_blank"><i class="ri-rss-fill"></i></a>
</div>
<div class="header-bio ">不以物喜,不以己悲</div>
</div>
</div>
<nav class="header-menu">
<ul class="flat">
<li class="active "><a href="/">首页</a></li>
<li class="active "><a href="/about.html">关于</a></li>
<li class="active "><a href="/circles.html">友圈</a></li>
<li class="active "><a href="/comment.html">留言</a></li>
<li class="active "><a href="/archives.html">归档</a></li>
<li class="active "><a href="/links.html">友链</a></li>
</ul>
</nav>
</div>
<div id="pjax-wrapper" style="position: relative; min-height: 50vh;">
<div id="pjax-container">
<style>
.links ul>li {
position: relative;
padding-left: 1.75em;
}
.links a {
color: var(--link-color-light);
font-weight: 500;
text-decoration: none;
}
.links li {
margin-top: .5em;
margin-bottom: .5em;
}
.links ul>li:before {
content: "";
position: absolute;
background-color: #d1d5db;
border-radius: 50%;
width: .375em;
height: .375em;
top: .6875em;
left: .25em;
}
.url-name {
position: relative;
display: inline-block;
}
.url-name::before {
content: "";
position: absolute;
height: 12px;
bottom: 3px;
left: -4px;
z-index: -1;
background-color: #5d5d5d;
opacity: .3;
transform: skew(-35deg);
transition: opacity .2s ease;
border-radius: 3px 8px 10px 6px;
transition: 0.1s ease background-color;
width: 112%;
}
.url-name:hover::before {
opacity: 0.5;
}
[data-theme="dark"] .links a {
color: var(--link-color-dark);
}
[data-theme="dark"] .url-name::before {
background-color: #e5e7eb;
opacity: 0.18;
}
[data-theme="dark"] .url-name:hover::before {
opacity: 0.35;
}
</style>
<div class="post-content" itemprop="articleBody">
<div class="links">
<ul id="links-list" uk-scrollspy="target: > li; cls: uk-animation-slide-bottom-small; delay: 50">
</ul>
</div>
</div>
<script>
(function() {
var list = document.getElementById('links-list');
if (!list) return;
var CACHE_KEY = 'friend-links-v1';
var CACHE_OPTIONS = {
version: 2,
softTtl: 6 * 60 * 60 * 1000,
hardTtl: 24 * 60 * 60 * 1000,
validate: function(data) {
return !!data && Array.isArray(data.links);
}
};
function escapeHtml(value) {
return String(value || '')
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function renderState(message, className) {
list.innerHTML = '<li class="' + className + '">' + escapeHtml(message) + '</li>';
}
function renderLinks(links) {
if (!Array.isArray(links) || links.length === 0) {
renderState('暂无友链数据', 'links-empty');
return;
}
var html = '';
links.forEach(function(l) {
html += '<li><a href="' + escapeHtml(l.url) + '" class="url-name" target="_blank" rel="noopener noreferrer">' + escapeHtml(l.name) + '</a><span style="margin-left: 13px;">' + escapeHtml(l.description || '') + '</span></li>';
});
list.innerHTML = html;
}
function logCache(event, payload) {
if (window.BrowserCache && typeof window.BrowserCache.log === 'function') {
window.BrowserCache.log('[LinksCache][' + event + ']', payload);
}
}
function fetchLinks() {
logCache('fetch', {
key: window.BrowserCache ? window.BrowserCache.buildKey(CACHE_KEY) : CACHE_KEY,
softTtl: window.BrowserCache ? window.BrowserCache.formatDuration(CACHE_OPTIONS.softTtl) : CACHE_OPTIONS.softTtl,
hardTtl: window.BrowserCache ? window.BrowserCache.formatDuration(CACHE_OPTIONS.hardTtl) : CACHE_OPTIONS.hardTtl
});
return fetch('https://rssapi.usj.cc/api/links')
.then(function(res) {
if (!res.ok) throw new Error('Failed to fetch links');
return res.json();
})
.then(function(data) {
var links = Array.isArray(data.links) ? data.links : [];
var payload = { links: links };
window.BrowserCache.write(CACHE_KEY, CACHE_OPTIONS, payload);
return payload;
});
}
var cached = window.BrowserCache && window.BrowserCache.read(CACHE_KEY, CACHE_OPTIONS);
if (cached) {
logCache('render', {
key: cached.key,
age: cached.ageText,
isFresh: cached.isFresh,
softTtl: cached.softTtlText,
hardTtl: cached.hardTtlText
});
renderLinks(cached.data.links);
if (cached.isFresh) {
return;
}
} else {
renderState('友链加载中...', 'links-loading');
}
fetchLinks()
.then(function(payload) {
renderLinks(payload.links);
})
.catch(function(err) {
if (window.BrowserCache && window.BrowserCache.isDebug && window.BrowserCache.isDebug()) {
console.error('Links Error:', err);
}
if (!cached) {
renderState('友链加载失败,请稍后刷新重试', 'links-error');
}
});
})();
</script>
</div>
</div>
<div class="footer">
<nav class="nav" style="clear: both;">
© 2019 - 2026
<br>
<a href="https://beian.miit.gov.cn/" target="_blank"><span style="color:#999999;">鄂ICP备2022015735号-1</span></a>
<br>
本站由<a href="https://www.upyun.com/?utm_source=lianmeng&utm_medium=referral" target="blank" title="又拍云"
style="display:inline-block;text-decoration:none;height:20px;line-height:20px;">
<span style="color: var(--contentColor);font-weight: 700;">又拍云CDN</span>
</a>提供CDN加速服务
<br>
</nav>
</div>
</div>
</div>
<div class="floating-tools">
<a href="javascript:;" id="search-btn" title="搜索文章">
<i class="ri-search-line"></i>
</a>
<a href="javascript:;" id="theme-toggle" title="切换主题">
<i class="ri-sun-line"></i>
</a>
<a href="#Comments" id="to-comments" title="跳转评论">
<i class="ri-chat-2-line"></i>
</a>
<a href="#" id="back-to-top" title="返回顶部">
<i class="ri-arrow-up-line"></i>
</a>
</div>
<div id="search-modal" class="search-modal">
<div class="search-modal-content">
<div class="search-header">
<h3>搜索文章</h3>
<span class="close-search">&times;</span>
</div>
<div class="search-body">
<div class="search-input-wrapper">
<input type="text" id="search-input" placeholder="输入关键词搜索..." autocomplete="off">
<button id="search-submit"><i class="ri-search-line"></i></button>
</div>
<div id="search-results" class="search-results">
<p class="search-tip">输入关键词并回车进行搜索</p>
</div>
</div>
</div>
</div>
<script defer src="/js/bundle.min.ca22314448750e3cd87573167443c4f61447dd8c77fdb2a8ecf962e6e770a7b7.js"></script>
<script>
window.enableInfiniteScroll = false ;
</script>
<script async src="/js/bsz.js"></script>
</body>
</html>
-53
View File
@@ -3,7 +3,6 @@ const path = require('path');
const matter = require('gray-matter');
const axios = require('axios');
const FRIEND_CIRCLE_PATH = path.join(__dirname, '../themes/Ying/static/json/friend_circle_data.json');
const LINK_SUMMARY_PATH = path.join(__dirname, '../failed_links_summary.txt');
const POSTS_DIR = path.join(__dirname, '../content/post');
const HUGO_CONFIG_PATH = path.join(__dirname, '../hugo.toml');
@@ -341,58 +340,6 @@ async function main() {
console.error("Error reading link summary:", e);
}
try {
if (fs.existsSync(FRIEND_CIRCLE_PATH)) {
const data = JSON.parse(fs.readFileSync(FRIEND_CIRCLE_PATH, 'utf8'));
const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
const allPostsSorted = (data.posts || [])
.map(p => {
const dt = parseDateFlexible(p && p.date);
return Object.assign({}, p, { __date: dt });
})
.filter(p => p.__date instanceof Date && !Number.isNaN(p.__date.getTime()))
.sort((a, b) => b.__date.getTime() - a.__date.getTime());
const recentPosts = allPostsSorted.filter(post => post.__date > sevenDaysAgo);
const authorSet = new Set(recentPosts.map(p => p.author).filter(Boolean));
report += `### 👥 朋友圈近况 (近7天)\n`;
const circleMeta = getFileMetaString(FRIEND_CIRCLE_PATH);
if (circleMeta) report += `- 数据: ${circleMeta}\n`;
report += `- 更新: ${recentPosts.length} 条, 活跃作者: ${authorSet.size}\n`;
const toShow = recentPosts.length > 0 ? recentPosts : allPostsSorted;
if (toShow.length === 0) {
report += `无更新\n`;
report += `\n`;
} else {
if (recentPosts.length === 0) {
report += `- 近7天无更新,展示最近10条:\n`;
}
const limitedPosts = toShow.slice(0, 10);
limitedPosts.forEach(post => {
const dateStr = formatDateMDY(post.__date);
const author = post.author || '未知作者';
const link = post.link || post.url || '';
const blogUrl = post.blogUrl ? ` ${post.blogUrl}` : '';
if (link) {
report += `- [${author}] \`${link}\` (${dateStr})${blogUrl}\n`;
} else {
report += `- [${author}] (${dateStr})${blogUrl}\n`;
}
});
if (toShow.length > 10) {
report += `... 以及其他 ${toShow.length - 10} 篇\n`;
}
report += `\n`;
}
}
} catch (e) {
console.error("Error reading friend circle data:", e);
}
report += `### 🧩 环境\n`;
report += `- Node: ${process.version}\n`;
if (process.env.RUNNER_OS) report += `- Runner: ${process.env.RUNNER_OS}\n`;