rwadurian/frontend/admin-web/src/hooks/useDashboard.ts

167 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 仪表板数据 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秒自动刷新
});
}