<style>
:root {
--primary-blue: #2563eb;
--card-h: 320px;
}
.home-grid-box {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px;
margin: 10px 3px;
font-family: 'Segoe UI', system-ui, sans-serif;
}
.g-card {
background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
height: var(--card-h);
overflow: hidden;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
/* 广告区块 */
.ad-box {
grid-column: 1 / -1;
background: #f9f9f9;
border: 1px dashed #ccc;
border-radius: 4px;
min-height: 100px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
margin: 5px 0;
}
.ad-label { position: absolute; top: 0; left: 0; background: #eee; font-size: 10px; color: #999; padding: 2px 5px; }
/* Header 样式 */
.c-header {
display: flex; justify-content: space-between; align-items: center;
border-bottom: 2px solid var(--primary-blue);
margin: 0; padding: 10px 15px; background: #fcfcfc; flex-shrink: 0;
}
.c-header-title { display: flex; align-items: center; gap: 8px; text-decoration: none; color: #333; }
.c-header-title h3 { margin: 0; font-size: 16px; font-weight: 600; }
.title-svg { width: 18px; height: 18px; fill: var(--primary-blue); }
.c-more-btn {
display: flex; align-items: center; justify-content: center;
width: 24px; height: 24px; border-radius: 50%;
background: #eee; color: #666; transition: all 0.3s; text-decoration: none;
}
.c-more-btn:hover { background: var(--primary-blue); color: #fff; }
/* 列表样式 */
.c-list { list-style: none; padding: 5px 15px; margin: 0; flex-grow: 1; overflow: hidden; }
.c-item { border-bottom: 1px dashed #eee; padding: 11px 0; display: flex; align-items: center; justify-content: space-between; font-size: 16px; }
.c-link-wrap { display: flex; align-items: center; overflow: hidden; text-decoration: none; color: #444; }
.c-link-wrap:hover { color: var(--primary-blue); }
.c-icon { width: 6px; height: 6px; background-color: var(--primary-blue); border-radius: 1px; margin-right: 10px; flex-shrink: 0; }
.c-title-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.c-date { font-size: 12px; color: #999; margin-left: 15px; flex-shrink: 0; font-family: 'Courier New', monospace; }
/* 轮播图 */
.s-container { width: 100%; flex-grow: 1; position: relative; background: #333; }
.s-item { position: absolute; top:0; left:0; width:100%; height:100%; opacity: 0; transition: opacity 0.8s ease; background-size: cover; background-position: center; }
.s-item.active { opacity: 1; z-index: 2; }
.s-caption { position: absolute; bottom: 0; left: 0; right: 0; background: linear-gradient(transparent, rgba(0,0,0,0.8)); padding: 25px 15px 12px; color: #fff; font-size: 15px; font-weight: bold; }
@media (max-width: 768px) {
.home-grid-box { grid-template-columns: 1fr; }
:root { --card-h: auto; }
.g-card:first-child { height: 240px; }
.s-container { height: 200px; }
.ad-box { grid-column: auto; }
}
</style>
<div class="home-grid-box">
<div class="g-card">
<div class="c-header">
<a class="c-header-title" href="/search">
<svg class="title-svg" viewbox="0 0 24 24"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></path></svg>
<h3>图片关注</h3>
</a>
<a class="c-more-btn" href="/search"><svg width="12" height="12" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M9 18l6-6-6-6"/></path></svg></a>
</div>
<div class="s-container" id="hdSlider">
<div style="padding:20px; color:#999; text-align:center;">正在筛选图文...</div>
</div>
</div>
<div class="g-card">
<div class="c-header">
<a class="c-header-title" href="/search">
<svg class="title-svg" viewbox="0 0 24 24"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"/></path></svg>
<h3>最新日志</h3>
</a>
<a class="c-more-btn" href="/search"><svg width="12" height="12" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M9 18l6-6-6-6"/></path></svg></a>
</div>
<ul class="c-list" id="list-recent"></ul>
</div>
<div class="g-card" data-label="标签名称">
<div class="c-header">
<a class="c-header-title" href="/search/label/标签名称">
<svg class="title-svg" viewbox="0 0 24 24"><path d="M13 12h7v1.5h-7zm0-2.5h7V11h-7zm0 5h7V16h-7zM21 4H3c-1.1 0-2 .9-2 2v13c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 15h-9V6h9v13z"/></path></svg>
<h3>标签名称</h3>
</a>
<a class="c-more-btn" href="/search/label/文言批注"><svg width="12" height="12" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M9 18l6-6-6-6"/></path></svg></a>
</div>
<ul class="c-list"></ul>
</div>
<div class="g-card" data-label="标签名称">
<div class="c-header">
<a class="c-header-title" href="/search/label/标签名称">
<svg class="title-svg" viewbox="0 0 24 24"><path d="M12 3c-4.42 0-8 3.58-8 8v7c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-7c0-4.42-3.58-8-8-8zm0 2c3.31 0 6 2.69 6 6v1H6v-1c0-3.31 2.69-6 6-6z"/></path></svg>
<h3>标签名称</h3>
</a>
<a class="c-more-btn" href="/search/label/标签名称"><svg width="12" height="12" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M9 18l6-6-6-6"/></path></svg></a>
</div>
<ul class="c-list"></ul>
</div>
<div class="ad-box">
<div class="ad-label">AD</div>
<div id="ad-content" style="width:100%; text-align:center; color:#999;">广告内容位</div>
</div>
<div class="g-card" data-label="标签名称">
<div class="c-header">
<a class="c-header-title" href="/search/label/标签名称">
<svg class="title-svg" viewbox="0 0 24 24"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/></path></svg>
<h3>标签名称</h3>
</a>
<a class="c-more-btn" href="/search/label/标签名称"><svg width="12" height="12" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M9 18l6-6-6-6"/></path></svg></a>
</div>
<ul class="c-list"></ul>
</div>
<div class="g-card" data-label="标签名称">
<div class="c-header">
<a class="c-header-title" href="/search/label/标签名称">
<svg class="title-svg" viewbox="0 0 24 24"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></path></svg>
<h3>标签名称</h3>
</a>
<a class="c-more-btn" href="/search/label/标签名称"><svg width="12" height="12" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M9 18l6-6-6-6"/></path></svg></a>
</div>
<ul class="c-list"></ul>
</div>
<div class="g-card" data-label="标签名称">
<div class="c-header">
<a class="c-header-title" href="/search/label/标签名称">
<svg class="title-svg" viewbox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></path></svg>
<h3>标签名称</h3>
</a>
<a class="c-more-btn" href="/search/label/标签名称"><svg width="12" height="12" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M9 18l6-6-6-6"/></path></svg></a>
</div>
<ul class="c-list"></ul>
</div>
<div class="g-card" data-label="标签名称">
<div class="c-header">
<a class="c-header-title" href="/search/label/标签名称">
<svg class="title-svg" viewbox="0 0 24 24"><path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></path></svg>
<h3>标签名称</h3>
</a>
<a class="c-more-btn" href="/search/label/标签名称"><svg width="12" height="12" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M9 18l6-6-6-6"/></path></svg></a>
</div>
<ul class="c-list"></ul>
</div>
</div>
<script>
(function() {
// 通用的 Feed 请求路径,使用 alt=json 格式
const getFeedPath = (label = null) => {
const base = '/feeds/posts/default';
const suffix = '?alt=json&max-results=6';
return label ? `${base}/-/${encodeURIComponent(label)}${suffix}` : `${base}${suffix}`;
};
const getSpeedyImg = (entry) => {
let imgUrl = null;
if (entry.media$thumbnail) {
imgUrl = entry.media$thumbnail.url.replace(/\/s[0-9]+.*?\//, '/s1600/');
} else if (entry.content && entry.content.$t.includes('<img')) {
const match = entry.content.$t.match(/src=["'](.*?)["']/);
if (match) imgUrl = match[1];
}
if (imgUrl && (imgUrl.includes('blogspot.com') || imgUrl.includes('googleusercontent.com'))) {
return `https://wsrv.nl/?url=${encodeURIComponent(imgUrl)}&af&output=webp&q=75`;
}
return imgUrl;
};
const formatMMDD = (dateStr) => {
const d = new Date(dateStr);
return `${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')}`;
};
const getT = (e) => e.title.$t || e.title || "Untitled";
const getL = (e) => (e.link.find(l => l.rel === 'alternate') || {href:"#"}).href;
const renderList = (entries) => {
if(!entries || entries.length === 0) return '<li class="c-item" style="color:#999;border:none;">暂无内容</li>';
return entries.slice(0, 6).map(e => `
<li class="c-item">
<a class="c-link-wrap" href="${getL(e)}">
<span class="c-icon"></span>
<span class="c-title-text">${getT(e)}</span>
</a>
<span class="c-date">${e.published ? formatMMDD(e.published.$t) : '--'}</span>
</li>
`).join('');
};
// 1. 获取主数据及轮播(仅有图文章)
fetch(getFeedPath() + '&max-results=25')
.then(res => res.json())
.then(data => {
const allEntries = data.feed.entry || [];
const slider = document.getElementById('hdSlider');
// 过滤有图文章用于轮播
const imgEntries = allEntries.filter(e => {
return e.media$thumbnail || (e.content && e.content.$t.includes('<img'));
}).slice(0, 4);
if(imgEntries.length > 0) {
slider.innerHTML = imgEntries.map((e, i) => `
<a href="${getL(e)}" class="s-item ${i===0?'active':''}" style="background-image:url(${getSpeedyImg(e)})">
<div class="s-caption">${getT(e)}</div>
</a>
`).join('');
if(imgEntries.length >= 2) startS();
} else {
slider.innerHTML = '<div style="padding:20px; color:#999; text-align:center;">暂无图文</div>';
}
document.getElementById('list-recent').innerHTML = renderList(allEntries);
});
// 2. 自动化获取所有分类区块
document.querySelectorAll('.g-card[data-label]').forEach(card => {
const label = card.dataset.label;
const ul = card.querySelector('.c-list');
fetch(getFeedPath(label))
.then(res => res.json())
.then(data => {
ul.innerHTML = renderList(data.feed.entry || []);
})
.catch(() => { ul.innerHTML = renderList([]); });
});
function startS() {
let cur = 0;
setInterval(() => {
const items = document.querySelectorAll('.s-item');
if(items.length < 2) return;
items[cur].classList.remove('active');
cur = (cur + 1) % items.length;
items[cur].classList.add('active');
}, 5000);
}
})();
</script>