- 热力图:桌面 10px 格+2px 缝收进版心(53 列 634px 无横滚——唯一有
数据的最新列曾被裁在滚出区呈空表);移动端锚定 scrollLeft 到最新列
- en 首页补 IdCard 名片区 + Latest photos 影像条(视觉复核版面平权建议)
- en/index 重复导入 getCollection 修复(构建炸点)
验证: pnpm astro build 21 页 exit 0;node tests/e2e.mjs 30/30 PASS
(新构建全链)
Spec: 2026-10-25_fix-site-polish
Co-authored-by: GLM-5.3
87 lines
4.0 KiB
Plaintext
87 lines
4.0 KiB
Plaintext
---
|
|
// /en/ 首页:英文 UI + 双语内容(postsEn 优先,缺则中文回退)
|
|
import { getCollection } from 'astro:content';
|
|
import BaseLayout from '../../layouts/BaseLayout.astro';
|
|
import { t } from '../../i18n/ui';
|
|
import IdCard from '../../components/IdCard.astro';
|
|
import { Image } from 'astro:assets';
|
|
const photos = (await getCollection('photos')).slice(0, 4);
|
|
import Heatmap from '../../components/geek/Heatmap.astro';
|
|
import { POST_TRACKS, trackOf } from '../../content.config';
|
|
|
|
const en = await getCollection('postsEn');
|
|
const zh = await getCollection('posts');
|
|
const bySlug = new Map(en.map((e) => [e.id, e]));
|
|
const posts = zh
|
|
.filter(({ data }) => !data.draft)
|
|
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf())
|
|
.map((p) => ({ zh: p, en: bySlug.get(p.id) }));
|
|
|
|
const years = [...new Set(posts.map((p) => p.zh.data.pubDate.getFullYear()))].sort((a, b) => b - a);
|
|
const t9 = (cat: keyof typeof POST_TRACKS) => trackOf(cat);
|
|
---
|
|
|
|
<BaseLayout title="wait4x" description="wait4x's blog: reading · code · photography" track="tech">
|
|
<h1 class="visually-hidden">wait4x</h1>
|
|
<IdCard>
|
|
<a href="https://github.com/wait4xx" rel="noopener noreferrer" aria-label="GitHub">↗</a>
|
|
<a href="/en/rss.xml" aria-label="RSS">RSS</a>
|
|
</IdCard>
|
|
{years.map((year) => (
|
|
<section class="latest" aria-label={t('latest_photos', 'en')}>
|
|
<span class="lab">{t('latest_photos', 'en')}</span>
|
|
<a href="/en/gallery/">{t('enter_gallery', 'en')}</a>
|
|
<div class="strip">
|
|
{photos.map((p) => (<a href="/en/gallery/"><Image src={p.data.image} alt={p.data.alt ?? p.data.title} widths={[160, 320]} sizes="20vw" loading="lazy" /></a>))}
|
|
</div>
|
|
</section>
|
|
<section class="year">
|
|
<h2 class="y-label">{year}</h2>
|
|
{(['reading', 'tech', 'photo'] as const).map((cat) => {
|
|
const list = posts.filter((p) => p.zh.data.category === cat && p.zh.data.pubDate.getFullYear() === year);
|
|
return list.length ? (
|
|
<>
|
|
<h3 class="track">{t(cat === 'reading' ? 'category_reading' : cat === 'tech' ? 'category_tech' : 'category_photo', 'en')}</h3>
|
|
<ul class="plist">
|
|
{list.map(({ zh: p, en: e }) => (
|
|
<li>
|
|
<a href={`/en/archives/${p.id}/`} class="plink">
|
|
<span class="ptitle" style={p.data.mood ? `--mood:${p.data.mood}` : undefined}>
|
|
{p.data.mood && <i class="mdot" aria-hidden="true" />}
|
|
{e?.data.title ?? p.data.title}
|
|
</span>
|
|
{!e && <i class="fall">zh</i>}
|
|
<time class="pdate">{p.data.pubDate.toISOString().slice(5, 10)}</time>
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</>
|
|
) : null;
|
|
})}
|
|
</section>
|
|
))}
|
|
<Heatmap
|
|
labels={{
|
|
title: t('heatmap_title', 'en'),
|
|
summary: t('heatmap_summary', 'en'),
|
|
less: t('heatmap_less', 'en'),
|
|
more: t('heatmap_more', 'en'),
|
|
note: t('heatmap_note', 'en'),
|
|
}}
|
|
/>
|
|
</BaseLayout>
|
|
|
|
<style>
|
|
.year { margin-top: var(--space-5); }
|
|
.y-label { font-family: var(--font-mono); font-size: 20px; color: var(--ink-1); }
|
|
.track { font-size: 13px; color: var(--ink-3); margin: var(--space-3) 0 var(--space-2); letter-spacing: 0.06em; }
|
|
.plist { list-style: none; padding: 0; display: grid; gap: var(--space-1); }
|
|
.plink { display: flex; align-items: baseline; gap: var(--space-2); padding-block: var(--space-1); }
|
|
.plink:hover .ptitle { color: var(--accent); }
|
|
.ptitle { color: var(--ink-1); transition: color var(--dur) var(--ease); }
|
|
.mdot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--mood, var(--ink-4)); margin-right: 6px; }
|
|
.fall { font-family: var(--font-mono); font-size: 10px; color: var(--ink-4); border: 1px solid var(--line); border-radius: 3px; padding: 0 3px; font-style: normal; }
|
|
.pdate { margin-left: auto; font-family: var(--font-mono); font-size: 12px; color: var(--ink-3); }
|
|
</style>
|