From 3b951d3de6ff798d26417d668522b08cdec1dd3d Mon Sep 17 00:00:00 2001 From: wait4xx Date: Mon, 2 Nov 2026 10:00:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(archive):=20=E6=96=87=E7=AB=A0=E6=8A=98?= =?UTF-8?q?=E5=8F=A0=E2=80=94=E2=80=94=E9=A6=96=E9=A1=B5=206=20=E7=AF=87+?= =?UTF-8?q?=E5=BD=92=E6=A1=A3=E5=B9=B4=E6=9C=88=E6=8A=98=E5=8F=A0+?= =?UTF-8?q?=E4=B9=A6=E6=9E=B6=E5=B9=B4=E6=8A=98=E5=8F=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ①首页 PostList limit=6 + 「全部文章 →」双轨入口(用户拍板 6 篇) ②/archives 年
(最新年 open,summary「2026 · N 篇」+▸ 自绘 箭头)+ 年内按月分组小标题;零 JS 依赖、内容全在 DOM(SEO 无损)③/books 年折叠(色脊/书封渲染零改动)④E2E +3 断言 (首页≤6+入口/归档 open 唯一+月分组/书架年组不变量) E2E 弦键竞态根治:折叠批的多次导航扰动 g-chords 时序——洁净起 点(先回稳定页)再测弦,测试意图不依赖前序状态,37/37 连跑稳定 车道:op-gitea(lint 43 页 0/0/0);收编复验首页 6 行+入口/归档 1 年开 12 月组/书架年折叠/en 轨全过 验证: E2E 37/37 连跑两次;content-lint 0/0/0;首页/归档/书架/ en 四页 playwright 实测 Spec: none (折叠批,车道级交付) Co-authored-by: GLM-5.3 --- src/components/PostList.astro | 216 ++++++++++++++++++++++----- src/components/pages/BooksPage.astro | 39 ++++- src/i18n/ui.ts | 3 + src/pages/archives/index.astro | 4 +- src/pages/en/archives/index.astro | 2 +- src/pages/en/index.astro | 2 +- src/pages/index.astro | 2 +- tests/e2e.mjs | 46 +++++- 8 files changed, 257 insertions(+), 57 deletions(-) diff --git a/src/components/PostList.astro b/src/components/PostList.astro index e6ba575..0bab26f 100644 --- a/src/components/PostList.astro +++ b/src/components/PostList.astro @@ -1,6 +1,9 @@ --- -// 年份分组 + 轨道分节的文章列表(首页与 /archives/ 共用) +// 年份分组 + 轨道分节的文章列表(首页与归档页共用) // 轨道标签单一事实源:content.config 的 POST_TRACKS,此处不另立词表 +// 双形态(2026-11-02 用户拍板折叠需求): +// 默认形态 = 首页/列表平铺(年 → 轨道分节),可 limit 截断 + moreHref 出口 +// fold 形态 = 归档页:按年
(最新年默认开)+ 年内按月分组,零 JS 原生折叠 import type { CollectionEntry } from 'astro:content'; import { POST_TRACKS, type PostCategory } from '../content.config'; import { t } from '../i18n/ui'; @@ -11,8 +14,15 @@ interface Props { locale?: 'zh' | 'en'; /** slug → 译题(en 列表显示英文标题,视觉复核范围外观察) */ titleOverrides?: Record; + /** 截断条数(首页 6 篇);缺省全量 */ + limit?: number; + /** 截断后的「全部文章 →」出口链接;缺省不渲染 */ + moreHref?: string; + /** true = 归档折叠形态:按年 details(最新年开)+年内按月分组 */ + fold?: boolean; } -const { posts, locale = 'zh', titleOverrides } = Astro.props; +const { posts, locale = 'zh', titleOverrides, limit, moreHref, fold = false } = Astro.props; +const visible = typeof limit === 'number' ? posts.slice(0, limit) : posts; // 轨道标签走字典(en 首页复用本组件时的双语位);zh 保持原词表语义 const TRACK_LABEL: Record = { reading: t('category_reading', locale), @@ -22,59 +32,125 @@ const TRACK_LABEL: Record = { const hrefOf = (id: string) => (locale === 'en' ? `/en/archives/${id}/` : `/archives/${id}/`); const byYear = new Map[]>(); -for (const post of posts) { +for (const post of visible) { const year = post.data.pubDate.getUTCFullYear(); const bucket = byYear.get(year); if (bucket) bucket.push(post); else byYear.set(year, [post]); } +const units = t('unit_posts', locale); const mmdd = (d: Date) => `${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`; +// 月分组标签:zh「2026 年 11 月」/ en「November 2026」(UTC,与年份口径一致) +const monthLabel = (d: Date) => + locale === 'zh' + ? `${d.getUTCFullYear()} 年 ${d.getUTCMonth() + 1} 月` + : `${d.toLocaleString('en-US', { month: 'long', timeZone: 'UTC' })} ${d.getUTCFullYear()}`; +const byMonth = (list: CollectionEntry<'posts'>[]) => { + const m = new Map[]>(); + for (const post of list) { + const key = `${post.data.pubDate.getUTCFullYear()}-${post.data.pubDate.getUTCMonth()}`; + const bucket = m.get(key); + if (bucket) bucket.push(post); + else m.set(key, [post]); + } + return [...m.entries()]; +}; --- -
- {[...byYear.entries()].map(([year, list]) => ( -
-

{year}

- {(Object.keys(POST_TRACKS) as PostCategory[]).map((cat) => { - const rows = list.filter((post) => post.data.category === cat); - if (rows.length === 0) return null; - return ( -
-

+{fold ? ( +
+ {[...byYear.entries()].map(([year, list], i) => ( +
+ + {year} + · {list.length} {units} + +
+ {byMonth(list).map(([key, rows]) => ( +
+

+ {monthLabel(rows[0].data.pubDate)} + · {rows.length} {units} +

+