"use client"; import { useEffect, useState } from "react"; import { Loader2, RefreshCw, WalletCards } from "lucide-react"; import clsx from "clsx"; import { useBrowserAuth } from "@/components/browser-auth"; import { formatBillingAmount } from "@/lib/billing"; import { fetchOrganizationBalance, type OrganizationBalance } from "@/lib/client/organization-balance"; type BalanceState = { scope: string; balance: OrganizationBalance | null; loading: boolean; error: string | null; }; export function CreationBalance({ refreshKey, estimatedAmountFen }: { refreshKey: string; estimatedAmountFen?: number }) { const { user, status, isSuperAdmin } = useBrowserAuth(); const organizationId = user?.organizationId || ""; const scope = `${user?.id || ""}:${organizationId}:${isSuperAdmin}`; const [retry, setRetry] = useState(0); const [state, setState] = useState({ scope: "", balance: null, loading: false, error: null }); useEffect(() => { if (status !== "ready" || isSuperAdmin || !organizationId) return; let active = true; let controller: AbortController | null = null; const refresh = async () => { controller?.abort(); const request = new AbortController(); controller = request; setState((previous) => ({ scope, balance: previous.scope === scope ? previous.balance : null, loading: true, error: null })); try { const balance = await fetchOrganizationBalance(organizationId, request.signal); if (active && !request.signal.aborted) setState({ scope, balance, loading: false, error: null }); } catch (cause) { if (active && !request.signal.aborted) { setState({ scope, balance: null, loading: false, error: cause instanceof Error ? cause.message : "余额读取失败,请重试。" }); } } }; const refreshWhenVisible = () => { if (document.visibilityState === "visible") void refresh(); }; void refresh(); const timer = window.setInterval(refreshWhenVisible, 30000); window.addEventListener("focus", refreshWhenVisible); document.addEventListener("visibilitychange", refreshWhenVisible); return () => { active = false; controller?.abort(); window.clearInterval(timer); window.removeEventListener("focus", refreshWhenVisible); document.removeEventListener("visibilitychange", refreshWhenVisible); }; }, [scope, organizationId, status, isSuperAdmin, refreshKey, retry]); if (status !== "ready") return 正在读取余额…; if (isSuperAdmin) { return ; } if (!organizationId) { return ; } const current = state.scope === scope ? state : null; const balance = current?.balance; const loading = !current || current.loading; const error = current?.error; const insufficient = balance && (balance.wallet.balanceFen <= 0 || estimatedAmountFen !== undefined && balance.wallet.balanceFen < estimatedAmountFen); const amount = balance ? formatBillingAmount(balance.wallet.balanceFen) : error ? "暂不可用" : "读取中…"; const description = error || (insufficient ? "组织余额不足,请联系管理员充值;点击查看余额明细。" : `${balance?.organization.name || user?.organizationName || "当前组织"}的共享可用余额,图片和视频共用;点击查看余额明细。`); return (
{insufficient ? 余额不足,请联系管理员充值 : null}
); }