imeeting/components/StatCard/StatCard.jsx

79 lines
2.2 KiB
JavaScript

import { ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons'
import './StatCard.css'
/**
* 统计卡片组件
* @param {Object} props
* @param {string} props.title - 卡片标题
* @param {number|string} props.value - 统计值
* @param {ReactNode} props.icon - 图标
* @param {string} props.color - 主题颜色,默认 'blue'
* @param {Object} props.trend - 趋势信息 { value: number, direction: 'up' | 'down' }
* @param {string} props.suffix - 后缀单位
* @param {string} props.layout - 布局模式: 'column' | 'row',默认 'column'(一列)
* @param {string} props.gridColumn - 网格列跨度,如 '1 / -1' 表示占满整行
* @param {string} props.className - 自定义类名
* @param {Function} props.onClick - 点击事件处理函数
* @param {Object} props.style - 自定义样式对象
*/
function StatCard({
title,
value,
icon,
color = 'blue',
trend,
suffix = '',
layout = 'column',
gridColumn,
className = '',
onClick,
style: customStyle = {},
}) {
const colorMap = {
blue: '#1677ff',
green: '#52c41a',
orange: '#faad14',
red: '#ff4d4f',
purple: '#722ed1',
gray: '#8c8c8c',
}
const themeColor = colorMap[color] || color
const style = {
...(gridColumn ? { gridColumn } : {}),
...customStyle,
}
return (
<div className={`stat-card stat-card-${layout} ${className}`} style={style} onClick={onClick}>
<div className="stat-card-header">
<span className="stat-card-title">{title}</span>
{icon && (
<span className="stat-card-icon" style={{ color: themeColor }}>
{icon}
</span>
)}
</div>
<div className="stat-card-body">
<div className="stat-card-value" style={{ color: themeColor }}>
{value}
{suffix && <span className="stat-card-suffix">{suffix}</span>}
</div>
{trend && (
<div
className={`stat-card-trend ${trend.direction === 'up' ? 'trend-up' : 'trend-down'}`}
>
{trend.direction === 'up' ? <ArrowUpOutlined /> : <ArrowDownOutlined />}
<span>{Math.abs(trend.value)}%</span>
</div>
)}
</div>
</div>
)
}
export default StatCard