diff --git a/src/modules/energy/HydrogenDaily.tsx b/src/modules/energy/HydrogenDaily.tsx index 5dca2d9..1794b81 100644 --- a/src/modules/energy/HydrogenDaily.tsx +++ b/src/modules/energy/HydrogenDaily.tsx @@ -1,7 +1,173 @@ +import { useMemo, useState } from 'react'; +import { ChevronRight } from 'lucide-react'; +import { motion, AnimatePresence } from 'motion/react'; +import TrendBadge from './TrendBadge'; +import { HYDROGEN_DAILY } from './mock'; +import type { CustomerType, DateQuickPick, HydrogenDailyRow } from './types'; + +const TODAY = new Date('2026-04-28'); + +const QUICK_PICK_OPTIONS: Array<{ id: DateQuickPick; label: string }> = [ + { id: 'today', label: '当天' }, + { id: 'thisWeek', label: '本周' }, + { id: 'thisMonth', label: '本月' }, + { id: 'thisQuarter', label: '本季度' }, + { id: 'last7', label: '最近7天' }, + { id: 'last30', label: '最近30天' }, +]; + +function isInPick(date: string, pick: DateQuickPick): boolean { + const d = new Date(date); + switch (pick) { + case 'today': { + return d.toISOString().slice(0, 10) === TODAY.toISOString().slice(0, 10); + } + case 'thisWeek': { + const day = TODAY.getDay() || 7; + const start = new Date(TODAY); start.setDate(TODAY.getDate() - day + 1); + return d >= start && d <= TODAY; + } + case 'thisMonth': + return d.getFullYear() === TODAY.getFullYear() && d.getMonth() === TODAY.getMonth(); + case 'thisQuarter': { + const q = Math.floor(TODAY.getMonth() / 3); + const dq = Math.floor(d.getMonth() / 3); + return d.getFullYear() === TODAY.getFullYear() && dq === q; + } + case 'last7': { + const c = new Date(TODAY); c.setDate(TODAY.getDate() - 6); + return d >= c && d <= TODAY; + } + case 'last30': { + const c = new Date(TODAY); c.setDate(TODAY.getDate() - 29); + return d >= c && d <= TODAY; + } + } +} + export default function HydrogenDaily() { + const [pick, setPick] = useState('last30'); + const [customer, setCustomer] = useState('external'); + const [expanded, setExpanded] = useState>(new Set()); + + const rows = useMemo(() => { + return HYDROGEN_DAILY + .filter(r => r.customerType === customer) + .filter(r => isInPick(r.date, pick)) + .sort((a, b) => b.date.localeCompare(a.date)); + }, [pick, customer]); + + 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 ( -
- 每日氢能视图占位 — 将在 Task 5 实现 +
+ {/* 日期速选 */} +
+ {QUICK_PICK_OPTIONS.map(opt => ( + + ))} +
+ + {/* 客户类型 segmented */} +
+ {(['external', 'lingniu'] as const).map(c => ( + + ))} +
+ + {/* 表格 */} +
+ {/* 表头 */} +
+ 日期 / 加氢站带价格 + 单价 + 加氢量(Kg) + 环比 +
+ {/* 合计行 */} +
+ 合计 + + {totalKg.toLocaleString('zh-CN', { maximumFractionDigits: 2 })} + +
+ {/* 主行 + 子行 */} + {rows.length === 0 ? ( +
暂无数据
+ ) : rows.map(r => { + const open = expanded.has(r.date); + return ( +
+ + + {open && ( + + {r.stations.map(s => ( +
+ + {s.name} + · {s.pricePerKg} 元/Kg + + {s.pricePerKg} 元/Kg + + {s.kg.toLocaleString('zh-CN', { maximumFractionDigits: 2 })} + + +
+ ))} +
+ )} +
+
+ ); + })} +
); }