02---vue+element+admin将本地路由修改为权限路由

1.修改路由导航守卫,判断何时获取路由数据,并处理获取数据的js,阻止通过网址想直接进入后台进行权限管理

路由导航守卫文件在scr/permission.js中,下面是修改好之后的代码

import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken, getNickName } from '@/utils/auth' // get token from cookie
import { resetRouter } from '@/router'



import getPageTitle from '@/utils/get-page-title'

NProgress.configure({ showSpinner: false }) // NProgress Configuration

const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist

router.beforeEach(async(to, from, next) => {
    // start progress bar
    NProgress.start()

    // set page title
    document.title = getPageTitle(to.meta.title)

    // determine whether the user has logged in
    const hasToken = getToken() //获取登录token
    const nickName = getNickName(); //获取刚才在模块页使用cookie保存的模块名称
    // 判断是否有token
    if (hasToken) {
        // 判断当前路径是否为登录页
        if (to.path === '/login') {
            // 进入模块页
            next({ path: '/cache' })
            NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939

            // 判断当前是否为根路径
        } else if (to.path === '/') {
            //进入模块页
            next({ path: '/cache' })
                // 判断当前是否为模块页
        } else if (to.path === '/cache') {
            // 清除cookie保存的模块名称
            await store.dispatch("user/cache");
            next();
            // 判断当前是否为重定项页,首页
        } else if (to.path === '/dashboard') {
            resetRouter() //重置路由
            if (nickName == undefined) { //判断名称是否为空
                //为空直接跳回模块页
                next({ path: '/cache' });
                NProgress.done()
            } else {
                // 获取路由
                const { roles } = await store.dispatch('user/getInfo')
                const accessRoutes = await store.dispatch('permission/generateRoutes', { roles, nickName });
                //动态添加
                router.addRoutes(accessRoutes);
                next();
            }
            // 解决动态页面,强制刷新,路径丢失,和退出登录,重新登录,路径丢失问题
        } else if (to.path != '/dashboard') {
            // 先放行
            next();
            // 判断动态路由是否有数据,没有重新动态添加
            if (store.getters.permission_routes.length == 0) {
                const { roles } = await store.dispatch('user/getInfo')
                const accessRoutes = await store.dispatch('permission/generateRoutes', { roles, nickName });
                router.addRoutes(accessRoutes)
                next();
                // 名称为空,直接跳转到模块页面
            } else if (nickName == undefined) {
                next({ path: '/cache' });
                NProgress.done()
            }
        } else {
            const hasRoles = store.getters.roles && store.getters.roles.length > 0
            if (hasRoles) {
                next()
            } else {
                try {
                    // get user info
                    // 注意:角色必须是对象数组!例如:['admin']或,['developer','editor']
                    const { roles } = await store.dispatch('user/getInfo')
                    const accessRoutes = await store.dispatch('permission/generateRoutes', { roles, nickName })
                    router.addRoutes(accessRoutes);
                    // 黑客方法,以确保addRoutes是完整的
                    // 设置replace:true,这样导航就不会留下历史记录
                    next({...to, replace: true })
                } catch (error) { // 获取用户信息失败,进入以下一级
                    await store.dispatch('user/resetToken') // 获取用户信息失败后,就删除token
                    Message.error(error || 'Has Error') // 提示相应的错误
                        //next(`/login?redirect=${to.path}`) // 并跳转回登录界面,重新登录
                    next('login')
                    NProgress.done()
                }
            }
        }
    } else {
        /* 没有令牌*/
        if (whiteList.indexOf(to.path) !== -1) {
            // 在免费登录白名单中,直接进入
            next()
        } else {
            // 其他没有访问权限的页面将被重定向到登录页面。
            // next(`/login?redirect=${to.path}`)
            next('/login')
            NProgress.done()
        }
    }
})

router.afterEach(() => {
    // 完成进度条
    NProgress.done()
})

判断当前路径为/cache时删除cookie中保存的模块名称,不然通过网址进入后台管理页面时就会出现导航守卫死循环bug,其中await store.dispatch(‘user/cache’);是使用vuex中的方法,这个方法在上一篇博客01---vue+element+admin将本地路由修改为动态路由_天尘不打野的博客-CSDN博客中的src/store/modules/user.js文件中已经定义了,这里就不贴代码了

判断当前路径为/dashboard,并且模块名称不能为空时,获取路由数据,并动态添加进去。其中await store.dispatch(‘permission/generateRoutes’, nickName);是使用vuex中的方法,给permission.js中的generateRoutes,传递一个模块名称。

2.在src/store/modules/permission.js文件中定义generateRoutes方法

