diff --git a/src/renderer/src/components/MinApp/MinApp.tsx b/src/renderer/src/components/MinApp/MinApp.tsx index 3fb0e89715..d4da03c945 100644 --- a/src/renderer/src/components/MinApp/MinApp.tsx +++ b/src/renderer/src/components/MinApp/MinApp.tsx @@ -47,7 +47,7 @@ const MinApp: FC = ({ app, onClick, size = 60, isLast }) => { const handleClick = () => { if (isTopNavbar) { // 顶部导航栏:导航到小程序页面 - navigate({ to: `/apps/${app.id}` }) + navigate({ to: '/app/minapp/$appId', params: { appId: app.id } }) } else { // 侧边导航栏:保持原有弹窗行为 openMinappKeepAlive(app) diff --git a/src/renderer/src/components/MinApp/MinAppTabsPool.tsx b/src/renderer/src/components/MinApp/MinAppTabsPool.tsx index 6bf54d4c7f..26594ad08d 100644 --- a/src/renderer/src/components/MinApp/MinAppTabsPool.tsx +++ b/src/renderer/src/components/MinApp/MinAppTabsPool.tsx @@ -31,10 +31,10 @@ const MinAppTabsPool: React.FC = () => { // 使用集中工具进行更稳健的路由判断 const isAppDetail = (() => { const pathname = location.pathname - if (pathname === '/apps') return false - if (!pathname.startsWith('/apps/')) return false - const parts = pathname.split('/').filter(Boolean) // ['apps', '', ...] - return parts.length >= 2 + if (pathname === '/app/minapp') return false + if (!pathname.startsWith('/app/minapp/')) return false + const parts = pathname.split('/').filter(Boolean) // ['app', 'minapp', '', ...] + return parts.length >= 3 })() const shouldShow = isTopNavbar && isAppDetail diff --git a/src/renderer/src/components/app/Sidebar.tsx b/src/renderer/src/components/app/Sidebar.tsx index 587016dffd..b6b69f190d 100644 --- a/src/renderer/src/components/app/Sidebar.tsx +++ b/src/renderer/src/components/app/Sidebar.tsx @@ -149,15 +149,15 @@ const MainMenus: FC = () => { } const pathMap = { - assistants: '/chat', - store: '/store', - paintings: `/paintings/${defaultPaintingProvider}`, - translate: '/translate', - minapp: '/apps', - knowledge: '/knowledge', - files: '/files', - code_tools: '/code', - notes: '/notes' + assistants: '/app/chat', + store: '/app/assistant', + paintings: `/app/paintings/${defaultPaintingProvider}`, + translate: '/app/translate', + minapp: '/app/minapp', + knowledge: '/app/knowledge', + files: '/app/files', + code_tools: '/app/code', + notes: '/app/notes' } // 在当前 Tab 内跳转 diff --git a/src/renderer/src/hooks/useTabs.ts b/src/renderer/src/hooks/useTabs.ts index bee3bb22fd..5f02d5ac52 100644 --- a/src/renderer/src/hooks/useTabs.ts +++ b/src/renderer/src/hooks/useTabs.ts @@ -15,8 +15,8 @@ const logger = loggerService.withContext('useTabs') const DEFAULT_TAB: Tab = { id: 'home', type: 'route', - url: '/', - title: getDefaultRouteTitle('/'), + url: '/home', + title: getDefaultRouteTitle('/home'), lastAccessTime: Date.now(), isDormant: false } diff --git a/src/renderer/src/pages/history/components/TopicMessages.tsx b/src/renderer/src/pages/history/components/TopicMessages.tsx index 48ab4ad6bd..a0569288d8 100644 --- a/src/renderer/src/pages/history/components/TopicMessages.tsx +++ b/src/renderer/src/pages/history/components/TopicMessages.tsx @@ -54,7 +54,7 @@ const TopicMessages: FC = ({ topic: _topic, ...props }) => { await modelGenerating() SearchPopup.hide() const assistant = getAssistantById(topic.assistantId) - navigate({ to: '/chat', search: { assistantId: assistant?.id, topicId: topic.id } }) + navigate({ to: '/app/chat', search: { assistantId: assistant?.id, topicId: topic.id } }) setTimeoutTimer('onContinueChat', () => EventEmitter.emit(EVENT_NAMES.SHOW_TOPIC_SIDEBAR), 100) } diff --git a/src/renderer/src/pages/home/Inputbar/tools/components/KnowledgeBaseButton.tsx b/src/renderer/src/pages/home/Inputbar/tools/components/KnowledgeBaseButton.tsx index 22f15ec8a7..74135ea42e 100644 --- a/src/renderer/src/pages/home/Inputbar/tools/components/KnowledgeBaseButton.tsx +++ b/src/renderer/src/pages/home/Inputbar/tools/components/KnowledgeBaseButton.tsx @@ -54,7 +54,7 @@ const KnowledgeBaseButton: FC = ({ quickPanel, selectedBases, onSelect, d items.push({ label: t('knowledge.add.title') + '...', icon: , - action: () => navigate({ to: '/knowledge' }), + action: () => navigate({ to: '/app/knowledge' }), isSelected: false }) diff --git a/src/renderer/src/pages/launchpad/LaunchpadPage.tsx b/src/renderer/src/pages/launchpad/LaunchpadPage.tsx index e17597975b..f8408f0f9b 100644 --- a/src/renderer/src/pages/launchpad/LaunchpadPage.tsx +++ b/src/renderer/src/pages/launchpad/LaunchpadPage.tsx @@ -18,49 +18,49 @@ const LaunchpadPage: FC = () => { { icon: , text: t('title.apps'), - path: '/apps', + path: '/app/minapp', bgColor: 'linear-gradient(135deg, #8B5CF6, #A855F7)' // 小程序:紫色,代表多功能和灵活性 }, { icon: , text: t('title.knowledge'), - path: '/knowledge', + path: '/app/knowledge', bgColor: 'linear-gradient(135deg, #10B981, #34D399)' // 知识库:翠绿色,代表生长和知识 }, { icon: , text: t('title.paintings'), - path: `/paintings/${defaultPaintingProvider}`, + path: `/app/paintings/${defaultPaintingProvider}`, bgColor: 'linear-gradient(135deg, #EC4899, #F472B6)' // 绘画:活力粉色,代表创造力和艺术 }, { icon: , text: t('title.store'), - path: '/store', + path: '/app/assistant', bgColor: 'linear-gradient(135deg, #6366F1, #4F46E5)' // AI助手:靛蓝渐变,代表智能和科技 }, { icon: , text: t('title.translate'), - path: '/translate', + path: '/app/translate', bgColor: 'linear-gradient(135deg, #06B6D4, #0EA5E9)' // 翻译:明亮的青蓝色,代表沟通和流畅 }, { icon: , text: t('title.files'), - path: '/files', + path: '/app/files', bgColor: 'linear-gradient(135deg, #F59E0B, #FBBF24)' // 文件:金色,代表资源和重要性 }, { icon: , text: t('title.code'), - path: '/code', + path: '/app/code', bgColor: 'linear-gradient(135deg, #1F2937, #374151)' // Code CLI:高级暗黑色,代表专业和技术 }, { icon: , text: t('title.notes'), - path: '/notes', + path: '/app/notes', bgColor: 'linear-gradient(135deg, #F97316, #FB923C)' // 笔记:橙色,代表活力和清晰思路 } ] diff --git a/src/renderer/src/pages/minapps/MinAppPage.tsx b/src/renderer/src/pages/minapps/MinAppPage.tsx index 003d374880..b7ac3bd6fe 100644 --- a/src/renderer/src/pages/minapps/MinAppPage.tsx +++ b/src/renderer/src/pages/minapps/MinAppPage.tsx @@ -64,7 +64,7 @@ const MinAppPage: FC = () => { useEffect(() => { // If app not found, redirect to apps list if (!app) { - navigate({ to: '/apps' }) + navigate({ to: '/app/minapp' }) return } @@ -72,7 +72,7 @@ const MinAppPage: FC = () => { // Only check once and only if we haven't already redirected if (!initialIsTopNavbar.current && !hasRedirected.current) { hasRedirected.current = true - navigate({ to: '/apps' }) + navigate({ to: '/app/minapp' }) // Open popup after navigation setTimeout(() => { openMinappKeepAlive(app) diff --git a/src/renderer/src/pages/minapps/components/MinimalToolbar.tsx b/src/renderer/src/pages/minapps/components/MinimalToolbar.tsx index f94f594a2f..18d3d68a04 100644 --- a/src/renderer/src/pages/minapps/components/MinimalToolbar.tsx +++ b/src/renderer/src/pages/minapps/components/MinimalToolbar.tsx @@ -213,7 +213,7 @@ const MinimalToolbar: FC = ({ app, webviewRef, currentUrl, onReload, onOp }, [app.id, webviewRef, scheduleNavigationUpdate]) const handleMinimize = useCallback(() => { - navigate({ to: '/apps' }) + navigate({ to: '/app/minapp' }) }, [navigate]) const handleTogglePin = useCallback(() => { diff --git a/src/renderer/src/routeTree.gen.ts b/src/renderer/src/routeTree.gen.ts index ab8672e768..9afa09ec72 100644 --- a/src/renderer/src/routeTree.gen.ts +++ b/src/renderer/src/routeTree.gen.ts @@ -9,18 +9,11 @@ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. import { Route as rootRouteImport } from './routes/__root' -import { Route as TranslateRouteImport } from './routes/translate' -import { Route as StoreRouteImport } from './routes/store' import { Route as SettingsRouteImport } from './routes/settings' -import { Route as NotesRouteImport } from './routes/notes' -import { Route as KnowledgeRouteImport } from './routes/knowledge' -import { Route as FilesRouteImport } from './routes/files' -import { Route as CodeRouteImport } from './routes/code' -import { Route as ChatRouteImport } from './routes/chat' +import { Route as HomeRouteImport } from './routes/home' +import { Route as AppRouteImport } from './routes/app' import { Route as IndexRouteImport } from './routes/index' import { Route as SettingsIndexRouteImport } from './routes/settings/index' -import { Route as PaintingsIndexRouteImport } from './routes/paintings/index' -import { Route as AppsIndexRouteImport } from './routes/apps/index' import { Route as SettingsWebsearchRouteImport } from './routes/settings/websearch' import { Route as SettingsShortcutRouteImport } from './routes/settings/shortcut' import { Route as SettingsSelectionAssistantRouteImport } from './routes/settings/selectionAssistant' @@ -37,10 +30,17 @@ import { Route as SettingsDisplayRouteImport } from './routes/settings/display' import { Route as SettingsDataRouteImport } from './routes/settings/data' import { Route as SettingsApiServerRouteImport } from './routes/settings/api-server' import { Route as SettingsAboutRouteImport } from './routes/settings/about' -import { Route as PaintingsSplatRouteImport } from './routes/paintings/$' -import { Route as AppsAppIdRouteImport } from './routes/apps/$appId' +import { Route as AppTranslateRouteImport } from './routes/app/translate' +import { Route as AppNotesRouteImport } from './routes/app/notes' +import { Route as AppKnowledgeRouteImport } from './routes/app/knowledge' +import { Route as AppFilesRouteImport } from './routes/app/files' +import { Route as AppCodeRouteImport } from './routes/app/code' +import { Route as AppChatRouteImport } from './routes/app/chat' +import { Route as AppAssistantRouteImport } from './routes/app/assistant' import { Route as SettingsWebsearchIndexRouteImport } from './routes/settings/websearch/index' import { Route as SettingsMcpIndexRouteImport } from './routes/settings/mcp/index' +import { Route as AppPaintingsIndexRouteImport } from './routes/app/paintings/index' +import { Route as AppMinappIndexRouteImport } from './routes/app/minapp/index' import { Route as SettingsWebsearchGeneralRouteImport } from './routes/settings/websearch/general' import { Route as SettingsMcpServersRouteImport } from './routes/settings/mcp/servers' import { Route as SettingsMcpNpxSearchRouteImport } from './routes/settings/mcp/npx-search' @@ -48,47 +48,24 @@ import { Route as SettingsMcpMcpInstallRouteImport } from './routes/settings/mcp import { Route as SettingsMcpMarketplacesRouteImport } from './routes/settings/mcp/marketplaces' import { Route as SettingsMcpBuiltinRouteImport } from './routes/settings/mcp/builtin' import { Route as SettingsMcpSplatRouteImport } from './routes/settings/mcp/$' +import { Route as AppPaintingsSplatRouteImport } from './routes/app/paintings/$' +import { Route as AppMinappAppIdRouteImport } from './routes/app/minapp/$appId' import { Route as SettingsWebsearchProviderProviderIdRouteImport } from './routes/settings/websearch/provider.$providerId' import { Route as SettingsMcpSettingsServerIdRouteImport } from './routes/settings/mcp/settings.$serverId' -const TranslateRoute = TranslateRouteImport.update({ - id: '/translate', - path: '/translate', - getParentRoute: () => rootRouteImport, -} as any) -const StoreRoute = StoreRouteImport.update({ - id: '/store', - path: '/store', - getParentRoute: () => rootRouteImport, -} as any) const SettingsRoute = SettingsRouteImport.update({ id: '/settings', path: '/settings', getParentRoute: () => rootRouteImport, } as any) -const NotesRoute = NotesRouteImport.update({ - id: '/notes', - path: '/notes', +const HomeRoute = HomeRouteImport.update({ + id: '/home', + path: '/home', getParentRoute: () => rootRouteImport, } as any) -const KnowledgeRoute = KnowledgeRouteImport.update({ - id: '/knowledge', - path: '/knowledge', - getParentRoute: () => rootRouteImport, -} as any) -const FilesRoute = FilesRouteImport.update({ - id: '/files', - path: '/files', - getParentRoute: () => rootRouteImport, -} as any) -const CodeRoute = CodeRouteImport.update({ - id: '/code', - path: '/code', - getParentRoute: () => rootRouteImport, -} as any) -const ChatRoute = ChatRouteImport.update({ - id: '/chat', - path: '/chat', +const AppRoute = AppRouteImport.update({ + id: '/app', + path: '/app', getParentRoute: () => rootRouteImport, } as any) const IndexRoute = IndexRouteImport.update({ @@ -101,16 +78,6 @@ const SettingsIndexRoute = SettingsIndexRouteImport.update({ path: '/', getParentRoute: () => SettingsRoute, } as any) -const PaintingsIndexRoute = PaintingsIndexRouteImport.update({ - id: '/paintings/', - path: '/paintings/', - getParentRoute: () => rootRouteImport, -} as any) -const AppsIndexRoute = AppsIndexRouteImport.update({ - id: '/apps/', - path: '/apps/', - getParentRoute: () => rootRouteImport, -} as any) const SettingsWebsearchRoute = SettingsWebsearchRouteImport.update({ id: '/websearch', path: '/websearch', @@ -192,15 +159,40 @@ const SettingsAboutRoute = SettingsAboutRouteImport.update({ path: '/about', getParentRoute: () => SettingsRoute, } as any) -const PaintingsSplatRoute = PaintingsSplatRouteImport.update({ - id: '/paintings/$', - path: '/paintings/$', - getParentRoute: () => rootRouteImport, +const AppTranslateRoute = AppTranslateRouteImport.update({ + id: '/translate', + path: '/translate', + getParentRoute: () => AppRoute, } as any) -const AppsAppIdRoute = AppsAppIdRouteImport.update({ - id: '/apps/$appId', - path: '/apps/$appId', - getParentRoute: () => rootRouteImport, +const AppNotesRoute = AppNotesRouteImport.update({ + id: '/notes', + path: '/notes', + getParentRoute: () => AppRoute, +} as any) +const AppKnowledgeRoute = AppKnowledgeRouteImport.update({ + id: '/knowledge', + path: '/knowledge', + getParentRoute: () => AppRoute, +} as any) +const AppFilesRoute = AppFilesRouteImport.update({ + id: '/files', + path: '/files', + getParentRoute: () => AppRoute, +} as any) +const AppCodeRoute = AppCodeRouteImport.update({ + id: '/code', + path: '/code', + getParentRoute: () => AppRoute, +} as any) +const AppChatRoute = AppChatRouteImport.update({ + id: '/chat', + path: '/chat', + getParentRoute: () => AppRoute, +} as any) +const AppAssistantRoute = AppAssistantRouteImport.update({ + id: '/assistant', + path: '/assistant', + getParentRoute: () => AppRoute, } as any) const SettingsWebsearchIndexRoute = SettingsWebsearchIndexRouteImport.update({ id: '/', @@ -212,6 +204,16 @@ const SettingsMcpIndexRoute = SettingsMcpIndexRouteImport.update({ path: '/', getParentRoute: () => SettingsMcpRoute, } as any) +const AppPaintingsIndexRoute = AppPaintingsIndexRouteImport.update({ + id: '/paintings/', + path: '/paintings/', + getParentRoute: () => AppRoute, +} as any) +const AppMinappIndexRoute = AppMinappIndexRouteImport.update({ + id: '/minapp/', + path: '/minapp/', + getParentRoute: () => AppRoute, +} as any) const SettingsWebsearchGeneralRoute = SettingsWebsearchGeneralRouteImport.update({ id: '/general', @@ -248,6 +250,16 @@ const SettingsMcpSplatRoute = SettingsMcpSplatRouteImport.update({ path: '/$', getParentRoute: () => SettingsMcpRoute, } as any) +const AppPaintingsSplatRoute = AppPaintingsSplatRouteImport.update({ + id: '/paintings/$', + path: '/paintings/$', + getParentRoute: () => AppRoute, +} as any) +const AppMinappAppIdRoute = AppMinappAppIdRouteImport.update({ + id: '/minapp/$appId', + path: '/minapp/$appId', + getParentRoute: () => AppRoute, +} as any) const SettingsWebsearchProviderProviderIdRoute = SettingsWebsearchProviderProviderIdRouteImport.update({ id: '/provider/$providerId', @@ -263,16 +275,16 @@ const SettingsMcpSettingsServerIdRoute = export interface FileRoutesByFullPath { '/': typeof IndexRoute - '/chat': typeof ChatRoute - '/code': typeof CodeRoute - '/files': typeof FilesRoute - '/knowledge': typeof KnowledgeRoute - '/notes': typeof NotesRoute + '/app': typeof AppRouteWithChildren + '/home': typeof HomeRoute '/settings': typeof SettingsRouteWithChildren - '/store': typeof StoreRoute - '/translate': typeof TranslateRoute - '/apps/$appId': typeof AppsAppIdRoute - '/paintings/$': typeof PaintingsSplatRoute + '/app/assistant': typeof AppAssistantRoute + '/app/chat': typeof AppChatRoute + '/app/code': typeof AppCodeRoute + '/app/files': typeof AppFilesRoute + '/app/knowledge': typeof AppKnowledgeRoute + '/app/notes': typeof AppNotesRoute + '/app/translate': typeof AppTranslateRoute '/settings/about': typeof SettingsAboutRoute '/settings/api-server': typeof SettingsApiServerRoute '/settings/data': typeof SettingsDataRoute @@ -289,9 +301,9 @@ export interface FileRoutesByFullPath { '/settings/selectionAssistant': typeof SettingsSelectionAssistantRoute '/settings/shortcut': typeof SettingsShortcutRoute '/settings/websearch': typeof SettingsWebsearchRouteWithChildren - '/apps': typeof AppsIndexRoute - '/paintings': typeof PaintingsIndexRoute '/settings/': typeof SettingsIndexRoute + '/app/minapp/$appId': typeof AppMinappAppIdRoute + '/app/paintings/$': typeof AppPaintingsSplatRoute '/settings/mcp/$': typeof SettingsMcpSplatRoute '/settings/mcp/builtin': typeof SettingsMcpBuiltinRoute '/settings/mcp/marketplaces': typeof SettingsMcpMarketplacesRoute @@ -299,6 +311,8 @@ export interface FileRoutesByFullPath { '/settings/mcp/npx-search': typeof SettingsMcpNpxSearchRoute '/settings/mcp/servers': typeof SettingsMcpServersRoute '/settings/websearch/general': typeof SettingsWebsearchGeneralRoute + '/app/minapp': typeof AppMinappIndexRoute + '/app/paintings': typeof AppPaintingsIndexRoute '/settings/mcp/': typeof SettingsMcpIndexRoute '/settings/websearch/': typeof SettingsWebsearchIndexRoute '/settings/mcp/settings/$serverId': typeof SettingsMcpSettingsServerIdRoute @@ -306,15 +320,15 @@ export interface FileRoutesByFullPath { } export interface FileRoutesByTo { '/': typeof IndexRoute - '/chat': typeof ChatRoute - '/code': typeof CodeRoute - '/files': typeof FilesRoute - '/knowledge': typeof KnowledgeRoute - '/notes': typeof NotesRoute - '/store': typeof StoreRoute - '/translate': typeof TranslateRoute - '/apps/$appId': typeof AppsAppIdRoute - '/paintings/$': typeof PaintingsSplatRoute + '/app': typeof AppRouteWithChildren + '/home': typeof HomeRoute + '/app/assistant': typeof AppAssistantRoute + '/app/chat': typeof AppChatRoute + '/app/code': typeof AppCodeRoute + '/app/files': typeof AppFilesRoute + '/app/knowledge': typeof AppKnowledgeRoute + '/app/notes': typeof AppNotesRoute + '/app/translate': typeof AppTranslateRoute '/settings/about': typeof SettingsAboutRoute '/settings/api-server': typeof SettingsApiServerRoute '/settings/data': typeof SettingsDataRoute @@ -329,9 +343,9 @@ export interface FileRoutesByTo { '/settings/quickphrase': typeof SettingsQuickphraseRoute '/settings/selectionAssistant': typeof SettingsSelectionAssistantRoute '/settings/shortcut': typeof SettingsShortcutRoute - '/apps': typeof AppsIndexRoute - '/paintings': typeof PaintingsIndexRoute '/settings': typeof SettingsIndexRoute + '/app/minapp/$appId': typeof AppMinappAppIdRoute + '/app/paintings/$': typeof AppPaintingsSplatRoute '/settings/mcp/$': typeof SettingsMcpSplatRoute '/settings/mcp/builtin': typeof SettingsMcpBuiltinRoute '/settings/mcp/marketplaces': typeof SettingsMcpMarketplacesRoute @@ -339,6 +353,8 @@ export interface FileRoutesByTo { '/settings/mcp/npx-search': typeof SettingsMcpNpxSearchRoute '/settings/mcp/servers': typeof SettingsMcpServersRoute '/settings/websearch/general': typeof SettingsWebsearchGeneralRoute + '/app/minapp': typeof AppMinappIndexRoute + '/app/paintings': typeof AppPaintingsIndexRoute '/settings/mcp': typeof SettingsMcpIndexRoute '/settings/websearch': typeof SettingsWebsearchIndexRoute '/settings/mcp/settings/$serverId': typeof SettingsMcpSettingsServerIdRoute @@ -347,16 +363,16 @@ export interface FileRoutesByTo { export interface FileRoutesById { __root__: typeof rootRouteImport '/': typeof IndexRoute - '/chat': typeof ChatRoute - '/code': typeof CodeRoute - '/files': typeof FilesRoute - '/knowledge': typeof KnowledgeRoute - '/notes': typeof NotesRoute + '/app': typeof AppRouteWithChildren + '/home': typeof HomeRoute '/settings': typeof SettingsRouteWithChildren - '/store': typeof StoreRoute - '/translate': typeof TranslateRoute - '/apps/$appId': typeof AppsAppIdRoute - '/paintings/$': typeof PaintingsSplatRoute + '/app/assistant': typeof AppAssistantRoute + '/app/chat': typeof AppChatRoute + '/app/code': typeof AppCodeRoute + '/app/files': typeof AppFilesRoute + '/app/knowledge': typeof AppKnowledgeRoute + '/app/notes': typeof AppNotesRoute + '/app/translate': typeof AppTranslateRoute '/settings/about': typeof SettingsAboutRoute '/settings/api-server': typeof SettingsApiServerRoute '/settings/data': typeof SettingsDataRoute @@ -373,9 +389,9 @@ export interface FileRoutesById { '/settings/selectionAssistant': typeof SettingsSelectionAssistantRoute '/settings/shortcut': typeof SettingsShortcutRoute '/settings/websearch': typeof SettingsWebsearchRouteWithChildren - '/apps/': typeof AppsIndexRoute - '/paintings/': typeof PaintingsIndexRoute '/settings/': typeof SettingsIndexRoute + '/app/minapp/$appId': typeof AppMinappAppIdRoute + '/app/paintings/$': typeof AppPaintingsSplatRoute '/settings/mcp/$': typeof SettingsMcpSplatRoute '/settings/mcp/builtin': typeof SettingsMcpBuiltinRoute '/settings/mcp/marketplaces': typeof SettingsMcpMarketplacesRoute @@ -383,6 +399,8 @@ export interface FileRoutesById { '/settings/mcp/npx-search': typeof SettingsMcpNpxSearchRoute '/settings/mcp/servers': typeof SettingsMcpServersRoute '/settings/websearch/general': typeof SettingsWebsearchGeneralRoute + '/app/minapp/': typeof AppMinappIndexRoute + '/app/paintings/': typeof AppPaintingsIndexRoute '/settings/mcp/': typeof SettingsMcpIndexRoute '/settings/websearch/': typeof SettingsWebsearchIndexRoute '/settings/mcp/settings/$serverId': typeof SettingsMcpSettingsServerIdRoute @@ -392,16 +410,16 @@ export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath fullPaths: | '/' - | '/chat' - | '/code' - | '/files' - | '/knowledge' - | '/notes' + | '/app' + | '/home' | '/settings' - | '/store' - | '/translate' - | '/apps/$appId' - | '/paintings/$' + | '/app/assistant' + | '/app/chat' + | '/app/code' + | '/app/files' + | '/app/knowledge' + | '/app/notes' + | '/app/translate' | '/settings/about' | '/settings/api-server' | '/settings/data' @@ -418,9 +436,9 @@ export interface FileRouteTypes { | '/settings/selectionAssistant' | '/settings/shortcut' | '/settings/websearch' - | '/apps' - | '/paintings' | '/settings/' + | '/app/minapp/$appId' + | '/app/paintings/$' | '/settings/mcp/$' | '/settings/mcp/builtin' | '/settings/mcp/marketplaces' @@ -428,6 +446,8 @@ export interface FileRouteTypes { | '/settings/mcp/npx-search' | '/settings/mcp/servers' | '/settings/websearch/general' + | '/app/minapp' + | '/app/paintings' | '/settings/mcp/' | '/settings/websearch/' | '/settings/mcp/settings/$serverId' @@ -435,15 +455,15 @@ export interface FileRouteTypes { fileRoutesByTo: FileRoutesByTo to: | '/' - | '/chat' - | '/code' - | '/files' - | '/knowledge' - | '/notes' - | '/store' - | '/translate' - | '/apps/$appId' - | '/paintings/$' + | '/app' + | '/home' + | '/app/assistant' + | '/app/chat' + | '/app/code' + | '/app/files' + | '/app/knowledge' + | '/app/notes' + | '/app/translate' | '/settings/about' | '/settings/api-server' | '/settings/data' @@ -458,9 +478,9 @@ export interface FileRouteTypes { | '/settings/quickphrase' | '/settings/selectionAssistant' | '/settings/shortcut' - | '/apps' - | '/paintings' | '/settings' + | '/app/minapp/$appId' + | '/app/paintings/$' | '/settings/mcp/$' | '/settings/mcp/builtin' | '/settings/mcp/marketplaces' @@ -468,6 +488,8 @@ export interface FileRouteTypes { | '/settings/mcp/npx-search' | '/settings/mcp/servers' | '/settings/websearch/general' + | '/app/minapp' + | '/app/paintings' | '/settings/mcp' | '/settings/websearch' | '/settings/mcp/settings/$serverId' @@ -475,16 +497,16 @@ export interface FileRouteTypes { id: | '__root__' | '/' - | '/chat' - | '/code' - | '/files' - | '/knowledge' - | '/notes' + | '/app' + | '/home' | '/settings' - | '/store' - | '/translate' - | '/apps/$appId' - | '/paintings/$' + | '/app/assistant' + | '/app/chat' + | '/app/code' + | '/app/files' + | '/app/knowledge' + | '/app/notes' + | '/app/translate' | '/settings/about' | '/settings/api-server' | '/settings/data' @@ -501,9 +523,9 @@ export interface FileRouteTypes { | '/settings/selectionAssistant' | '/settings/shortcut' | '/settings/websearch' - | '/apps/' - | '/paintings/' | '/settings/' + | '/app/minapp/$appId' + | '/app/paintings/$' | '/settings/mcp/$' | '/settings/mcp/builtin' | '/settings/mcp/marketplaces' @@ -511,6 +533,8 @@ export interface FileRouteTypes { | '/settings/mcp/npx-search' | '/settings/mcp/servers' | '/settings/websearch/general' + | '/app/minapp/' + | '/app/paintings/' | '/settings/mcp/' | '/settings/websearch/' | '/settings/mcp/settings/$serverId' @@ -519,36 +543,13 @@ export interface FileRouteTypes { } export interface RootRouteChildren { IndexRoute: typeof IndexRoute - ChatRoute: typeof ChatRoute - CodeRoute: typeof CodeRoute - FilesRoute: typeof FilesRoute - KnowledgeRoute: typeof KnowledgeRoute - NotesRoute: typeof NotesRoute + AppRoute: typeof AppRouteWithChildren + HomeRoute: typeof HomeRoute SettingsRoute: typeof SettingsRouteWithChildren - StoreRoute: typeof StoreRoute - TranslateRoute: typeof TranslateRoute - AppsAppIdRoute: typeof AppsAppIdRoute - PaintingsSplatRoute: typeof PaintingsSplatRoute - AppsIndexRoute: typeof AppsIndexRoute - PaintingsIndexRoute: typeof PaintingsIndexRoute } declare module '@tanstack/react-router' { interface FileRoutesByPath { - '/translate': { - id: '/translate' - path: '/translate' - fullPath: '/translate' - preLoaderRoute: typeof TranslateRouteImport - parentRoute: typeof rootRouteImport - } - '/store': { - id: '/store' - path: '/store' - fullPath: '/store' - preLoaderRoute: typeof StoreRouteImport - parentRoute: typeof rootRouteImport - } '/settings': { id: '/settings' path: '/settings' @@ -556,39 +557,18 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof SettingsRouteImport parentRoute: typeof rootRouteImport } - '/notes': { - id: '/notes' - path: '/notes' - fullPath: '/notes' - preLoaderRoute: typeof NotesRouteImport + '/home': { + id: '/home' + path: '/home' + fullPath: '/home' + preLoaderRoute: typeof HomeRouteImport parentRoute: typeof rootRouteImport } - '/knowledge': { - id: '/knowledge' - path: '/knowledge' - fullPath: '/knowledge' - preLoaderRoute: typeof KnowledgeRouteImport - parentRoute: typeof rootRouteImport - } - '/files': { - id: '/files' - path: '/files' - fullPath: '/files' - preLoaderRoute: typeof FilesRouteImport - parentRoute: typeof rootRouteImport - } - '/code': { - id: '/code' - path: '/code' - fullPath: '/code' - preLoaderRoute: typeof CodeRouteImport - parentRoute: typeof rootRouteImport - } - '/chat': { - id: '/chat' - path: '/chat' - fullPath: '/chat' - preLoaderRoute: typeof ChatRouteImport + '/app': { + id: '/app' + path: '/app' + fullPath: '/app' + preLoaderRoute: typeof AppRouteImport parentRoute: typeof rootRouteImport } '/': { @@ -605,20 +585,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof SettingsIndexRouteImport parentRoute: typeof SettingsRoute } - '/paintings/': { - id: '/paintings/' - path: '/paintings' - fullPath: '/paintings' - preLoaderRoute: typeof PaintingsIndexRouteImport - parentRoute: typeof rootRouteImport - } - '/apps/': { - id: '/apps/' - path: '/apps' - fullPath: '/apps' - preLoaderRoute: typeof AppsIndexRouteImport - parentRoute: typeof rootRouteImport - } '/settings/websearch': { id: '/settings/websearch' path: '/websearch' @@ -731,19 +697,54 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof SettingsAboutRouteImport parentRoute: typeof SettingsRoute } - '/paintings/$': { - id: '/paintings/$' - path: '/paintings/$' - fullPath: '/paintings/$' - preLoaderRoute: typeof PaintingsSplatRouteImport - parentRoute: typeof rootRouteImport + '/app/translate': { + id: '/app/translate' + path: '/translate' + fullPath: '/app/translate' + preLoaderRoute: typeof AppTranslateRouteImport + parentRoute: typeof AppRoute } - '/apps/$appId': { - id: '/apps/$appId' - path: '/apps/$appId' - fullPath: '/apps/$appId' - preLoaderRoute: typeof AppsAppIdRouteImport - parentRoute: typeof rootRouteImport + '/app/notes': { + id: '/app/notes' + path: '/notes' + fullPath: '/app/notes' + preLoaderRoute: typeof AppNotesRouteImport + parentRoute: typeof AppRoute + } + '/app/knowledge': { + id: '/app/knowledge' + path: '/knowledge' + fullPath: '/app/knowledge' + preLoaderRoute: typeof AppKnowledgeRouteImport + parentRoute: typeof AppRoute + } + '/app/files': { + id: '/app/files' + path: '/files' + fullPath: '/app/files' + preLoaderRoute: typeof AppFilesRouteImport + parentRoute: typeof AppRoute + } + '/app/code': { + id: '/app/code' + path: '/code' + fullPath: '/app/code' + preLoaderRoute: typeof AppCodeRouteImport + parentRoute: typeof AppRoute + } + '/app/chat': { + id: '/app/chat' + path: '/chat' + fullPath: '/app/chat' + preLoaderRoute: typeof AppChatRouteImport + parentRoute: typeof AppRoute + } + '/app/assistant': { + id: '/app/assistant' + path: '/assistant' + fullPath: '/app/assistant' + preLoaderRoute: typeof AppAssistantRouteImport + parentRoute: typeof AppRoute } '/settings/websearch/': { id: '/settings/websearch/' @@ -759,6 +760,20 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof SettingsMcpIndexRouteImport parentRoute: typeof SettingsMcpRoute } + '/app/paintings/': { + id: '/app/paintings/' + path: '/paintings' + fullPath: '/app/paintings' + preLoaderRoute: typeof AppPaintingsIndexRouteImport + parentRoute: typeof AppRoute + } + '/app/minapp/': { + id: '/app/minapp/' + path: '/minapp' + fullPath: '/app/minapp' + preLoaderRoute: typeof AppMinappIndexRouteImport + parentRoute: typeof AppRoute + } '/settings/websearch/general': { id: '/settings/websearch/general' path: '/general' @@ -808,6 +823,20 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof SettingsMcpSplatRouteImport parentRoute: typeof SettingsMcpRoute } + '/app/paintings/$': { + id: '/app/paintings/$' + path: '/paintings/$' + fullPath: '/app/paintings/$' + preLoaderRoute: typeof AppPaintingsSplatRouteImport + parentRoute: typeof AppRoute + } + '/app/minapp/$appId': { + id: '/app/minapp/$appId' + path: '/minapp/$appId' + fullPath: '/app/minapp/$appId' + preLoaderRoute: typeof AppMinappAppIdRouteImport + parentRoute: typeof AppRoute + } '/settings/websearch/provider/$providerId': { id: '/settings/websearch/provider/$providerId' path: '/provider/$providerId' @@ -825,6 +854,36 @@ declare module '@tanstack/react-router' { } } +interface AppRouteChildren { + AppAssistantRoute: typeof AppAssistantRoute + AppChatRoute: typeof AppChatRoute + AppCodeRoute: typeof AppCodeRoute + AppFilesRoute: typeof AppFilesRoute + AppKnowledgeRoute: typeof AppKnowledgeRoute + AppNotesRoute: typeof AppNotesRoute + AppTranslateRoute: typeof AppTranslateRoute + AppMinappAppIdRoute: typeof AppMinappAppIdRoute + AppPaintingsSplatRoute: typeof AppPaintingsSplatRoute + AppMinappIndexRoute: typeof AppMinappIndexRoute + AppPaintingsIndexRoute: typeof AppPaintingsIndexRoute +} + +const AppRouteChildren: AppRouteChildren = { + AppAssistantRoute: AppAssistantRoute, + AppChatRoute: AppChatRoute, + AppCodeRoute: AppCodeRoute, + AppFilesRoute: AppFilesRoute, + AppKnowledgeRoute: AppKnowledgeRoute, + AppNotesRoute: AppNotesRoute, + AppTranslateRoute: AppTranslateRoute, + AppMinappAppIdRoute: AppMinappAppIdRoute, + AppPaintingsSplatRoute: AppPaintingsSplatRoute, + AppMinappIndexRoute: AppMinappIndexRoute, + AppPaintingsIndexRoute: AppPaintingsIndexRoute, +} + +const AppRouteWithChildren = AppRoute._addFileChildren(AppRouteChildren) + interface SettingsMcpRouteChildren { SettingsMcpSplatRoute: typeof SettingsMcpSplatRoute SettingsMcpBuiltinRoute: typeof SettingsMcpBuiltinRoute @@ -913,18 +972,9 @@ const SettingsRouteWithChildren = SettingsRoute._addFileChildren( const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, - ChatRoute: ChatRoute, - CodeRoute: CodeRoute, - FilesRoute: FilesRoute, - KnowledgeRoute: KnowledgeRoute, - NotesRoute: NotesRoute, + AppRoute: AppRouteWithChildren, + HomeRoute: HomeRoute, SettingsRoute: SettingsRouteWithChildren, - StoreRoute: StoreRoute, - TranslateRoute: TranslateRoute, - AppsAppIdRoute: AppsAppIdRoute, - PaintingsSplatRoute: PaintingsSplatRoute, - AppsIndexRoute: AppsIndexRoute, - PaintingsIndexRoute: PaintingsIndexRoute, } export const routeTree = rootRouteImport ._addFileChildren(rootRouteChildren) diff --git a/src/renderer/src/routes/app.tsx b/src/renderer/src/routes/app.tsx new file mode 100644 index 0000000000..24d8dc2b3c --- /dev/null +++ b/src/renderer/src/routes/app.tsx @@ -0,0 +1,5 @@ +import { createFileRoute, Outlet } from '@tanstack/react-router' + +export const Route = createFileRoute('/app')({ + component: () => +}) diff --git a/src/renderer/src/routes/store.tsx b/src/renderer/src/routes/app/assistant.tsx similarity index 77% rename from src/renderer/src/routes/store.tsx rename to src/renderer/src/routes/app/assistant.tsx index 2b3ea3e85e..d6e9e458b5 100644 --- a/src/renderer/src/routes/store.tsx +++ b/src/renderer/src/routes/app/assistant.tsx @@ -1,6 +1,6 @@ import AssistantPresetsPage from '@renderer/pages/store/assistants/presets/AssistantPresetsPage' import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/store')({ +export const Route = createFileRoute('/app/assistant')({ component: AssistantPresetsPage }) diff --git a/src/renderer/src/routes/chat.tsx b/src/renderer/src/routes/app/chat.tsx similarity index 72% rename from src/renderer/src/routes/chat.tsx rename to src/renderer/src/routes/app/chat.tsx index 575800f7a9..46f568edc1 100644 --- a/src/renderer/src/routes/chat.tsx +++ b/src/renderer/src/routes/app/chat.tsx @@ -1,6 +1,6 @@ import HomePage from '@renderer/pages/home/HomePage' import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/chat')({ +export const Route = createFileRoute('/app/chat')({ component: HomePage }) diff --git a/src/renderer/src/routes/code.tsx b/src/renderer/src/routes/app/code.tsx similarity index 74% rename from src/renderer/src/routes/code.tsx rename to src/renderer/src/routes/app/code.tsx index adee178762..6479af6682 100644 --- a/src/renderer/src/routes/code.tsx +++ b/src/renderer/src/routes/app/code.tsx @@ -1,6 +1,6 @@ import CodeToolsPage from '@renderer/pages/code/CodeToolsPage' import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/code')({ +export const Route = createFileRoute('/app/code')({ component: CodeToolsPage }) diff --git a/src/renderer/src/routes/files.tsx b/src/renderer/src/routes/app/files.tsx similarity index 72% rename from src/renderer/src/routes/files.tsx rename to src/renderer/src/routes/app/files.tsx index 164d9dae81..153bcd8596 100644 --- a/src/renderer/src/routes/files.tsx +++ b/src/renderer/src/routes/app/files.tsx @@ -1,6 +1,6 @@ import FilesPage from '@renderer/pages/files/FilesPage' import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/files')({ +export const Route = createFileRoute('/app/files')({ component: FilesPage }) diff --git a/src/renderer/src/routes/knowledge.tsx b/src/renderer/src/routes/app/knowledge.tsx similarity index 73% rename from src/renderer/src/routes/knowledge.tsx rename to src/renderer/src/routes/app/knowledge.tsx index 3d923e94bc..add14eb0e6 100644 --- a/src/renderer/src/routes/knowledge.tsx +++ b/src/renderer/src/routes/app/knowledge.tsx @@ -1,6 +1,6 @@ import KnowledgePage from '@renderer/pages/knowledge/KnowledgePage' import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/knowledge')({ +export const Route = createFileRoute('/app/knowledge')({ component: KnowledgePage }) diff --git a/src/renderer/src/routes/apps/$appId.tsx b/src/renderer/src/routes/app/minapp/$appId.tsx similarity index 70% rename from src/renderer/src/routes/apps/$appId.tsx rename to src/renderer/src/routes/app/minapp/$appId.tsx index 6bb3922645..fbd89c6770 100644 --- a/src/renderer/src/routes/apps/$appId.tsx +++ b/src/renderer/src/routes/app/minapp/$appId.tsx @@ -1,6 +1,6 @@ import MinAppPage from '@renderer/pages/minapps/MinAppPage' import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/apps/$appId')({ +export const Route = createFileRoute('/app/minapp/$appId')({ component: MinAppPage }) diff --git a/src/renderer/src/routes/apps/index.tsx b/src/renderer/src/routes/app/minapp/index.tsx similarity index 72% rename from src/renderer/src/routes/apps/index.tsx rename to src/renderer/src/routes/app/minapp/index.tsx index 0f9b26b7db..41a47c45d3 100644 --- a/src/renderer/src/routes/apps/index.tsx +++ b/src/renderer/src/routes/app/minapp/index.tsx @@ -1,6 +1,6 @@ import MinAppsPage from '@renderer/pages/minapps/MinAppsPage' import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/apps/')({ +export const Route = createFileRoute('/app/minapp/')({ component: MinAppsPage }) diff --git a/src/renderer/src/routes/notes.tsx b/src/renderer/src/routes/app/notes.tsx similarity index 72% rename from src/renderer/src/routes/notes.tsx rename to src/renderer/src/routes/app/notes.tsx index b3541b1d89..ab659b3809 100644 --- a/src/renderer/src/routes/notes.tsx +++ b/src/renderer/src/routes/app/notes.tsx @@ -1,6 +1,6 @@ import NotesPage from '@renderer/pages/notes/NotesPage' import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/notes')({ +export const Route = createFileRoute('/app/notes')({ component: NotesPage }) diff --git a/src/renderer/src/routes/paintings/$.tsx b/src/renderer/src/routes/app/paintings/$.tsx similarity index 58% rename from src/renderer/src/routes/paintings/$.tsx rename to src/renderer/src/routes/app/paintings/$.tsx index b0e7718061..d29fe06a8a 100644 --- a/src/renderer/src/routes/paintings/$.tsx +++ b/src/renderer/src/routes/app/paintings/$.tsx @@ -1,7 +1,7 @@ import PaintingsRoutePage from '@renderer/pages/paintings/PaintingsRoutePage' import { createFileRoute } from '@tanstack/react-router' -// 通配符路由:捕获 /paintings/* 所有子路径 -export const Route = createFileRoute('/paintings/$')({ +// 通配符路由:捕获 /app/paintings/* 所有子路径 +export const Route = createFileRoute('/app/paintings/$')({ component: PaintingsRoutePage }) diff --git a/src/renderer/src/routes/paintings/index.tsx b/src/renderer/src/routes/app/paintings/index.tsx similarity index 74% rename from src/renderer/src/routes/paintings/index.tsx rename to src/renderer/src/routes/app/paintings/index.tsx index 14f62c1e8d..49374a570e 100644 --- a/src/renderer/src/routes/paintings/index.tsx +++ b/src/renderer/src/routes/app/paintings/index.tsx @@ -1,6 +1,6 @@ import PaintingsRoutePage from '@renderer/pages/paintings/PaintingsRoutePage' import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/paintings/')({ +export const Route = createFileRoute('/app/paintings/')({ component: PaintingsRoutePage }) diff --git a/src/renderer/src/routes/translate.tsx b/src/renderer/src/routes/app/translate.tsx similarity index 73% rename from src/renderer/src/routes/translate.tsx rename to src/renderer/src/routes/app/translate.tsx index 9c9bd265a3..e85cb2ce8b 100644 --- a/src/renderer/src/routes/translate.tsx +++ b/src/renderer/src/routes/app/translate.tsx @@ -1,6 +1,6 @@ import TranslatePage from '@renderer/pages/translate/TranslatePage' import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/translate')({ +export const Route = createFileRoute('/app/translate')({ component: TranslatePage }) diff --git a/src/renderer/src/routes/home.tsx b/src/renderer/src/routes/home.tsx new file mode 100644 index 0000000000..5cf75bbeea --- /dev/null +++ b/src/renderer/src/routes/home.tsx @@ -0,0 +1,6 @@ +import LaunchpadPage from '@renderer/pages/launchpad/LaunchpadPage' +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/home')({ + component: LaunchpadPage +}) diff --git a/src/renderer/src/routes/index.tsx b/src/renderer/src/routes/index.tsx index 693694c738..4f341f0857 100644 --- a/src/renderer/src/routes/index.tsx +++ b/src/renderer/src/routes/index.tsx @@ -1,6 +1,7 @@ -import LaunchpadPage from '@renderer/pages/launchpad/LaunchpadPage' -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute, redirect } from '@tanstack/react-router' export const Route = createFileRoute('/')({ - component: LaunchpadPage + beforeLoad: () => { + throw redirect({ to: '/home' }) + } }) diff --git a/src/renderer/src/services/MessagesService.ts b/src/renderer/src/services/MessagesService.ts index 2773a56cec..85be71c515 100644 --- a/src/renderer/src/services/MessagesService.ts +++ b/src/renderer/src/services/MessagesService.ts @@ -75,7 +75,7 @@ export async function locateToMessage(navigate: UseNavigateResult, messa const assistant = getAssistantById(message.assistantId) const topic = await getTopicById(message.topicId) - navigate({ to: '/chat', search: { assistantId: assistant?.id, topicId: topic?.id } }) + navigate({ to: '/app/chat', search: { assistantId: assistant?.id, topicId: topic?.id } }) setTimeout(() => EventEmitter.emit(EVENT_NAMES.SHOW_TOPIC_SIDEBAR), 0) setTimeout(() => EventEmitter.emit(EVENT_NAMES.LOCATE_MESSAGE + ':' + message.id), 300) diff --git a/src/renderer/src/utils/__tests__/routeTitle.test.ts b/src/renderer/src/utils/__tests__/routeTitle.test.ts index 601db51ca5..688af39434 100644 --- a/src/renderer/src/utils/__tests__/routeTitle.test.ts +++ b/src/renderer/src/utils/__tests__/routeTitle.test.ts @@ -5,17 +5,17 @@ vi.mock('@renderer/i18n', () => ({ default: { t: vi.fn((key: string) => { const translations: Record = { - 'tab.new': '新标签页', - 'assistants.title': '助手', - 'assistants.presets.title': '预设助手', - 'paintings.title': '绘图', - 'translate.title': '翻译', - 'minapp.title': '小程序', - 'knowledge.title': '知识库', - 'files.title': '文件', - 'code.title': '代码', - 'notes.title': '笔记', - 'settings.title': '设置' + 'title.home': '首页', + 'common.chat': '聊天', + 'title.store': '助手库', + 'title.paintings': '绘画', + 'title.translate': '翻译', + 'title.apps': '小程序', + 'title.knowledge': '知识库', + 'title.files': '文件', + 'title.code': 'Code', + 'title.notes': '笔记', + 'title.settings': '设置' } return translations[key] || key }) @@ -32,16 +32,17 @@ describe('routeTitle', () => { describe('getDefaultRouteTitle', () => { describe('exact route matches', () => { it.each([ - ['/', '新标签页'], - ['/chat', '助手'], - ['/store', '预设助手'], - ['/paintings', '绘图'], - ['/translate', '翻译'], - ['/apps', '小程序'], - ['/knowledge', '知识库'], - ['/files', '文件'], - ['/code', '代码'], - ['/notes', '笔记'], + ['/', '首页'], + ['/home', '首页'], + ['/app/chat', '聊天'], + ['/app/assistant', '助手库'], + ['/app/paintings', '绘画'], + ['/app/translate', '翻译'], + ['/app/minapp', '小程序'], + ['/app/knowledge', '知识库'], + ['/app/files', '文件'], + ['/app/code', 'Code'], + ['/app/notes', '笔记'], ['/settings', '设置'] ])('should return correct title for %s', (url, expectedTitle) => { expect(getDefaultRouteTitle(url)).toBe(expectedTitle) @@ -50,25 +51,25 @@ describe('routeTitle', () => { describe('nested route matches', () => { it('should match base path for nested routes', () => { - expect(getDefaultRouteTitle('/chat/topic-123')).toBe('助手') + expect(getDefaultRouteTitle('/app/chat/topic-123')).toBe('聊天') expect(getDefaultRouteTitle('/settings/provider')).toBe('设置') expect(getDefaultRouteTitle('/settings/mcp/servers')).toBe('设置') - expect(getDefaultRouteTitle('/paintings/zhipu')).toBe('绘图') + expect(getDefaultRouteTitle('/app/paintings/zhipu')).toBe('绘画') }) }) describe('URL with query params and hash', () => { it('should handle URLs with query parameters', () => { - expect(getDefaultRouteTitle('/chat?topicId=123')).toBe('助手') + expect(getDefaultRouteTitle('/app/chat?topicId=123')).toBe('聊天') expect(getDefaultRouteTitle('/settings/provider?id=openai')).toBe('设置') }) it('should handle URLs with hash', () => { - expect(getDefaultRouteTitle('/knowledge#section1')).toBe('知识库') + expect(getDefaultRouteTitle('/app/knowledge#section1')).toBe('知识库') }) it('should handle URLs with both query and hash', () => { - expect(getDefaultRouteTitle('/chat?id=1#message-5')).toBe('助手') + expect(getDefaultRouteTitle('/app/chat?id=1#message-5')).toBe('聊天') }) }) @@ -85,20 +86,20 @@ describe('routeTitle', () => { describe('edge cases', () => { it('should handle trailing slashes', () => { - expect(getDefaultRouteTitle('/chat/')).toBe('助手') + expect(getDefaultRouteTitle('/app/chat/')).toBe('聊天') expect(getDefaultRouteTitle('/settings/')).toBe('设置') }) it('should handle double slashes (protocol-relative URL)', () => { // '//chat' is a protocol-relative URL, so 'chat' becomes the hostname // This is expected behavior per URL standard - expect(getDefaultRouteTitle('//chat')).toBe('新标签页') + expect(getDefaultRouteTitle('//chat')).toBe('首页') }) it('should handle relative-like paths', () => { // URL constructor with base will normalize these - expect(getDefaultRouteTitle('chat')).toBe('助手') - expect(getDefaultRouteTitle('./chat')).toBe('助手') + expect(getDefaultRouteTitle('app/chat')).toBe('聊天') + expect(getDefaultRouteTitle('./app/chat')).toBe('聊天') }) }) }) @@ -106,10 +107,10 @@ describe('routeTitle', () => { describe('getRouteTitleKey', () => { describe('exact matches', () => { it.each([ - ['/', 'tab.new'], - ['/chat', 'assistants.title'], - ['/store', 'assistants.presets.title'], - ['/settings', 'settings.title'] + ['/', 'title.home'], + ['/app/chat', 'common.chat'], + ['/app/assistant', 'title.store'], + ['/settings', 'title.settings'] ])('should return i18n key for %s', (url, expectedKey) => { expect(getRouteTitleKey(url)).toBe(expectedKey) }) @@ -117,8 +118,8 @@ describe('routeTitle', () => { describe('base path matches', () => { it('should return base path key for nested routes', () => { - expect(getRouteTitleKey('/chat/topic-123')).toBe('assistants.title') - expect(getRouteTitleKey('/settings/provider')).toBe('settings.title') + expect(getRouteTitleKey('/app/chat/topic-123')).toBe('common.chat') + expect(getRouteTitleKey('/settings/provider')).toBe('title.settings') }) }) diff --git a/src/renderer/src/utils/routeTitle.ts b/src/renderer/src/utils/routeTitle.ts index 5873f2713e..df9588d686 100644 --- a/src/renderer/src/utils/routeTitle.ts +++ b/src/renderer/src/utils/routeTitle.ts @@ -7,28 +7,42 @@ const BASE_URL = 'https://www.cherry-ai.com/' * Route to i18n key mapping for default tab titles */ const routeTitleKeys: Record = { - '/': 'tab.new', - '/chat': 'assistants.title', - '/store': 'assistants.presets.title', - '/paintings': 'paintings.title', - '/translate': 'translate.title', - '/apps': 'minapp.title', - '/knowledge': 'knowledge.title', - '/files': 'files.title', - '/code': 'code.title', - '/notes': 'notes.title', - '/settings': 'settings.title' + '/': 'title.home', + '/home': 'title.home', + '/app/chat': 'common.chat', + '/app/assistant': 'title.store', + '/app/paintings': 'title.paintings', + '/app/translate': 'title.translate', + '/app/minapp': 'title.apps', + '/app/knowledge': 'title.knowledge', + '/app/files': 'title.files', + '/app/code': 'title.code', + '/app/notes': 'title.notes', + '/settings': 'title.settings' +} + +/** + * Get the base path for route matching + * For /app/* routes, returns first two segments (e.g., '/app/chat') + * For other routes, returns first segment (e.g., '/settings') + */ +function getBasePath(pathname: string): string { + const segments = pathname.split('/').filter(Boolean) + if (segments[0] === 'app' && segments.length >= 2) { + return '/' + segments.slice(0, 2).join('/') + } + return '/' + (segments[0] || '') } /** * Get the default title for a route URL * - * @param url - Route URL (e.g., '/settings', '/chat/123') + * @param url - Route URL (e.g., '/settings', '/app/chat/123') * @returns Translated title or URL path fallback * * @example * getDefaultRouteTitle('/settings') // '设置' - * getDefaultRouteTitle('/chat/abc123') // '助手' + * getDefaultRouteTitle('/app/chat/abc123') // '助手' * getDefaultRouteTitle('/unknown') // 'unknown' */ export function getDefaultRouteTitle(url: string): string { @@ -40,9 +54,8 @@ export function getDefaultRouteTitle(url: string): string { return i18n.t(exactKey) } - // Try matching base path (e.g., '/chat/123' -> '/chat') - const basePath = '/' + sanitizedUrl.split('/').filter(Boolean)[0] - const baseKey = routeTitleKeys[basePath] + // Try matching base path + const baseKey = routeTitleKeys[getBasePath(sanitizedUrl)] if (baseKey) { return i18n.t(baseKey) } @@ -61,6 +74,5 @@ export function getRouteTitleKey(url: string): string | undefined { const exactKey = routeTitleKeys[sanitizedUrl] if (exactKey) return exactKey - const basePath = '/' + sanitizedUrl.split('/').filter(Boolean)[0] - return routeTitleKeys[basePath] + return routeTitleKeys[getBasePath(sanitizedUrl)] }