mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-13 02:26:36 +08:00
fix(frontend): keep browser API on same-origin rewrites in dev
Document that NEXT_PUBLIC_WAVELET_BACKEND_URL must stay unset for local next dev so axios hits /api/* and Next rewrites proxy to the backend.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import {
|
||||
Database,
|
||||
@@ -51,40 +52,41 @@ const categoryMap: Record<string, string> = {
|
||||
|
||||
const statsChartConfig = {
|
||||
images: {
|
||||
label: '图片',
|
||||
label: 'images',
|
||||
color: 'hsl(var(--chart-1))',
|
||||
},
|
||||
videos: {
|
||||
label: '视频',
|
||||
label: 'videos',
|
||||
color: 'hsl(var(--chart-2))',
|
||||
},
|
||||
audio: {
|
||||
label: '音频',
|
||||
label: 'audio',
|
||||
color: 'hsl(var(--chart-3))',
|
||||
},
|
||||
documents: {
|
||||
label: '文档',
|
||||
label: 'documents',
|
||||
color: 'hsl(var(--chart-4))',
|
||||
},
|
||||
archives: {
|
||||
label: '压缩包',
|
||||
label: 'archives',
|
||||
color: 'hsl(var(--chart-5))',
|
||||
},
|
||||
others: {
|
||||
label: '其他',
|
||||
label: 'others',
|
||||
color: 'hsl(var(--chart-6))',
|
||||
},
|
||||
count: {
|
||||
label: '新增文件数',
|
||||
label: 'count',
|
||||
color: 'hsl(var(--primary))',
|
||||
},
|
||||
size: {
|
||||
label: '新增大小',
|
||||
label: 'size',
|
||||
color: 'hsl(var(--chart-2))',
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
export function FileStats() {
|
||||
const t = useTranslations('admin.files');
|
||||
const [trendMetric, setTrendMetric] = React.useState<'count' | 'size'>(
|
||||
'count',
|
||||
);
|
||||
@@ -182,9 +184,9 @@ export function FileStats() {
|
||||
<div className='flex flex-col items-center justify-center py-24 border border-dashed rounded-xl bg-card text-muted-foreground gap-4'>
|
||||
<Upload className='size-14 text-muted-foreground/25' />
|
||||
<div className='text-center space-y-1'>
|
||||
<p className='font-medium'>暂无上传数据</p>
|
||||
<p className='font-medium'>{t('stats.noData')}</p>
|
||||
<p className='text-xs text-muted-foreground'>
|
||||
上传文件后即可在此查看容量与文件分布分析。
|
||||
{t('stats.noDataDesc')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -198,7 +200,7 @@ export function FileStats() {
|
||||
<Card className='bg-card/25 border-border/40 hover:shadow-md transition-shadow'>
|
||||
<CardHeader className='flex flex-row items-center justify-between pb-2 space-y-0'>
|
||||
<CardTitle className='text-xs font-semibold tracking-tight text-muted-foreground'>
|
||||
总文件数
|
||||
{t('stats.totalFiles')}
|
||||
</CardTitle>
|
||||
<Files className='size-4 text-sky-500' />
|
||||
</CardHeader>
|
||||
@@ -206,11 +208,11 @@ export function FileStats() {
|
||||
<div className='text-2xl font-bold font-mono text-sky-500'>
|
||||
{stats.total_count.toLocaleString()}{' '}
|
||||
<span className='text-xs font-normal text-muted-foreground'>
|
||||
个
|
||||
{t('stats.countUnit')}
|
||||
</span>
|
||||
</div>
|
||||
<p className='text-[10px] text-muted-foreground mt-1'>
|
||||
您上传的可用文件数量汇总
|
||||
{t('stats.totalFilesDesc')}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -218,7 +220,7 @@ export function FileStats() {
|
||||
<Card className='bg-card/25 border-border/40 hover:shadow-md transition-shadow'>
|
||||
<CardHeader className='flex flex-row items-center justify-between pb-2 space-y-0'>
|
||||
<CardTitle className='text-xs font-semibold tracking-tight text-muted-foreground'>
|
||||
占用存储容量
|
||||
{t('stats.totalSize')}
|
||||
</CardTitle>
|
||||
<Database className='size-4 text-emerald-500' />
|
||||
</CardHeader>
|
||||
@@ -227,7 +229,7 @@ export function FileStats() {
|
||||
{formatFileSize(stats.total_size)}
|
||||
</div>
|
||||
<p className='text-[10px] text-muted-foreground mt-1'>
|
||||
文件实际在磁盘/S3中占用的总空间
|
||||
{t('stats.totalSizeDesc')}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -235,7 +237,7 @@ export function FileStats() {
|
||||
<Card className='bg-card/25 border-border/40 hover:shadow-md transition-shadow'>
|
||||
<CardHeader className='flex flex-row items-center justify-between pb-2 space-y-0'>
|
||||
<CardTitle className='text-xs font-semibold tracking-tight text-muted-foreground'>
|
||||
近 7 天新增文件
|
||||
{t('stats.weeklyNewFiles')}
|
||||
</CardTitle>
|
||||
<TrendingUp className='size-4 text-indigo-500' />
|
||||
</CardHeader>
|
||||
@@ -243,11 +245,11 @@ export function FileStats() {
|
||||
<div className='text-2xl font-bold font-mono text-indigo-500'>
|
||||
+{trendSummary.count.toLocaleString()}{' '}
|
||||
<span className='text-xs font-normal text-muted-foreground'>
|
||||
个
|
||||
{t('stats.countUnit')}
|
||||
</span>
|
||||
</div>
|
||||
<p className='text-[10px] text-muted-foreground mt-1'>
|
||||
最近 7 天上传成功的文件总数
|
||||
{t('stats.weeklyNewFilesDesc')}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -255,7 +257,7 @@ export function FileStats() {
|
||||
<Card className='bg-card/25 border-border/40 hover:shadow-md transition-shadow'>
|
||||
<CardHeader className='flex flex-row items-center justify-between pb-2 space-y-0'>
|
||||
<CardTitle className='text-xs font-semibold tracking-tight text-muted-foreground'>
|
||||
近 7 天新增大小
|
||||
{t('stats.weeklyNewSize')}
|
||||
</CardTitle>
|
||||
<HardDrive className='size-4 text-amber-500' />
|
||||
</CardHeader>
|
||||
@@ -264,7 +266,7 @@ export function FileStats() {
|
||||
+{formatFileSize(trendSummary.size)}
|
||||
</div>
|
||||
<p className='text-[10px] text-muted-foreground mt-1'>
|
||||
最近 7 天上传所消耗的存储带宽
|
||||
{t('stats.weeklyNewSizeDesc')}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -275,10 +277,10 @@ export function FileStats() {
|
||||
<CardHeader className='flex flex-row items-center justify-between'>
|
||||
<div>
|
||||
<CardTitle className='text-sm font-bold'>
|
||||
最近 7 天新增趋势
|
||||
{t('stats.trendTitle')}
|
||||
</CardTitle>
|
||||
<CardDescription className='text-xs'>
|
||||
按日统计近一周期内的上传波动
|
||||
{t('stats.trendDesc')}
|
||||
</CardDescription>
|
||||
</div>
|
||||
<div className='flex items-center gap-1 border rounded-lg p-0.5 bg-muted/30'>
|
||||
@@ -288,7 +290,7 @@ export function FileStats() {
|
||||
className='h-7 text-xs px-2.5 rounded-md'
|
||||
onClick={() => setTrendMetric('count')}
|
||||
>
|
||||
新增数量 (个)
|
||||
{t('stats.trendCount')}
|
||||
</Button>
|
||||
<Button
|
||||
size='sm'
|
||||
@@ -296,7 +298,7 @@ export function FileStats() {
|
||||
className='h-7 text-xs px-2.5 rounded-md'
|
||||
onClick={() => setTrendMetric('size')}
|
||||
>
|
||||
新增大小 (MB)
|
||||
{t('stats.trendSize')}
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
@@ -361,7 +363,9 @@ export function FileStats() {
|
||||
hideLabel
|
||||
formatter={(value) => {
|
||||
const label =
|
||||
trendMetric === 'count' ? '新增文件数' : '新增大小';
|
||||
trendMetric === 'count'
|
||||
? t('stats.chartLabelCount')
|
||||
: t('stats.chartLabelSize');
|
||||
const formattedValue =
|
||||
trendMetric === 'size'
|
||||
? formatFileSize(Number(value))
|
||||
@@ -419,16 +423,16 @@ export function FileStats() {
|
||||
<Card className='bg-card/20 border-border/40 flex flex-col'>
|
||||
<CardHeader>
|
||||
<CardTitle className='text-sm font-bold'>
|
||||
文件格式数量分布
|
||||
{t('stats.countDistTitle')}
|
||||
</CardTitle>
|
||||
<CardDescription className='text-xs'>
|
||||
各种格式类型的文件个数占比
|
||||
{t('stats.countDistDesc')}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className='flex-1 flex flex-col justify-between gap-4'>
|
||||
{categoryCountData.length === 0 ? (
|
||||
<div className='h-[240px] flex items-center justify-center text-xs text-muted-foreground'>
|
||||
暂无分类数据
|
||||
{t('stats.noCategoryData')}
|
||||
</div>
|
||||
) : (
|
||||
<div className='h-[240px] w-full'>
|
||||
@@ -494,15 +498,10 @@ export function FileStats() {
|
||||
<div className='bg-sky-500/5 border border-sky-500/10 rounded-lg p-3 flex items-start gap-2.5 text-xs text-sky-600 dark:text-sky-400'>
|
||||
<Info className='size-4 shrink-0 mt-0.5' />
|
||||
<p className='leading-normal'>
|
||||
文件类型中数量最多的是{' '}
|
||||
<strong className='font-bold'>
|
||||
「{maxStats.maxCountName}」
|
||||
</strong>
|
||||
,累计上传了{' '}
|
||||
<strong className='font-mono font-bold'>
|
||||
{maxStats.maxCount}
|
||||
</strong>{' '}
|
||||
个文件。
|
||||
{t('stats.maxCountHint', {
|
||||
name: maxStats.maxCountName,
|
||||
count: maxStats.maxCount,
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -512,16 +511,16 @@ export function FileStats() {
|
||||
<Card className='bg-card/20 border-border/40 flex flex-col'>
|
||||
<CardHeader>
|
||||
<CardTitle className='text-sm font-bold'>
|
||||
文件占用容量分布
|
||||
{t('stats.sizeDistTitle')}
|
||||
</CardTitle>
|
||||
<CardDescription className='text-xs'>
|
||||
各种格式类型的文件大小占比
|
||||
{t('stats.sizeDistDesc')}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className='flex-1 flex flex-col justify-between gap-4'>
|
||||
{categorySizeData.length === 0 ? (
|
||||
<div className='h-[240px] flex items-center justify-center text-xs text-muted-foreground'>
|
||||
暂无容量数据
|
||||
{t('stats.noSizeData')}
|
||||
</div>
|
||||
) : (
|
||||
<div className='h-[240px] w-full'>
|
||||
@@ -587,15 +586,10 @@ export function FileStats() {
|
||||
<div className='bg-emerald-500/5 border border-emerald-500/10 rounded-lg p-3 flex items-start gap-2.5 text-xs text-emerald-600 dark:text-emerald-400'>
|
||||
<Info className='size-4 shrink-0 mt-0.5' />
|
||||
<p className='leading-normal'>
|
||||
文件类型中占用存储最大的是{' '}
|
||||
<strong className='font-bold'>
|
||||
「{maxStats.maxSizeName}」
|
||||
</strong>
|
||||
,共消耗了{' '}
|
||||
<strong className='font-mono font-bold'>
|
||||
{formatFileSize(maxStats.maxSize)}
|
||||
</strong>{' '}
|
||||
存储容量。
|
||||
{t('stats.maxSizeHint', {
|
||||
name: maxStats.maxSizeName,
|
||||
size: formatFileSize(maxStats.maxSize),
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
Reference in New Issue
Block a user