vue+element后台菜单权限动态配置
vue+element后台菜单权限动态配置
·
文章目录
1、说明
后台权限列表用的是element的table组件(https://element.eleme.cn/#/zh-CN/component/table)
2、后端返回的菜单权限数据
let data = [
{
"id": "1580804966837141505",
"parentId": "0",
"seq": 0,
"children": [
{
"id": "1580805570087108610",
"parentId": "1580804966837141505",
"seq": 0,
"name": "用户管理",
"spread": false,
"path": "index",
"keepAlive": "0",
"menuType": "0",
"label": "用户管理",
"createdAt": "2022-10-14 14:19:50",
"updatedAt": "2022-11-07 14:22:34"
},
{
"id": "1580805641843261441",
"parentId": "1580804966837141505",
"seq": 1,
"name": "积分记录",
"spread": false,
"path": "points",
"keepAlive": "0",
"menuType": "0",
"label": "积分记录",
"createdAt": "2022-10-14 14:20:07",
"updatedAt": "2022-11-07 14:22:39"
}
],
"name": "用户管理",
"spread": false,
"path": "user",
"keepAlive": "0",
"menuType": "0",
"label": "用户管理",
"createdAt": "2022-10-14 14:17:27",
"updatedAt": "2022-10-14 14:17:27"
},
{
"id": "1580805083585593346",
"parentId": "0",
"seq": 1,
"children": [
{
"id": "1580805723388919810",
"parentId": "1580805083585593346",
"seq": 1,
"name": "供应商管理",
"spread": false,
"path": "supplier",
"keepAlive": "0",
"menuType": "0",
"label": "供应商管理",
"createdAt": "2022-10-14 14:20:27",
"updatedAt": "2022-11-07 14:22:45"
},
{
"id": "1580805784856444930",
"parentId": "1580805083585593346",
"seq": 2,
"name": "商品分类管理",
"spread": false,
"path": "category",
"keepAlive": "0",
"menuType": "0",
"label": "商品分类管理",
"createdAt": "2022-10-14 14:20:42",
"updatedAt": "2022-11-07 14:22:54"
},
{
"id": "1580805854662246401",
"parentId": "1580805083585593346",
"seq": 3,
"name": "商品管理",
"spread": false,
"path": "goods",
"keepAlive": "0",
"menuType": "0",
"label": "商品管理",
"createdAt": "2022-10-14 14:20:58",
"updatedAt": "2022-11-07 14:23:01"
}
],
"name": "供应商管理",
"spread": false,
"path": "supplier",
"keepAlive": "0",
"menuType": "0",
"label": "供应商管理",
"createdAt": "2022-10-14 14:17:54",
"updatedAt": "2022-10-14 14:17:54"
},
]
3、router/index.js
router / index.js
静态配置页面路由是在这个js里配置的,首页是没有权限的也可以访问
import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);
import Layout from "@/layout";
export const constantRoutes = [
{
path: "/login",
component: () => import("@/views/login/index"),
hidden: true,
},
{
path: "/404",
component: () => import("@/views/404"),
hidden: true,
},
{
path: "/",
component: Layout,
redirect: "/",
meta: { title: "首页", icon: "el-icon-s-home" },
children: [
{
path: "/",
name: "/",
component: () => import("@/views/index/index"),
meta: { title: "首页", icon: "el-icon-s-home" },
},
],
},
];
const createRouter = () =>
new Router({
mode: "history", // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes,
});
const router = createRouter();
export function resetRouter() {
const newRouter = createRouter();
router.matcher = newRouter.matcher; // reset router
}
export default router;
4、store/getters.js
store/getters.js
const getters = {
...//其他内容
addRouters_: state => state.permission.addRouters,
permissionList: state => state.user.permissionList
};
export default getters;
5、store/modules/user.js
store/modules/user.js
import { constantRoutes } from "@/router";
import { getUserMenu } from "@/api/auth";//获取登录账号的菜单权限
import Layout from "@/layout";
import router from "@/router";
const getDefaultState = () => {
return {
//当前用户能够访问的路由对象
routes: [],
permissionList:[]
};
};
const state = getDefaultState();
function lazyComponent(item,i){
let url = `@/views/${item.path}/${i.path}`
let obj = {
path: i.path,
name: `${item.path}/${i.path}`,
component: (resolve) => require([`@/views/${item.path}/${i.path}`], resolve),
meta: { title: i.name, icon: "el-icon-s-grid" },
}
return obj
}
const mutations = {
RESET_STATE: (state) => {
Object.assign(state, getDefaultState());
},
//过滤之后的路由对象
SET_ROUTES: (state, routes) => {
state.routes = routes;
},
SET_PERMISSIONLIST: (state, permissionList) => {
state.permissionList = constantRoutes.concat(permissionList)
},
};
const actions = {
...
// 获取用户菜单信息
GetPermissionList({ commit }){
return new Promise((resolve, reject)=>{
getUserMenu().then(response=>{
let menuData = response.data
let arr = []
menuData.forEach((item,index)=>{
if(item.children){
let obj = {
path: '/' + item.path,
component: Layout,
redirect: '/' + item.path,
name:item.path,
meta: { title: item.name, icon: "el-icon-s-grid" },
children:[]
}
item.children.forEach((i,k)=>{
let a = lazyComponent(item,i)
obj.children.push(a)
})
commit('SET_PERMISSIONLIST', arr)
commit("SET_ROUTES", arr);
arr.push(obj)
}
})
resolve(arr)
}).catch(error => {
reject(error)
})
})
},
};
export default {
namespaced: true,
state,
mutations,
actions,
};
6、src/permission.js
src/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 } from "@/utils/auth"; // get token from cookie
import getPageTitle from "@/utils/get-page-title";
import { getUserMenu } from "@/api/auth.js";
import { generateIndexRouter } from '@/utils/util'
NProgress.configure({ showSpinner: false }); // NProgress Configuration
const whiteList = ["/login"]; // no redirect whitelist
router.beforeEach(async (to, from, next) => {
NProgress.start();
document.title = getPageTitle(to.meta.title);
const hasToken = getToken();
if (hasToken) {
if (to.path === "/login") {
next({ path: "/" });
NProgress.done();
} else {
//重点代码 重点代码 重点代码
if(store.getters.permissionList.length === 0){
store.dispatch('user/GetPermissionList').then(res=>{
router.addRoutes(store.getters.permissionList)
const redirect = decodeURIComponent(from.query.redirect || to.path)
if (to.path === redirect) {
next({ ...to, replace: true })
} else {
// 跳转到目的路由
next({ path: redirect })
}
})
}else{
next()
}
//重点代码 重点代码 重点代码 到此结束
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next();
} else {
next(`/login`);
NProgress.done();
}
}
});
router.afterEach(() => {
// finish progress bar
NProgress.done();
});
7、layout/components/Sidebar/index.vue
layout/components/Sidebar/index.vue
<template>
<div :class="{ 'has-logo': showLogo }">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:unique-opened="false"
:active-text-color="variables.menuActiveText"
:collapse-transition="false"
mode="vertical"
>
<sidebar-item
v-for="route in routes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
</el-scrollbar>
</div>
</template>
<script>
import { mapGetters, mapState } from "vuex";
import Logo from "./Logo";
import SidebarItem from "./SidebarItem";
import variables from "@/styles/variables.scss";
export default {
components: { SidebarItem, Logo },
computed: {
...mapGetters([
"sidebar",
// 'routes'
]),
// 获取筛选过后的路由对象
routes() {
return this.$store.state.user.permissionList;//重点这个,获取处理好的路由,展示在左侧菜单里
},
activeMenu() {
const route = this.$route;
const { meta, path } = route;
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu;
}
return path;
},
showLogo() {
return this.$store.state.settings.sidebarLogo;
},
variables() {
return variables;
},
isCollapse() {
return !this.sidebar.opened;
},
},
mounted() {
// console.log(this.routes);
},
};
</script>
8、在过程中出现的一些问题
1、src/permission.js不加store.getters.permissionList.length === 0判断的话,会一直死循环下面的操作(就是一直请求接口),加判断第二次执行就会到else里
2、store/modules/user.js里,因为我后端有可能返回只有一级菜单,没添加二级菜单即item没有children这个字段,不加item.children判断,就会一直提示
下面的问题
3、store/modules/user.js里,之前用的是component: () => import(url),虽然没报错,但是点击左侧菜单一直没反应,后面查了下,说是不能用import,后来改成component: (resolve) => require([@/views/${item.path}/${i.path}
], resolve)
ps:layout/components/Sidebar/index.vue左侧菜单组件,这个看每个人项目用的组件吧
更多推荐
已为社区贡献7条内容
所有评论(0)