From 5d7a8d7f5cdda32cbb9cb70807eb01fb0703856b Mon Sep 17 00:00:00 2001 From: root Date: Sun, 1 Dec 2024 16:45:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=99=BB=E5=BD=95=E6=88=90?= =?UTF-8?q?=E5=8A=9F=E8=B7=B3=E8=BD=AC=E9=80=BB=E8=BE=91=20=E7=BB=86?= =?UTF-8?q?=E5=8C=96=E5=89=8D=E7=AB=AF=E9=A1=B5=E9=9D=A2=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/Layout.vue | 47 +++++++++++++++++++++------------------- src/router/index.js | 39 ++++++++++++++------------------- src/utils/permission.js | 48 +++++++++++++++++++++++++++++++++++++++++ src/views/LoginView.vue | 28 ++++++++++++++---------- 4 files changed, 106 insertions(+), 56 deletions(-) create mode 100644 src/utils/permission.js diff --git a/src/layout/Layout.vue b/src/layout/Layout.vue index 449d5d5..5a53c8a 100644 --- a/src/layout/Layout.vue +++ b/src/layout/Layout.vue @@ -22,30 +22,26 @@ text-color="rgba(255,255,255,0.65)" active-text-color="#fff" :collapse="isCollapse"> - + 概览面板 - + + + 任务管理 + + + + 系统配置 + + + + 用户管理 + + + + 事件记录 + @@ -91,11 +87,18 @@ import { ref, computed, onMounted, onUnmounted, watch } from 'vue' import { useRouter, useRoute } from 'vue-router' import { DataLine, List, Expand, Fold, Setting, User, SwitchButton } from '@element-plus/icons-vue' import { ADMIN_ROUTE_BASE } from '@/config/api.config' +import { UserMask, hasPermission } from '@/utils/permission' const router = useRouter() const route = useRoute() const userRole = computed(() => localStorage.getItem('userRole')) -const userInfo = computed(() => JSON.parse(localStorage.getItem('userInfo'))) +const userInfo = computed(() => { + try { + return JSON.parse(localStorage.getItem('userInfo')) + } catch { + return null + } +}) const handleLogout = () => { localStorage.removeItem('token') diff --git a/src/router/index.js b/src/router/index.js index 16ad7be..7479b90 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -3,6 +3,7 @@ import { ElMessage } from 'element-plus' import Layout from '../layout/Layout.vue' import { UserAPI } from '../api/user' import { ADMIN_ROUTE_BASE } from '@/config/api.config' +import { UserMask, hasPermission } from '@/utils/permission' const routes = [ { @@ -28,25 +29,33 @@ const routes = [ path: 'dashboard', name: 'Dashboard', component: () => import('../views/Dashboard.vue'), - meta: { roles: ['admin', 'guest'] } + meta: { + minMask: UserMask.Admin // 管理员及以上权限可访问 + } }, { path: 'tasks', name: 'Tasks', component: () => import('../views/TaskManagement.vue'), - meta: { roles: ['admin'] } + meta: { + minMask: UserMask.Admin // 管理员及以上权限可访问 + } }, { path: 'config', name: 'Config', component: () => import('../views/ConfigView.vue'), - meta: { roles: ['admin'] } + meta: { + minMask: UserMask.Admin // 管理员及以上权限可访问 + } }, { path: 'users', name: 'Users', component: () => import('../views/UserManagement.vue'), - meta: { roles: ['admin'] } + meta: { + minMask: UserMask.SuperAdmin // 仅超级管理员可访问 + } }, { path: 'profile', @@ -129,31 +138,15 @@ router.beforeEach(async (to, from, next) => { if (to.path.startsWith(ADMIN_ROUTE_BASE)) { const token = localStorage.getItem('token') const isAuthenticated = localStorage.getItem('isAuthenticated') - const userRole = localStorage.getItem('userRole') + const userInfo = JSON.parse(localStorage.getItem('userInfo')) - if (!isAuthenticated) { + if (!isAuthenticated || !token || !userInfo) { next('/login') return } - // 如果是管理员但没有用户信息,尝试获取 - if (userRole === 'admin' && token) { - try { - const response = await UserAPI.getUserInfo() - if (response.retcode !== 0) { - localStorage.clear() - next('/login') - return - } - } catch (error) { - localStorage.clear() - next('/login') - return - } - } - // 检查权限 - if (to.meta.roles && !to.meta.roles.includes(userRole)) { + if (to.meta.minMask !== undefined && !hasPermission(to.meta.minMask, userInfo.mask)) { ElMessage.error('没有访问权限') next('/admin/dashboard') return diff --git a/src/utils/permission.js b/src/utils/permission.js new file mode 100644 index 0000000..c65c03e --- /dev/null +++ b/src/utils/permission.js @@ -0,0 +1,48 @@ +// 用户权限掩码 +export const UserMask = { + Guest: -1, + User: 0, + Admin: 1, + SuperAdmin: 2 +} + +// 检查用户是否有权限 +export function hasPermission(requiredMask, userMask) { + // 超级管理员拥有所有权限 + if (userMask === UserMask.SuperAdmin) { + return true + } + + // 管理员拥有除超级管理员外的所有权限 + if (userMask === UserMask.Admin && requiredMask !== UserMask.SuperAdmin) { + return true + } + + // 普通用户只能访问用户级别的功能 + if (userMask === UserMask.User && requiredMask <= UserMask.User) { + return true + } + + // 访客只能访问访客功能 + if (userMask === UserMask.Guest && requiredMask === UserMask.Guest) { + return true + } + + return false +} + +// 获取用户角色标签 +export function getUserRoleLabel(mask) { + switch (mask) { + case UserMask.SuperAdmin: + return '超级管理员' + case UserMask.Admin: + return '管理员' + case UserMask.User: + return '普通用户' + case UserMask.Guest: + return '访客' + default: + return '未知' + } +} \ No newline at end of file diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue index 21d7695..037309b 100644 --- a/src/views/LoginView.vue +++ b/src/views/LoginView.vue @@ -65,6 +65,7 @@ import { useRouter } from 'vue-router' import { ElMessage } from 'element-plus' import { User, Lock } from '@element-plus/icons-vue' import { UserAPI } from '../api/user' +import { UserMask } from '@/utils/permission' const router = useRouter() const loginFormRef = ref(null) @@ -102,27 +103,32 @@ const handleLogin = async () => { if (valid) { loading.value = true try { - const response = await UserAPI.login({ - username: loginForm.value.username, - password: loginForm.value.password - }) - + const response = await UserAPI.login(loginForm.value) if (response.retcode === 0) { - // 保存 用户信息 localStorage.setItem('token', JSON.stringify(response.data)) localStorage.setItem('isAuthenticated', 'true') + localStorage.setItem('userRole', 'admin') // 获取用户信息 - const userInfo = await UserAPI.getUserInfo() - if (userInfo.retcode === 0) { - localStorage.setItem('userRole', 'admin') - localStorage.setItem('userInfo', JSON.stringify(userInfo.data)) + const userInfoResponse = await UserAPI.getUserInfo() + if (userInfoResponse.retcode === 0) { + localStorage.setItem('userInfo', JSON.stringify(userInfoResponse.data)) + + // 根据用户权限决定跳转页面 + if (userInfoResponse.data.mask >= UserMask.Admin) { + router.push('/admin/dashboard') // 管理员及以上跳转到概览页 + } else { + router.push('/admin/events') // 普通用户跳转到事件记录页 + } + ElMessage.success('登录成功') - router.push('/dashboard') } + } else { + ElMessage.error(response.message || '登录失败') } } catch (error) { console.error('登录失败:', error) + ElMessage.error('登录失败,请重试') } finally { loading.value = false }