import { useMemo } from 'react'; interface Props { realtime?: { pv_power: number; heatpump_power: number; total_load: number; grid_power: number; }; } export default function EnergyFlow({ realtime }: Props) { const pv = realtime?.pv_power || 0; const load = realtime?.total_load || 0; const grid = realtime?.grid_power || 0; const hp = realtime?.heatpump_power || 0; // Calculate flows const pvToLoad = Math.min(pv, load); const pvToGrid = Math.max(0, pv - load); const gridToLoad = Math.max(0, grid); const gridExport = Math.max(0, -grid); const selfUseRate = load > 0 ? ((pvToLoad / load) * 100).toFixed(1) : '0.0'; // Determine which flows are active (> 0.1 kW threshold) const flows = useMemo(() => ({ pvToLoad: pvToLoad > 0.1, pvToGrid: pvToGrid > 0.1 || gridExport > 0.1, gridToLoad: gridToLoad > 0.1, gridToHp: hp > 0.1, }), [pvToLoad, pvToGrid, gridExport, gridToLoad, hp]); // SVG layout constants const W = 560; const H = 340; // Node positions (center points) const nodes = { pv: { x: W / 2, y: 40 }, load: { x: 100, y: 200 }, grid: { x: W - 100, y: 200 }, heatpump: { x: W / 2, y: 300 }, }; return (
{/* Glow filters */} {/* Gradient for PV -> Load (green) */} {/* Gradient for PV -> Grid (green to orange) */} {/* Gradient for Grid -> Load (orange to blue) */} {/* Gradient for Grid -> HeatPump (orange to cyan) */} {/* ===== FLOW LINES ===== */} {/* PV -> Load */} {flows.pvToLoad && ( {pvToLoad.toFixed(1)} kW )} {/* PV -> Grid (export) */} {flows.pvToGrid && ( {(pvToGrid || gridExport).toFixed(1)} kW )} {/* Grid -> Load (import) */} {flows.gridToLoad && ( {gridToLoad.toFixed(1)} kW )} {/* Load -> HeatPump */} {flows.gridToHp && ( {hp.toFixed(1)} kW )} {/* ===== NODES ===== */} {/* PV Solar Node */} ☀️ 光伏发电 {pv.toFixed(1)} kW {/* Building Load Node */} 🏢 建筑负载 {load.toFixed(1)} kW {/* Grid Node */} {grid >= 0 ? '电网购入' : '电网输出'} {Math.abs(grid).toFixed(1)} kW {/* HeatPump Node */} 🔥 热泵系统 {hp.toFixed(1)} kW {/* Self-consumption badge */} 自消纳 {selfUseRate}%
); }