import { createRouter, createWebHashHistory, type RouteRecordRaw } from 'vue-router' import AdminLayout from './layouts/AdminLayout.vue' import { useAuthStore } from './stores/auth' /** * 路由表。 * * 系统设置与日志的接口是 admin-only,这里用 meta.requiresAdmin 兜底: * 直接改 hash 深链也进不去,避免 recorder/guest 触发一串 403 请求。 */ const routes: RouteRecordRaw[] = [ { path: '/login', name: 'login', component: () => import('./pages/LoginPage.vue'), meta: { title: '登录' }, }, { path: '/', component: AdminLayout, children: [ { path: '', redirect: { name: 'dashboard' } }, { path: 'dashboard', name: 'dashboard', component: () => import('./pages/DashboardPage.vue'), meta: { title: '仪表盘' }, }, { path: 'entry', name: 'entry', component: () => import('./pages/EntryPage.vue'), meta: { title: '成绩录入' }, }, { path: 'review', name: 'review', component: () => import('./pages/ReviewPage.vue'), meta: { title: '成绩审核' }, }, { path: 'records', name: 'records', component: () => import('./pages/RecordsPage.vue'), meta: { title: '破纪录' }, }, { path: 'adjustments', name: 'adjustments', component: () => import('./pages/AdjustmentsPage.vue'), meta: { title: '积分调整' }, }, { path: 'standings', name: 'standings', component: () => import('./pages/StandingsPage.vue'), meta: { title: '积分榜' }, }, { path: 'display', name: 'display', component: () => import('./pages/DisplayPage.vue'), meta: { title: '大屏控制' }, }, { path: 'base-data', name: 'base-data', component: () => import('./pages/BaseDataPage.vue'), meta: { title: '基础数据' }, }, { path: 'export', name: 'export', component: () => import('./pages/ExportPage.vue'), meta: { title: '导出' }, }, { path: 'history', name: 'history', component: () => import('./pages/HistoryPage.vue'), meta: { title: '变更历史' }, }, { path: 'logs', name: 'logs', component: () => import('./pages/LogsPage.vue'), meta: { title: '日志', requiresAdmin: true }, }, { path: 'system', name: 'system', component: () => import('./pages/SystemPage.vue'), meta: { title: '系统设置', requiresAdmin: true }, }, { path: 'password', name: 'password', component: () => import('./pages/ChangePasswordPage.vue'), meta: { title: '修改密码' }, }, { path: 'about', name: 'about', component: () => import('./pages/AboutPage.vue'), meta: { title: '关于' }, }, ], }, { path: '/:pathMatch(.*)*', redirect: { name: 'dashboard' } }, ] export const router = createRouter({ // 服务端只在 /admin 精确路径返回 admin.html(见 httpapi/server.go 静态路由), // 用 hash 模式才能让刷新 / 深链(#/entry?eventId=101)不落到 404。 history: createWebHashHistory(), routes, }) router.beforeEach(async (to) => { if (to.meta.requiresAdmin !== true) return true const auth = useAuthStore() // 刷新页面时深链先于布局层挂载,这里补一次会话探测,避免把管理员误判成访客。 if (!auth.initialized) await auth.load() if (auth.user?.role === 'admin') return true return { name: 'dashboard' } }) router.afterEach((to) => { const title = typeof to.meta.title === 'string' ? to.meta.title : '' document.title = title === '' ? '管理面板' : `${title} · 管理面板` })