vue-element-admin从后台动态查询菜单并生成路由信息

45 篇文章 1 订阅
17 篇文章 0 订阅

项目是gitee下载的 地址 https://gitee.com/panjiachen/vue-element-admin

由于分支较多,最初我下载的master版本的 ,但是权限版本比较老了,权限这块我使用的是

vue-element-admin权限验证: vue-element-admin权限验证,根据不同角色动态生成路由渲染侧边栏https://gitee.com/gsx1992/vue-element-admin.git这个里面的, 修改最大的地方就是 src/store/modules/permission.js文件,从后台获取的动态路由格式为:

export const asyncRoutes = [
  {
    path: '/app',
    component: Layout,
    redirect: 'noRedirect',
    name: 'appmanager',
    title: '店铺管理',
    icon: 'el-icon-s-help',
    alwaysShow: true, // 始终显示根目录
    children: [
      {
        path: 'applist',
        component: 'lass/app/index',
        name: 'appmanagerlist',
        title: '渠道列表',
        icon: 'el-icon-s-help'
      }
    ]
  },
  {
    path: '/user',
    component: Layout,
    redirect: 'noRedirect',
    name: 'System',
    title: '系统管理',
    icon: 'el-icon-s-help',
    children: [
      {
        path: 'userlist',
        component: 'lass/user/index',
        name: 'user',
        title: '用户管理',
        icon: 'el-icon-s-help'
      },
      {
        path: 'rolelist',
        component: 'lass/user/role/index',
        name: 'RoleList',
        title: '角色管理',
        icon: 'el-icon-s-help'
      },
      {  
        path: 'lass/user/role/detail/:id(\\d+)',  
        component: 'lass/user/role/detail',
        name: 'Roledetail',
        title: '角色列表',
        activeMenu: '/lass/user/role/orglist',
        icon: 'el-icon-s-help'
      }
    ]
  },
  {
    path: '/task',
    component: Layout,
    redirect: 'noRedirect',
    name: 'Task',
    title: '定时任务管理',
    icon: 'el-icon-s-help',
    alwaysShow: true, // 始终显示根目录
    children: [
      {
        path: 'list',
        component: 'lass/task/list',
        name: 'TaskList',
        title: '任务列表',
        icon: 'el-icon-s-help'
      }
    ]
  },
  {
    path: '/costList',
    component: Layout,
    redirect: '/costList/index',
    title: 'SKU系统管理',
    name: 'cost',
    icon: 'link',
    children: [
      {
        path: 'skuindex',
        component: 'lass/skusysList/skuindex',
        name: 'skuindex',
        title: 'sku计费列表',
        icon: 'guide',
        type: 4,
        url: 'admin/skusysList/skuindex'
      }, 
      {
        path: 'supplier',
        component: 'lass/skusysList/supplier',
        name: 'supplierList',
        title: '供应商管理',
        icon: 'guide',
        type: 4,
        url: 'admin/supplier/index'
      }
    ]
  },
 
]

 其中store里面的permission.js目录如下:

 代码修改如下:

import { constantRoutes } from '@/router'
import { formatRouter, getIframeIdList, save } from '@/utils'

// 自定义多维数组包特定对象转一维数组过滤children,后端若返回一维数组则直接交由filterAsyncRoutes处理
function MultidimensionalToOnedimensional(routesMap) {
  const filterRoutesMap = []
  !(function fn(routesMap) {
    routesMap.forEach(route => {
      const tmp = {}
      for (const key in route) {
        if (Object.hasOwnProperty.call(route, key)) {
          if (key !== 'children') {
            tmp[key] = route[key]
          } else if (key === 'children') {
            fn(route[key])
          }
        }
      }
      filterRoutesMap.push(tmp)
    })
  }(routesMap))
  return filterRoutesMap
}

