"use client" import { useEffect, useRef } from "react" import * as echarts from "echarts" import type { FamilyMember } from "@/types/family" import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card" interface StatisticsChartsProps { members: FamilyMember[] } export function StatisticsCharts({ members }: StatisticsChartsProps) { const genderChartRef = useRef(null) const generationChartRef = useRef(null) const ageDistributionRef = useRef(null) const birthYearChartRef = useRef(null) useEffect(() => { if (!genderChartRef.current || members.length === 0) return // 性别分布饼图 const genderChart = echarts.init(genderChartRef.current) const genderData = { male: members.filter(m => m.gender === 'male').length, female: members.filter(m => m.gender === 'female').length, other: members.filter(m => m.gender === 'other').length, } genderChart.setOption({ title: { text: '性别分布', left: 'center', top: 10, textStyle: { fontSize: 14, fontWeight: 'normal' } }, tooltip: { trigger: 'item', formatter: '{b}: {c} 人 ({d}%)' }, legend: { bottom: 10, left: 'center' }, series: [ { type: 'pie', radius: ['40%', '70%'], center: ['50%', '50%'], avoidLabelOverlap: false, itemStyle: { borderRadius: 10, borderColor: '#fff', borderWidth: 2 }, label: { show: false }, emphasis: { label: { show: true, fontSize: 16, fontWeight: 'bold' } }, data: [ { value: genderData.male, name: '男性', itemStyle: { color: '#3b82f6' } }, { value: genderData.female, name: '女性', itemStyle: { color: '#ec4899' } }, ...(genderData.other > 0 ? [{ value: genderData.other, name: '其他', itemStyle: { color: '#8b5cf6' } }] : []) ] } ] }) return () => { genderChart.dispose() } }, [members]) useEffect(() => { if (!generationChartRef.current || members.length === 0) return // 世代分布柱状图 const generationChart = echarts.init(generationChartRef.current) const generationData = new Map() members.forEach(m => { const gen = m.generation || 0 generationData.set(gen, (generationData.get(gen) || 0) + 1) }) const sortedGenerations = Array.from(generationData.entries()).sort((a, b) => a[0] - b[0]) generationChart.setOption({ title: { text: '世代分布', left: 'center', top: 10, textStyle: { fontSize: 14, fontWeight: 'normal' } }, tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, formatter: '{b}世: {c} 人' }, grid: { left: '3%', right: '4%', bottom: '3%', top: '15%', containLabel: true }, xAxis: { type: 'category', data: sortedGenerations.map(([gen]) => `第${gen}世`), axisLabel: { rotate: 45 } }, yAxis: { type: 'value', name: '人数' }, series: [ { type: 'bar', data: sortedGenerations.map(([, count]) => count), itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#83bff6' }, { offset: 0.5, color: '#188df0' }, { offset: 1, color: '#188df0' } ]) }, emphasis: { itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#2378f7' }, { offset: 0.7, color: '#2378f7' }, { offset: 1, color: '#83bff6' } ]) } } } ] }) return () => { generationChart.dispose() } }, [members]) useEffect(() => { if (!ageDistributionRef.current || members.length === 0) return // 年龄分布图 const ageChart = echarts.init(ageDistributionRef.current) const currentYear = new Date().getFullYear() const ageGroups = { '0-18': 0, '19-35': 0, '36-50': 0, '51-65': 0, '66+': 0, '已故': 0 } members.forEach(m => { if (m.deathDate) { ageGroups['已故']++ } else if (m.birthDate) { const age = currentYear - new Date(m.birthDate).getFullYear() if (age <= 18) ageGroups['0-18']++ else if (age <= 35) ageGroups['19-35']++ else if (age <= 50) ageGroups['36-50']++ else if (age <= 65) ageGroups['51-65']++ else ageGroups['66+']++ } }) ageChart.setOption({ title: { text: '年龄分布', left: 'center', top: 10, textStyle: { fontSize: 14, fontWeight: 'normal' } }, tooltip: { trigger: 'item', formatter: '{b}: {c} 人 ({d}%)' }, legend: { bottom: 10, left: 'center' }, series: [ { type: 'pie', radius: '60%', center: ['50%', '50%'], data: Object.entries(ageGroups) .filter(([, count]) => count > 0) .map(([name, value]) => ({ name, value })), emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ] }) return () => { ageChart.dispose() } }, [members]) useEffect(() => { if (!birthYearChartRef.current || members.length === 0) return // 出生年份趋势图 const birthYearChart = echarts.init(birthYearChartRef.current) const birthYearData = new Map() members.forEach(m => { if (m.birthDate) { const year = new Date(m.birthDate).getFullYear() if (year >= 1900) { // 只统计1900年以后的 const decade = Math.floor(year / 10) * 10 birthYearData.set(decade, (birthYearData.get(decade) || 0) + 1) } } }) const sortedYears = Array.from(birthYearData.entries()).sort((a, b) => a[0] - b[0]) birthYearChart.setOption({ title: { text: '出生年代分布', left: 'center', top: 10, textStyle: { fontSize: 14, fontWeight: 'normal' } }, tooltip: { trigger: 'axis', formatter: '{b}年代: {c} 人' }, grid: { left: '3%', right: '4%', bottom: '3%', top: '15%', containLabel: true }, xAxis: { type: 'category', data: sortedYears.map(([year]) => `${year}s`), axisLabel: { rotate: 45 } }, yAxis: { type: 'value', name: '人数' }, series: [ { type: 'line', data: sortedYears.map(([, count]) => count), smooth: true, areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: 'rgba(99, 102, 241, 0.5)' }, { offset: 1, color: 'rgba(99, 102, 241, 0.1)' } ]) }, lineStyle: { color: '#6366f1', width: 2 }, itemStyle: { color: '#6366f1' } } ] }) return () => { birthYearChart.dispose() } }, [members]) return (
性别分布 家族成员性别比例
世代分布 各世代人数统计
年龄分布 按年龄段划分的人数
出生年代分布 各年代出生人数趋势
) }