refactor: 引入 SWR 统一钱包余额查询与轮询逻辑

This commit is contained in:
2026-06-10 13:58:26 +08:00
parent 4707101da4
commit 20d2befa55
12 changed files with 255 additions and 268 deletions

View File

@@ -1,51 +1,40 @@
"use client";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import { useCallback, useEffect } from "react";
import { useSWRConfig } from "swr";
import { getWalletBalance } from "@/api/wallet";
import { TransferInPage } from "@/features/wallet/wallet-transfer-forms";
import { Skeleton } from "@/components/ui/skeleton";
import { useActivePlayerCurrency } from "@/hooks/use-active-player-currency";
import { useApiQuery } from "@/hooks/use-api-query";
import { PLAYER_CURRENCY_CHANGE_EVENT } from "@/lib/player-currency-preference";
import type { WalletBalanceData } from "@/types/api/wallet-balance";
const BALANCE_KEY = (currency: string) => ["wallet/balance", currency];
/** 独立路由 `/wallet/transfer-in` */
export function TransferInScreen() {
const router = useRouter();
const { activeCurrency: currency } = useActivePlayerCurrency();
const [balance, setBalance] = useState<WalletBalanceData | null>(null);
const [loading, setLoading] = useState(true);
const { mutate } = useSWRConfig();
const load = useCallback(async () => {
const b = await getWalletBalance({ currency });
setBalance(b);
}, [currency]);
const { data: balance, isLoading: loading } = useApiQuery(
BALANCE_KEY(currency),
() => getWalletBalance({ currency }),
);
// 币种切换时 SWR key 自动变化,此处仅处理全局事件触发的刷新
useEffect(() => {
let c = false;
void (async () => {
try {
await load();
} finally {
if (!c) setLoading(false);
}
})();
return () => {
c = true;
};
}, [load]);
useEffect(() => {
const onCurrencyChange = () => void load();
window.addEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange);
return () => window.removeEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange);
}, [load]);
const onRefresh = () => void mutate(BALANCE_KEY(currency));
window.addEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onRefresh);
return () => window.removeEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onRefresh);
}, [mutate, currency]);
const onSuccess = useCallback(async () => {
await load();
await mutate(BALANCE_KEY(currency));
router.push("/wallet");
}, [load, router]);
}, [mutate, currency, router]);
if (loading && !balance) {
return (

View File

@@ -1,51 +1,40 @@
"use client";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import { useCallback, useEffect } from "react";
import { useSWRConfig } from "swr";
import { getWalletBalance } from "@/api/wallet";
import { TransferOutPage } from "@/features/wallet/wallet-transfer-forms";
import { Skeleton } from "@/components/ui/skeleton";
import { useActivePlayerCurrency } from "@/hooks/use-active-player-currency";
import { useApiQuery } from "@/hooks/use-api-query";
import { PLAYER_CURRENCY_CHANGE_EVENT } from "@/lib/player-currency-preference";
import type { WalletBalanceData } from "@/types/api/wallet-balance";
const BALANCE_KEY = (currency: string) => ["wallet/balance", currency];
/** 独立路由 `/wallet/transfer-out` */
export function TransferOutScreen() {
const router = useRouter();
const { activeCurrency: currency } = useActivePlayerCurrency();
const [balance, setBalance] = useState<WalletBalanceData | null>(null);
const [loading, setLoading] = useState(true);
const { mutate } = useSWRConfig();
const load = useCallback(async () => {
const b = await getWalletBalance({ currency });
setBalance(b);
}, [currency]);
const { data: balance, isLoading: loading } = useApiQuery(
BALANCE_KEY(currency),
() => getWalletBalance({ currency }),
);
// 币种切换时 SWR key 自动变化,此处仅处理全局事件触发的刷新
useEffect(() => {
let c = false;
void (async () => {
try {
await load();
} finally {
if (!c) setLoading(false);
}
})();
return () => {
c = true;
};
}, [load]);
useEffect(() => {
const onCurrencyChange = () => void load();
window.addEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange);
return () => window.removeEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange);
}, [load]);
const onRefresh = () => void mutate(BALANCE_KEY(currency));
window.addEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onRefresh);
return () => window.removeEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onRefresh);
}, [mutate, currency]);
const onSuccess = useCallback(async () => {
await load();
await mutate(BALANCE_KEY(currency));
router.push("/wallet");
}, [load, router]);
}, [mutate, currency, router]);
if (loading && !balance) {
return (

View File

@@ -66,11 +66,13 @@ export function WalletScreen() {
setLogsLoading(true);
}
try {
const b = await getWalletBalance({ currency });
// 并行请求余额和日志,避免瀑布式串行等待
const [b, nextLogs] = await Promise.all([
getWalletBalance({ currency }),
loadLogs(1, false),
]);
if (cancelled) return;
setBalance(b);
const nextLogs = await loadLogs(1, false);
if (cancelled) return;
setLogs(nextLogs);
} catch (e) {
if (!cancelled) {
@@ -93,9 +95,12 @@ export function WalletScreen() {
setError(null);
setLogsLoading(true);
try {
const b = await getWalletBalance({ currency });
// 并行请求余额和日志
const [b] = await Promise.all([
getWalletBalance({ currency }),
loadLogs(1, false),
]);
setBalance(b);
await loadLogs(1, false);
} catch (e) {
setError(formatWalletClientError(e, t));
} finally {