Files
SuBlog/pages/archive.vue
T

81 lines
3.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>