This commit is contained in:
2025-12-13 14:46:18 +08:00
parent dead4c62ae
commit 64878ac8cf

View File

@@ -0,0 +1,69 @@
import React from 'react';
import { LucideIcon } from 'lucide-react';
interface MetricCardProps {
title: string;
value: string | number;
subtitle?: string;
icon: LucideIcon;
trend?: 'up' | 'down' | 'neutral';
trendValue?: string;
color?: 'blue' | 'green' | 'yellow' | 'red';
onClick?: () => void;
}
/**
* 指标卡片组件
* 用于 Dashboard 展示关键数据
*/
export const MetricCard: React.FC<MetricCardProps> = ({
title,
value,
subtitle,
icon: Icon,
trend,
trendValue,
color = 'blue',
onClick,
}) => {
const colorClasses = {
blue: 'bg-blue-50 text-blue-600',
green: 'bg-green-50 text-green-600',
yellow: 'bg-yellow-50 text-yellow-600',
red: 'bg-red-50 text-red-600',
};
const trendColors = {
up: 'text-green-600',
down: 'text-red-600',
neutral: 'text-gray-600',
};
return (
<div
onClick={onClick}
className={`
card p-6
${onClick ? 'cursor-pointer hover:shadow-xl transition-shadow' : ''}
`}
>
<div className="flex items-start justify-between">
<div className="flex-1">
<p className="text-sm text-gray-600 font-medium mb-2">{title}</p>
<p className="text-3xl font-bold text-gray-900 mb-1">{value}</p>
{subtitle && (
<p className="text-sm text-gray-500">{subtitle}</p>
)}
{trend && trendValue && (
<p className={`text-sm font-medium mt-2 ${trendColors[trend]}`}>
{trend === 'up' ? '↑' : trend === 'down' ? '↓' : '→'} {trendValue}
</p>
)}
</div>
<div className={`p-3 rounded-xl ${colorClasses[color]}`}>
<Icon size={24} />
</div>
</div>
</div>
);
};