'use client'; import { useEffect, useRef } from 'react'; import { DeviceAnalytics } from '@/app/api/types'; import { Chart, PieController, ArcElement, Tooltip, Legend, CategoryScale, LinearScale } from 'chart.js'; // 注册Chart.js组件 Chart.register(PieController, ArcElement, Tooltip, Legend, CategoryScale, LinearScale); interface DevicePieChartsProps { data: DeviceAnalytics; } // 颜色配置 const COLORS = { deviceTypes: ['rgba(59, 130, 246, 0.8)', 'rgba(96, 165, 250, 0.8)', 'rgba(147, 197, 253, 0.8)', 'rgba(191, 219, 254, 0.8)', 'rgba(219, 234, 254, 0.8)'], browsers: ['rgba(16, 185, 129, 0.8)', 'rgba(52, 211, 153, 0.8)', 'rgba(110, 231, 183, 0.8)', 'rgba(167, 243, 208, 0.8)', 'rgba(209, 250, 229, 0.8)'], os: ['rgba(239, 68, 68, 0.8)', 'rgba(248, 113, 113, 0.8)', 'rgba(252, 165, 165, 0.8)', 'rgba(254, 202, 202, 0.8)', 'rgba(254, 226, 226, 0.8)'] }; export default function DevicePieCharts({ data }: DevicePieChartsProps) { // 创建图表引用 const deviceTypesChartRef = useRef(null); const browsersChartRef = useRef(null); const osChartRef = useRef(null); // 图表实例引用 const deviceTypesChartInstance = useRef(null); const browsersChartInstance = useRef(null); const osChartInstance = useRef(null); // 初始化和更新图表 useEffect(() => { if (!data) return; // 销毁旧的图表实例 if (deviceTypesChartInstance.current) { deviceTypesChartInstance.current.destroy(); } if (browsersChartInstance.current) { browsersChartInstance.current.destroy(); } if (osChartInstance.current) { osChartInstance.current.destroy(); } // 创建设备类型图表 if (deviceTypesChartRef.current && data.deviceTypes.length > 0) { const ctx = deviceTypesChartRef.current.getContext('2d'); if (ctx) { deviceTypesChartInstance.current = new Chart(ctx, { type: 'pie', data: { labels: data.deviceTypes.map(item => item.type), datasets: [{ data: data.deviceTypes.map(item => item.count), backgroundColor: COLORS.deviceTypes, borderColor: COLORS.deviceTypes.map(color => color.replace('0.8', '1')), borderWidth: 1 }] }, options: { responsive: true, plugins: { legend: { position: 'bottom', labels: { color: 'currentColor' } }, tooltip: { callbacks: { label: function(context) { const label = context.label || ''; const value = context.raw as number; const total = (context.chart.data.datasets[0].data as number[]).reduce((a, b) => (a as number) + (b as number), 0); const percentage = Math.round((value * 100) / total); return `${label}: ${value} (${percentage}%)`; } } } } } }); } } // 创建浏览器图表 if (browsersChartRef.current && data.browsers.length > 0) { const ctx = browsersChartRef.current.getContext('2d'); if (ctx) { browsersChartInstance.current = new Chart(ctx, { type: 'pie', data: { labels: data.browsers.map(item => item.name), datasets: [{ data: data.browsers.map(item => item.count), backgroundColor: COLORS.browsers, borderColor: COLORS.browsers.map(color => color.replace('0.8', '1')), borderWidth: 1 }] }, options: { responsive: true, plugins: { legend: { position: 'bottom', labels: { color: 'currentColor' } }, tooltip: { callbacks: { label: function(context) { const label = context.label || ''; const value = context.raw as number; const total = (context.chart.data.datasets[0].data as number[]).reduce((a, b) => (a as number) + (b as number), 0); const percentage = Math.round((value * 100) / total); return `${label}: ${value} (${percentage}%)`; } } } } } }); } } // 创建操作系统图表 if (osChartRef.current && data.operatingSystems.length > 0) { const ctx = osChartRef.current.getContext('2d'); if (ctx) { osChartInstance.current = new Chart(ctx, { type: 'pie', data: { labels: data.operatingSystems.map(item => item.name), datasets: [{ data: data.operatingSystems.map(item => item.count), backgroundColor: COLORS.os, borderColor: COLORS.os.map(color => color.replace('0.8', '1')), borderWidth: 1 }] }, options: { responsive: true, plugins: { legend: { position: 'bottom', labels: { color: 'currentColor' } }, tooltip: { callbacks: { label: function(context) { const label = context.label || ''; const value = context.raw as number; const total = (context.chart.data.datasets[0].data as number[]).reduce((a, b) => (a as number) + (b as number), 0); const percentage = Math.round((value * 100) / total); return `${label}: ${value} (${percentage}%)`; } } } } } }); } } // 清理函数 return () => { if (deviceTypesChartInstance.current) { deviceTypesChartInstance.current.destroy(); } if (browsersChartInstance.current) { browsersChartInstance.current.destroy(); } if (osChartInstance.current) { osChartInstance.current.destroy(); } }; }, [data]); return (
{/* 设备类型 */}

Device Types

{/* 浏览器 */}

Browsers

{/* 操作系统 */}

Operating Systems

); }