当前站点已经不是只有一个文章列表页了。现在至少有这几种“列表型页面”:
- 首页的最新文章
- 首页的最新系列章节
- 系列列表页
这些页面的数据来源不同,但有一部分都属于“浏览几个最新条目或目录项”。当前仓库的做法,是先把共同的卡片 UI 抽成 ContentCardList.astro,再让 page view 组件只负责喂数据。首页和系列总览现在都继续走卡片流;文章页和归档页则因为要强调日期、分类与分页,独立成了更高密度的索引列表组件。
卡片组件只认统一输入
ContentCardList 的输入很小:
export type ContentCardItem = {
href: string;
eyebrow?: string;
title: string;
description?: string;
meta?: string;
};
再加两个控制项:
emptyLabellayout?: "stack" | "grid"
这意味着无论卡片来自首页摘要还是系列目录项,只要先被映射成这几个字段,就能被同一个组件渲染。
组件层只管渲染,不管来源
ContentCardList.astro 本身不知道文章来自哪里,也不知道系列有什么区别。它只做这些事:
- 有内容时渲染卡片列表
- 没有内容时显示空状态文本
- 根据
layout决定是纵向堆叠还是响应式网格
核心结构如下:
{items.length > 0 ? (
<div class:list={["content-card-list", layout === "grid" && "content-card-list-grid"]}>
{items.map((item) => (
<a class="content-card" href={item.href}>
<div class="content-card-body">
{item.eyebrow ? <p class="content-card-eyebrow">{item.eyebrow}</p> : null}
<h2>{item.title}</h2>
{item.description ? <p class="content-card-description">{item.description}</p> : null}
{item.meta ? <p class="content-card-meta">{item.meta}</p> : null}
</div>
</a>
))}
</div>
) : (
<p>{emptyLabel}</p>
)}
这里的设计重点,是把“信息结构”稳定下来,而不是在组件里判断一堆内容类型。
首页用两组数据,复用一套卡片
HomePageView.astro 现在同时组合两块数据:
getPublishedArticles().slice(0, 4)getLatestSeriesChapters(4)
但最终都被整理成卡片项交给 ContentCardList。而 section 标题本身则交给 PageSectionHeader,因此首页只是把两个 feed 摆进稳定的区块骨架里,并不需要为“最新文章”和“最新章节”各写一套列表组件。
系列目录仍然适合卡片流
后来文章页和归档页都改成了更高密度的索引列表,但系列目录和首页摘要仍然更适合卡片流,因为它们更像“浏览入口”而不是“时间归档”。
SeriesPageView.astro 现在也重新回到 ContentCardList,与首页摘要共用同一套浏览入口卡片语言。
这也说明了一件事:组件复用并不意味着所有列表都必须长得一样,关键是让“浏览入口”和“归档索引”各自用对信息密度。
归档页后来单独拆出
一开始归档页也能复用卡片组件,因为它同样只是“把数据映射成统一字段再渲染”。但当归档页需要强调这些信息时:
- 年份分组
- 明确的发布日期
- 文章分类
- 系列章节所属系列
卡片流就开始显得不够紧凑。于是归档页后来改成了专用的时间序列组件,保留统一页面壳层,但不再强行复用 ContentCardList。
这个变化也说明了一件事:统一组件很有用,但当页面任务从“浏览最近内容”转成“按时间查找全部内容”时,视觉密度和信息结构也应该跟着变化。
Page view 组件因此保持很薄
当前和卡片直接相关的 src/components/pages/ 文件主要是:
HomePageView.astroSeriesPageView.astro
本质上都在做同一件事:
- 读取数据
- 选用页面文案
- 把数据映射成卡片项
- 交给通用组件渲染
这也是为什么路由文件现在能薄到只剩一句:
<SeriesPageView locale="zh" />
这种拆法的好处
当前结构把变化点分得很清楚:
- 如果改视觉,就改
ContentCardList - 如果改归档时间线,就改归档专用组件
- 如果改数据排序或来源,就改
lib/* - 如果改页面组合,就改 page view
这样首页和系列页虽然都在展示“内容卡片”,但不会因为共用一个组件而互相缠死;而文章页和归档页也能在需要更高密度时独立演化。