import { useEffect, 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 { fetchYLogConfig } from "@/core/log/y-log-config"; 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 { resolveForcedEmbedTheme, syncEmbedSessionFromSearch, } from "@/core/embed/embed-session"; 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 PositionRoundtablePage from "@/position-roundtable/pages/PositionRoundtablePage"; import WeKnoraWikiPageView from "@/strategy-components/components/resource-management/llmwiki/WeKnoraWikiPageView"; import { isPositionRoundtableStandaloneMode, POSITION_ROUNDTABLE_ROUTE, } from "@/position-roundtable/demo/position-roundtable-demo-config"; import { ChatRuntime } from "./pages/WorkspaceRoutes"; import { NotFoundPage } from "./pages/NotFoundPage"; import OfficialDeerFlowEntry from "./pages/OfficialDeerFlowEntry"; const PUBLIC_EMBED_PREFIXES = [ "/share/", "/public/", "/roundtable-share/", "/embed/knowledge/", ]; function AppProviders({ children }: { children: React.ReactNode }) { const locale = useMemo(() => detectLocale(), []); const location = useLocation(); const publicEmbedTheme = usePublicEmbedTheme(); const positionStandaloneMode = isPositionRoundtableStandaloneMode(); // iframe 嵌入会话(按标签页 sessionStorage)集中在此同步:任何带 `&embed=1` 的入口(深链登录页 // 或直接深链路由)一进来就启用、`embed=0` 关闭,后续干净路由靠会话维持去 chrome + 强制主题。 useEffect(() => { syncEmbedSessionFromSearch(location.search); }, [location.search]); // 操作日志(Y-Log):启动早期预热上报配置,使 writeYLog 同步读缓存即可工作 // (刷新后 module 缓存清空,token 登录用户也能继续上报)。失败静默。 useEffect(() => { if (positionStandaloneMode) return; void fetchYLogConfig(); }, [positionStandaloneMode]); const forcedTheme = useMemo(() => { // iframe 嵌入模式(外部系统 `&embed=1`)最高优先:按本标签页的嵌入主题强制明/暗。 // 走 next-themes forcedTheme(不写 localStorage)→ 同浏览器另开的正常系统页不受影响。 const embedTheme = resolveForcedEmbedTheme(location.search); if (embedTheme) return embedTheme; const routeTheme = resolveForcedThemeForPath( location.pathname, location.search, ); 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 ( {!positionStandaloneMode && } {children} ); } /** * 根路由 `/` → `/login` 重定向,**保留 query string**。 * 外部系统的任务深链落在 `#/?taskId=...&goPath=...`,裸 `` 会丢掉 * query,导致 LoginPage 读不到参数;这里把 search 一并带过去。 */ function RootRedirect() { const { search } = useLocation(); if (isPositionRoundtableStandaloneMode()) { return ; } return ; } export function App() { const positionStandaloneMode = isPositionRoundtableStandaloneMode(); const standaloneLoginRedirect = ( ); const pageElement = positionStandaloneMode ? ( ) : ( ); return ( } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> ); }