← 返回列表
component

图表组件

使用 Recharts 库的多功能数据可视化组件,支持折线图、柱状图、面积图和饼图,包含示例数据和统计卡片

import { useState } from 'react';
import {
  LineChart,
  Line,
  BarChart,
  Bar,
  AreaChart,
  Area,
  PieChart,
  Pie,
  Cell,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from 'recharts';
import { Card } from './ui/card';
import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs';

// 示例数据
const monthlyData = [
  { name: '1月', 销售额: 4000, 利润: 2400, 访问量: 2400 },
  { name: '2月', 销售额: 3000, 利润: 1398, 访问量: 2210 },
  { name: '3月', 销售额: 2000, 利润: 9800, 访问量: 2290 },
  { name: '4月', 销售额: 2780, 利润: 3908, 访问量: 2000 },
  { name: '5月', 销售额: 1890, 利润: 4800, 访问量: 2181 },
  { name: '6月', 销售额: 2390, 利润: 3800, 访问量: 2500 },
  { name: '7月', 销售额: 3490, 利润: 4300, 访问量: 2100 },
];

const categoryData = [
  { name: '电子产品', value: 400 },
  { name: '服装', value: 300 },
  { name: '食品', value: 300 },
  { name: '图书', value: 200 },
  { name: '其他', value: 100 },
];

const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042', '#8884D8'];

export function ChartDemo() {
  const [activeTab, setActiveTab] = useState('line');

  return (
    <div className="w-full max-w-6xl mx-auto p-6 space-y-6">
      <div className="text-center">
        <h1 className="mb-2">数据可视化图表</h1>
        <p className="text-muted-foreground">
          使用 Recharts 库展示多种图表类型
        </p>
      </div>

      <Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
        <TabsList className="grid w-full grid-cols-4">
          <TabsTrigger value="line">折线图</TabsTrigger>
          <TabsTrigger value="bar">柱状图</TabsTrigger>
          <TabsTrigger value="area">面积图</TabsTrigger>
          <TabsTrigger value="pie">饼图</TabsTrigger>
        </TabsList>

        <TabsContent value="line" className="space-y-4">
          <Card className="p-6">
            <h3 className="mb-4">月度销售趋势</h3>
            <ResponsiveContainer width="100%" height={400}>
              <LineChart data={monthlyData}>
                <CartesianGrid strokeDasharray="3 3" />
                <XAxis dataKey="name" />
                <YAxis />
                <Tooltip />
                <Legend />
                <Line
                  type="monotone"
                  dataKey="销售额"
                  stroke="#8884d8"
                  strokeWidth={2}
                  activeDot={{ r: 8 }}
                />
                <Line
                  type="monotone"
                  dataKey="利润"
                  stroke="#82ca9d"
                  strokeWidth={2}
                />
                <Line
                  type="monotone"
                  dataKey="访问量"
                  stroke="#ffc658"
                  strokeWidth={2}
                />
              </LineChart>
            </ResponsiveContainer>
          </Card>
        </TabsContent>

        <TabsContent value="bar" className="space-y-4">
          <Card className="p-6">
            <h3 className="mb-4">月度数据对比</h3>
            <ResponsiveContainer width="100%" height={400}>
              <BarChart data={monthlyData}>
                <CartesianGrid strokeDasharray="3 3" />
                <XAxis dataKey="name" />
                <YAxis />
                <Tooltip />
                <Legend />
                <Bar dataKey="销售额" fill="#8884d8" />
                <Bar dataKey="利润" fill="#82ca9d" />
                <Bar dataKey="访问量" fill="#ffc658" />
              </BarChart>
            </ResponsiveContainer>
          </Card>
        </TabsContent>

        <TabsContent value="area" className="space-y-4">
          <Card className="p-6">
            <h3 className="mb-4">累积趋势分析</h3>
            <ResponsiveContainer width="100%" height={400}>
              <AreaChart data={monthlyData}>
                <CartesianGrid strokeDasharray="3 3" />
                <XAxis dataKey="name" />
                <YAxis />
                <Tooltip />
                <Legend />
                <Area
                  type="monotone"
                  dataKey="销售额"
                  stackId="1"
                  stroke="#8884d8"
                  fill="#8884d8"
                  fillOpacity={0.6}
                />
                <Area
                  type="monotone"
                  dataKey="利润"
                  stackId="1"
                  stroke="#82ca9d"
                  fill="#82ca9d"
                  fillOpacity={0.6}
                />
                <Area
                  type="monotone"
                  dataKey="访问量"
                  stackId="1"
                  stroke="#ffc658"
                  fill="#ffc658"
                  fillOpacity={0.6}
                />
              </AreaChart>
            </ResponsiveContainer>
          </Card>
        </TabsContent>

        <TabsContent value="pie" className="space-y-4">
          <Card className="p-6">
            <h3 className="mb-4">产品类别占比</h3>
            <ResponsiveContainer width="100%" height={400}>
              <PieChart>
                <Pie
                  data={categoryData}
                  cx="50%"
                  cy="50%"
                  labelLine={false}
                  label={({ name, percent }) =>
                    `${name}: ${(percent * 100).toFixed(0)}%`
                  }
                  outerRadius={120}
                  fill="#8884d8"
                  dataKey="value"
                >
                  {categoryData.map((entry, index) => (
                    <Cell
                      key={`cell-${index}`}
                      fill={COLORS[index % COLORS.length]}
                    />
                  ))}
                </Pie>
                <Tooltip />
                <Legend />
              </PieChart>
            </ResponsiveContainer>
          </Card>
        </TabsContent>
      </Tabs>

      <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
        <Card className="p-6">
          <div className="text-sm text-muted-foreground mb-1">总销售额</div>
          <div className="text-3xl font-bold">¥19,550</div>
          <div className="text-sm text-green-600 mt-1">↑ 12.5%</div>
        </Card>
        <Card className="p-6">
          <div className="text-sm text-muted-foreground mb-1">总利润</div>
          <div className="text-3xl font-bold">¥30,406</div>
          <div className="text-sm text-green-600 mt-1">↑ 8.2%</div>
        </Card>
        <Card className="p-6">
          <div className="text-sm text-muted-foreground mb-1">总访问量</div>
          <div className="text-3xl font-bold">15,681</div>
          <div className="text-sm text-red-600 mt-1">↓ 3.1%</div>
        </Card>
      </div>
    </div>
  );
}