- A 站点文案单例:content/site/{home,about,opensource}.yaml +
src/lib/site-content.ts 访问层(字段级回落默认,默认值=原文案逐字
一致,零回归);接线主页 tagline(en 首页新增该块)、关于页 intro、
开源页叙述三段 + PINNED 参数化(projects.ts: loadProjects(pinned)
/orderPinned,PINNED_DEFAULT 仅缺省兜底)
- loader 语义修正(返工如实入档):Astro 7 的 file() 把 YAML 顶层对象
按 Object.entries 拆成多条目(id=key、data=value),单例字段必炸
schema;改 glob 精确到单文件 = 真单例语义,data 即文件根对象,
Sveltia 可编辑根字段零嵌套(比包 main: 层的方案后台体验更好)
- B 文章媒体:posts +video/+poster;Sveltia file 字段
(media_folder=public/media、public_folder=/media、hint ≤50MB);
正文后渲染 video controls preload=metadata playsinline,无则不渲染;
图片链路核对本已一致(./assets 走 Astro 管线);链接 markdown 原生
- docs/写作指南.md 补「后台上传」节(三类媒体 + 三单例操作 + 体积纪律)
Sveltia 集合:posts / moments / photos / site_pages(三单例)
车道:op-gitea(实测 tagline 改 yaml 产物联动、置空回落默认、pinned
改名排序变、视频临时件渲染全对、构建绿 + lint 45 页 0/0/0);收编
复验:构建 44 页 + E2E 37/37 + 三 yaml 扁平键就位
验证: pnpm astro build 44 页 exit 0;E2E 37/37 PASS;content-lint
0/0/0;播放器/单例/置顶 playwright 实测全过
Spec: none (内容管理闭环,车道级交付)
Co-authored-by: GLM-5.3
170 lines
5.5 KiB
Plaintext
170 lines
5.5 KiB
Plaintext
---
|
|
// /en/ 首页:与 zh 版结构逐区对齐(名片区/文章列表/最新影像/热力图/项目墙)
|
|
import { Image } from 'astro:assets';
|
|
import { getCollection } from 'astro:content';
|
|
import BaseLayout from '../../layouts/BaseLayout.astro';
|
|
import IdCard from '../../components/IdCard.astro';
|
|
import PostList from '../../components/PostList.astro';
|
|
import ProjectWall from '../../components/geek/ProjectWall.astro';
|
|
import Heatmap from '../../components/geek/Heatmap.astro';
|
|
import { t } from '../../i18n/ui';
|
|
import { homeTagline } from '../../lib/site-content';
|
|
|
|
const posts = (await getCollection('posts', ({ data }) => !data.draft && !data.tags.includes('hidden'))).sort(
|
|
(a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime(),
|
|
);
|
|
// 列表标题吃 postsEn 译题(缺译回退 zh,与 /en/archives 同策略)
|
|
const enTitle = Object.fromEntries(
|
|
(await getCollection('postsEn')).map((e) => [e.id, e.data.title]),
|
|
);
|
|
const photos = (await getCollection('photos')).slice(0, 4);
|
|
// 身份语与 zh 版同源(content/site/home.yaml 的 en 字段),缺值回落默认
|
|
const tagline = await homeTagline('en');
|
|
---
|
|
|
|
<BaseLayout title="wait4x" description="wait4x's blog: reading · code · photography">
|
|
<IdCard>
|
|
<p class="tagline">{tagline}</p>
|
|
<div class="socials">
|
|
<a
|
|
class="tap social"
|
|
href="https://github.com/wait4xx"
|
|
rel="noopener noreferrer"
|
|
aria-label="GitHub"
|
|
title="GitHub"
|
|
>
|
|
<svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true">
|
|
<path
|
|
d="M12 2C6.48 2 2 6.58 2 12.25c0 4.53 2.87 8.37 6.84 9.73.5.1.68-.22.68-.49 0-.24-.01-.88-.01-1.73-2.78.62-3.37-1.37-3.37-1.37-.45-1.18-1.11-1.5-1.11-1.5-.91-.63.07-.62.07-.62 1 .07 1.53 1.06 1.53 1.06.89 1.57 2.34 1.12 2.91.85.09-.66.35-1.11.63-1.37-2.22-.26-4.56-1.14-4.56-5.07 0-1.12.39-2.03 1.03-2.75-.1-.26-.45-1.3.1-2.7 0 0 .84-.28 2.75 1.05a9.3 9.3 0 0 1 5 0c1.91-1.33 2.75-1.05 2.75-1.05.55 1.4.2 2.44.1 2.7.64.72 1.03 1.63 1.03 2.75 0 3.94-2.34 4.8-4.57 5.06.36.32.68.94.68 1.9 0 1.37-.01 2.47-.01 2.81 0 .27.18.6.69.49A10.26 10.26 0 0 0 22 12.25C22 6.58 17.52 2 12 2Z"
|
|
></path>
|
|
</svg>
|
|
</a>
|
|
<a class="tap social" href="/en/rss.xml" aria-label="RSS feed" title="RSS feed">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
width="16"
|
|
height="16"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="1.8"
|
|
stroke-linecap="round"
|
|
aria-hidden="true"
|
|
>
|
|
<path d="M4 11.5a8.5 8.5 0 0 1 8.5 8.5M4 4.5a15.5 15.5 0 0 1 15.5 15.5"></path>
|
|
<circle cx="5.4" cy="18.6" r="1.5" fill="currentColor" stroke="none"></circle>
|
|
</svg>
|
|
</a>
|
|
<a class="tap social" href="mailto:admin@wait4x.online" aria-label="Email" title="Email">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
width="16"
|
|
height="16"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="1.8"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
aria-hidden="true"
|
|
>
|
|
<rect x="3" y="5.5" width="18" height="13" rx="2.5"></rect>
|
|
<path d="m4 7.5 8 5.5 8-5.5"></path>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
</IdCard>
|
|
|
|
<PostList {posts} locale="en" titleOverrides={enTitle} limit={6} moreHref="/en/archives/" />
|
|
|
|
<section class="latest" aria-label={t('latest_photos', 'en')}>
|
|
<div class="latest-head">
|
|
<span class="lab">{t('latest_photos', 'en')}</span>
|
|
<a class="tap more" href="/en/gallery/">{t('enter_gallery', 'en')}</a>
|
|
</div>
|
|
<div class="thumbs">
|
|
{photos.map((photo) => (
|
|
<a class="thumb" href="/en/gallery/" aria-label={`Gallery: ${photo.data.title}`}>
|
|
<Image
|
|
src={photo.data.image}
|
|
alt={photo.data.alt ?? photo.data.title}
|
|
widths={[180, 360]}
|
|
sizes="(min-width: 820px) 20vw, 42vw"
|
|
/>
|
|
</a>
|
|
))}
|
|
</div>
|
|
</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'),
|
|
}}
|
|
/>
|
|
<ProjectWall locale="en" />
|
|
</BaseLayout>
|
|
|
|
<style>
|
|
.tagline {
|
|
font-size: 14px;
|
|
color: var(--ink-3);
|
|
margin-top: 4px;
|
|
letter-spacing: 0.01em;
|
|
}
|
|
.socials {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
margin-top: var(--space-2);
|
|
}
|
|
.social {
|
|
color: var(--ink-3);
|
|
border-radius: 8px;
|
|
transition: color var(--dur) var(--ease);
|
|
}
|
|
.social:hover { color: var(--accent); }
|
|
|
|
.latest { margin-top: var(--space-6); }
|
|
.latest-head {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: var(--space-3);
|
|
}
|
|
.lab {
|
|
font-size: 12.5px;
|
|
color: var(--ink-4);
|
|
letter-spacing: 0.08em;
|
|
}
|
|
.more {
|
|
font-size: 13px;
|
|
color: var(--accent);
|
|
padding-inline: var(--space-2);
|
|
transition: color var(--dur) var(--ease);
|
|
}
|
|
.more:hover { color: var(--ink-1); }
|
|
.thumbs {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: var(--space-2);
|
|
margin-top: var(--space-3);
|
|
}
|
|
.thumb {
|
|
aspect-ratio: 1;
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
}
|
|
.thumb :global(img) {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
transition: transform var(--dur) var(--ease);
|
|
}
|
|
.thumb:hover :global(img) { transform: scale(1.03); }
|
|
@media (min-width: 820px) {
|
|
.thumbs { grid-template-columns: repeat(4, 1fr); }
|
|
}
|
|
</style>
|