feat: 集成网络连接管理与降级轮询功能
- 在 PlayerAppShell 中引入 NetworkStatusBanner 组件以显示网络状态 - 在 HallBettingGrid 中实现下注后触发钱包轮询 - 在 HallWalletStrip 中添加网络连接状态管理与定期刷新逻辑 - 在 useHallDrawLive 中集成 WebSocket 连接状态与降级轮询机制,确保在断开时自动切换到轮询模式
This commit is contained in:
@@ -14,10 +14,12 @@ import {
|
||||
import { formatMinorAsCurrency } from "@/lib/money";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { usePlayerSessionStore } from "@/stores/player-session-store";
|
||||
import { useNetworkConnectionStore } from "@/stores/network-connection-store";
|
||||
import type { WalletBalanceData } from "@/types/api/wallet-balance";
|
||||
|
||||
/**
|
||||
* 高保真稿:大厅顶部红卡 + Transfer In(蓝)/ Transfer Out(白底红边),§4.2
|
||||
* 已集成网络降级模式下的轮询刷新
|
||||
*/
|
||||
export function HallWalletStrip() {
|
||||
const profile = usePlayerSessionStore((s) => s.profile);
|
||||
@@ -25,6 +27,19 @@ export function HallWalletStrip() {
|
||||
const [balance, setBalance] = useState<WalletBalanceData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
// 网络连接状态(用于降级模式下的轮询)
|
||||
const mode = useNetworkConnectionStore((s) => s.mode);
|
||||
const walletPollingIntervalId = useNetworkConnectionStore(
|
||||
(s) => s.walletPollingIntervalId,
|
||||
);
|
||||
const setWalletPollingIntervalId = useNetworkConnectionStore(
|
||||
(s) => s.setWalletPollingIntervalId,
|
||||
);
|
||||
const setWalletPollingExpiryAt = useNetworkConnectionStore(
|
||||
(s) => s.setWalletPollingExpiryAt,
|
||||
);
|
||||
const clearWalletPolling = useNetworkConnectionStore((s) => s.clearWalletPolling);
|
||||
|
||||
const currency = useMemo(
|
||||
() =>
|
||||
(balance?.currency_code ?? profile?.default_currency ?? "NPR").toUpperCase(),
|
||||
@@ -57,6 +72,50 @@ export function HallWalletStrip() {
|
||||
return () => window.removeEventListener("lottery-wallet-refresh", onRefresh);
|
||||
}, [refresh]);
|
||||
|
||||
// 监听钱包轮询状态变化(由下注或开奖结果触发)
|
||||
useEffect(() => {
|
||||
// 如果有活跃的轮询计时器,监听它并执行刷新
|
||||
if (walletPollingIntervalId) {
|
||||
// 轮询已在全局管理中设置,这里只需监听轮询触发的事件
|
||||
const handlePollingRefresh = () => void refresh();
|
||||
window.addEventListener("lottery-wallet-refresh", handlePollingRefresh);
|
||||
return () => {
|
||||
window.removeEventListener("lottery-wallet-refresh", handlePollingRefresh);
|
||||
};
|
||||
}
|
||||
}, [walletPollingIntervalId, refresh]);
|
||||
|
||||
// 降级模式下的定期刷新(作为兜底)
|
||||
useEffect(() => {
|
||||
// 只有在降级模式下才启动兜底轮询
|
||||
if (mode !== "polling" && mode !== "offline") {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果已经有活跃的轮询计时器,不重复设置
|
||||
if (walletPollingIntervalId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置兜底轮询(60秒一次,避免过于频繁)
|
||||
const intervalId = window.setInterval(() => {
|
||||
void refresh();
|
||||
}, 60_000);
|
||||
|
||||
setWalletPollingIntervalId(intervalId);
|
||||
|
||||
return () => {
|
||||
window.clearInterval(intervalId);
|
||||
clearWalletPolling();
|
||||
};
|
||||
}, [
|
||||
mode,
|
||||
walletPollingIntervalId,
|
||||
refresh,
|
||||
setWalletPollingIntervalId,
|
||||
clearWalletPolling,
|
||||
]);
|
||||
|
||||
const lotteryMinor = Number(balance?.balance ?? 0);
|
||||
const availableMinor = Number(balance?.available_balance ?? 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user