项目是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有点区别。