import { Layout, Modal, Input, message, ConfigProvider, theme as antTheme } from "antd" import { useEffect, useMemo, useState } from "react" import { HashRouter, useLocation, useNavigate, Routes, Route } from "react-router-dom" import { useTranslation } from "react-i18next" import { Sidebar } from "./components/Sidebar" import { ContentArea } from "./components/ContentArea" import { OOBE } from "./components/OOBE/OOBE" import { ThemeProvider, useTheme } from "./contexts/ThemeContext" function MainContent(): React.JSX.Element { const { t } = useTranslation() const navigate = useNavigate() const location = useLocation() const { currentTheme } = useTheme() const [messageApi, contextHolder] = message.useMessage() useEffect(() => { const api = (window as any).api if (!api) return let disposed = false let unlisten: (() => void) | null = null api .onNavigate((route: string) => { const currentPath = location.pathname === "/" ? "/home" : location.pathname const targetPath = route === "/" ? "/home" : route if (currentPath !== targetPath) { navigate(route) } }) .then((fn: () => void) => { if (disposed) { fn() return } unlisten = fn }) .catch(() => void 0) return () => { disposed = true if (unlisten) unlisten() } }, [navigate, location.pathname]) const [wizardVisible, setWizardVisible] = useState(false) const [permission, setPermission] = useState<"admin" | "points" | "view">("view") const [hasAnyPassword, setHasAnyPassword] = useState(false) const [authVisible, setAuthVisible] = useState(false) const [authPassword, setAuthPassword] = useState("") const [authLoading, setAuthLoading] = useState(false) const [isPortraitMode, setIsPortraitMode] = useState(false) const [sidebarCollapsed, setSidebarCollapsed] = useState(false) const [floatingSidebarExpanded, setFloatingSidebarExpanded] = useState(false) const activeMenu = useMemo(() => { const p = location.pathname if (p === "/" || p.startsWith("/home")) return "home" if (p.startsWith("/students")) return "students" if (p.startsWith("/score")) return "score" if (p.startsWith("/leaderboard")) return "leaderboard" if (p.startsWith("/settlements")) return "settlements" if (p.startsWith("/reasons")) return "reasons" if (p.startsWith("/auto-score")) return "auto-score" if (p.startsWith("/settings")) return "settings" return "home" }, [location.pathname]) useEffect(() => { const checkWizard = async () => { if (!(window as any).api) return const res = await (window as any).api.getAllSettings() if (res.success && res.data && !res.data.is_wizard_completed) { setWizardVisible(true) } } checkWizard() }, []) useEffect(() => { const loadAuthAndSettings = async () => { if (!(window as any).api) return const authRes = await (window as any).api.authGetStatus() if (authRes?.success && authRes.data) { setPermission(authRes.data.permission) const anyPwd = Boolean(authRes.data.hasAdminPassword || authRes.data.hasPointsPassword) setHasAnyPassword(anyPwd) if (anyPwd && authRes.data.permission === "view") setAuthVisible(true) } } loadAuthAndSettings() }, []) const login = async () => { if (!(window as any).api) return setAuthLoading(true) const res = await (window as any).api.authLogin(authPassword) setAuthLoading(false) if (res.success && res.data) { setPermission(res.data.permission) setAuthVisible(false) setAuthPassword("") messageApi.success(t("auth.unlocked")) } else { messageApi.error(res.message || t("common.error")) } } const logout = async () => { if (!(window as any).api) return const res = await (window as any).api.authLogout() if (res?.success && res.data) { setPermission(res.data.permission) messageApi.success(t("auth.logout")) } } const onMenuChange = (v: string) => { const key = String(v) if (key === "home") navigate("/") if (key === "students") navigate("/students") if (key === "score") navigate("/score") if (key === "leaderboard") navigate("/leaderboard") if (key === "settlements") navigate("/settlements") if (key === "reasons") navigate("/reasons") if (key === "auto-score") navigate("/auto-score") if (key === "settings") navigate("/settings") } const toggleOrientationMode = async () => { const api = (window as any).api if (!api) return const nextPortraitMode = !isPortraitMode try { const maximized = await api.windowIsMaximized() if (maximized) { await api.windowMaximize() } if (nextPortraitMode) { await api.windowSetResizable(false) await api.windowResize(940, 1600) setSidebarCollapsed(true) setFloatingSidebarExpanded(false) } else { await api.windowSetResizable(true) await api.windowResize(2560, 1440) setSidebarCollapsed(false) setFloatingSidebarExpanded(false) } setIsPortraitMode(nextPortraitMode) } catch (error) { messageApi.error(t("common.error")) console.error("Failed to toggle orientation mode:", error) } } useEffect(() => { if (!isPortraitMode || !sidebarCollapsed) { setFloatingSidebarExpanded(false) } }, [isPortraitMode, sidebarCollapsed]) const toggleSidebar = () => { if (isPortraitMode && sidebarCollapsed) { setFloatingSidebarExpanded((prev) => !prev) return } setSidebarCollapsed((prev) => !prev) } const isDark = currentTheme?.mode === "dark" const brandColor = currentTheme?.config?.tdesign?.brandColor || "#0052D9" return ( {contextHolder} setAuthVisible(true)} onLogout={logout} isPortraitMode={isPortraitMode} sidebarCollapsed={sidebarCollapsed} floatingExpand={isPortraitMode} floatingExpanded={floatingSidebarExpanded} onToggleSidebar={toggleSidebar} onToggleOrientation={toggleOrientationMode} /> setWizardVisible(false)} /> setAuthVisible(false)} onOk={login} confirmLoading={authLoading} okText={t("auth.unlockButton")} cancelText={t("common.cancel")} > {t("auth.unlockHint")} setAuthPassword(e.target.value)} placeholder={t("auth.passwordPlaceholder")} maxLength={6} /> {import.meta.env.DEV ? ( 开发中画面,不代表最终品质 SecScore Dev ({getPlatform()}-{getArchitecture()}) ) : null} ) } function getArchitecture(): string { const userAgent = navigator.userAgent.toLowerCase() if (userAgent.includes("arm64") || userAgent.includes("aarch64")) { return "ARM64" } else if (userAgent.includes("x64") || userAgent.includes("amd64")) { return "x64" } else if (userAgent.includes("i386") || userAgent.includes("i686")) { return "x86" } return userAgent } function getPlatform(): string { const userAgent = navigator.userAgent.toLowerCase() if (userAgent.includes("windows")) { return "Windows" } else if (userAgent.includes("mac")) { return "Mac" } else if (userAgent.includes("linux")) { return "Linux" } return "Unknown" } function App(): React.JSX.Element { return ( } /> ) } export default App
开发中画面,不代表最终品质
SecScore Dev ({getPlatform()}-{getArchitecture()})