// 路由索引匹配
export function filterAsyncRoutes(routes, filterRoutesMap) {
  const accessedRoutes = []
  routes.forEach(route => {
    const tmp = {}
    if (filterRoutesMap.some(a => a.path === route.path)) {
      for (const key in route) {
        if (Object.hasOwnProperty.call(route, key)) {
          if (key !== 'children') {
            tmp[key] = route[key]
          } else if (key === 'children') {
            const tmpC = filterAsyncRoutes(route[key], filterRoutesMap);
            (tmpC.length > 0) && (tmp.children = tmpC)
          }
        }
      }
    }
    tmp.path && accessedRoutes.push(tmp)
  })

  return accessedRoutes
}

const getDefaultState = () => {
  return {
    routes: [],
    addRoutes: [],
    iframePages: {}
  }
}
const state = getDefaultState

const mutations = {
  SET_ROUTES: (state, routes) => {
    routes.push({ path: '*', redirect: '/404', hidden: true })
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
    // state.routes.push({ path: '*', redirect: '/404', hidden: true })
  },
  RESET_STATE: state => {
    Object.assign(state, getDefaultState())
  },
  setIframeIds(state, iframePages) {
    if (typeof iframePages !== 'string' && iframePages) {
      state.iframePages = JSON.stringify(iframePages)
    } else {
      state.iframePages = iframePages
    }
    save('iframePages', state.iframePages)
  }
}

const actions = {
  generateRoutes({ commit, dispatch }, { asyncRoutes, routesMap }) {
    const loadMenuData = []
    let formatRutes = []
    Object.assign(loadMenuData, JSON.parse(asyncRoutes))
    const tempAsyncRoutes = Object.assign([], [])
    // 格式化路由
    formatRutes = formatRouter(tempAsyncRoutes, loadMenuData)
    // 获取iframe外链列表
    const iframeList = getIframeIdList([], JSON.parse(asyncRoutes), {})

    const asyncFormatRoutes = formatRutes
    const routesFormatMap = asyncFormatRoutes
    return new Promise(resolve => {
      const filterRoutesMap = MultidimensionalToOnedimensional(routesFormatMap)
      const accessedRoutes = filterAsyncRoutes(asyncFormatRoutes, filterRoutesMap)
      commit('SET_ROUTES', accessedRoutes)
      if (iframeList) {
        commit('setIframeIds', iframeList)
        // 设置iframe外链列表
        dispatch('iframes/setPage', iframeList, { root: true })
      }
      resolve(accessedRoutes)
    })
  },
  resetState({ commit }) {
    return new Promise(resolve => {
      commit('RESET_STATE')
      resolve()
    })
  }
}

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

 其中路由从接口返回后,转换动态路由的方法formatRouter的代码如下:

/**
 * 后台查询的菜单数据拼装成路由格式的数据
 * @param routes
 * @param data
 */
export function formatRouter(routes, data) {
  const len = data.length
  for (let i = 0; i < len; i++) {
    const menu = {
      path: data[i].path,
      component: Layout,
      alwaysShow: data[i].alwaysShow,
      redirect: data[i].redirect,
      name: data[i].name,
      meta: { title: data[i].title, noCache: true, icon: data[i].icon },
      children: []
    }
    if (data[i].children) {
      const children = data[i].children
      for (let j = 0; j < children.length; j++) {
        let metaSet = {}
        if (children[j].activeMenu && children[j].activeMenu !== undefined) {
          metaSet = { title: children[j].title, noCache: true, activeMenu: children[j].activeMenu }
        } else {
          metaSet = { title: children[j].title, noCache: true }
        }
        const viewPath = children[j].component
        var childrenList = {
          path: children[j].path,
          component: (resolve) => require([`@/views/${viewPath}`], resolve),
          name: children[j].name,
          meta: metaSet,
          hidden: children[j].hasOwnProperty('hidden') ? children[j].hidden : false
        }
        menu.children.push(childrenList)
      }
    }
    routes.push(menu)
  }
  return routes
}

以上就是从后台动态查询菜单并生成路由信息的改动,原来的demo版本权限是在前端控制,也就是把每页路由的角色带上,实际一般都是从后台动态 获取来控制,这个和demo有点区别。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值