iview-admin3.0 动态权限路由实现

效果

后台新建行业和子模块,左侧导航栏动态添加一级导航和二级导航,登录后根据权限列表渲染相应模块。

实现

1.rouer/routers.js存放不需要权限控制的路由
2.api/user.js 添加获取路由的方法

export const getRequestRouter = () => {
  return axios.request({
    url: baseUri + '',
    method: 'get',
    headers: { }
  })
}

3.lib/util.js中添加获取缓存菜单和格式化菜单的的方法

export const loadMenu = () => {
  let list = []
  let data = localRead('variableMenuList')
  if (!data) {
    return list
  }
  list = formatMenu(JSON.parse(data))
  return list
}
export const formatMenu = (list) => {
  let res = []
  forEach(list, item => {
    if (item.componentAddress === 'main') {
      item.component = Main
    } else {
      item.component = () => import('@/view/' + item.componentAddress)
    }
    if (hasChild(item)) {
      item.children = formatMenu(item.children)
    }
    res.push(item)
  })
  return res
}
export const updateVariableMenuList=(data,router,store)=>{
  return new Promise(resolve => {
    let res = []
    data.forEach(industry => {
      let route = {
        path: '/industry-' + industry.value,
        name: 'industry-' + industry.value,
        meta: {
          icon: 'ios-apps',
          access:[],
          title: industry.name
        },
        component:null,
        componentAddress: 'main',
        children: []
      }
      industry.industryModules.forEach(industryModule => {
        route.meta.access.push(industryModule.permission)
        let moduleRoute = {
          value: industryModule.value,
          path: route.path + '/modules/' + industryModule.value,
          name: route.name + 'modules-' + industryModule.value,
          meta: {
            icon: 'md-cube',
            title: industryModule.name,
            notCache: true,
            access:[industryModule.permission],
            industryValue: industry.value,
            industryModuleValue: industryModule.value
          },
          component:null,
          componentAddress: 'industry-modules/industry_modules_index.vue'  
        }
        route.children.push(moduleRoute)

      })
      res.push(route)
    })
    store.commit('updateMenuList', res)
    resolve(res)
  })

}

4.store/module/app.js,引入添加的方法,修改getters,在mutations中添加updateMenuList方法

import {
  formatMenu,
  loadMenu
} from '@/libs/util'

state: {
    variableMenuList: loadMenu(),//添加的路由
    menuRouters: routers //固定路由
  },
getters: {
    menuList: (state, getters, rootState) => getMenuByRouter(state.menuRouters.concat(state.variableMenuList), rootState.user.access),
    errorCount: state => state.errorList.length
  },
mutations: {
    // 刷新菜单
    updateMenuList (state, data) {
      if (data) {
        localSave('variableMenuList', JSON.stringify(data)) //只能存储格式化之前的路由
        state.variableMenuList=[];
        state.variableMenuList=formatMenu(data)
      }
    },
}

5.router/index.js ,引入格式化函数和获取菜单数据的函数,处理路由守卫

import {updateVariableMenuList} from '@/libs/util'
import {getRequestRouter} from '@/api/user'

router.beforeEach((to, from, next) => {
  const token = getToken('token')
  const access= getToken('access')
  if (!token && to.name !== LOGIN_PAGE_NAME) {
    // 未登录且要跳转的页面不是登录页
    next({
      name: LOGIN_PAGE_NAME // 跳转到登录页
    })
  } else if (!token && to.name === LOGIN_PAGE_NAME) {
    // 未登陆且要跳转的页面是登录页
    next() // 跳转
  } else if (token && to.name === LOGIN_PAGE_NAME) {
    // 已登录且要跳转的页面是登录页
    next({
      name: homeName // 跳转到homeName页
    })
  } else {
    if(!localRead('variableMenuList')){// 如果本地不存在路由缓存
      getRequestRouter().then(json=>{
        if (json.status == 200) {
          updateVariableMenuList(json.data,router,store).then(res=>{
            router.addRoutes(res)
            next({ ...to, replace: true })
          })
        }
      })
    } else if(!store.state.user.access){//用户登录后进行了刷新
      store.commit('setAccess', access) //刷新后store中的数据会置空,这里重新赋值,不然权限路由出不来
      getRequestRouter().then(json=>{
        if (json.status == 200) {
          updateVariableMenuList(json.data,router,store).then(res=>{
            router.addRoutes(res)
            next({ ...to, replace: true })//hack方法 确保addRoutes已完成,防止页面空白
          })
        }
      })
    }
    else {
      next()
    }
  }

})

6.在添加路由模块页面引入格式化函数,添加新建函数并更新路由

import router from '@/router'
import store from '@/store'
import {updateVariableMenuList}  from '@/libs/util'
import {getRequestRouter} from '@/api/user'
methods(){
  getIndustryList() {
        getRequestRouter().then(json => {
          if (json.status == 200) {
            updateVariableMenuList(json.data,router,store)
          }
        })
      }
}

参考:https://blog.csdn.net/weixin_41538490/article/details/93749942

关于路由页面

项目中动态添加的每个路由的页面相同,路径不同,所以在meta里添加了行业value和子模块value来区分,
在mounted中接收,但是第二次进入不触发页面渲染,这时可以监听$route的变化,相应组件也要监听value的最新值,来触发页面更新

<template>
  <div>
    <bannerTop v-if ="industry.moduleValue===1" :industryValue="industry.value" ></bannerTop>
    <fugeWebiner v-if ="industry.moduleValue===2" :industryValue="industry.value" ></fugeWebiner>
    <fugeLive v-if ="industry.moduleValue===3" :industryValue="industry.value" ></fugeLive>
  </div>
</template>

<script>
  export default {
    name:"",
    components: { },
    data(){
      return{
        industry:{
          value:0,
          moduleValue:0
        }
      }
    },
    watch:{
       "$route"(to,from){
         this.industry.value=this.$route.meta.industryValue
         this.industry.moduleValue=this.$route.meta.industryModuleValue
       },
   },
    mounted(){
      this.industry.value=this.$route.meta.industryValue
      this.industry.moduleValue=this.$route.meta.industryModuleValue
    }
  }
</script>
//bannerTop 
 props:{
        industryValue:{
          type:Number
        }
      },
  watch: {
          "industryValue"(to,from){
            this.query.category=to
            this.getActivityList.bind(this)()
          },
        },
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值