import { createRouter, createWebHistory } from 'vue-router' import { useAuthStore } from '../stores/auth' import { trackPageView } from '../composables/useAnalytics' const routes = [ // 公开路由 { path: '/', component: () => import('../views/public/PublicLayout.vue'), children: [ { path: '', name: 'home', component: () => import('../views/public/HomeView.vue') }, { path: 'feed', redirect: '/' }, { path: 'literature/:pmid', name: 'public-detail', component: () => import('../views/public/LiteratureDetailView.vue') }, { path: 'journals', name: 'journals', component: () => import('../views/public/JournalBrowseView.vue') }, { path: 'cancers', name: 'cancers', component: () => import('../views/public/CancerBrowseView.vue') }, { path: 'drugs', name: 'drugs', component: () => import('../views/public/DrugApprovalsView.vue') }, { path: 'guidelines', name: 'guidelines', component: () => import('../views/public/GuidelinesView.vue') }, { path: 'guidelines/compare', name: 'guideline-compare', component: () => import('../views/public/GuidelineCompareView.vue') }, { path: 'guidelines/plans', name: 'treatment-plans', component: () => import('../views/public/TreatmentPlansView.vue') }, { path: 'pricing', name: 'pricing', component: () => import('../views/public/PricingView.vue') }, { path: 'about', name: 'about', component: () => import('../views/public/AboutView.vue') }, { path: 'help', name: 'help', component: () => import('../views/public/HelpView.vue') }, ], }, // 认证路由(登录/注册) { path: '/auth', component: () => import('../views/auth/AuthLayout.vue'), children: [ { path: 'login', name: 'login', component: () => import('../views/auth/LoginView.vue') }, { path: 'admin-login', name: 'admin-login', component: () => import('../views/auth/AdminLoginView.vue') }, { path: 'register', name: 'register', component: () => import('../views/auth/RegisterView.vue') }, { path: 'accept', name: 'accept-invite', component: () => import('../views/auth/AcceptInviteView.vue') }, { path: 'forgot-password', name: 'forgot-password', component: () => import('../views/auth/ForgotPasswordView.vue') }, { path: 'reset-password', name: 'reset-password', component: () => import('../views/auth/ResetPasswordView.vue') }, // { path: 'wechat-login-callback', name: 'wechat-login-callback', component: () => import('../views/auth/WeChatLoginCallback.vue') }, // 微信登录(第一版已注释) ], }, // 已登录应用路由 { path: '/app', component: () => import('../views/app/AppLayout.vue'), meta: { requiresAuth: true }, children: [ { path: '', redirect: '/app/feed' }, { path: 'feed', name: 'feed', component: () => import('../views/app/FeedView.vue') }, { path: 'profile', name: 'profile', component: () => import('../views/app/ProfileView.vue') }, { path: 'search', name: 'search', component: () => import('../views/app/SearchView.vue') }, { path: 'library', name: 'library', component: () => import('../views/app/LibraryView.vue') }, { path: 'literature/:pmid', name: 'detail', component: () => import('../views/app/LiteratureDetailView.vue') }, { path: 'team', name: 'team', component: () => import('../views/app/TeamView.vue') }, { path: 'settings', name: 'settings', component: () => import('../views/app/SettingsView.vue') }, { path: 'settings/interests', name: 'interests', component: () => import('../views/app/InterestSettingsView.vue') }, { path: 'domains', name: 'domains', component: () => import('../views/app/DomainCenterView.vue') }, { path: 'stats', redirect: '/app/profile' }, { path: 'journal-club', name: 'journal-club', component: () => import('../views/app/JournalClubView.vue') }, { path: 'mdt', name: 'mdt', component: () => import('../views/app/MdtView.vue') }, { path: 'activity', name: 'activity', component: () => import('../views/app/ActivityHistoryView.vue') }, { path: 'api', name: 'api-management', component: () => import('../views/app/ApiManagementView.vue') }, { path: 'notifications', name: 'notifications', component: () => import('../views/app/NotificationsView.vue') }, { path: 'notes', name: 'notes', component: () => import('../views/app/MyNotesView.vue') }, { path: 'reviews', name: 'reviews', component: () => import('../views/app/ReviewsView.vue') }, { path: 'reviews/:id', name: 'review-detail', component: () => import('../views/app/ReviewDetailView.vue') }, { path: 'journals/:issn', name: 'journal-detail', component: () => import('../views/app/JournalDetailView.vue') }, ], }, // 管理后台 { path: '/admin', component: () => import('../views/admin/AdminLayout.vue'), meta: { requiresAuth: true, requiresSuperuser: true }, children: [ { path: '', redirect: '/admin/dashboard' }, { path: 'dashboard', name: 'admin-dashboard', component: () => import('../views/admin/DashboardView.vue') }, { path: 'tenants', name: 'admin-tenants', component: () => import('../views/admin/TenantsView.vue') }, { path: 'users', name: 'admin-users', component: () => import('../views/admin/UsersView.vue') }, { path: 'pipeline', name: 'admin-pipeline', component: () => import('../views/admin/PipelineView.vue') }, { path: 'tags', name: 'admin-tags', component: () => import('../views/admin/TagsView.vue') }, { path: 'journals', name: 'admin-journals', component: () => import('../views/admin/JournalsView.vue') }, { path: 'drug-approvals', name: 'admin-drug-approvals', component: () => import('../views/admin/DrugApprovalsAdminView.vue') }, { path: 'guidelines', name: 'admin-guidelines', component: () => import('../views/admin/GuidelinesAdminView.vue') }, { path: 'notifications', name: 'admin-notifications', component: () => import('../views/admin/NotificationsView.vue') }, { path: 'page-views', name: 'admin-page-views', component: () => import('../views/admin/PageViewsView.vue') }, { path: 'feedback', name: 'admin-feedback', component: () => import('../views/admin/FeedbackView.vue') }, { path: 'analytics', name: 'admin-analytics', component: () => import('../views/admin/AnalyticsView.vue') }, { path: 'config', name: 'admin-config', component: () => import('../views/admin/ConfigView.vue') }, { path: 'roles', name: 'admin-roles', component: () => import('../views/admin/PlatformRolesView.vue') }, ], }, ] export const router = createRouter({ history: createWebHistory(), routes: [ ...routes, // 404 catch-all { path: '/:pathMatch(.*)*', name: 'not-found', component: () => import('../views/misc/NotFoundView.vue') }, ], }) router.beforeEach(async (to, _from, next) => { const auth = useAuthStore() // 确保会话初始化完成再判断登录态(避免路由守卫比 initialize 先触发) if (!auth.initialized) { await auth.initialize() } // 已登录用户访问公共详情页 → 重定向到 App 详情页(获得 AI 总结/收藏/标注等功能) if (to.name === 'public-detail' && auth.isAuthenticated) { next({ name: 'detail', params: { pmid: to.params.pmid }, query: to.query }) return } if (to.meta.requiresAuth && !auth.isAuthenticated) { next({ name: 'login', query: { redirect: to.fullPath } }) } else if (to.meta.requiresSuperuser && !auth.user?.platform_role) { next({ name: 'feed' }) } else { next() } }) // 页面访问追踪(afterEach 不阻塞导航) router.afterEach((to) => { trackPageView(to) })