/** * 仪表板数据 Hooks * 使用 React Query 进行数据获取和缓存管理 */ import { useQuery } from '@tanstack/react-query'; import { dashboardService } from '@/services/dashboardService'; import type { DashboardPeriod } from '@/types'; /** Query Keys */ export const dashboardKeys = { all: ['dashboard'] as const, overview: () => [...dashboardKeys.all, 'overview'] as const, stats: () => [...dashboardKeys.all, 'stats'] as const, trend: (period: DashboardPeriod) => [...dashboardKeys.all, 'trend', period] as const, region: () => [...dashboardKeys.all, 'region'] as const, activities: (limit: number) => [...dashboardKeys.all, 'activities', limit] as const, plantingStats: () => [...dashboardKeys.all, 'plantingStats'] as const, // [2026-01-06] 新增:planting-service 趋势数据(用于仪表板) plantingTrend: (days: number) => [...dashboardKeys.all, 'plantingTrend', days] as const, // [2026-01-07] 新增:热钱包余额 hotWalletBalance: () => [...dashboardKeys.all, 'hotWalletBalance'] as const, }; /** * 获取仪表板概览数据 */ export function useDashboardOverview() { return useQuery({ queryKey: dashboardKeys.overview(), queryFn: async () => { const response = await dashboardService.getOverview(); return response.data; }, staleTime: 30 * 1000, // 30秒后标记为过期 gcTime: 5 * 60 * 1000, // 5分钟后垃圾回收 }); } /** * 获取统计卡片数据 */ export function useDashboardStats() { return useQuery({ queryKey: dashboardKeys.stats(), queryFn: async () => { const response = await dashboardService.getStats(); // 确保返回数组,即使 API 返回 undefined 或非数组 return response?.data?.stats ?? []; }, staleTime: 30 * 1000, gcTime: 5 * 60 * 1000, }); } /** * 获取趋势图表数据 * @param period 时间周期 */ export function useDashboardTrend(period: DashboardPeriod = '7d') { return useQuery({ queryKey: dashboardKeys.trend(period), queryFn: async () => { const response = await dashboardService.getTrendData(period); return response.data.trend; }, staleTime: 60 * 1000, // 1分钟后标记为过期 gcTime: 5 * 60 * 1000, }); } /** * 获取区域分布数据 */ export function useDashboardRegion() { return useQuery({ queryKey: dashboardKeys.region(), queryFn: async () => { const response = await dashboardService.getRegionDistribution(); // 确保返回数组 return response?.data?.regions ?? []; }, staleTime: 5 * 60 * 1000, // 5分钟后标记为过期 gcTime: 10 * 60 * 1000, }); } /** * 获取最近活动数据 * @param limit 返回数量限制 */ export function useDashboardActivities(limit = 5) { return useQuery({ queryKey: dashboardKeys.activities(limit), queryFn: async () => { const response = await dashboardService.getRecentActivities(limit); // 确保返回数组 return response?.data?.activities ?? []; }, staleTime: 30 * 1000, // 30秒后标记为过期 gcTime: 5 * 60 * 1000, refetchInterval: 60 * 1000, // 每分钟自动刷新 }); } /** * 获取认种统计数据(来自 planting-service,直接从订单表聚合) * 数据更可靠,用于显示总认种量 */ export function usePlantingStats() { return useQuery({ queryKey: dashboardKeys.plantingStats(), queryFn: async () => { const response = await dashboardService.getPlantingStats(); return response?.data ?? null; }, staleTime: 60 * 1000, // 1分钟后标记为过期 gcTime: 5 * 60 * 1000, }); } /** * 获取认种趋势数据(用于仪表板趋势图) * [2026-01-06] 新增:直接使用 planting-service 数据 * @param days 天数:7, 30, 90 对应仪表板的三个选项 */ export function usePlantingTrendForDashboard(days: 7 | 30 | 90 = 7) { return useQuery({ queryKey: dashboardKeys.plantingTrend(days), queryFn: async () => { // 使用 day 维度获取趋势数据 const response = await dashboardService.getPlantingTrendData('day'); if (!response?.data) return []; // 根据 days 参数截取最近的数据 const allData = response.data; const slicedData = allData.slice(-days); // 转换为 TrendChart 组件需要的格式 return slicedData.map(item => ({ date: item.label.slice(5), // 2026-01-06 -> 01-06 value: item.treeCount, })); }, staleTime: 60 * 1000, gcTime: 5 * 60 * 1000, }); } // [2026-01-07] 新增:热钱包余额查询 /** * 获取热钱包余额(公共账户和因子) * 用于仪表板显示实时余额 */ export function useHotWalletBalance() { return useQuery({ queryKey: dashboardKeys.hotWalletBalance(), queryFn: async () => { const response = await dashboardService.getHotWalletBalance(); return response?.data ?? null; }, staleTime: 10 * 1000, // 10秒后标记为过期(实时性要求较高) gcTime: 60 * 1000, refetchInterval: 15 * 1000, // 每15秒自动刷新 }); }