vue admin 动态路由权限管理

主要思路 通过后端接口返回数据 进行判断 (通过后端实现的权限管理有许多种),在这里 我们主要通过 关键字匹配前端路由meta.menu值来实现权限管理通常会把路由权限列表存至vux中

在这里插入图片描述

箭头所指的便是 后端接口返回的权限列表

实现方法通过 通过 配置路由meta.menu来实现权限匹配 通过 router.addRoute来实现路由添加 通过meta.hidden 来决定是否在侧边栏展示当前页面

第一步 在router/index.js 中完成 无需权限路由的配置 我这里配备的便是 登录 404首页

const routes = [{
    
    
	  path: '/login',
	  component: () => import('@/views/Login.vue'),
	  meta: {
    
    
	    title: '登录'
	  }
	},
	{
    
    
	  path: '/404',
	  name: '404',
	  component: () => import('@/views/error/404'),
	  hidden: true
	},
	
	{
    
    
	  path: '',
	  redirect: '/',
	  component: Layout,
	  children: [{
    
    
	    path: '/',
	    component: () =>
	      import('../views/Home.vue'),
	    meta: {
    
    
	      title: '首页',
	      parentpath: '/home'
	    }
	  }]
	}
]


第二步 动态权限的配置存放在vueX中

const asyncRouters=[
 {
    
    
          path: '/User',
          redirect: '/User/index',
          component: () => import('@/views/layout/index.vue'),
          meta: {
    
    
            title: '用户',
            menu: "user"
          },
          children: [
            // 用户
            {
    
    
              path: 'index',
              name: 'User',
              component: (resolve) => require(['@/views/member/user/index.vue'], resolve),
              meta: {
    
    
                title: '用户',
                menu: "user"
              }
            },
            {
    
    
              path: 'detail',
              name: 'userDetail',
              component: (resolve) => require(['@/views/member/user/detail.vue'], resolve),
              meta: {
    
    
                title: '用户',
                menu: "user"
              }
            },
            {
    
    
              path: 'staff',
              name: 'UserStaff',
              component: (resolve) => require(['@/views/member/staff/index.vue'], resolve),
              meta: {
    
    
                title: '员工',
                menu: "manager"
              }
            },
            // 这个路由不需要展示
            {
    
    
              path: 'supplier',
              name: 'UserSupplier',
              hidden:true,
              component: (resolve) => require(['@/views/member/supplier/index.vue'], resolve),
              meta: {
    
    
                title: '供应商',
                menu: "thirdPlat"
              }
            },
          ]
        }]

第三步 路由守卫中拦截 和添加动态路由可在main.js 或者router/index.js中写

// 关键 添加flag防止多次获取动态路由和栈溢出
let asyncRouterFlag = 0;

router.beforeEach(async (to, from, next) => {
    
    
  const token = window.localStorage.getItem('token')
  document.title = to.meta.title
  if (to.path == '/login') {
    
    
    next()
  } else {
    
    
    if (!token) {
    
    
      next('/login')
    } else {
    
    
      if (!asyncRouterFlag) {
    
    
        // 添加flag防止多次获取动态路由和栈溢出
        asyncRouterFlag++
        //同步调用获取菜单方法
        await store.dispatch('SetAsyncRouter')   //发请求获取菜单,并将菜单设置到vuex中,
        const asyncRouters = store.getters['asyncRouters'];
        var roleList = store.state.rolelist || []
        if (roleList.length > 0) {
    
    
        //	自写方法  根据关键词匹配
          addRouter(asyncRouters, roleList)
        } else {
    
    
          api.LoginInfo().then(res => {
    
    
            console.log(res, '数据')
            if (res.code == 200) {
    
    
              roleList = res.data.roles
              store.commit('setRoleList', roleList)
              console.log(4)
              addRouter(asyncRouters, roleList)
            } else {
    
    
              Message.error(res.data.message || res.statusText);
            }
          }).catch(err => {
    
    
            next('/login')
          })
        }
        next({
    
     ...to, replace: true })
      } else {
    
    
        next()
      }

    }
  }
})

