import React, { useState, useEffect } from 'react'; import { Routes, Route, useNavigate, useLocation, Navigate } from 'react-router-dom'; import Sidebar, { PageId } from './components/Sidebar'; import Navbar from './components/Navbar'; import Home from './pages/Home'; import ModelSquare from './pages/ModelSquare'; import Profile from './pages/Profile'; import Login from './pages/Login'; import Register from './pages/Register'; import OpenPlatform from './pages/OpenPlatform'; import UserAgreement from './pages/UserAgreement'; import PrivacyPolicy from './pages/PrivacyPolicy'; import SSOCallback from './pages/SSOCallback'; import ModelPricingDetail from './pages/ModelPricingDetail'; import { authService } from './services/authService'; import { Loader2 } from './icons/commonIcons'; import { NotificationProvider } from './contexts/NotificationContext'; import './styles/markdown.css'; const API_BASE = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:8010'; // 品牌配置 Context export interface BrandingConfig { system_name: string; system_logo: string; icp_number: string } export const BrandingContext = React.createContext({ system_name: '四川路桥Maas算力平台', system_logo: '', icp_number: '' }) const pagePathMap: Record = { home: '/', models: '/models', platform: '/platform', profile: '/profile', }; // 公开路由(不需要登录) const publicRoutes = ['/login', '/register', '/sso-callback', '/auth/callback', '/user-agreement', '/privacy-policy']; // 认证状态检查组件 const AuthGuard: React.FC<{ children: React.ReactNode }> = ({ children }) => { const location = useLocation(); const [isChecking, setIsChecking] = useState(true); const [isAuthenticated, setIsAuthenticated] = useState(false); useEffect(() => { const checkAuth = async () => { if (publicRoutes.includes(location.pathname)) { setIsChecking(false); return; } if (!authService.isAuthenticated()) { setIsAuthenticated(false); setIsChecking(false); return; } try { const isValid = await authService.checkAndRefreshToken(); setIsAuthenticated(isValid); } catch (error) { console.error('[AuthGuard] Auth check failed:', error); setIsAuthenticated(false); } finally { setIsChecking(false); } }; checkAuth(); }, [location.pathname]); // 订阅认证状态变化 useEffect(() => { const unsubscribe = authService.subscribe(() => { const authenticated = authService.isAuthenticated(); setIsAuthenticated(authenticated); }); return () => unsubscribe(); }, []); // 正在检查认证状态 if (isChecking && !publicRoutes.includes(location.pathname)) { return (
验证登录状态...
); } // 未登录且不是公开路由 → 一律跳登录页(登录页上有 SSO 按钮供用户选择) if (!isAuthenticated && !publicRoutes.includes(location.pathname)) { return ; } // 已登录且访问登录/注册页,重定向到首页 if (isAuthenticated && (location.pathname === '/login' || location.pathname === '/register')) { return ; } return <>{children}; }; // 主布局(带侧边栏和导航栏) const MainLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => { const location = useLocation(); const branding = React.useContext(BrandingContext); return (
{children} {location.pathname === '/' && ( )}
); }; // 认证布局(无侧边栏和导航栏,用于登录/注册页面) const AuthLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => { return <>{children}; }; const App: React.FC = () => { const navigate = useNavigate(); const location = useLocation(); // 品牌配置 const [branding, setBranding] = React.useState({ system_name: '四川路桥Maas算力平台', system_logo: '', icp_number: '' }); useEffect(() => { fetch(`${API_BASE}/api/public/branding`) .then(r => r.json()) .then(d => { if (d.system_name) { setBranding(d); document.title = d.system_name; } // 动态更新 favicon if (d.system_logo) { let link = document.querySelector("link[rel~='icon']"); if (!link) { link = document.createElement('link'); link.rel = 'icon'; document.head.appendChild(link); } link.href = d.system_logo; } }) .catch(() => {}); }, []); // 判断是否是认证页面(登录/注册) const isAuthPage = publicRoutes.includes(location.pathname); return ( {isAuthPage ? ( } /> } /> } /> } /> } /> } /> ) : ( } /> } /> } /> } /> } /> } /> } /> )} ); }; export default App;