chore: add frontend/src/stores/dataStore.ts

This commit is contained in:
2026-04-29 10:53:38 +08:00
parent 717b05a3b8
commit 60f0ac62bb
+226
View File
@@ -0,0 +1,226 @@
/**
* 数据状态管理 - 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<void>;
fetchRecords: (params?: {
accountId?: number;
type?: 'income' | 'expense';
category?: string;
startDate?: string;
endDate?: string;
}) => Promise<void>;
fetchBudgets: (month?: string) => Promise<void>;
fetchDashboardSummary: () => Promise<void>;
fetchTrendData: (startDate: string, endDate: string) => Promise<void>;
fetchMonthlyCompare: (month: string) => Promise<void>;
// ===== Actions - 数据操作 =====
createRecord: (data: any) => Promise<void>;
updateRecord: (id: number, data: any) => Promise<void>;
deleteRecord: (id: number) => Promise<void>;
createBudget: (data: any) => Promise<void>;
updateBudget: (id: number, data: any) => Promise<void>;
deleteBudget: (id: number) => Promise<void>;
clearError: () => void;
}
export const useDataStore = create<DataState>((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 }),
}));