From 732793c5c30282064a50c612de2a55a9c77141d4 Mon Sep 17 00:00:00 2001 From: admin <1297598740@qq.com> Date: Thu, 29 Jan 2026 07:49:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E9=A6=96=E9=A1=B5?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=EF=BC=8C=E5=B1=95=E7=A4=BA=E8=B4=A6=E6=88=B7?= =?UTF-8?q?=E6=A6=82=E8=A7=88=E3=80=81=E4=BA=A4=E6=98=93=E8=B6=8B=E5=8A=BF?= =?UTF-8?q?=E3=80=81=E9=A2=84=E7=AE=97=E4=BF=A1=E6=81=AF=E5=8F=8A=E6=8F=90?= =?UTF-8?q?=E4=BE=9B=E5=BF=AB=E6=8D=B7=E6=93=8D=E4=BD=9C=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home/Home.tsx | 91 ++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx index 5901188..4f1ff31 100644 --- a/src/pages/Home/Home.tsx +++ b/src/pages/Home/Home.tsx @@ -69,7 +69,7 @@ function Home() { setLoading(true); setError(null); - // Helper for local date string YYYY-MM-DD to fix timezone issues + // Helper for local date string YYYY-MM-DD const toLocalDate = (d: Date) => { const year = d.getFullYear(); const month = String(d.getMonth() + 1).padStart(2, '0'); @@ -77,56 +77,74 @@ function Home() { return `${year}-${month}-${day}`; }; - // Calculate dates for today, yesterday, and last week same day + // Helper to check if two dates are the same day (using local time) + const isSameDay = (d1: Date, d2: Date) => { + return d1.getFullYear() === d2.getFullYear() && + d1.getMonth() === d2.getMonth() && + d1.getDate() === d2.getDate(); + }; + const today = new Date(); const yesterday = new Date(today); yesterday.setDate(yesterday.getDate() - 1); - const lastWeek = new Date(today); - lastWeek.setDate(lastWeek.getDate() - 7); + const lastWeekSameDay = new Date(today); + lastWeekSameDay.setDate(lastWeekSameDay.getDate() - 7); - const todayStr = toLocalDate(today); - const yesterdayStr = toLocalDate(yesterday); - const lastWeekStr = toLocalDate(lastWeek); + // Calculate range for fetching: 8 days ago to Tomorrow (to cover timezone shifts) + const rangeStart = new Date(today); + rangeStart.setDate(rangeStart.getDate() - 8); + const rangeEnd = new Date(today); + rangeEnd.setDate(rangeEnd.getDate() + 1); - // Generate last 7 days date strings (from 6 days ago to today) - const last7Days: string[] = []; - for (let i = 6; i >= 0; i--) { - const d = new Date(today); - d.setDate(d.getDate() - i); - last7Days.push(toLocalDate(d)); - } + const rangeStartStr = toLocalDate(rangeStart); + const rangeEndStr = toLocalDate(rangeEnd); - // Load accounts, recent transactions, today/yesterday stats... AND last 7 days - const [accountsData, transactionsData, categoriesData, ledgersData, settingsData, budgetsData, todayData, yesterdayData, lastWeekData, streakData, ...last7DaysData] = await Promise.all([ + // Parallel fetch optimized: Single request for transaction history + const [accountsData, recentTxData, categoriesData, ledgersData, settingsData, budgetsData, streakData, rangeTxData] = await Promise.all([ getAccounts(), - getTransactions({ page: 1, pageSize: 5 }), // Recent + getTransactions({ page: 1, pageSize: 5 }), // Recent list (server sort) getCategories(), getLedgers().catch(() => []), getSettings().catch(() => null), getBudgets().catch(() => []), - getTransactions({ startDate: todayStr, endDate: todayStr, type: 'expense', pageSize: 100 }), - getTransactions({ startDate: yesterdayStr, endDate: yesterdayStr, type: 'expense', pageSize: 100 }), - getTransactions({ startDate: lastWeekStr, endDate: lastWeekStr, type: 'expense', pageSize: 100 }), // Last week same day getStreakInfo().catch(() => null), - // Fetch last 7 days data - ...last7Days.map(dateStr => - getTransactions({ startDate: dateStr, endDate: dateStr, type: 'expense', pageSize: 100 }) - ), + getTransactions({ startDate: rangeStartStr, endDate: rangeEndStr, type: 'expense', pageSize: 1000 }), // Bulk fetch ]); setAccounts(accountsData || []); - setRecentTransactions(transactionsData?.items || []); + setRecentTransactions(recentTxData?.items || []); setCategories(categoriesData || []); setLedgers(ledgersData || []); setSettings(settingsData); + setStreakInfo(streakData); - // Calculate daily spends - setTodaySpend(calculateTotalExpense(todayData.items)); - setTodayTransactions(todayData.items || []); - setYesterdaySpend(calculateTotalExpense(yesterdayData.items)); - setLastWeekSpend(calculateTotalExpense(lastWeekData.items)); + // In-Memory Aggregation for Daily Spend (Fixes Timezone Issues) + const allRangeTx = rangeTxData?.items || []; - // Calculate monthly budget stats (Normalized) + // Today + const todayTxItems = allRangeTx.filter(t => isSameDay(new Date(t.transactionDate), today)); + setTodayTransactions(todayTxItems); + setTodaySpend(calculateTotalExpense(todayTxItems)); + + // Yesterday + const yesterdayTxItems = allRangeTx.filter(t => isSameDay(new Date(t.transactionDate), yesterday)); + setYesterdaySpend(calculateTotalExpense(yesterdayTxItems)); + + // Last Week Same Day + const lastWeekTxItems = allRangeTx.filter(t => isSameDay(new Date(t.transactionDate), lastWeekSameDay)); + setLastWeekSpend(calculateTotalExpense(lastWeekTxItems)); + + // Last 7 Days Array (for chart) + const last7DaysSpendArray = []; + for (let i = 6; i >= 0; i--) { + const d = new Date(today); + d.setDate(d.getDate() - i); + const dayTx = allRangeTx.filter(t => isSameDay(new Date(t.transactionDate), d)); + last7DaysSpendArray.push(calculateTotalExpense(dayTx)); + } + setLast7DaysSpend(last7DaysSpendArray); + + // Monthly Budget Stats let mTotal = 0; let mSpent = 0; (budgetsData || []).forEach((b: any) => { @@ -136,22 +154,11 @@ function Home() { else if (b.periodType === 'yearly') multiplier = 1 / 12; mTotal += b.amount * multiplier; - // We add the actual spent amount regardless of period, as it contributes to "Monthly Spending" in a general sense - // But strictly speaking, Daily spent resets daily. - // For the purpose of "Monthly Overview", we just want to know if there IS a budget. mSpent += (b.spent || 0); }); setMonthlyBudgetTotal(mTotal); setMonthlyBudgetSpentTotal(mSpent); - // Set streak info - setStreakInfo(streakData); - - // Calculate last 7 days spending array - const last7DaysSpendArray = last7DaysData.map(dayData => - calculateTotalExpense(dayData?.items || []) - ); - setLast7DaysSpend(last7DaysSpendArray); } catch (err) { setError(err instanceof Error ? err.message : '加载数据失败'); console.error('Failed to load home page data:', err);