perf(platform): 创作页加载 - 合并用户数据与余额请求并按路由延迟加载

This commit is contained in:
ddCat
2026-08-14 18:35:17 +08:00
parent 2d3dd86fbe
commit 920cd92c16
9 changed files with 160 additions and 148 deletions

View File

@@ -1,76 +1,44 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect } from "react";
import { getWallet } from "@/services/api/wallet";
const WALLET_REFRESH_INTERVAL_MS = 30_000;
type WalletBalanceSnapshot = {
userId: string;
availableMicrocredits: number | null;
refreshing: boolean;
};
const walletBalanceQueryKey = (userId: string) => ["wallet-balance", userId] as const;
export function useWalletBalance(userId?: string, enabled = true) {
const activeUserId = enabled ? userId || "" : "";
const requestSequence = useRef(0);
const [snapshot, setSnapshot] = useState<WalletBalanceSnapshot>({ userId: "", availableMicrocredits: null, refreshing: false });
const refresh = useCallback(async () => {
const requestedUserId = activeUserId;
const sequence = ++requestSequence.current;
if (!requestedUserId) {
setSnapshot({ userId: "", availableMicrocredits: null, refreshing: false });
return;
}
setSnapshot((current) => ({
userId: requestedUserId,
availableMicrocredits: current.userId === requestedUserId ? current.availableMicrocredits : null,
refreshing: true,
}));
try {
const queryClient = useQueryClient();
const queryKey = walletBalanceQueryKey(activeUserId);
const query = useQuery({
queryKey,
enabled: Boolean(activeUserId),
queryFn: async () => {
const wallet = await getWallet(1, 1);
if (sequence !== requestSequence.current) return;
if (wallet.account.userId !== requestedUserId) throw new Error("积分账户与当前用户不一致");
setSnapshot({ userId: requestedUserId, availableMicrocredits: wallet.account.availableMicrocredits, refreshing: false });
} catch (error) {
if (sequence !== requestSequence.current) return;
console.warn("积分余额刷新失败", error);
setSnapshot((current) => ({
userId: requestedUserId,
availableMicrocredits: current.userId === requestedUserId ? current.availableMicrocredits : null,
refreshing: false,
}));
}
}, [activeUserId]);
if (wallet.account.userId !== activeUserId) throw new Error("积分账户与当前用户不一致");
return wallet.account.availableMicrocredits;
},
staleTime: 15_000,
refetchInterval: WALLET_REFRESH_INTERVAL_MS,
refetchOnWindowFocus: true,
});
useEffect(() => {
if (!activeUserId) {
requestSequence.current += 1;
setSnapshot({ userId: "", availableMicrocredits: null, refreshing: false });
return;
}
void refresh();
const timer = window.setInterval(() => void refresh(), WALLET_REFRESH_INTERVAL_MS);
const handleFocus = () => void refresh();
const handleVisibility = () => {
if (document.visibilityState === "visible") void refresh();
};
window.addEventListener("focus", handleFocus);
window.addEventListener("wallet:updated", handleFocus);
document.addEventListener("visibilitychange", handleVisibility);
if (!activeUserId) return;
const handleUpdated = () => void queryClient.invalidateQueries({ queryKey: walletBalanceQueryKey(activeUserId) });
window.addEventListener("wallet:updated", handleUpdated);
return () => {
requestSequence.current += 1;
window.clearInterval(timer);
window.removeEventListener("focus", handleFocus);
window.removeEventListener("wallet:updated", handleFocus);
document.removeEventListener("visibilitychange", handleVisibility);
window.removeEventListener("wallet:updated", handleUpdated);
};
}, [activeUserId, refresh]);
}, [activeUserId, queryClient]);
useEffect(() => {
if (query.error) console.warn("积分余额刷新失败", query.error);
}, [query.error]);
const snapshotMatchesUser = snapshot.userId === activeUserId;
return {
availableMicrocredits: snapshotMatchesUser ? snapshot.availableMicrocredits : null,
refreshing: snapshotMatchesUser ? snapshot.refreshing : Boolean(activeUserId),
refresh,
availableMicrocredits: query.data ?? null,
refreshing: query.isFetching,
refresh: query.refetch,
};
}