74 lines
2.3 KiB
Vue
74 lines
2.3 KiB
Vue
<template>
|
|
<div class="min-h-screen bg-[#0a0a0a] text-zinc-100">
|
|
<div class="max-w-4xl mx-auto px-4 py-10 space-y-8">
|
|
<div class="flex items-end justify-between gap-4">
|
|
<div>
|
|
<h1 class="text-3xl font-black tracking-tight">更新日志</h1>
|
|
<p class="text-sm text-zinc-500 mt-2">记录每次更新的内容与说明</p>
|
|
</div>
|
|
<NuxtLink to="/" class="text-sm text-blue-400 hover:text-blue-300 font-semibold">
|
|
返回首页
|
|
</NuxtLink>
|
|
</div>
|
|
|
|
<div v-if="loading" class="py-10 text-center text-zinc-500">加载中...</div>
|
|
|
|
<div v-else-if="entries.length === 0" class="py-10 text-center text-zinc-500">
|
|
暂无已发布更新日志
|
|
</div>
|
|
|
|
<div v-else class="space-y-5">
|
|
<section
|
|
v-for="item in entries"
|
|
:key="item.id"
|
|
class="bg-zinc-900/40 border border-zinc-800 rounded-2xl p-6"
|
|
>
|
|
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
|
|
<div class="flex items-center gap-3">
|
|
<span class="px-2.5 py-1 rounded-lg bg-blue-500/10 text-blue-300 text-xs font-black">
|
|
v{{ item.version }}
|
|
</span>
|
|
<h2 class="text-lg font-black text-zinc-100">{{ item.title }}</h2>
|
|
</div>
|
|
<p class="text-xs text-zinc-500 font-semibold">
|
|
{{ formatDate(item.publishedAt || item.createdAt) }}
|
|
</p>
|
|
</div>
|
|
|
|
<pre class="mt-4 whitespace-pre-wrap text-sm text-zinc-300 leading-relaxed">{{
|
|
item.content
|
|
}}</pre>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
|
|
<SiteFooter />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { onMounted, ref } from 'vue'
|
|
|
|
const loading = ref(true)
|
|
const entries = ref([])
|
|
|
|
const formatDate = (value) => {
|
|
if (!value) return ''
|
|
const d = new Date(value)
|
|
if (Number.isNaN(d.getTime())) return ''
|
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
|
}
|
|
|
|
const load = async () => {
|
|
try {
|
|
loading.value = true
|
|
const data = await $fetch('/api/changelog', { query: { t: Date.now() } })
|
|
entries.value = Array.isArray(data) ? data : []
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
onMounted(load)
|
|
</script>
|