mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-02 14:56:38 +08:00
feat(access-logs): 优化概览饼图布局并在查询出错时增加日志记录
- 将设备类型与状态码饼图的断点由 xl 降为 lg,在大屏/笔记本视口下保持双列展示 - 修复 valueCountDistribution 在 ClickHouse 查询出错时静默吞掉错误的缺陷,引入 logger.ErrorF 捕获 - 补充 unreleased 变更日志
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@/components/ui/card';
|
||||
|
||||
import { RankChart } from './rank-chart';
|
||||
|
||||
type RankCardItem = {
|
||||
label: string;
|
||||
value: number;
|
||||
};
|
||||
|
||||
type RankCardProps = {
|
||||
title: string;
|
||||
description: string;
|
||||
items: RankCardItem[];
|
||||
color?: string;
|
||||
};
|
||||
|
||||
export function RankCard({
|
||||
title,
|
||||
description,
|
||||
items,
|
||||
color = '#3b82f6',
|
||||
}: RankCardProps) {
|
||||
return (
|
||||
<Card className='border-dashed shadow-none'>
|
||||
<CardHeader className='pb-3'>
|
||||
<CardTitle className='text-sm font-semibold text-foreground'>
|
||||
{title}
|
||||
</CardTitle>
|
||||
<CardDescription className='text-xs text-muted-foreground'>
|
||||
{description}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className='pt-0'>
|
||||
<RankChart
|
||||
items={items}
|
||||
color={color}
|
||||
emptyMessage={`暂无 ${title} 数据`}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -17,7 +17,15 @@ type RankChartProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const defaultFormatter = (value: number) => value.toLocaleString('zh-CN');
|
||||
const defaultFormatter = (value: number) => {
|
||||
if (value >= 1000000) {
|
||||
return `${Number((value / 1000000).toFixed(2))}M`;
|
||||
}
|
||||
if (value >= 1000) {
|
||||
return `${Number((value / 1000).toFixed(2))}k`;
|
||||
}
|
||||
return value.toLocaleString('zh-CN');
|
||||
};
|
||||
|
||||
export function RankChart({
|
||||
items,
|
||||
@@ -35,7 +43,7 @@ export function RankChart({
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex h-[450px] items-center justify-center rounded-md border border-dashed bg-muted/20 text-sm text-muted-foreground',
|
||||
'flex h-[320px] items-center justify-center rounded-md border border-dashed bg-muted/20 text-sm text-muted-foreground',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
@@ -45,31 +53,39 @@ export function RankChart({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn('h-[450px] space-y-1.5 overflow-y-auto', className)}>
|
||||
<div
|
||||
className={cn(
|
||||
'h-[320px] space-y-0.5 overflow-y-auto pr-1 hide-scrollbar',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{items.map((item) => {
|
||||
const ratio = maxValue > 0 ? (item.value / maxValue) * 100 : 0;
|
||||
return (
|
||||
<div key={item.label} className='group space-y-1'>
|
||||
<div className='flex items-center justify-between gap-3 text-[13px] leading-none'>
|
||||
<span
|
||||
className='min-w-0 truncate font-medium text-foreground'
|
||||
title={item.label}
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
<span className='shrink-0 tabular-nums text-foreground/80'>
|
||||
<div
|
||||
key={item.label}
|
||||
className='group flex items-center justify-between gap-3 py-1.5 text-sm'
|
||||
>
|
||||
<span
|
||||
className='min-w-0 flex-1 truncate text-[13px] font-normal text-foreground/90'
|
||||
title={item.label}
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
<div className='flex items-center gap-3 shrink-0'>
|
||||
<div className='h-1.5 w-24 sm:w-28 overflow-hidden rounded-full bg-muted/60'>
|
||||
<div
|
||||
className='h-full rounded-full transition-[width] duration-300'
|
||||
style={{
|
||||
width: `${ratio}%`,
|
||||
backgroundColor: color,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className='w-14 text-right tabular-nums text-foreground/80 text-[13px] font-medium'>
|
||||
{valueFormatter(item.value)}
|
||||
</span>
|
||||
</div>
|
||||
<div className='h-1.5 overflow-hidden rounded-full bg-muted'>
|
||||
<div
|
||||
className='h-full rounded-full transition-[width] duration-300'
|
||||
style={{
|
||||
width: `${ratio}%`,
|
||||
backgroundColor: color,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user