定义方法之前先将scr/router/modules中的四个路由文件里面的路由数据改为数组对象形式,因为动态路由需要数组对象形式,否则报错

 修改src/store/modules/permission.js文件

import { asyncRoutes, constantRoutes } from '@/router'
import Layout from '@/layout'
// 引入刚才改好的四个路由文件
import componentsRouter from '@/router/modules/components'
import chartsRouter from '@/router/modules/charts'
import tableRouter from '@/router/modules/table'
import nestedRouter from '@/router/modules/nested'


/**
 * Use meta.role to determine if the current user has permission
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
    if (route.meta && route.meta.roles) {
        return roles.some(role => route.meta.roles.includes(role))
    } else {
        return true
    }
}

/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes(routes, roles) {
    const res = []

    routes.forEach(route => {
        const tmp = {...route }
        if (hasPermission(roles, tmp)) {
            if (tmp.children) {
                tmp.children = filterAsyncRoutes(tmp.children, roles)
            }
            res.push(tmp)
        }
    })

    return res
}

const state = {
    routes: [],
    addRoutes: []
}

const mutations = {
    SET_ROUTES: (state, routes) => {
        state.addRoutes = routes
        state.routes = constantRoutes.concat(routes)
    }
}

// 懒加载
export const loadView = (view) => {
    return (resolve) => require([`@/views${view}`], resolve)
}

/**
 * 
 * @param { * 后台查询的菜单数据拼装成路由格式的数据
 * @param routes} routes 
 * @param {*} data 
 */
export function generaMenu(routes, data) {
    data.forEach(item => {
        const menu = {
            path: item.path === '#' ? item.menuId + '_key' : item.path,
            // component: item.component === '#' ? Layout : loadView(item.component),
            /**
             * 因为引入的路由文件里已经做了路由懒加载,这里就直接赋值就行
             * 如果是调用后台接口获取的数组对象,把下面的代码注释,上面的代码解开就可以了
             */
            component: item.component,
            hidden: item.hidden,
            children: [],
            //在4.4.0中路由父节点允许name属性存在值否则出现VUE之Router命令行警告:Named Route 'Home' has a default child route 警告
            name: item.component === '#' ? "" : item.name,
            meta: item.meta
        }
        if (item.children) {
            generaMenu(menu.children, item.children)
        }
        // 当存在单路由时要将children为空的属性删除否则无法在左侧菜单中展示独立的路由菜单
        if (menu.children.length <= 0) delete menu.children
        routes.push(menu)
    })
}

/**
 * 删除子节点children 为空数组
 * @param {*} data 
 */
export function deleteChildren(data) {
    let childs = data
    for (let i = childs.length; i--; i > 0) {
        //if(childs[i].meta != null){
        //  childs[i].meta = (childs[i].meta).replace("\"","").replace("\"","");
        //}	
        if (childs[i].children) {
            if (childs[i].children.length) {
                deleteChildren(childs[i].children)
            } else {
                delete childs[i].children
            }
        }
    }
    return data
}

const actions = {
    // 自己封装一个js
    //这个就为刚才在导航守卫,条件判断通过后,调用的获取数据的方法
    generateRoutes({ commit }, obj) {
        return new Promise(resolve => {
            const loadMenuData = [];
            let response = [];
            // 在这里可以调取后端接口,获取动态路由数组对象并把数据添加到路由
            if (obj.nickName === "组件系统") {
                response = deleteChildren(componentsRouter);
            } else if (obj.nickName === "图表系统") {
                response = deleteChildren(chartsRouter);
            } else if (obj.nickName === "表格系统") {
                response = deleteChildren(tableRouter);
            } else if (obj.nickName === "多级路由") {
                response = deleteChildren(nestedRouter);
            }
            Object.assign(loadMenuData, response)
            const tempAsyncRoutes = Object.assign([], asyncRoutes)
            generaMenu(tempAsyncRoutes, loadMenuData)
            let accessedRoutes
            if (obj.roles.includes('admin')) {
                accessedRoutes = tempAsyncRoutes || []
            } else {
                accessedRoutes = filterAsyncRoutes(tempAsyncRoutes, obj.roles)
            }
            commit('SET_ROUTES', accessedRoutes);
            //抛出路由,导航守卫获取数据要使用
            resolve(accessedRoutes)
        })
    }
}

export default {
    namespaced: true,
    state,
    mutations,
    actions
}

 注:因为内容太多,后面的内容在我另外的几个博客里:

01---vue+element+admin将本地路由修改为动态路由_天尘不打野的博客-CSDN博客

03---vue+element+admin将本地路由修改为动态路由_天尘不打野的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值