import { useEffect, useMemo, useState } from 'react'; import { ChevronRight, Plug } from 'lucide-react'; import { motion, AnimatePresence } from 'motion/react'; import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer, Cell, Tooltip } from 'recharts'; import TrendBadge from './TrendBadge'; import { fetchHydrogenDaily } from './api'; import type { CustomerType, DateQuickPick, HydrogenDailyRow } from './types'; import RotatingFooterHint from '../../components/RotatingFooterHint'; const QUICK_PICK_OPTIONS: Array<{ id: DateQuickPick; label: string }> = [ { id: 'thisWeek', label: '本周' }, { id: 'thisMonth', label: '本月' }, { id: 'last15', label: '近 15 天' }, ]; export default function HydrogenDaily() { const [pick, setPick] = useState('last15'); const [customer, setCustomer] = useState('lingniu'); const [expanded, setExpanded] = useState>(new Set()); const [rows, setRows] = useState(null); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; setError(null); fetchHydrogenDaily(pick, customer) .then(r => { if (!cancelled) setRows(r); }) .catch(e => { if (!cancelled) setError(e instanceof Error ? e.message : String(e)); }); return () => { cancelled = true; }; }, [pick, customer]); // 柱图:按日期升序,用于"从左到右时间流" const trendData = useMemo(() => (rows ? [...rows].sort((a, b) => a.date.localeCompare(b.date)) : []), [rows]); const totalKg = (rows ?? []).reduce((a, r) => a + r.totalKg, 0); const toggle = (date: string) => setExpanded(prev => { const next = new Set(prev); next.has(date) ? next.delete(date) : next.add(date); return next; }); return (
{/* 日期速选 */}
{QUICK_PICK_OPTIONS.map(opt => ( ))}
{/* 客户类型 segmented */}
{(['lingniu', 'external'] as const).map(c => ( ))}
{/* 外部车辆:新系统数据还没准备好 */} {customer === 'external' && rows !== null && totalKg === 0 && (
外部车辆 · 数据未就绪
新系统的外部车辆加氢数据还在准备中
上线后此处将展示完整明细
)} {/* 时段加氢量柱图(外部车辆无数据时不渲染) */} {!(customer === 'external' && totalKg === 0) && trendData.length > 0 && (
每日加氢量 单位 Kg
v.slice(5)} tick={{ fontSize: 10, fill: '#94a3b8' }} tickLine={false} axisLine={false} interval="preserveStartEnd" minTickGap={8} /> [`${Number(v ?? 0).toLocaleString('zh-CN', { maximumFractionDigits: 2 })} Kg`, '加氢量']} labelFormatter={(d) => `日期 ${d}`} contentStyle={{ borderRadius: 12, fontSize: 12 }} cursor={{ fill: 'rgba(34, 211, 238, 0.06)' }} /> {trendData.map((_, i) => ( ))}
)} {/* 表格(外部车辆 + 全 0 时不渲染,由上方友好空状态替代) */} {!(customer === 'external' && rows !== null && totalKg === 0) && (
{/* 表头 */}
日期 / 加氢站 单价 (元/Kg) 加氢量 (Kg) 环比
{/* 合计行 */}
合计 {totalKg.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}
{/* 主行 + 子行 */} {error ? (
加载失败:{error}
) : rows === null ? (
加载中…
) : rows.length === 0 ? (
暂无数据
) : rows.map(r => { const open = expanded.has(r.date); const isAbnormal = Math.abs(r.chainPct) >= 0.3; const abnormalBg = isAbnormal ? r.chainPct > 0 ? 'bg-emerald-50/40' : 'bg-red-50/40' : ''; return (
{open && ( {r.stations.map(s => (
{s.name}
{s.pricePerKg > 0 && (
单价 {s.pricePerKg} 元/Kg
)}
{s.pricePerKg > 0 ? s.pricePerKg : '—'} {s.kg.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}
))}
)}
); })}
)}
); }