diff --git a/.reasonix/desktop-topic-title-sources.json b/.reasonix/desktop-topic-title-sources.json new file mode 100644 index 0000000..f04e650 --- /dev/null +++ b/.reasonix/desktop-topic-title-sources.json @@ -0,0 +1,3 @@ +{ + "topic_20260626-113733_9874ba9ab889b7ed": "manual" +} \ No newline at end of file diff --git a/.reasonix/desktop-topic-titles.json b/.reasonix/desktop-topic-titles.json new file mode 100644 index 0000000..cd04107 --- /dev/null +++ b/.reasonix/desktop-topic-titles.json @@ -0,0 +1,3 @@ +{ + "topic_20260626-113733_9874ba9ab889b7ed": "新的会话" +} \ No newline at end of file diff --git a/app/components/admin/AdminSidebarNav.vue b/app/components/admin/AdminSidebarNav.vue index 6497bde..020a2a3 100644 --- a/app/components/admin/AdminSidebarNav.vue +++ b/app/components/admin/AdminSidebarNav.vue @@ -4,6 +4,7 @@ export interface NavItem { to?: string icon?: string children?: NavItem[] + requireAdmin?: boolean } const props = defineProps<{ diff --git a/app/middleware/auth.global.ts b/app/middleware/auth.global.ts index 4500ed5..99d4032 100644 --- a/app/middleware/auth.global.ts +++ b/app/middleware/auth.global.ts @@ -26,6 +26,18 @@ export default defineNuxtRouteMiddleware(async (to) => { const currentFullPath = to.fullPath; const isLoggedIn = loggedIn.value; + // 管理员路由守卫:除仪表板外 /admin/* 需要管理员权限 + const isAdminRoute = currentPath.startsWith("/admin"); + const isDashboardOnly = currentPath === "/admin" || currentPath === "/admin/dashboard"; + if (isLoggedIn && isAdminRoute && !isDashboardOnly) { + const { user } = useAuthSession(); + if (user.value?.role !== "admin") { + const { $toast } = useNuxtApp(); + $toast?.warning("需要管理员权限"); + return navigateTo("/"); + } + } + if (!isLoggedIn && !isPublicRoute(currentPath)) { return navigateTo({ path: FRONTEND_LOGIN_PATH, diff --git a/app/pages/admin.vue b/app/pages/admin.vue index 5a3936b..92d938f 100644 --- a/app/pages/admin.vue +++ b/app/pages/admin.vue @@ -15,17 +15,25 @@ const adminNav: NavItem[] = [ { label: '定时任务', to: '/admin/scheduler', - icon: 'lucide:clock' + icon: 'lucide:clock', + requireAdmin: true, }, { label: '系统管理', icon: 'lucide:settings', + requireAdmin: true, children: [ { label: '用户管理', to: '/admin/users' }, + { label: '邮件配置', to: '/admin/email' }, ] }, ] +const visibleNav = computed(() => { + const isAdmin = user.value?.role === 'admin' + return adminNav.filter(item => !item.requireAdmin || isAdmin) +}) + const logout = async () => { await clear() navigateTo("/") @@ -45,7 +53,7 @@ const logout = async () => { - +