feat: 优化首页个人名片与内容入口

This commit is contained in:
2026-07-16 23:51:55 +08:00
parent 92360e4f49
commit 991264c32c
25 changed files with 1158 additions and 130 deletions
+80
View File
@@ -0,0 +1,80 @@
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { siteConfig } from '~/config/site'
import { formatPostDate, getArchiveGroups, isVisiblePost } from '~/utils/posts'
useSeoMeta({
title: `归档 - ${siteConfig.siteName}`,
description: `${siteConfig.siteName} 的文章时间线`,
})
const { data: posts } = await useAsyncData('archive-posts', () =>
queryCollection('posts')
.order('published', 'DESC')
.all()
)
const archiveGroups = computed(() => getArchiveGroups((posts.value || []).filter(isVisiblePost)))
const totalPosts = computed(() =>
archiveGroups.value.reduce((total, year) => total + year.months.reduce((sum, month) => sum + month.posts.length, 0), 0)
)
</script>
<template>
<div class="container mx-auto max-w-4xl px-4 py-12">
<header class="mb-12 text-center anim-fade-in-up">
<h1 class="mb-4 text-4xl font-bold">文章归档</h1>
<p class="text-muted-foreground">按时间整理所有文章方便回头翻旧账</p>
<p class="mt-2 text-sm text-muted-foreground"> {{ totalPosts }} 篇文章</p>
</header>
<div v-if="archiveGroups.length" class="space-y-10 anim-fade-in-up anim-delay-1">
<section v-for="year in archiveGroups" :key="year.year">
<div class="mb-5 flex items-center gap-3">
<h2 class="text-2xl font-bold">{{ year.year }}</h2>
<span class="h-px flex-1" style="background-color: var(--color-border);" />
</div>
<div class="space-y-6">
<div v-for="month in year.months" :key="`${year.year}-${month.month}`" class="grid gap-4 md:grid-cols-[6rem_1fr]">
<div class="text-sm font-medium text-muted-foreground">{{ month.label }}</div>
<div class="space-y-3">
<NuxtLink
v-for="post in month.posts"
:key="post.path || post.id"
:to="post.path || '/posts'"
class="group block rounded-lg border p-4 transition-colors hover:bg-muted"
style="border-color: var(--color-border);"
>
<div class="mb-2 flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
<time v-if="post.published">{{ formatPostDate(post.published) }}</time>
<span v-if="post.series">· {{ post.series }}</span>
<span v-if="post.difficulty">· {{ post.difficulty }}</span>
</div>
<h3 class="font-semibold transition-opacity group-hover:opacity-70">
{{ post.title }}
</h3>
<p v-if="post.description" class="mt-1 text-sm text-muted-foreground">
{{ post.description }}
</p>
<div v-if="post.tags?.length" class="mt-3 flex flex-wrap gap-1.5">
<span v-for="tag in post.tags" :key="tag" class="tag-pill">
{{ tag }}
</span>
</div>
</NuxtLink>
</div>
</div>
</div>
</section>
</div>
<div v-else class="rounded-xl border p-8 text-center text-muted-foreground anim-fade-in-up anim-delay-1" style="border-color: var(--color-border); background-color: var(--color-bg-card);">
<Icon icon="mdi:archive-outline" class="mx-auto mb-3 h-8 w-8" />
暂无可归档文章
</div>
</div>
</template>