fix: 路由权限控制 - 访客只能访问机器列表,admin页面需登录

This commit is contained in:
shirainbown
2026-06-19 13:05:54 +08:00
parent 7f9a883ed2
commit 93227db553
3 changed files with 19 additions and 74 deletions

View File

@@ -39,8 +39,8 @@
<div class="user-info" v-if="isLoggedIn">
<el-icon class="user-icon"><UserFilled /></el-icon>
<div class="user-meta">
<span class="user-name">{{ isAdmin ? '管理员' : '访客' }}</span>
<span class="user-role">{{ isAdmin ? 'Admin' : 'Guest' }}</span>
<span class="user-name">管理员</span>
<span class="user-role">Admin</span>
</div>
</div>
<div class="footer-actions" v-if="isLoggedIn">
@@ -56,18 +56,8 @@
</div>
</aside>
<!-- 访客顶部极简标题栏 -->
<header class="guest-header" v-if="!isAdmin">
<div class="guest-brand">
<img src="/logo.svg" alt="LAN Manager" style="width:22px;height:22px;" />
<span>LAN Manager</span>
</div>
<div class="guest-theme-toggle" @click="toggleTheme">
<el-icon><component :is="isDark ? Sunny : Moon" /></el-icon>
</div>
</header>
<main class="main" :class="{ 'guest-main': !isAdmin }">
<!-- 未登录用户无侧边栏只显示内容 -->
<main class="main" :class="{ 'no-sidebar': !isAdmin }">
<div class="main-inner">
<router-view />
</div>
@@ -386,54 +376,14 @@ html.dark .brand-logo {
background: var(--page-bg);
transition: background .25s ease;
}
.main.no-sidebar {
margin-left: 0;
}
.main-inner {
padding: 10px;
}
.guest-main {
margin-left: 0;
padding-top: 48px;
}
.guest-header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 48px;
background: var(--sidebar-bg);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
z-index: 100;
}
.guest-brand {
display: flex;
align-items: center;
gap: 8px;
font-weight: 600;
font-size: 14px;
color: var(--text-primary);
}
.guest-theme-toggle {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--card-bg);
border: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: var(--text);
transition: all .2s ease;
}
.guest-theme-toggle:hover {
background: var(--hover-bg);
}
@media (max-width: 768px) {
.sidebar { width: 64px; }
.brand-text, .nav-item span, .user-meta, .footer-btn span, .theme-toggle span { display: none; }
@@ -442,6 +392,6 @@ html.dark .brand-logo {
.user-info { justify-content: center; padding: 10px; }
.theme-toggle { justify-content: center; padding: 10px; }
.main { margin-left: 64px; }
.guest-main { margin-left: 0; }
.main.no-sidebar { margin-left: 0; }
}
</style>

View File

@@ -6,7 +6,7 @@ const routes = [
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue'),
meta: { public: true, guestOnly: true },
meta: { guestOnly: true },
},
{
path: '/',
@@ -59,30 +59,25 @@ router.beforeEach(async (to, from, next) => {
if (!authChecked) {
try {
const { data } = await checkAuth()
authState = { ...data, is_logged_in: true }
authState = { is_admin: data.is_admin, is_logged_in: true }
} catch (e) {
authState = { is_admin: false, is_logged_in: false }
}
authChecked = true
}
// 未登录,且不是公开页面也不是登录页 → 强制去登录
if (!authState.is_logged_in && !to.meta.public && !to.meta.guestOnly) {
return next('/login?redirect=' + encodeURIComponent(to.fullPath))
// 未登录用户访问 admin 专属页面 → 去机器列表
if (!authState.is_logged_in && to.meta.admin) {
return next('/machines')
}
// 已登录访客,访问需要 admin 页面 → 去机器列表
// 已登录但非管理员(防御性)访问 admin 页面 → 去机器列表
if (authState.is_logged_in && !authState.is_admin && to.meta.admin) {
return next('/machines')
}
// 已登录访客,访问登录页 → 去机器列表
if (authState.is_logged_in && !authState.is_admin && to.meta.guestOnly) {
return next('/machines')
}
// 管理员访问登录页 → 去仪表盘
if (authState.is_admin && to.meta.guestOnly) {
// 管理员已登录,访问登录页 → 去仪表盘
if (authState.is_logged_in && authState.is_admin && to.meta.guestOnly) {
return next('/dashboard')
}
@@ -95,7 +90,7 @@ export function refreshAuth() {
}
export function setAuth(data) {
authState = { ...data, is_logged_in: true }
authState = { is_admin: data.is_admin, is_logged_in: true }
}
export function getAuth() {

View File

@@ -115,7 +115,7 @@
</div>
</div>
<!-- 访客卡片仅主机名 + 状态 + OS不可点击 -->
<!-- 未登录用户卡片仅主机名 + 状态 + OS不可点击 -->
<div v-if="!isAdmin" v-for="m in machines" :key="m.id" class="server-card guest-card"
:class="[{ 'offline-card': !m.is_online }]">
<div class="card-header">