Files
blog/themes/Ying/layouts/page/links.html
T
2026-05-25 13:06:26 +08:00

269 lines
7.4 KiB
HTML

{{ define "main" }}
<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;
}
@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>
<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://api.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>
{{ end }}