From ccf76cba79860424641d07c88097c0c9b2468b15 Mon Sep 17 00:00:00 2001 From: kkfluous Date: Tue, 28 Apr 2026 11:39:55 +0800 Subject: [PATCH] feat(energy): electric view with mini KPI + month grouping Co-Authored-By: Claude Opus 4.7 (1M context) --- src/modules/energy/ElectricView.tsx | 143 +++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 2 deletions(-) diff --git a/src/modules/energy/ElectricView.tsx b/src/modules/energy/ElectricView.tsx index bc99a69..9bef3f3 100644 --- a/src/modules/energy/ElectricView.tsx +++ b/src/modules/energy/ElectricView.tsx @@ -1,7 +1,146 @@ +import { useMemo, useState } from 'react'; +import { ChevronRight, Wallet, BatteryCharging, CalendarClock } from 'lucide-react'; +import { motion, AnimatePresence } from 'motion/react'; +import TrendBadge from './TrendBadge'; +import { ELECTRIC_KPI, ELECTRIC_MONTHLY } from './mock'; +import type { CustomerType } from './types'; + +function fmtYuan(yuan: number) { + return `¥${yuan.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}`; +} +function fmtKwh(kwh: number) { + return `${kwh.toLocaleString('zh-CN', { maximumFractionDigits: 2 })} 度`; +} + export default function ElectricView() { + const [customer, setCustomer] = useState('external'); + const [openMonths, setOpenMonths] = useState>(new Set([ELECTRIC_MONTHLY[0]?.month])); + + const months = useMemo(() => { + // mock 暂不区分客户类型,customer 切换不影响数据;保留 UI 切换以与 BI 一致 + void customer; + return ELECTRIC_MONTHLY; + }, [customer]); + + const k = ELECTRIC_KPI; + + const toggleMonth = (m: string) => setOpenMonths(prev => { + const next = new Set(prev); + next.has(m) ? next.delete(m) : next.add(m); + return next; + }); + return ( -
- 电能视图占位 — 将在 Task 6 实现 +
+
+ 龙王路停车场充电站,期初 2025-01-01,手工导入每日更新 +
+ + {/* 横向 mini KPI 头 */} +
+
+
+ 累计 +
+
{fmtYuan(k.totalFee)}
+
{fmtKwh(k.totalKwh)}
+
+
+
+ 本月 +
+
{fmtYuan(k.monthFee)}
+
{fmtKwh(k.monthKwh)}
+
+
+
+ 今日 +
+
+
{fmtYuan(k.todayFee)}
+ +
+
{fmtKwh(k.todayKwh)}
+
+
+ + {/* 客户类型 */} +
+ {(['external', 'lingniu'] as const).map(c => ( + + ))} +
+ + {/* 月份分组表 */} +
+
+ 月份 / 日期 + 充电电量 + + 充电费用(元) + 环比 +
+ {months.map(m => { + const open = openMonths.has(m.month); + return ( +
+ + + {open && ( + + {m.rows.map(d => ( +
+ {d.date} + + {d.kwh.toLocaleString('zh-CN', { maximumFractionDigits: 2 })} + + + {d.fee.toLocaleString('zh-CN', { maximumFractionDigits: 2 })} + + +
+ ))} +
+ )} +
+
+ ); + })} +
); }