// web/src/App.tsx - 教师专用版本(ClareCourseWare) import React, { useState, useEffect, ErrorInfo, Component } from "react"; import { LoginScreen } from "./components/LoginScreen"; import { TeacherDashboard } from "./components/TeacherDashboard"; import { Toaster } from "./components/ui/sonner"; export interface User { name: string; email: string; } // ✅ Error Boundary for catching React errors class ErrorBoundary extends Component< { children: React.ReactNode }, { hasError: boolean; error: Error | null } > { constructor(props: { children: React.ReactNode }) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error: Error) { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: ErrorInfo) { console.error("React Error:", error, errorInfo); } render() { if (this.state.hasError) { return (

应用错误

{this.state.error?.message || "未知错误"}

); } return this.props.children; } } // ✅ localStorage helpers for user profile function profileStorageKey(email: string) { return `teacher_profile::${email}`; } function hydrateUserFromStorage(base: User): User { try { const raw = localStorage.getItem(profileStorageKey(base.email)); if (!raw) return base; const saved = JSON.parse(raw) as Partial; return { ...base, ...saved }; } catch { return base; } } function App() { const [user, setUser] = useState(null); // ✅ persist user profile whenever it changes (per-email) useEffect(() => { if (!user?.email) return; try { localStorage.setItem(profileStorageKey(user.email), JSON.stringify(user)); } catch { // ignore } }, [user]); // ✅ 教师专用:登录后直接进入 TeacherDashboard const handleLogin = (newUser: User) => { const hydrated = hydrateUserFromStorage(newUser); setUser(hydrated); }; if (!user) return ; // ✅ 教师专用:只显示 TeacherDashboard,移除所有学生界面 return (
setUser(null)} />
); } export default App;