import { useCallback, useEffect, useMemo, useState } from 'react'; import { formatAdminApiError, getAdminMe, isAdminApiError, loginAdmin, } from '../api/adminApiClient'; import type { AdminSessionPayload, ProfileRechargeProductConfigAdminResponse, ProfileTaskConfigAdminResponse, ProfileWalletConfigAdminResponse, } from '../api/adminApiTypes'; import { clearStoredAdminToken, getStoredAdminToken, setStoredAdminToken, } from '../auth/adminAuthStore'; import { AdminAccountsPage } from '../pages/AdminAccountsPage'; import { AdminAgcModelsPage } from '../pages/AdminAgcModelsPage'; import { AdminAgcTemplatesPage } from '../pages/AdminAgcTemplatesPage'; import { AdminAgcTrackingPage } from '../pages/AdminAgcTrackingPage'; import { AdminDashboardPage } from '../pages/AdminDashboardPage'; import { AdminDatabaseTablesPage } from '../pages/AdminDatabaseTablesPage'; import { AdminDebugHttpPage } from '../pages/AdminDebugHttpPage'; import { AdminEditorAssetQueryPage } from '../pages/AdminEditorAssetQueryPage'; import { AdminEditorGenerationPricingPage } from '../pages/AdminEditorGenerationPricingPage'; import { AdminEditorShowcaseReviewPage } from '../pages/AdminEditorShowcaseReviewPage'; import { AdminErrorReportsPage } from '../pages/AdminErrorReportsPage'; import { AdminGameDistributionReviewPage } from '../pages/AdminGameDistributionReviewPage'; import { AdminGrayReleaseConfigPage } from '../pages/AdminGrayReleaseConfigPage'; import { AdminInviteCodePage } from '../pages/AdminInviteCodePage'; import { AdminLoginPage } from '../pages/AdminLoginPage'; import { AdminOverviewPage } from '../pages/AdminOverviewPage'; import { AdminProfileWalletConfigPage } from '../pages/AdminProfileWalletConfigPage'; import { AdminProjectSnapshotsPage } from '../pages/AdminProjectSnapshotsPage'; import { AdminRechargeOrderPage } from '../pages/AdminRechargeOrderPage'; import { AdminRechargeProductPage } from '../pages/AdminRechargeProductPage'; import { AdminRedeemCodePage } from '../pages/AdminRedeemCodePage'; import { AdminTaskConfigPage } from '../pages/AdminTaskConfigPage'; import { AdminTrackingEventsPage } from '../pages/AdminTrackingEventsPage'; import type { AdminRouteId } from './adminRoutes'; import { getAccessibleAdminRoutes, resolveAccessibleAdminRoute, resolveAdminRoute, routeHash, } from './adminRoutes'; import { AdminShell } from './AdminShell'; type SessionStatus = 'checking' | 'guest' | 'authenticated'; export function AdminApp() { const [status, setStatus] = useState('checking'); const [admin, setAdmin] = useState(null); const [token, setToken] = useState(''); const [routeId, setRouteId] = useState(() => resolveAdminRoute(window.location.hash), ); const [loginNotice, setLoginNotice] = useState(''); const [taskConfigResult, setTaskConfigResult] = useState(null); const [profileWalletConfigResult, setProfileWalletConfigResult] = useState(null); const [rechargeProductResult, setRechargeProductResult] = useState(null); const accessibleRoutes = useMemo( () => (admin ? getAccessibleAdminRoutes(admin) : []), [admin], ); const activeRouteId = accessibleRoutes.some((route) => route.id === routeId) ? routeId : null; const clearSession = useCallback((message = '') => { clearStoredAdminToken(); setToken(''); setAdmin(null); setTaskConfigResult(null); setProfileWalletConfigResult(null); setRechargeProductResult(null); setStatus('guest'); setLoginNotice(message); }, []); useEffect(() => { let isMounted = true; const storedToken = getStoredAdminToken(); if (!storedToken) { setStatus('guest'); return; } void getAdminMe(storedToken) .then((response) => { if (!isMounted) { return; } setToken(storedToken); setAdmin(response.admin); setStatus('authenticated'); }) .catch((error: unknown) => { if (!isMounted) { return; } clearStoredAdminToken(); setToken(''); setAdmin(null); setStatus('guest'); setLoginNotice( isAdminApiError(error) && error.status === 401 ? '登录状态已失效' : formatAdminApiError(error), ); }); return () => { isMounted = false; }; }, []); useEffect(() => { if (status !== 'authenticated' || !admin) { return; } const nextRouteId = resolveAccessibleAdminRoute( window.location.hash, accessibleRoutes, ); if (!nextRouteId) { return; } setRouteId(nextRouteId); const nextHash = routeHash(nextRouteId); if (window.location.hash !== nextHash) { window.history.replaceState(null, '', nextHash); } }, [accessibleRoutes, admin, routeId, status]); useEffect(() => { const handleHashChange = () => { setRouteId(resolveAdminRoute(window.location.hash)); }; window.addEventListener('hashchange', handleHashChange); return () => window.removeEventListener('hashchange', handleHashChange); }, []); const handleRouteChange = useCallback((nextRouteId: AdminRouteId) => { setRouteId(nextRouteId); const nextHash = routeHash(nextRouteId); if (window.location.hash !== nextHash) { window.location.hash = nextHash; } }, []); const handleLogin = useCallback( async (username: string, password: string) => { const response = await loginAdmin(username, password); setStoredAdminToken(response.token); setToken(response.token); setAdmin(response.admin); setTaskConfigResult(null); setProfileWalletConfigResult(null); setRechargeProductResult(null); setLoginNotice(''); setStatus('authenticated'); }, [], ); const handleUnauthorized = useCallback( (message = '登录状态已失效') => { clearSession(message); }, [clearSession], ); const handleLogout = useCallback(() => { clearSession(''); }, [clearSession]); if (status === 'checking') { return (
正在校验会话
); } if (status === 'guest' || !admin || !token) { return ; } return ( {activeRouteId === null ? (

暂无访问权限

) : null} {activeRouteId === 'dashboard' ? ( ) : null} {activeRouteId === 'overview' ? ( ) : null} {activeRouteId === 'tables' ? ( ) : null} {activeRouteId === 'debug' ? ( ) : null} {activeRouteId === 'tracking' ? ( ) : null} {activeRouteId === 'agc-tracking' ? ( ) : null} {activeRouteId === 'error-reports' ? ( ) : null} {activeRouteId === 'gray-release' ? ( ) : null} {activeRouteId === 'redeem' ? ( ) : null} {activeRouteId === 'invite' ? ( ) : null} {activeRouteId === 'tasks' ? ( ) : null} {activeRouteId === 'profile-wallet' ? ( ) : null} {activeRouteId === 'recharge-products' ? ( ) : null} {activeRouteId === 'recharge-orders' ? ( ) : null} {activeRouteId === 'editor-generation-pricing' ? ( ) : null} {activeRouteId === 'agc-models' ? ( ) : null} {activeRouteId === 'agc-templates' ? ( ) : null} {activeRouteId === 'editor-showcase' ? ( ) : null} {activeRouteId === 'game-distribution' ? ( ) : null} {activeRouteId === 'editor-assets' ? ( ) : null} {activeRouteId === 'accounts' ? ( ) : null} {activeRouteId === 'project-snapshots' ? ( ) : null}
); }