Vue后臺管理系統(tǒng)權(quán)限控制與動態(tài)路由的實現(xiàn)
在開發(fā)后臺管理系統(tǒng)時,權(quán)限控制是不可或缺的一部分。本文將詳細介紹如何使用Vue實現(xiàn)根據(jù)不同角色動態(tài)生成路由,從而控制用戶訪問權(quán)限。
步驟一:基礎(chǔ)路由配置
首先,我們需要配置基礎(chǔ)路由,這些路由是所有用戶共有的,例如登錄頁和404頁。
const allRoutes = [ // 基礎(chǔ)路由 { path: '/', name: 'login', component: () => import("@/views/LoginView.vue") }, { path: '/404', name: '404', component: () => import('@/views/Error/404View.vue') }, // 動態(tài)路由容器(登錄后內(nèi)容) { path: '/layout', name: 'layout', component: () => import('@/Layout/MainLayout.vue'), children: [] }, ]
步驟二:完整路由數(shù)據(jù)
接下來,創(chuàng)建一個包含所有可能路由的數(shù)組。這個數(shù)組將用于與后端返回的權(quán)限數(shù)據(jù)對比,以篩選出當前用戶有權(quán)訪問的路由。
// 所有路由 const totalRoute = [ { path: '/', name: 'login', component: () => import("@/views/LoginView.vue") }, { path: '/404', name: '404', component: () => import('@/views/Error/404View.vue') }, { path: '/layout', name: 'layout', component: () => import('@/Layout/MainLayout.vue'), }, { path: '/home', name: '首頁', id: 1, pid: 0, }, { id: 2, pid: 0, redirect: null, path: '/comp', name: '門診', children: [{ id: 3, pid: 2, redirect: null, component: () => import('@/views/payView.vue'), path: "/pay", name: "門診繳費記錄", },{ id: 4, pid: 2, redirect: null, component: () => import('@/views/reservationView.vue'), path: "/reservation", name: "預(yù)約記錄", }] }, { id: 8, pid: 0, path: '/hospital', name: '住院', children: [{ id: 9, pid: 8, redirect: null, component: () => import('@/views/hospitalView.vue'), path: "/hospitalpay", name: "住院繳費記錄", },{ id: 10, pid: 8, redirect: null, component: () => import('@/views/roomView.vue'), path: "/room", name: "房間管理", },{ id: 11, pid: 8, redirect: null, component: () => import('@/views/inpatientView.vue'), path: "/inpatient", name: "住院人", }] } ];
步驟三:模擬后端權(quán)限數(shù)據(jù)
為了演示,我們使用模擬數(shù)據(jù)來代表后端返回的權(quán)限信息。
然后是后端接口返回的數(shù)據(jù),我就先用假數(shù)據(jù)進行代替了。配置的基礎(chǔ)路由和假數(shù)據(jù)要一致就行。假數(shù)據(jù)就是動態(tài)路由(會發(fā)生改變的)
// 動態(tài)訪問 const dynamicRouteConfigs = [ // 動態(tài)路由容器(登錄后內(nèi)容) { path: '/home', name: '首頁', id: 1, pid: 0, }, { id: 2, pid: 0, redirect: null, path: '/comp', name: '門診', children: [{ id: 3, pid: 2, redirect: null, path: "/pay", name: "門診繳費記錄", },{ id: 4, pid: 2, redirect: null, path: "/reservation", name: "預(yù)約記錄", }] }, { id: 8, pid: 0, path: '/hospital', name: '住院', children: [{ id: 9, pid: 8, redirect: null, path: "/hospitalpay", name: "住院繳費記錄", },{ id: 10, pid: 8, redirect: null, path: "/room", name: "房間管理", },{ id: 11, pid: 8, redirect: null, path: "/inpatient", name: "住院人", }] }, { id: 12, pid: 0, redirect: null, path: '/userinfor', name: '用戶管理', children: [{ id: 13, pid: 12, redirect: null, path: "/user", name: "用戶管理", },{ id: 14, pid: 12, redirect: null, path: "/role", name: "角色管理", },{ id: 15, pid: 12, redirect: null, path: "/admin", name: "管理員管理", },{ id: 27, pid: 12, redirect: null, path: "/visit", name: "就診卡", }] }, { id: 16, pid: 0, path: '/department', name: '科室管理', children: [{ id: 24, pid: 16, redirect: null, path: "/departments", name: "科室管理", }] }, { id: 17, pid: 0, path: '/hospitals', name: '醫(yī)院信息', redirect: null, children: [{ id: 18, pid: 17, redirect: null, path: "/hospitalList", name: "醫(yī)院信息", },{ id: 19, pid: 17, redirect: null, path: "/doctor", name: "醫(yī)生管理", },{ id: 20, pid: 17, redirect: null, path: "/scheduling", name: "醫(yī)生排班管理", },{ id: 21, pid: 17, redirect: null, path: "/label", name: "標簽管理", },{ id: 22, pid: 17, redirect: null, path: "/drug", name: "藥品管理", }, { id: 23, pid: 17, redirect: null, path: "/physical", name: "體檢管理", },{ id: 26, pid: 17, redirect: null, path: "/trends", name: "醫(yī)院動態(tài)", }] } ];
步驟四:創(chuàng)建路由實例
使用Vue Router創(chuàng)建路由實例,并初始化注冊基礎(chǔ)路由。
// 創(chuàng)建路由實例 const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: allRoutes })
步驟五:篩選匹配路由
編寫一個函數(shù)來篩選出匹配的路由。這個函數(shù)將遍歷后端返回的權(quán)限數(shù)據(jù)和完整路由數(shù)據(jù),找出匹配的路由并添加組件。
- 然后就進行改變判斷,通過遍歷兩個數(shù)組,判斷兩者的name或者path相同的時候?qū)⑵浞湃胍粋€新數(shù)組中。
- 然后再聲明一個變量等于component,就是添加基礎(chǔ)路由的component組件
const filterRoutes = (dynamicRouteConfigs, totalRoute) => { // 打印動態(tài)路由配置 console.log('動態(tài)路由', dynamicRouteConfigs); // 打印總路由 console.log('基礎(chǔ)路由', totalRoute); // 定義一個遞歸函數(shù)findMatchedRoute,用于在路由數(shù)組中查找匹配的目標路由 const findMatchedRoute = (routes, target) => { // 遍歷路由數(shù)組 for (const route of routes) { // 如果路由名稱在排除列表中,則跳過 if (['404', 'home'].includes(route.name)) continue; // 如果路由名稱或路徑與目標匹配,則返回該路由 if (route.name === target.name || route.path === target.path) { return route; } // 如果當前路由有子路由,則遞歸查找匹配的子路由 if (route.children) { const matchedChild = findMatchedRoute(route.children, target); // 如果找到匹配的子路由,則返回 if (matchedChild) return matchedChild; } } // 如果沒有找到匹配的路由,則返回null return null; }; // 定義一個函數(shù)mergeRoutes,用于合并源路由和匹配的路由 const mergeRoutes = (source, target) => { // 返回一個新的路由對象,包含源路由的所有屬性,以及匹配路由的component屬性 return { ...source, component: target.component, // 如果源路由有子路由,則遞歸合并子路由 children: source.children ? source.children.map(child => mergeRoutes(child, findMatchedRoute([target], child) || {})) : undefined, // 可以在這里合并其他可能需要的內(nèi)容,例如meta屬性 }; }; // 映射動態(tài)路由配置,對每個路由進行匹配和合并操作 const result = dynamicRouteConfigs .map(route => { // 查找匹配的路由 const matchedRoute = findMatchedRoute(totalRoute, route); // 打印匹配的路由 console.log(matchedRoute); // 如果找到匹配的路由,則合并路由,否則返回null return matchedRoute ? mergeRoutes(route, matchedRoute) : null; }) // 過濾掉結(jié)果中的null值 .filter(route => route !== null); // 打印過濾后的路由數(shù)組 console.log('過濾后的路由數(shù)組:', result); // 返回過濾后的路由數(shù)組 return result; };
步驟六:動態(tài)添加路由
編寫一個函數(shù)來動態(tài)添加篩選后的路由到基礎(chǔ)路由的layout
容器中。
然后后臺控制路由就完成了。主要和起那段控制是一樣的,都是需要一個基礎(chǔ)的路由數(shù)組,然后我們將數(shù)組對比過濾過之后,需要把過濾好的數(shù)組添加注冊到路由中。邏輯都是一樣的,疏通邏輯就可以了。
只不過前后端控制路由的接口返回不一樣而已。
// 動態(tài)添加路由到layout const addDynamicRoutes = (roles) => { // 清空已有動態(tài)路由 const layout = router.getRoutes().find(r => r.name === 'layout') layout.children.forEach(child => { router.removeRoute(child.name) }) // 過濾并添加新路由 const allowedRoutes = filterRoutes(dynamicRouteConfigs, allRoutes); allowedRoutes.forEach(route => { router.addRoute('layout', route); }); console.log(allowedRoutes); sessionStorage.setItem('menuPath',JSON.stringify(allowedRoutes));//存儲的篩選過的動態(tài)路由 // 確保404最后處理 router.addRoute({ path: '/:pathMatch(.*)*', redirect: '/404' }) }
步驟七:存儲和渲染菜單
將篩選后的路由存儲在會話存儲中,并在菜單頁面進行渲染。
通過以上步驟,我們完成了基于Vue的后臺管理系統(tǒng)權(quán)限控制與動態(tài)路由的設(shè)置。不同角色的用戶將看到不同的菜單和頁面,實現(xiàn)了權(quán)限的精細化管理。
最后路由導(dǎo)航守衛(wèi)加上去就ok了。
// 路由守衛(wèi)修改部分(router/index.ts) router.beforeEach(async (to, from, next) => { const store = loginStore() const isLogin = !!store.id // 未登錄狀態(tài)處理 if (!isLogin) { return to.path === '/' ? next() : next('/') } // 已登錄但訪問登錄頁時重定向 if (to.path === '/') { return next('/home') } // 動態(tài)路由加載邏輯 if (!store.routesLoaded) { try { // 直接從store獲取已保存的角色信息 const userRoles = store.roles; // 如果角色信息不存在則拋出錯誤 if (!userRoles || userRoles.length === 0) { throw new Error('用戶角色信息未獲取') } // 添加動態(tài)路由 addDynamicRoutes(dynamicRouteConfigs) // 在添加路由后打印 console.log('當前所有路由:', router.getRoutes().map(r => r.path)) // 更新加載狀態(tài) store.setRoutesLoaded(true) // 使用replace方式跳轉(zhuǎn)避免重復(fù)記錄歷史 return next({ ...to, replace: true }) } catch (error) { console.error('路由加載失敗:', error) // 清除用戶狀態(tài)并跳轉(zhuǎn)登錄頁 store.$reset() return next('/') } } next(); })
總結(jié)
本文介紹了如何使用Vue和Vue Router實現(xiàn)后臺管理系統(tǒng)的權(quán)限控制。通過動態(tài)生成路由,我們可以根據(jù)用戶的角色靈活控制頁面訪問權(quán)限,提高系統(tǒng)的安全性和用戶體驗。
到此這篇關(guān)于Vue后臺管理系統(tǒng)權(quán)限控制與動態(tài)路由的實現(xiàn)的文章就介紹到這了,更多相關(guān)Vue 權(quán)限控制與動態(tài)路由內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue使用富文本編輯器vue-quill-editor的操作指南和注意事項
vue中很多項目都需要用到富文本編輯器,在使用了ueditor和tinymce后,發(fā)現(xiàn)并不理想,所以果斷使用vue-quill-editor來實現(xiàn),下面這篇文章主要給大家介紹了關(guān)于vue使用富文本編輯器vue-quill-editor的操作指南和注意事項,需要的朋友可以參考下2023-05-05el-select如何獲取下拉框選中l(wèi)abel和value的值
在開發(fā)業(yè)務(wù)場景中我們通常遇到一些奇怪的需求,例如el-select業(yè)務(wù)場景需要同時獲取我們選中的label跟 value,下面這篇文章主要給大家介紹了關(guān)于el-select如何獲取下拉框選中l(wèi)abel和value的值,需要的朋友可以參考下2022-10-10解決Vue的文本編輯器 vue-quill-editor 小圖標樣式排布錯亂問題
這篇文章主要介紹了解決Vue的文本編輯器 vue-quill-editor 小圖標樣式排布錯亂問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08vue中使用animate.css實現(xiàn)炫酷動畫效果
這篇文章主要介紹了vue中使用animate.css實現(xiàn)動畫效果,我們使用它,只需要寫很少的代碼,就可以實現(xiàn)非常炫酷的動畫效果,感興趣的朋友跟隨小編一起看看吧2022-04-04vue3.x使用swiperUI動態(tài)加載圖片失敗的解決方法
這篇文章主要為大家詳細介紹了vue3.x使用swiperUI動態(tài)加載圖片失敗的解決方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07