feat(energy): 氢能总览删除 4 张 KPI 卡,底部加动态幽默提示
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- 删除:年加氢量 / 年加氢费 / 累计羚牛承担 / 本月-今日 四张顶部 KPI 卡 (及对应的 Skeleton 占位、未用的 Fuel/Wallet/Coins/CalendarClock import 与 fmt 工具函数) - 新增 RotatingFooterHint:底部居中蓝色脉冲点 + 6 条幽默文案 4s 轮换淡入 例如「更多统计维度接入中,欢迎您的建议 ~」「数据科学家正在深夜挖掘新维度…」 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
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';
|
||||
|
||||
@@ -30,16 +29,15 @@ const REGION_COLORS = [
|
||||
'#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 })}`;
|
||||
}
|
||||
// 幽默动态提示词,每 4 秒轮换一条
|
||||
const FOOTER_HINTS = [
|
||||
'更多统计维度接入中,欢迎您的建议 ~',
|
||||
'下一个图表,可能就是您建议的那个',
|
||||
'数据科学家正在深夜挖掘新维度…',
|
||||
'想看哪个角度的数据?告诉我们一下嘛',
|
||||
'维度灵感正在路上,钉一下产品同学也行',
|
||||
'数字背后还有故事,等下一次上线揭晓',
|
||||
];
|
||||
|
||||
export default function HydrogenOverview() {
|
||||
const [data, setData] = useState<HydrogenOverviewResponse | null>(null);
|
||||
@@ -67,50 +65,6 @@ export default function HydrogenOverview() {
|
||||
<div className="bg-white rounded-xl border border-slate-100 px-3 py-1.5 text-[11px] text-slate-400">
|
||||
数据自 2025-01-01 起,每 1 分钟更新
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||
{/* 卡 1:年加氢量 */}
|
||||
<div className="bg-gradient-to-br from-cyan-50 to-blue-50 rounded-2xl border border-slate-100 shadow-sm p-4 flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between text-[11px] text-slate-500">
|
||||
<span className="flex items-center gap-1 font-bold"><Fuel size={12} className="text-cyan-600" />年加氢量</span>
|
||||
</div>
|
||||
<div className="text-2xl lg:text-3xl font-bold text-slate-800 leading-tight">{fmtKg(k.yearKg)}</div>
|
||||
</div>
|
||||
{/* 卡 2:年加氢费 */}
|
||||
<div className="bg-gradient-to-br from-blue-50 to-violet-50 rounded-2xl border border-slate-100 shadow-sm p-4 flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between text-[11px] text-slate-500">
|
||||
<span className="flex items-center gap-1 font-bold"><Wallet size={12} className="text-blue-600" />年加氢费</span>
|
||||
</div>
|
||||
<div className="text-2xl lg:text-3xl font-bold text-slate-800 leading-tight">{fmtYuanWan(k.yearFee)}</div>
|
||||
</div>
|
||||
{/* 卡 3:累计羚牛承担 */}
|
||||
<div className="bg-gradient-to-br from-amber-50 to-orange-50 rounded-2xl border border-slate-100 shadow-sm p-4 flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between text-[11px] text-slate-500">
|
||||
<span className="flex items-center gap-1 font-bold"><Coins size={12} className="text-amber-600" />累计羚牛承担</span>
|
||||
</div>
|
||||
<div className="text-2xl lg:text-3xl font-bold text-slate-800 leading-tight">{fmtYuanWan(k.lingniuBornFee)}</div>
|
||||
<div className="text-[11px] text-slate-500 font-bold space-y-0.5">
|
||||
<div>量 <span className="text-slate-700">{fmtKg(k.lingniuBornKg)}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 卡 4:本月 / 今日 */}
|
||||
<div className="bg-white rounded-2xl border border-slate-100 shadow-sm p-4 flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between text-[11px] text-slate-500">
|
||||
<span className="flex items-center gap-1 font-bold"><CalendarClock size={12} className="text-slate-500" />本月 / 今日</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<div className="text-[10px] text-slate-400 font-bold">本月</div>
|
||||
<div className="text-base md:text-lg font-bold text-slate-800">{fmtKg(k.monthKg)}</div>
|
||||
<div className="text-[11px] text-slate-500 font-bold">{fmtYuanWan(k.monthFee)}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-[10px] text-slate-400 font-bold">今日</div>
|
||||
<div className="text-base md:text-lg font-bold text-slate-800">{fmtKg(k.todayKg)}</div>
|
||||
<div className="text-[11px] text-slate-500 font-bold">{fmtYuan(k.todayFee)}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
{/* Top5 加氢站 */}
|
||||
<div className="bg-white rounded-2xl border border-slate-100 shadow-sm p-4">
|
||||
@@ -194,6 +148,33 @@ export default function HydrogenOverview() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<RotatingFooterHint />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RotatingFooterHint() {
|
||||
const [idx, setIdx] = useState(0);
|
||||
useEffect(() => {
|
||||
const t = setInterval(() => setIdx(i => (i + 1) % FOOTER_HINTS.length), 4000);
|
||||
return () => clearInterval(t);
|
||||
}, []);
|
||||
return (
|
||||
<div className="mt-1 flex items-center justify-center gap-1.5 text-[11px] text-slate-400 font-bold">
|
||||
<span className="inline-block w-1.5 h-1.5 rounded-full bg-blue-400 animate-pulse" />
|
||||
<span
|
||||
key={idx}
|
||||
className="transition-opacity duration-300"
|
||||
style={{ animation: 'hintFade 0.5s ease' }}
|
||||
>
|
||||
{FOOTER_HINTS[idx]}
|
||||
</span>
|
||||
<style>{`
|
||||
@keyframes hintFade {
|
||||
from { opacity: 0; transform: translateY(2px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -206,20 +187,6 @@ function HydrogenOverviewSkeleton() {
|
||||
<div className="h-3 w-44 bg-slate-100 rounded" />
|
||||
</div>
|
||||
|
||||
{/* 4 张 KPI 卡 */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||
{Array.from({ length: 4 }).map((_, i) => (
|
||||
<div key={i} className="bg-gradient-to-br from-slate-50 to-slate-100/60 rounded-2xl border border-slate-100 shadow-sm p-4 flex flex-col gap-3">
|
||||
<div className="h-3 w-16 bg-slate-200/70 rounded" />
|
||||
<div className="h-7 w-24 bg-slate-200 rounded" />
|
||||
<div className="space-y-1.5 mt-1">
|
||||
<div className="h-2.5 w-20 bg-slate-100 rounded" />
|
||||
<div className="h-2.5 w-24 bg-slate-100 rounded" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
{/* Top5 占位 */}
|
||||
<div className="bg-white rounded-2xl border border-slate-100 shadow-sm p-4">
|
||||
|
||||
Reference in New Issue
Block a user