// 筛选出满足条件的路由    这里因人而异
function addRouter(asyncRouters, roleList) {
    
    
  asyncRouters.map(item => {
    
    
    if (roleList.indexOf(item.meta.menu > -1)) {
    
    
      let temp = cloneLoop(item)
      delete temp.children
      if (item.children.length > 0) {
    
    
        temp.children = []
        item.children.map(item1 => {
    
    
          if (roleList.indexOf(item1.meta.menu > -1)) {
    
    
            temp.children.push(item1)
          }
        })
      }
      router.addRoute(temp)
    }
  })

//   最后 加入* 重定向404
  router.addRoute({
    
    
    path: '*',
    redirect: "/404",
  })
}

最后在实现侧边栏

<template>
  <div>
    <el-menu :default-active="this.$route.path"   active-text-color='#13C479'  class="el-menu-vertical-demo" router>
      <!-- 首页 -->
      <el-menu-item index="/">
       // 图标  可自定义
        <i class="el-icon-s-home"></i>
        <span slot="title" style="margin-left:10px">首页</span>
      </el-menu-item>

      <el-submenu :index="item.path" v-for="(item,index) in routeList" :key="index">
        <template slot="title">
           <i class="el-icon-s-home"></i>
          <span slot="title" style="margin-left:10px"  v-if="item.meta">{
   
   {item.meta.title}}</span>
        </template>

        <template v-if="item.children">
          <div v-for="(item1,index1) in item.children" :key="index1">
            <el-menu-item :index="`${item.path}/${item1.path}`" v-if="!item1.hidden">
             <i class="el-icon-s-home"></i>
              <span slot="title" style="margin-left:10px" >{
   
   {item1.meta.title}}</span>
            </el-menu-item>
          </div>
        </template>
      </el-submenu>
    </el-menu>
  </div>
</template>

<script>
export default {
      
      
  data() {
      
      
    return {
      
      
      routeList: []
    };
  },
  computed: {
      
      },
  watch: {
      
      },
  mounted() {
      
      
  // 这里把无需权限的路由复制过来
    var tempRouter = [
      // 订单
      {
      
      
        path: "/order",
        component: () => import("@/views/layout/index.vue"),
        redirect: "/order/index",
        meta: {
      
      
          title: "订单"
        },
        children: [
          {
      
      
            path: "index",
            name: "orderTickets",
            component: () => import("@/views/order/tickets.vue"),
            meta: {
      
      
              title: "系统门票订单"
            }
          },
          {
      
      
            path: "seasonTickets",
            name: "orderSeasonTickets",
            component: () => import("@/views/order/seasonTickets.vue"),
            meta: {
      
      
              title: "套餐门票订单"
            }
          }
        ]
      },

      // 优惠券
      {
      
      
        path: "/coupon",
        component: () => import("@/views/layout/index.vue"),
        redirect: "/coupon/index",
        meta: {
      
      
          title: "优惠券"
        },
        children: [
          {
      
      
            path: "index",
            name: "coupon",
            component: () => import("@/views/coupon/index.vue"),
            meta: {
      
      
              title: "优惠券"
            }
          }
        ]
      }
    ];
	// 把筛选出来的权限列表和无需权限的列表组合起来
    this.routeList = [...this.$store.state.asyncRouters, ...tempRouter];

    console.log(this.routeList, "全部");
  },
  methods: {
      
      }
};
</script>

<style lang='scss' scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
      
      
  width: 200px;
  min-height: 400px;
}

/deep/ .el-menu {
      
      
  background: none;
}
</style>

第四步 token过期后端没有返回refush-token时,退出登录切换账号我们需要清除已经注册的路由,防止其他用户获得到已经注册好了的路由。

router.replace({
    
    path: '/login'});
    window.location.reload();

service.interceptors.response.use((res) => {
    
    
  console.log(res, '我是拦截')
  // if(res.)
  nprogress.done()
  return res.data
}, err => {
    
    
  let status = err.response.status
  if (err.response && err.response.status) {
    
    
    console.log(err.response)
    if (status == 401) {
    
    
      Message.error('登录失效,请刷新后重试')
      router.replace({
    
    path: '/login'});
        window.location.reload();
    }
  }
  return Promise.reject(err.response)

可参考写法—vue 动态路由权限管理

猜你喜欢

转载自blog.csdn.net/IT_iosers/article/details/120811869