import { useMemo } from "react"; import { Navigate, Route, Routes } from "react-router-dom"; import { ThemeProvider as NextThemesProvider } from "next-themes"; import { DesensitizeWordsLoader } from "@/components/desensitize-words-loader"; import { FontScaleApplier } from "@/components/font-scale"; import { QueryClientProvider } from "@/components/query-client-provider"; import { AuthSyncWatcher } from "@/core/auth/sync"; import { I18nProvider } from "@/core/i18n/context"; import { detectLocale } from "@/core/i18n/locale"; import { resolveForcedThemeForPath } from "@/core/page-layout/chats-iframe-route"; import { ChatProvider } from "@/contexts/ChatContext"; import { ThemeProvider } from "@/contexts/ThemeContext"; import { resolveEmbedRoundtableTheme, resolveEmbedTheme, } from "@/core/embed/params"; import { usePublicEmbedTheme } from "@/core/embed/background"; import { readWujieProps } from "@/core/embed/wujie"; import { HashRouter, useLocation } from "react-router-dom"; import LandingPage from "./pages/LandingPage"; import LoginPage from "./pages/LoginPage"; import PageRoutes from "./pages/PageRoutes"; import PublicScheduledTaskPage, { PublicScheduledTaskFullscreenPage, } from "./pages/PublicScheduledTaskPage"; import PublicSharePage from "./pages/PublicSharePage"; import PublicLeaderboardPage from "./pages/PublicLeaderboardPage"; import PublicRoundtableSharePage from "./pages/PublicRoundtableSharePage"; import EmbedChatPage from "./pages/EmbedChatPage"; import EmbedRoundtablePage from "./pages/EmbedRoundtablePage"; import DashboardStandalonePage from "@/roundtable-planning/pages/DashboardStandalonePage"; import { ChatRuntime } from "./pages/WorkspaceRoutes"; import { NotFoundPage } from "./pages/NotFoundPage"; const PUBLIC_EMBED_PREFIXES = ["/share/", "/public/", "/roundtable-share/"]; function AppProviders({ children }: { children: React.ReactNode }) { const locale = useMemo(() => detectLocale(), []); const location = useLocation(); const publicEmbedTheme = usePublicEmbedTheme(); const forcedTheme = useMemo(() => { const routeTheme = resolveForcedThemeForPath(location.pathname); if (routeTheme) return routeTheme; if (location.pathname === "/embed/roundtable") { const wp = readWujieProps(); const raw = (typeof wp.theme === "string" && wp.theme.trim()) || new URLSearchParams(location.search).get("theme")?.trim() || "dark"; return resolveEmbedRoundtableTheme(raw); } if (location.pathname.startsWith("/embed/chats")) { const raw = new URLSearchParams(location.search).get("theme")?.trim(); return raw ? resolveEmbedTheme(raw) : undefined; } if (PUBLIC_EMBED_PREFIXES.some((p) => location.pathname.startsWith(p))) { return publicEmbedTheme; } return undefined; }, [location.pathname, location.search, publicEmbedTheme]); return ( {children} ); } /** * 根路由 `/` → `/login` 重定向,**保留 query string**。 * 外部系统的任务深链落在 `#/?taskId=...&goPath=...`,裸 `` 会丢掉 * query,导致 LoginPage 读不到参数;这里把 search 一并带过去。 */ function RootRedirect() { const { search } = useLocation(); return ; } export function App() { return ( } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> ); }