1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 菜单权限及按钮权限控制

菜单权限及按钮权限控制

时间:2023-06-21 00:47:38

相关推荐

菜单权限及按钮权限控制

实现思路:

1.通过利用动态路由、静态路由实现动态路由

2.通过router-beforeEach钩子监听是否有权限

3.利用Vue.directive监听页面挂在完成控制按钮权限

实现代码:

route.js

router文件下有两个文件,1个是用来存储静态路由(登录页)、动态路由,另一个文件则是用于监听路由钩子

/*** @description 默认路由*/export const constantRouterMap = [{path: '/',redirect: '/login',hidden: true},{path: '/login',name: 'login',hidden: true,component: () => import('../views/login/index.vue')}]/*** @description 动态路由*/export const asyncRouterMap = [{path:'/home',name:'home',meta: {title: '首页',icon:'' // 用于显示左侧菜单icon},component () => import(../views/Home/index.vue) //动态导入组件},{path:'/dosc',name:'Dosc',redirect:'/dosc/dosclist' //重定向meta: {title: '文件管理',icon:'' // 用于显示左侧菜单icon},component: () => import(../views/layout/index.vue) //默认入口组件children:[{path:'/dosc/dosclist',name:'doscList',meta:{name:'文件列表',breadcurmbName:'文件列表'},component:() => import(../view/dosc/dosclist/index.vue),children:[{hidden: true,path: '/dosc/detail/:id',name: 'doscDetail',meta: {breadcrumbName: '文件详情'},component: () => import('../views/dosclist/detail.vue')}]},{path:'/dosc/storelist',name:'storeList',meta:{name:'存储列表',breadcurmbName:'存储列表'},component:() => import(../view/dosc/store/index.vue)}]}]

index.js

页面刷新时,vuex会被清空所以需要从localStorage中重新获取路由及按钮权限。需要判断token是否过期,过期需要重新登录。

import { createRouter, createWebHistory } from 'vue-router'import { constantRouterMap } from './route'import store from '../store'import { getToken} from '../utils/cook'const router = createRouter({history: createWebHistory(process.env.BASE_URL),routes:constantRouterMap})router.beforeEach((to,from) => {try{const menu = localStorage.getItem("menus") !== null ?JSON.parse(window.decodeURIComponent(window.atob(localStorage.getItem("menus")))) : [] const buttons = localStorage.getItem("buttons") !== null ? JSON.parse(window.decodeURIComponent(window.atob(localStorage.getItem("buttons")))) : []if (to.path === '/login') {if (!getToken()) {localStorage.clear()return true}return router.push('/default')}if (!getToken()) {localStorage.clear()return router.push('/login')}if (store.getters.addRouters.length === 0) {if(menus.length > 0){store.dispatch('GenerateRoutes', { menus }).then(() => {// 动态添加可访问路由表addAsyncRoute(store.getters.addRouters)/*** @description 更新按钮权限*/store.dispatch('UpdateHasButtons',buttons)return router.push(to.path)})}else{store.dispatch('GetInfo').then(res => { // 拉取用户信息let {menus,buttons} = reslocalStorage.setItem('menus',window.btoa(window.encodeURIComponent(JSON.stringify(menus)))) localStorage.setItem('buttons',window.btoa(window.encodeURIComponent(JSON.stringify(buttons))))store.dispatch('UpdateHasButtons',buttons)store.dispatch('GenerateRoutes', { menus }).then(() => { // 生成可访问的路由表addAsyncRoute(store.getters.addRouters); // 动态添加可访问路由表return router.push(to.path)})}).catch((err) => {store.dispatch('ClearUserInfo')return router.push('/login')})/*** @description 更新按钮权限*/store.dispatch('getButtons')}}else{return true}}catch{localStorage.clear()router.push('/login')} })function addAsyncRoute(routers){for(let i= 0 ;i < routers.length;i++){const routeItem = Object.assign({},routers[i])router.addRoute(routeItem)}}

利用vuex存储路由及按钮

store文件夹下有modules模块文件夹(permession.js、user.js)、getters获取store文件

permession.js

用来存储路由权限、按钮权限。

import { asyncRouterMap, constantRouterMap } from '@/router/route';import store from '../../store'//判断是否有权限访问该菜单function hasPermission(menus, route,parent) {if (route.name) {let currMenu = getMenu(route.name, menus);if (currMenu!=null) {return true;} else {if (route.hidden !== undefined && route.hidden === true) {return true;} else {return false;}}} else {return true}}//根据路由名称获取菜单function getMenu(name, menus) {console.log('name',name);let targetMenu = {}for (let i = 0; i < menus.length; i++) {let menu = menus[i];if (menu.name === name) {return menu;}/*** @description 返回嵌套菜单权限*/if(menu.children && menu.children.length > 0){targetMenu = getMenu(name,menu.children)if(targetMenu !== undefined) return targetMenu}}// return null;}/*** @description 多层深度拷贝*/function deepCopy(params) {// 如果是数组if (Array.isArray(params)) {var res = [];for (var i = 0; i < params.length; i++) {if (params[i] instanceof Object) {// 将深层拷贝的结果的 添加到 res 中res.push(deepCopy(params[i]));} else {res.push(params[i]);}}return res;}// 如果是对象 进行 对象的拷贝if (params.constructor === Object) {var res = {}; // 1 声明空对象for (var x in params) {// 遍历被拷贝独享// 如果你是数组或者对象;需要再次拷贝if (params[x] instanceof Object && !params[x] instanceof Function) {// 将深层拷贝的结添加到 res中res[x] = deepCopy(params[x]);} else {// params[x] 为基本类型数据 直接添加大res中res[x] = params[x];}}return res}}const app = {state: () => ({routers: constantRouterMap,addRouters: [],hasButtons:[]}),mutations: {SET_ROUTERS: (state, routers) => {state.addRouters = routers;routers.push({path: '/:pathMatch(.*)*',name: 'error',hidden: true,component: () => import('../../views/error/404/index.vue')})if(routers[0].children && routers[0].children.length > 0){const path =routers[0].children[0].pathrouters[0].children[0].path = '/default'routers[0].children[0].alias = path}else{const path =routers[0].pathrouters[0].path = '/default'routers[0].alias = path}state.routers = constantRouterMap.concat(routers);},UPDATE_ROUTERS:(state,routers) =>{state.routers = routers},UPDATE_HASBUTTONS:(state,buttons) =>{state.hasButtons = buttons},CLEAR_ROUTES:(state) =>{state.routers = constantRouterMapstate.addRouters = []}},actions: {GenerateRoutes({ commit }, data) {return new Promise(resolve => {const { menus } = data;const primaryAsync = deepCopy(asyncRouterMap) const accessedRouters = primaryAsync.filter(v => {if (hasPermission(menus, v)) {if (v.children && v.children.length > 0) {v.children = v.children.filter(child => {if (hasPermission(menus, child,v)) { if(child.children && child.children.length > 0){ child.children = child.children.filter(ren => {if(hasPermission(menus,ren,child)){return ren}return false})return child}else{return child}}return false;});return v} else {return v}}return false;});commit('SET_ROUTERS', accessedRouters);resolve();})},UpdateRoutes({commit},routers){commit('UPDATE_ROUTERS',routers)},UpdateHasButtons({commit},buttons){commit('UPDATE_HASBUTTONS',buttons)},ClearRoutes({commit}){commit('CLEAR_ROUTES')}}};

user.js

用来存储用户权限。

import ajax from '@/api/account'const app = {state: () => ({userInfo: {username: localStorage.getItem('username') || '',name: localStorage.getItem('name') || '',role: localStorage.getItem('role') || ''}}),mutations: {CLEAR_USERINFO: (state) => {state.userInfo = {username: '',name: '',role: ''}},UPDATE_USERINFO: (state, userInfo) => {state.userInfo = {...state.userInfo,...userInfo}}},actions: {ClearUserInfo ({commit}) {commit('CLEAR_USERINFO')},UpdateUserInfo ({commit}, userInfo) {commit('UPDATE_USERINFO', userInfo)},// 获取用户信息GetInfo({ commit}) {return new Promise((resolve, reject) => {ajax.getInfo().then(response => {resolve(response)}).catch(error => {reject(error)})})},}}export default app

getters.js

用来获取store中的存储信息。

const getters = {userInfo: (state) => state.user.userInfo,addRouters: (state) => state.permission.addRouters,routers: (state) => state.permission.routers,hasButtons:(state) => state.permission.hasButtons}export default getters

按钮权限检验

挂载完成时通过用户名称去判断该用户是否拥有该按钮,来控制按钮的显示、隐藏。

import store from "../store"export default (Vue) => {/**自定义按钮权限指令 */Vue.directive('has', {mounted(el, binding) {//获取按钮权限if (!Vue.config.globalProperties.$_has(binding.value)) {//移除不匹配的按钮el.parentNode.removeChild(el)}},})//检查权限方法Vue.config.globalProperties.$_has = function (value) {let isExist = falseconst btnPermsArr = store.getters.hasButtonsif (btnPermsArr.includes(value)) {isExist = true}console.log('isExist',isExist);return isExist}}

登录时根据接口返回动态判断用户的路由、按钮,并同时存入vuex、locastorage

login(value).then(res => {if (res) {clearStorage()setToken(res.access)this.$store.dispatch('UpdateUserInfo', {username: res.username,name: res.name,role: res.role})this.$store.dispatch('GetInfo').then(res => {let {menus,buttons} = reslocalStorage.setItem('menus',window.btoa(window.encodeURIComponent(JSON.stringify(menus))))localStorage.setItem('buttons',window.btoa(window.encodeURIComponent(JSON.stringify(buttons))))this.$store.dispatch('UpdateHasButtons',buttons)this.$store.dispatch('GenerateRoutes', { menus }).then(() => { // 生成可访问的路由表this.addAsyncRoute(this.$store.getters.addRouters)this.$router.push('/default')})}).catch((err) => {clearStorage()return this.$router.push('/login')})}}).catch(() => {})

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。