import { useEffect, useState } from 'react'; import { Fuel, Wallet, Coins, CalendarClock } from 'lucide-react'; import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer, Cell, PieChart, Pie, Tooltip, LabelList } from 'recharts'; import { fetchHydrogenOverview, type HydrogenOverviewResponse } from './api'; interface YAxisTickProps { x?: number; y?: number; index?: number; payload?: { value: string }; } function RankYAxisTick({ x = 0, y = 0, index = 0, payload }: YAxisTickProps) { return ( {index + 1} {payload?.value} ); } const REGION_COLORS = [ '#3b82f6', '#22d3ee', '#a855f7', '#f59e0b', '#10b981', '#ef4444', '#6366f1', '#14b8a6', '#94a3b8', ]; function fmtKg(kg: number) { if (kg >= 1000) return `${(kg / 1000).toFixed(2)}T`; return `${kg.toFixed(2)}Kg`; } function fmtYuanWan(yuan: number) { return `¥${(yuan / 10_000).toFixed(2)}万`; } function fmtYuan(yuan: number) { return `¥${yuan.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}`; } export default function HydrogenOverview() { const [data, setData] = useState(null); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; fetchHydrogenOverview() .then(d => { if (!cancelled) setData(d); }) .catch(e => { if (!cancelled) setError(e instanceof Error ? e.message : String(e)); }); return () => { cancelled = true; }; }, []); if (error) { return 加载失败:{error}; } if (!data) { return 加载中…; } const k = data.kpi; const top5 = data.top5; const regions = data.regions; return ( 数据自 2025-01-01 起,每 1 分钟更新 {/* 卡 1:年加氢量 */} 年加氢量 {fmtKg(k.yearKg)} 我方 {fmtKg(k.ourYearKg)} 客户产生 {fmtKg(k.customerYearKg)} {/* 卡 2:年加氢费 */} 年加氢费 {fmtYuanWan(k.yearFee)} 我方 {fmtYuanWan(k.ourYearFee)} {/* 卡 3:累计羚牛承担 */} 累计羚牛承担 {fmtYuanWan(k.lingniuBornFee)} 量 {fmtKg(k.lingniuBornKg)} {/* 卡 4:本月 / 今日 */} 本月 / 今日 本月 {fmtKg(k.monthKg)} {fmtYuanWan(k.monthFee)} 今日 {fmtKg(k.todayKg)} {fmtYuan(k.todayFee)} {/* Top5 加氢站 */} 加氢站加注量 Top5 单位 Kg } tickLine={false} axisLine={false} /> `${Number(v ?? 0).toLocaleString('zh-CN')} Kg`} contentStyle={{ borderRadius: 12, fontSize: 12 }} /> {top5.map((_, i) => ( ))} `${Number(v ?? 0).toLocaleString('zh-CN', { maximumFractionDigits: 0 })}`} fill="#475569" fontSize={11} fontWeight={700} /> {/* 区域占比环 */} 各区域加氢占比 {regions.map((_, i) => ( ))} `${(Number(v ?? 0) / 1000).toFixed(2)}T`} contentStyle={{ borderRadius: 12, fontSize: 12 }} /> 年合计 {(k.yearKg / 1000).toFixed(2)}T {regions.map((r, i) => ( {r.region} {(r.share * 100).toFixed(1)}% ))} ); }