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 TextInteraction from './pages/TextInteraction'; import ImageGeneration from './pages/ImageGeneration'; import AudioWorkshop from './pages/AudioWorkshop'; import VideoSynthesis from './pages/VideoSynthesis'; import ModelSquare from './pages/ModelSquare'; import ModelPricingDetail from './pages/ModelPricingDetail'; import Toolbox from './pages/Toolbox'; import QwenOCR from './pages/QwenOCR'; import ImageTranslation from './pages/ImageTranslation'; import TingwuWorkshop from './pages/TingwuWorkshop'; import TingwuResult from './pages/TingwuResult'; import DataMining from './pages/DataMining'; import DeepResearch from './pages/DeepResearch'; import ResearchDetail from './pages/ResearchDetail'; import QwenMT from './pages/QwenMT'; import PhotoAnswer from './pages/PhotoAnswer'; import MultimodalTranslation from './pages/MultimodalTranslation'; import Profile from './pages/Profile'; import Billing from './pages/Billing'; import Login from './pages/Login'; import Register from './pages/Register'; import Recharge from './pages/Recharge'; import RechargeReturn from './pages/RechargeReturn'; import RechargeHistory from './pages/RechargeHistory'; import InvoiceManagement from './pages/InvoiceManagement'; import InvoiceApply from './pages/InvoiceApply'; import InvoiceResult from './pages/InvoiceResult'; import OpenPlatform from './pages/OpenPlatform'; import OpenClaw from './pages/OpenClaw'; import UserAgreement from './pages/UserAgreement'; import PrivacyPolicy from './pages/PrivacyPolicy'; import SSOCallback from './pages/SSOCallback'; import { authService } from './services/authService'; import { Loader2 } from './icons/commonIcons'; import BindPhoneReminder from './components/BindPhoneReminder'; import { NotificationProvider } from './contexts/NotificationContext'; import './styles/markdown.css'; // 品牌配置 Context export interface BrandingConfig { system_name: string; system_logo: string; icp_number: string } export const BrandingContext = React.createContext({ system_name: '智创空间', system_logo: '', icp_number: '' }) const API_BASE = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8010' const pagePathMap: Record = { home: '/', text: '/text', image: '/image', audio: '/audio', video: '/video', models: '/models', toolbox: '/toolbox', platform: '/platform', openclaw: '/openclaw', profile: '/profile', billing: '/billing', invoice: '/invoice', }; // 公开路由(不需要登录) const publicRoutes = ['/login', '/register', '/sso-callback', '/recharge-return', '/user-agreement', '/privacy-policy']; const CasLoginRedirect: React.FC<{ targetPath: string }> = ({ targetPath }) => { useEffect(() => { authService.startCasLogin(targetPath || '/'); }, [targetPath]); return (
正在跳转统一认证登录...
); }; // 认证状态检查组件 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; } // 检查本地是否有Token if (!authService.isAuthenticated()) { setIsAuthenticated(false); setIsChecking(false); return; } // 有Token,验证并刷新 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 (
验证登录状态...
); } // 未登录且不是公开路由 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 === '/' && (

© 2026 {branding.system_name}

)}
); }; // 认证布局(无侧边栏和导航栏,用于登录/注册页面) 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: '智创空间', system_logo: '', icp_number: '' }) useEffect(() => { fetch(`${API_BASE}/api/public/branding`) .then(r => r.json()) .then(d => { if (d.system_name) setBranding(d) }) .catch(() => {}) }, []) // States to keep track of selected models across the app // 默认模型ID会在模型加载后自动更新为第一个可用模型(如果当前ID不存在) const [textModelId, setTextModelId] = useState('gemini-pro'); const [imageModelId, setImageModelId] = useState('dall-e-3'); const [audioModelId, setAudioModelId] = useState('elevenlabs'); const [videoModelId, setVideoModelId] = useState('runway-gen3'); const handleModelNavigation = (page: PageId, modelId: string) => { if (page === 'text') setTextModelId(modelId); if (page === 'image') setImageModelId(modelId); if (page === 'audio') setAudioModelId(modelId); if (page === 'video') setVideoModelId(modelId); const path = pagePathMap[page]; navigate(path); }; // 判断是否是认证页面(登录/注册) const isAuthPage = publicRoutes.includes(location.pathname); return ( {isAuthPage ? ( } /> } /> } /> } /> } /> {/* 支付回调页也属于公开路由,需要在无主布局下渲染 */} } /> ) : ( } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> )} ); }; export default App;