/** * 数据状态管理 - DataStore * 功能:使用 Zustand 管理全局数据状态,包括账户、账单、预算、统计数据的 CRUD * 状态流转:每个 action 遵循 loading -> 请求 -> success/error -> loading=false 的流程 * 级联刷新:CRUD 操作成功后自动重新拉取列表和仪表盘汇总数据,保证跨页面数据一致性 * API 依赖:accountsApi、recordsApi、budgetsApi、statisticsApi */ import { create } from 'zustand'; import type { Account, Record, Budget, DashboardSummary, TrendStat, MonthlyCompare } from '../types'; import { accountsApi, recordsApi, budgetsApi, statisticsApi } from '../services'; /** * DataState 接口 - 定义全局数据状态的结构 */ interface DataState { // ===== 数据实体 ===== accounts: Account[]; // 账户列表 records: Record[]; // 账单记录列表 budgets: Budget[]; // 预算配置列表 dashboardSummary: DashboardSummary | null; // 仪表盘汇总数据(余额、收支、预算使用率) trendData: TrendStat[]; // 趋势统计数据(用于折线图) monthlyCompare: MonthlyCompare | null; // 月度对比数据(用于柱状对比图) loading: boolean; // 全局加载状态 error: string | null; // 全局错误信息 // ===== Actions - 数据查询 ===== fetchAccounts: () => Promise; fetchRecords: (params?: { accountId?: number; type?: 'income' | 'expense'; category?: string; startDate?: string; endDate?: string; }) => Promise; fetchBudgets: (month?: string) => Promise; fetchDashboardSummary: () => Promise; fetchTrendData: (startDate: string, endDate: string) => Promise; fetchMonthlyCompare: (month: string) => Promise; // ===== Actions - 数据操作 ===== createRecord: (data: any) => Promise; updateRecord: (id: number, data: any) => Promise; deleteRecord: (id: number) => Promise; createBudget: (data: any) => Promise; updateBudget: (id: number, data: any) => Promise; deleteBudget: (id: number) => Promise; clearError: () => void; } export const useDataStore = create((set, get) => ({ accounts: [], records: [], budgets: [], dashboardSummary: null, trendData: [], monthlyCompare: null, loading: false, error: null, // API: GET /api/accounts - 获取账户列表 fetchAccounts: async () => { set({ loading: true, error: null }); try { const data = await accountsApi.getAccounts(); set({ accounts: data }); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: GET /api/records - 获取账单记录列表(支持多条件筛选) fetchRecords: async (params) => { set({ loading: true, error: null }); try { const data = await recordsApi.getRecords(params); set({ records: data }); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: GET /api/budgets - 获取预算列表(可按月份筛选) fetchBudgets: async (month) => { set({ loading: true, error: null }); try { const data = await budgetsApi.getBudgets(month); set({ budgets: data }); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: GET /api/statistics/dashboard - 获取仪表盘汇总数据 // 同时更新 accounts 状态,因为汇总数据中包含账户信息 fetchDashboardSummary: async () => { set({ loading: true, error: null }); try { const data = await statisticsApi.getDashboardSummary(); set({ dashboardSummary: data, accounts: data.accounts }); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: fetchTrendData - 获取日期趋势数据(用于折线图) fetchTrendData: async (startDate: string, endDate: string) => { set({ loading: true, error: null }); try { const data = await statisticsApi.getTrendStats(startDate, endDate); set({ trendData: data }); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: fetchMonthlyCompare - 获取本月与上月对比数据(用于柱状对比图) fetchMonthlyCompare: async (month: string) => { set({ loading: true, error: null }); try { const data = await statisticsApi.getMonthlyCompare(month); set({ monthlyCompare: data }); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: POST /api/records - 创建账单记录,成功后级联刷新列表和仪表盘 // 级联刷新目的:确保其他页面(如 Dashboard、Budget)能立即看到最新数据 createRecord: async (data) => { set({ loading: true, error: null }); try { await recordsApi.createRecord(data); await get().fetchRecords(); await get().fetchDashboardSummary(); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: PUT /api/records/:id - 更新账单记录,成功后级联刷新 updateRecord: async (id, data) => { set({ loading: true, error: null }); try { await recordsApi.updateRecord(id, data); await get().fetchRecords(); await get().fetchDashboardSummary(); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: DELETE /api/records/:id - 删除账单记录,成功后级联刷新 deleteRecord: async (id) => { set({ loading: true, error: null }); try { await recordsApi.deleteRecord(id); await get().fetchRecords(); await get().fetchDashboardSummary(); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: POST /api/budgets - 创建预算,成功后级联刷新预算列表和仪表盘 createBudget: async (data) => { set({ loading: true, error: null }); try { await budgetsApi.createBudget(data); await get().fetchBudgets(); await get().fetchDashboardSummary(); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: PUT /api/budgets/:id - 更新预算,成功后级联刷新 updateBudget: async (id, data) => { set({ loading: true, error: null }); try { await budgetsApi.updateBudget(id, data); await get().fetchBudgets(); await get().fetchDashboardSummary(); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // API: DELETE /api/budgets/:id - 删除预算,成功后级联刷新 deleteBudget: async (id) => { set({ loading: true, error: null }); try { await budgetsApi.deleteBudget(id); await get().fetchBudgets(); await get().fetchDashboardSummary(); } catch (error) { set({ error: (error as Error).message }); } finally { set({ loading: false }); } }, // 清除全局错误信息,用于错误状态重置 clearError: () => set({ error: null }), }));