import { createBrowserRouter, Navigate } from 'react-router-dom' import { Layout } from './components/Layout' import { Watchlist } from './pages/Watchlist' import { Screener } from './pages/Screener' import { Backtest } from './pages/Backtest' import { Financials } from './pages/Financials' import { Onboarding } from './pages/Onboarding' import { Auth } from './pages/Auth' import { Data } from './pages/Data' import { Monitor } from './pages/Monitor' import { Trading } from './pages/Trading' import { Dashboard } from './pages/Dashboard' import { AnalysisDetail } from './pages/AnalysisDetail' import { ConceptAnalysis } from './pages/ConceptAnalysis' import { IndustryAnalysis } from './pages/IndustryAnalysis' import { StockAnalysis } from './pages/StockAnalysis' import { Review } from './pages/Review' import { LimitUpLadder } from './pages/LimitUpLadder' import { Branding } from './pages/Branding' import { Settings } from './pages/Settings' import { Indices } from './pages/Indices' import { Dev } from './pages/Dev' import { Sync } from './pages/Sync' import { useSettings } from './lib/useSharedQueries' import { Logo } from './components/Logo' // 首次使用守卫 —— 未完成向导则重定向到 /onboarding // 只挂在根路由上;/onboarding 本身不被守卫,避免循环重定向。 // settings 由 Layout 预取,守卫判定不产生额外请求。 function OnboardingGuard({ children }: { children: React.ReactNode }) { const settings = useSettings() // 仅首次加载(本地无缓存)时显示占位。 // 后台重取 (isFetching) 时本地已有上一份缓存可用, 直接放行, 避免切页时整屏 logo 闪烁。 // 防误重定向已由 Onboarding/AI 等处 invalidate 前的 setQueryData 同步缓存兜底。 if (settings.isLoading) { return (
加载中…
) } // 查询出错或字段缺失时不拦截 —— 宁可放行,也不把用户卡在空白页 if (settings.data && settings.data.onboarding_completed === false) { return } return <>{children} } export const router = createBrowserRouter([ { path: '/onboarding', element: }, { path: '/login', element: }, { path: '/', element: ( ), children: [ { index: true, element: }, { path: 'overview', element: }, { path: 'analysis', element: }, { path: 'analysis/:menuId', element: }, { path: 'concept-analysis', element: }, { path: 'industry-analysis', element: }, { path: 'stock-analysis', element: }, { path: 'review', element: }, { path: 'watchlist', element: }, { path: 'screener', element: }, { path: 'backtest', element: }, { path: 'financials', element: }, { path: 'data', element: }, { path: 'monitor', element: }, { path: 'trading', element: }, { path: 'sync', element: }, { path: 'limit-ladder', element: }, { path: 'indices', element: }, { path: 'branding', element: }, { path: 'settings', element: }, // 隐藏路由:开发者工具(不暴露在菜单,仅供调试) { path: 'dev', element: }, // 旧路由兼容重定向 { path: 'settings/keys', element: }, { path: 'settings/ai', element: }, { path: 'settings/queries', element: }, ], }, ])