import type { HydrogenOverviewResponse } from '../api'; export function formatKg(kg: number): { value: string; unit: string } { if (kg >= 1000) return { value: (kg / 1000).toFixed(2), unit: 'T' }; return { value: kg.toFixed(2), unit: 'Kg' }; } export function formatYuan(yuan: number): { value: string; unit: string } { const absolute = Math.abs(yuan); if (absolute >= 100_000_000) { return { value: (yuan / 100_000_000).toFixed(2), unit: '亿元' }; } if (absolute >= 10_000) { return { value: (yuan / 10_000).toLocaleString('zh-CN', { maximumFractionDigits: 2 }), unit: '万元', }; } return { value: yuan.toLocaleString('zh-CN', { maximumFractionDigits: 0 }), unit: '元', }; } export function formatRelative(timestamp: number, now = Date.now()): string { const seconds = Math.max(0, Math.floor((now - timestamp) / 1000)); if (seconds < 5) return '刚刚'; if (seconds < 60) return `${seconds} 秒前`; const minutes = Math.floor(seconds / 60); if (minutes < 60) return `${minutes} 分钟前`; const hours = Math.floor(minutes / 60); if (hours < 24) return `${hours} 小时前`; return new Date(timestamp).toLocaleString('zh-CN', { hour12: false }); } export function formatRefreshTime(timestamp: number, now = Date.now()): string { const exactTime = new Date(timestamp).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12: false, }); return `${formatRelative(timestamp, now)} · ${exactTime.replace(/\//g, '-')}`; } export function deriveOverviewMetrics(data: HydrogenOverviewResponse) { const { kpi, monthly, stations, top5 } = data; const monthAvgKg = monthly.length > 0 ? monthly.reduce((sum, month) => sum + month.kg, 0) / monthly.length : 0; const bestMonth = monthly.reduce( (best, item) => (!best || item.kg > best.kg ? item : best), null, ); const latestMonth = monthly[monthly.length - 1]; const previousMonth = monthly[monthly.length - 2]; return { monthAvgKg, bestMonth, latestMonth, monthMomentum: latestMonth && previousMonth && previousMonth.kg > 0 ? ((latestMonth.kg - previousMonth.kg) / previousMonth.kg) * 100 : null, top5Share: (top5.reduce((sum, item) => sum + item.kg, 0) / Math.max(1, kpi.yearKg)) * 100, profitYield: kpi.yearRevenue > 0 ? (kpi.yearProfit / kpi.yearRevenue) * 100 : 0, stationAvgKg: stations.length > 0 ? kpi.yearKg / stations.length : 0, monthlyDual: monthly.map(month => ({ ...month, monthLabel: `${month.month.slice(5).replace(/^0/, '')}月`, })), }; }