import React, { useState, useEffect } from 'react'; import { Icon } from '@iconify/react'; import { formatCurrency } from '../../../utils/format'; import { getDailyInsight } from '../../../services/aiService'; import './DailyInsightCard.css'; interface DailyInsightCardProps { todaySpend: number; yesterdaySpend: number; monthlyBudget: number; monthlySpent: number; topCategory?: { name: string; amount: number }; maxTransaction?: { note?: string; amount: number }; lastWeekSpend?: number; streakDays?: number; // 新增字段 budgetRemaining?: number; daysRemaining?: number; weeklyTotal?: number; avgDailySpend?: number; top3Categories?: { name: string; amount: number }[]; todayTransactionCount?: number; last7DaysSpend?: number[]; // 最近7天每日支出 } export const DailyInsightCard: React.FC = ({ todaySpend, yesterdaySpend, monthlyBudget, monthlySpent, topCategory, maxTransaction, lastWeekSpend, streakDays, budgetRemaining, daysRemaining, weeklyTotal, avgDailySpend, top3Categories, todayTransactionCount, last7DaysSpend, }) => { const [aiData, setAiData] = useState<{ spending: string; budget: string; emoji?: string; tip?: string } | null>(null); const [isAiLoading, setIsAiLoading] = useState(false); useEffect(() => { // Only fetch if has meaningful data or at least budget is set if (monthlyBudget === 0 && todaySpend === 0 && yesterdaySpend === 0) return; const fetchAI = async () => { setIsAiLoading(true); try { const today = new Date().getDate(); const daysInMonth = new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0).getDate(); const result = await getDailyInsight({ todaySpend, yesterdaySpend, monthlyBudget, monthlySpent, monthProgress: today / daysInMonth, topCategory, maxTransaction: maxTransaction ? { note: maxTransaction.note || '', amount: maxTransaction.amount } : undefined, lastWeekSpend, streakDays, // 新增数据 budgetRemaining, daysRemaining: daysRemaining ?? (daysInMonth - today), weeklyTotal, avgDailySpend, top3Categories, todayTransactionCount, last7DaysSpend, }); setAiData(result); } catch (e) { console.warn('AI insight fetch failed, sticking to local logic'); } finally { setIsAiLoading(false); } }; const timer = setTimeout(fetchAI, 500); return () => clearTimeout(timer); }, [todaySpend, yesterdaySpend, monthlyBudget, monthlySpent, topCategory, maxTransaction, lastWeekSpend, streakDays, budgetRemaining, daysRemaining, weeklyTotal, avgDailySpend, top3Categories, todayTransactionCount, last7DaysSpend]); const getSpendingInsight = (today: number, yesterday: number) => { if (aiData) return { text: {aiData.spending}, type: 'ai' }; if (today === 0) return { text: "今天还没有花钱,保持这种“零消费”状态就是最大的赚钱!", type: 'success' }; if (yesterday === 0) return { text: 今天花了 {formatCurrency(today)},既然昨天没花钱,今天稍微奢侈一点也无妨。, type: 'normal' }; const diff = today - yesterday; if (Math.abs(diff) < 10) return { text: 今天支出 {formatCurrency(today)},跟昨天差不多,生活节奏很稳。, type: 'normal' }; if (today < yesterday) { const percent = Math.round(((yesterday - today) / yesterday) * 100); return { text: 比昨天少花了 {percent}%!这就是进步,省下来的钱可以积少成多。, type: 'success' }; } else { const percent = Math.round(((today - yesterday) / yesterday) * 100); return { text: 比昨天多花了 {percent}%。如果不是必需品,记得明天稍微控制一下哦。, type: 'warning' }; } }; const getBudgetInsight = (spent: number, total: number) => { if (aiData) return { text: {aiData.budget}, type: 'ai' }; if (total === 0) return { text: "您还没有设置月度预算,建议去设置一个。", type: 'normal' }; const ratio = spent / total; const today = new Date().getDate(); const daysInMonth = new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0).getDate(); const timeRatio = today / daysInMonth; if (ratio >= 1) return { text: 本月预算已耗尽!接下来的每一天都需要极限生存挑战了。, type: 'danger' }; if (ratio > timeRatio + 0.15) { return { text: 进度 {Math.round(ratio * 100)}% (时间 {Math.round(timeRatio * 100)}%)。花钱速度有点快了,建议踩踩刹车。, type: 'warning' }; } if (ratio < timeRatio - 0.1) { return { text: 进度 {Math.round(ratio * 100)}% (时间 {Math.round(timeRatio * 100)}%)。控制得非常完美,月底可能有惊喜结余!, type: 'success' }; } return { text: 进度 {Math.round(ratio * 100)}% (时间 {Math.round(timeRatio * 100)}%)。目前节奏刚刚好,稳扎稳打。, type: 'normal' }; }; const spendingInsight = getSpendingInsight(todaySpend, yesterdaySpend); const budgetInsight = getBudgetInsight(monthlySpent, monthlyBudget); return (
{aiData ? 'AI 消费简报' : '消费简报'} {aiData?.emoji && {aiData.emoji}} {isAiLoading && !aiData && AI 思考中...}
今日消费 {lastWeekSpend !== undefined && lastWeekSpend > 0 && ( 周同比 {todaySpend <= lastWeekSpend ? '↓' : '↑'}{Math.abs(todaySpend - lastWeekSpend).toFixed(0)} )}

{spendingInsight.text}

预算风向标

{budgetInsight.text}

{aiData?.tip && (
{aiData.tip}
)}
); };