fix(usage): keep previous stats while filters, range or page change

None of the usage queries had placeholder data, so every new filter,
time range or page cleared the dashboard: hero metrics flashed to an
ellipsis, the trend chart spun, and the request log table collapsed to
its skeleton (scrolling back up and possibly toggling the scrollbar).
Use keepPreviousData on the summary, trend, provider/model stats and
request log queries so the old numbers stay until the new ones land.
This commit is contained in:
Jason committed 2026-10-03 23:29:00 +08:00
1 parent 416cc11799
commit 3dc46460fe
1 file changed
+14 -1
+14 -1
View File
@@ -1,4 +1,9 @@
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import {
keepPreviousData,
useQuery,
useMutation,
useQueryClient,
} from "@tanstack/react-query";
import { usageApi } from "@/lib/api/usage";
import { resolveUsageRange } from "@/lib/usageRange";
import type {
@@ -161,6 +166,8 @@ function normalizeScopeFilters(filters?: UsageScopeFilters): UsageScopeFilters {
}
// Hooks
// 统计类查询都带 keepPreviousData:换筛选、时间范围、翻页时先留着上一份数据,
// 新数据到了再换,不让指标闪成「…」、请求日志表塌成骨架。
export function useUsageSummary(
range: UsageRangeSelection,
filters?: UsageScopeFilters,
@@ -185,6 +192,7 @@ export function useUsageSummary(
effective.model,
);
},
placeholderData: keepPreviousData,
refetchInterval: options?.refetchInterval ?? DEFAULT_REFETCH_INTERVAL_MS,
refetchIntervalInBackground: options?.refetchIntervalInBackground ?? false,
});
@@ -212,6 +220,7 @@ export function useUsageSummaryByApp(
filters?.model,
);
},
placeholderData: keepPreviousData,
refetchInterval: options?.refetchInterval ?? DEFAULT_REFETCH_INTERVAL_MS,
refetchIntervalInBackground: options?.refetchIntervalInBackground ?? false,
});
@@ -241,6 +250,7 @@ export function useUsageTrends(
effective.model,
);
},
placeholderData: keepPreviousData,
refetchInterval: options?.refetchInterval ?? DEFAULT_REFETCH_INTERVAL_MS,
refetchIntervalInBackground: options?.refetchIntervalInBackground ?? false,
});
@@ -270,6 +280,7 @@ export function useProviderStats(
effective.model,
);
},
placeholderData: keepPreviousData,
refetchInterval: options?.refetchInterval ?? DEFAULT_REFETCH_INTERVAL_MS,
refetchIntervalInBackground: options?.refetchIntervalInBackground ?? false,
});
@@ -299,6 +310,7 @@ export function useModelStats(
effective.model,
);
},
placeholderData: keepPreviousData,
refetchInterval: options?.refetchInterval ?? DEFAULT_REFETCH_INTERVAL_MS,
refetchIntervalInBackground: options?.refetchIntervalInBackground ?? false,
});
@@ -328,6 +340,7 @@ export function useRequestLogs({
const effectiveFilters = { ...filters, ...resolveUsageRange(range) };
return usageApi.getRequestLogs(effectiveFilters, page, pageSize);
},
placeholderData: keepPreviousData,
refetchInterval: options?.refetchInterval ?? DEFAULT_REFETCH_INTERVAL_MS, // 每30秒自动刷新
refetchIntervalInBackground: options?.refetchIntervalInBackground ?? false,
});