初始化
This commit is contained in:
1 parent
34474bd5fc
commit
b638b541d0
3008 files changed
+837699
No files matched your search
@@ -0,0 +1,214 @@
|
||||
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 (
|
||||
<NextThemesProvider
|
||||
attribute="class"
|
||||
storageKey="strategy-theme"
|
||||
defaultTheme="light"
|
||||
themes={["light", "dark", "lightblue", "lightgreen", "iceblue", "lightyellow"]}
|
||||
enableSystem={false}
|
||||
disableTransitionOnChange
|
||||
forcedTheme={forcedTheme}
|
||||
>
|
||||
<QueryClientProvider>
|
||||
<AuthSyncWatcher disabled={positionStandaloneMode}>
|
||||
<I18nProvider initialLocale={locale}>
|
||||
<ThemeProvider>
|
||||
<ChatProvider>
|
||||
{!positionStandaloneMode && <DesensitizeWordsLoader />}
|
||||
<FontScaleApplier />
|
||||
{children}
|
||||
</ChatProvider>
|
||||
</ThemeProvider>
|
||||
</I18nProvider>
|
||||
</AuthSyncWatcher>
|
||||
</QueryClientProvider>
|
||||
</NextThemesProvider>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根路由 `/` → `/login` 重定向,**保留 query string**。
|
||||
* 外部系统的任务深链落在 `#/?taskId=...&goPath=...`,裸 `<Navigate to="/login">` 会丢掉
|
||||
* query,导致 LoginPage 读不到参数;这里把 search 一并带过去。
|
||||
*/
|
||||
function RootRedirect() {
|
||||
const { search } = useLocation();
|
||||
if (isPositionRoundtableStandaloneMode()) {
|
||||
return <Navigate to={POSITION_ROUNDTABLE_ROUTE} replace />;
|
||||
}
|
||||
return <Navigate to={`/login${search}`} replace />;
|
||||
}
|
||||
|
||||
export function App() {
|
||||
const positionStandaloneMode = isPositionRoundtableStandaloneMode();
|
||||
const standaloneLoginRedirect = (
|
||||
<Navigate to={POSITION_ROUNDTABLE_ROUTE} replace />
|
||||
);
|
||||
const pageElement = positionStandaloneMode ? (
|
||||
<ChatRuntime>
|
||||
<PositionRoundtablePage compactChrome />
|
||||
</ChatRuntime>
|
||||
) : (
|
||||
<PageRoutes />
|
||||
);
|
||||
|
||||
return (
|
||||
<HashRouter>
|
||||
<AppProviders>
|
||||
<Routes>
|
||||
<Route path="/" element={<RootRedirect />} />
|
||||
<Route
|
||||
path="/login"
|
||||
element={positionStandaloneMode ? standaloneLoginRedirect : <LoginPage />}
|
||||
/>
|
||||
<Route
|
||||
path="/login/:username"
|
||||
element={positionStandaloneMode ? standaloneLoginRedirect : <LoginPage />}
|
||||
/>
|
||||
<Route path="/landing" element={<LandingPage />} />
|
||||
<Route path="/share/:shareCode" element={<PublicSharePage />} />
|
||||
<Route path="/public/leaderboard" element={<PublicLeaderboardPage />} />
|
||||
<Route
|
||||
path="/roundtable-share/:shareCode"
|
||||
element={<PublicRoundtableSharePage view="landing" />}
|
||||
/>
|
||||
<Route
|
||||
path="/roundtable-share/:shareCode/report"
|
||||
element={<PublicRoundtableSharePage view="report" />}
|
||||
/>
|
||||
<Route
|
||||
path="/roundtable-share/:shareCode/dashboard"
|
||||
element={<PublicRoundtableSharePage view="dashboard" />}
|
||||
/>
|
||||
<Route
|
||||
path="/public/scheduled-tasks/:taskId"
|
||||
element={<PublicScheduledTaskPage />}
|
||||
/>
|
||||
<Route
|
||||
path="/public/scheduled-tasks/:taskId/runs/:runId/fullscreen"
|
||||
element={<PublicScheduledTaskFullscreenPage />}
|
||||
/>
|
||||
<Route
|
||||
path="/embed/chats/:thread_id"
|
||||
element={
|
||||
<ChatRuntime>
|
||||
<EmbedChatPage />
|
||||
</ChatRuntime>
|
||||
}
|
||||
/>
|
||||
<Route path="/embed/roundtable" element={<EmbedRoundtablePage />} />
|
||||
<Route
|
||||
path="/embed/knowledge/:noteId"
|
||||
element={<WeKnoraWikiPageView publicEmbed />}
|
||||
/>
|
||||
<Route
|
||||
path="/roundtable-dashboard"
|
||||
element={<DashboardStandalonePage />}
|
||||
/>
|
||||
<Route path="/official/*" element={<OfficialDeerFlowEntry />} />
|
||||
<Route path="/page/*" element={pageElement} />
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
</Routes>
|
||||
</AppProviders>
|
||||
</HashRouter>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user