import { createRouter, createWebHistory } from 'vue-router' import type { RouteRecordRaw } from 'vue-router' import MainLayout from '@/layout/MainLayout.vue' import { tools } from './tools' import { i18n } from '@/i18n' import { toolName } from '@/i18n/helpers' /** * 路由约定:每个工具对应一个独立路由,路径与 tools.ts 中的 path 一致。 * 所有工具页面均嵌套在 MainLayout 下,共享侧边导航与主题/语言切换。 * 未匹配路径统一重定向到首页。 * * 标题本地化:meta 里存的是「取词用的 key」而不是写死的标题文案, * 这样切换语言后重新计算即可得到对应语言的标题,无需重建路由表。 */ const routes: RouteRecordRaw[] = [ { path: '/', component: MainLayout, children: [ { path: '', name: 'home', component: () => import('@/views/HomeView.vue'), // 首页标题直接取站点名,避免出现「首页 · 在线工具箱」这类冗余 meta: { titleKey: 'app.name' }, }, // 由工具注册表自动生成路由,无需手动维护 ...tools.map((t) => ({ path: t.path, name: t.path, component: t.component, meta: { titleKey: `tool.${t.path}.name`, toolPath: t.path, fallbackName: t.name }, })), ], }, { path: '/:pathMatch(.*)*', redirect: '/' }, ] const router = createRouter({ // HTML5 History 模式(部署到 Nginx 等需配置 try_files 回退,见 README) history: createWebHistory(), routes, }) /** 按当前语言把 meta 转成页面标题 */ function resolveTitle(meta: Record): string { const key = meta.titleKey as string | undefined if (key === 'app.name') return i18n.global.t('app.name') if (key && i18n.global.te(key)) return i18n.global.t(key) const toolPath = meta.toolPath as string | undefined if (toolPath) return toolName(toolPath, (meta.fallbackName as string | undefined) ?? '') return i18n.global.t('app.name') } /** * 同步浏览器标题。 * 除路由切换外,切换语言时也需要调用一次,否则标题会停留在旧语言。 */ export function syncDocumentTitle() { const meta = (router.currentRoute.value.meta ?? {}) as Record document.title = `${resolveTitle(meta)} · ${i18n.global.t('app.short')}` } router.afterEach(() => { syncDocumentTitle() }) export default router