11"use client" ;
22
33import * as React from "react" ;
4+ import { useQuery } from "@tanstack/react-query" ;
45import { UserStatisticsChart } from "./chart" ;
56import { getUserStatistics } from "@/actions/statistics" ;
67import type { TimeRange , UserStatisticsData } from "@/types/statistics" ;
@@ -11,6 +12,16 @@ interface StatisticsWrapperProps {
1112 initialData ?: UserStatisticsData ;
1213}
1314
15+ const STATISTICS_REFRESH_INTERVAL = 5000 ; // 5秒刷新一次
16+
17+ async function fetchStatistics ( timeRange : TimeRange ) : Promise < UserStatisticsData > {
18+ const result = await getUserStatistics ( timeRange ) ;
19+ if ( result . ok && result . data ) {
20+ return result . data ;
21+ }
22+ throw new Error ( result . error || '获取统计数据失败' ) ;
23+ }
24+
1425/**
1526 * 统计组件包装器
1627 * 处理时间范围状态管理和数据获取
@@ -19,71 +30,39 @@ export function StatisticsWrapper({ initialData }: StatisticsWrapperProps) {
1930 const [ timeRange , setTimeRange ] = React . useState < TimeRange > (
2031 initialData ?. timeRange ?? DEFAULT_TIME_RANGE
2132 ) ;
22- const [ data , setData ] = React . useState < UserStatisticsData | null > ( initialData ?? null ) ;
23- const [ loading , setLoading ] = React . useState ( false ) ;
24-
25- // 防抖获取统计数据
26- const fetchStatistics = React . useCallback ( async ( newTimeRange : TimeRange ) => {
27- if ( loading ) return ; // 防止重复请求
28-
29- setLoading ( true ) ;
30- try {
31- const result = await getUserStatistics ( newTimeRange ) ;
32- if ( ! result . ok ) {
33- toast . error ( result . error || '获取统计数据失败' ) ;
34- return ;
35- }
3633
37- if ( ! result . data ) {
38- toast . error ( '统计数据为空' ) ;
39- return ;
40- }
34+ const { data, error } = useQuery < UserStatisticsData , Error > ( {
35+ queryKey : [ "user-statistics" , timeRange ] ,
36+ queryFn : ( ) => fetchStatistics ( timeRange ) ,
37+ initialData,
38+ refetchInterval : STATISTICS_REFRESH_INTERVAL ,
39+ } ) ;
4140
42- setData ( result . data ) ;
43- setTimeRange ( newTimeRange ) ;
44- } catch ( error ) {
45- console . error ( 'Failed to fetch statistics:' , error ) ;
46- toast . error ( '获取统计数据失败' ) ;
47- } finally {
48- // 添加一个小延迟让用户看到加载状态,避免闪烁
49- setTimeout ( ( ) => setLoading ( false ) , 150 ) ;
41+ // 错误提示
42+ React . useEffect ( ( ) => {
43+ if ( error ) {
44+ toast . error ( error . message ) ;
5045 }
51- } , [ loading ] ) ;
46+ } , [ error ] ) ;
5247
5348 // 处理时间范围变化
5449 const handleTimeRangeChange = React . useCallback ( ( newTimeRange : TimeRange ) => {
55- if ( newTimeRange !== timeRange && ! loading ) {
56- fetchStatistics ( newTimeRange ) ;
57- }
58- } , [ timeRange , loading , fetchStatistics ] ) ;
50+ setTimeRange ( newTimeRange ) ;
51+ } , [ ] ) ;
5952
60- // 如果没有数据且不在加载中 ,显示空状态
61- if ( ! data && ! loading ) {
53+ // 如果没有数据 ,显示空状态
54+ if ( ! data ) {
6255 return (
6356 < div className = "text-center py-8 text-muted-foreground" >
6457 暂无统计数据
6558 </ div >
6659 ) ;
6760 }
6861
69- // 如果有数据,显示图表
70- if ( data ) {
71- return (
72- < UserStatisticsChart
73- data = { data }
74- onTimeRangeChange = { handleTimeRangeChange }
75- loading = { loading }
76- />
77- ) ;
78- }
79-
80- // 纯加载状态
8162 return (
82- < div className = "text-center py-8" >
83- < div className = "flex items-center justify-center gap-2 text-sm text-muted-foreground" >
84- < div className = "h-4 w-4 animate-spin rounded-full border-2 border-orange-600 border-t-transparent" />
85- 加载统计数据...
86- </ div >
87- </ div >
63+ < UserStatisticsChart
64+ data = { data }
65+ onTimeRangeChange = { handleTimeRangeChange }
66+ />
8867 ) ;
8968}
0 commit comments