feat(front): enhance About page components to support shares and downloads statistics, improve layout, and add loading state

This commit is contained in:
keven
2025-10-19 18:20:38 +08:00
parent 028d0c10fe
commit 07fc182ccb
4 changed files with 89 additions and 21 deletions

View File

@@ -24,6 +24,7 @@ const { data, isLoading } = useQuery({
name?: string
email?: string
url?: string
content?: Record<string, string>
}
}>('/api/about')
return data?.data
@@ -65,7 +66,7 @@ const genUserAvatar = (email: string) => {
</div>
</template>
<template v-else>
<div class="grid grid-cols-2 gap-2">
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
<div class="rounded-xl bg-white/50 flex-1 flex flex-col p-3 gap-2">
<div class="opacity-75 text-xs">{{ t('about.admin') }}</div>
<div
@@ -106,4 +107,21 @@ const genUserAvatar = (email: string) => {
</div>
</div>
</template>
<template v-if="isLoading">
<Skeleton class="w-full h-16 rounded-xl" />
</template>
<template v-else>
<div v-if="data?.content" class="rounded-xl bg-white/50 flex flex-col px-3 gap-2">
<Accordion type="single" collapsible>
<AccordionItem value="about">
<AccordionTrigger>
<span class="font-semibold">{{ t('about.about') }}</span>
</AccordionTrigger>
<AccordionContent>
<MarkdownRender :markdown="renderI18n(data?.content ?? {}, 'en', locale) ?? ''" />
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
</template>
</template>

View File

@@ -8,9 +8,11 @@ import AboutChartTooltip from '@/components/AboutChartTooltip.vue'
import dayjs from 'dayjs'
import { times } from 'lodash-es'
interface FileChartData {
interface StatChartData {
file_size: number
file_num: number
share_num: number
download_num: number
date: string
}
@@ -20,7 +22,7 @@ interface QueueChartData {
date: string
}
type ChartDataItem = FileChartData | QueueChartData
type ChartDataItem = StatChartData | QueueChartData
type ChartConfig = {
data: ChartDataItem[]
@@ -35,7 +37,7 @@ const { data, isLoading } = useQuery({
const response = await $fetch<{
data: {
chart: {
storage: Record<string, FileChartData>
storage: Record<string, StatChartData>
queue: Record<string, QueueChartData>
}
}
@@ -52,7 +54,21 @@ const chartTabs = computed(() => {
label: t('about.file'),
value: 'storage',
total: data.value?.chart?.storage
? Object.values(data.value.chart.storage).reduce((acc: number, curr: FileChartData) => acc + curr.file_num, 0)
? Object.values(data.value.chart.storage).reduce((acc: number, curr: StatChartData) => acc + curr.file_num, 0)
: 0,
},
{
label: t('about.share'),
value: 'share',
total: data.value?.chart?.storage
? Object.values(data.value.chart.storage).reduce((acc: number, curr: StatChartData) => acc + curr.share_num, 0)
: 0,
},
{
label: t('about.download'),
value: 'download',
total: data.value?.chart?.storage
? Object.values(data.value.chart.storage).reduce((acc: number, curr: StatChartData) => acc + curr.download_num, 0)
: 0,
},
{
@@ -65,36 +81,64 @@ const chartTabs = computed(() => {
]
})
const currentChartTab = ref<'storage' | 'queue'>('storage')
const currentChartTab = ref<'storage' | 'queue' | 'share' | 'download'>('storage')
const currentChartData = computed((): ChartConfig => {
const { storage, queue } = data.value?.chart || {}
if (currentChartTab.value === 'storage') {
const storageData = times(30, (i) => {
if (currentChartTab.value === 'queue') {
const queueData = times(30, (i) => {
return {
date: dayjs().subtract(i, 'day').format('YYYY-MM-DD'),
file_size: storage?.[dayjs().subtract(i, 'day').format('YYYY-MM-DD')]?.file_size || 0,
file_num: storage?.[dayjs().subtract(i, 'day').format('YYYY-MM-DD')]?.file_num || 0,
processed: queue?.[dayjs().subtract(i, 'day').format('YYYY-MM-DD')]?.processed || 0,
failed: queue?.[dayjs().subtract(i, 'day').format('YYYY-MM-DD')]?.failed || 0,
}
})
return {
data: storageData,
data: queueData,
index: 'date' as const,
categories: ['file_size', 'file_num'] as const,
colors: ['#22d3ee', '#c084fc'],
categories: ['processed', 'failed'] as const,
colors: ['#4ade80', '#f87171'],
}
}
const queueData = times(30, (i) => {
const storageData = times(30, (i) => {
const base = { date: dayjs().subtract(i, 'day').format('YYYY-MM-DD') }
if (currentChartTab.value === 'share') {
return {
...base,
share_num: storage?.[dayjs().subtract(i, 'day').format('YYYY-MM-DD')]?.share_num || 0,
}
}
if (currentChartTab.value === 'download') {
return {
...base,
download_num: storage?.[dayjs().subtract(i, 'day').format('YYYY-MM-DD')]?.download_num || 0,
}
}
return {
date: dayjs().subtract(i, 'day').format('YYYY-MM-DD'),
processed: queue?.[dayjs().subtract(i, 'day').format('YYYY-MM-DD')]?.processed || 0,
failed: queue?.[dayjs().subtract(i, 'day').format('YYYY-MM-DD')]?.failed || 0,
...base,
file_size: storage?.[dayjs().subtract(i, 'day').format('YYYY-MM-DD')]?.file_size || 0,
file_num: storage?.[dayjs().subtract(i, 'day').format('YYYY-MM-DD')]?.file_num || 0,
}
})
let categories = ['file_size', 'file_num']
if (currentChartTab.value === 'share') {
categories = ['share_num']
}
if (currentChartTab.value === 'download') {
categories = ['download_num']
}
let colors = ['#38bdf8', '#a78bfa']
if (currentChartTab.value === 'share') {
colors = ['#ea580c']
}
if (currentChartTab.value === 'download') {
colors = ['#a3e635']
}
return {
data: queueData,
data: storageData as ChartDataItem[],
index: 'date' as const,
categories: ['processed', 'failed'] as const,
colors: ['#4ade80', '#f87171'],
categories,
colors,
}
})
</script>
@@ -108,7 +152,7 @@ const currentChartData = computed((): ChartConfig => {
</template>
<template v-else>
<div class="flex flex-col gap-2 bg-white/50 w-full rounded-xl py-5">
<div class="flex flex-row gap-2 px-5">
<div class="grid grid-cols-2 md:grid-cols-4 gap-2 px-5">
<div
:class="cx('rounded-md min-w-30 flex flex-col px-3 py-1.5 cursor-pointer', currentChartTab === tab.value && 'bg-black/10')"
v-for="tab in chartTabs"

View File

@@ -107,10 +107,13 @@
"about": {
"powerBy": "Power by {0} as a open source temporary file sharing platform",
"file": "File",
"share": "Share",
"download": "Download",
"task": "Task",
"admin": "Site Admin",
"author": "Author",
"title": "About",
"about": "About",
"systemInfo": "System Info",
"systemVersion": "System Version",
"storage": "Storage",

View File

@@ -107,10 +107,13 @@
"about": {
"powerBy": "由 {0} 驱动的开源自托管临时文件分享平台",
"file": "文件",
"share": "分享",
"download": "下载",
"task": "任务",
"admin": "本站管理员",
"author": "作者",
"title": "关于",
"about": "关于",
"systemInfo": "系统信息",
"systemVersion": "系统版本",
"storage": "已托管的文件",