vue admin template最详细的动态菜单路由权限改造+按钮权限

您所在的位置:网站首页 花裤衩头像 vue admin template最详细的动态菜单路由权限改造+按钮权限

vue admin template最详细的动态菜单路由权限改造+按钮权限

2023-10-23 06:29| 来源: 网络整理| 查看: 265

写在最前:

我站在巨人的肩膀上,总结并分享了如何改造花裤衩大佬vue admin template后台模板的动态菜单路由以及权限管理,文中有我mock的后台接口,能够模拟正式环境登陆退出,希望对你有帮助。

第一步:git命令拉取代码 git clone https://github.com/PanJiaChen/vue-admin-template.git 第二步:剔除烦人的eslint及删除多余路由 //vue.config.js文件 修改第30行 lintOnSave: false // router目录下的index.js删除不要的路由(我只留了下面两个) export const constantRoutes = [ { path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/', component: Layout, redirect: '/dashboard', children: [{ path: 'dashboard', name: 'Dashboard', component: () => import('@/views/dashboard/index'), meta: { title: 'Dashboard', icon: 'dashboard' } }] } ]

执行npm i下载依赖自动运行: 可以看到左侧菜单栏只剩dashboard一个菜单

0846e5570947eb9b391e88e0e438cd6.png

第三步:配置跨域 // vue.config.js文件在第39行删除before: require('./mock/mock-server.js') //加入下列代码 proxy: { '/api': { target: '',//****这里写上后端提供的基础地址(文末有我的接口地址) ***** // ws: true, //是否允许websocket // secure: false, changeOrigin: true, pathRewrite: {'^/api': ''} } }, 第四步:修改生产和开发环境 //文件.env.development修改 VUE_APP_BASE_API = '/api' //文件.env.production修改 VUE_APP_BASE_API = '/api' 第五步:修改登录接口和获取用户信息接口 export function login(obj) { return request({ url: '/user/login', // url = base url + request url method: 'post', params: obj }) } export function getInfo(token) { return request({ url: '/user/getUserInfoByToken?token=' + token, method: 'get' }) } 第六步:修改actions里面的login接口地址,根据字段正确存储token // store/modules/user.js const getDefaultState = () => { return { token: getToken(), name: '', avatar: '', roles: [], // 角色权限控制按钮显示 menus: [] // 菜单权限 } } const mutations = { RESET_STATE: (state) => { Object.assign(state, getDefaultState()) }, SET_TOKEN: (state, token) => { state.token = token }, SET_NAME: (state, name) => { state.name = name }, SET_AVATAR: (state, avatar) => { state.avatar = avatar }, SET_ROLES: (state, roles) => { state.roles = roles // 角色权限 }, SET_MENUS: (state, menus) => { state.menus = menus // 菜单权限 } } const actions = { // 登录 login({ commit }, userInfo) { const { username, password } = userInfo return new Promise((resolve, reject) => { login({ username: username.trim(), password: password }).then(response => { const { token } = response.data.data.data commit('SET_TOKEN', token) // vuex存储token setToken(token) // cookie存储token resolve() }).catch(error => { reject(error) }) }) }, // 获取用户信息 getInfo({ commit, state }) { return new Promise((resolve, reject) => { getInfo(state.token).then(response => { const { data } = response.data.data if (!data) { return reject('Verification failed, please Login again.') } const { name, avatar, roles, menus } = data /** * 获取异步路由后加入404路由能解决刷新后【丢失路由跳转404页面】问题 (因为异步获取路由优先级比静态路由表低,导致404路由在异步添加的路由之前) */ menus.push({ 'path': '/404', 'component': '404', 'hide': 'true' }, { 'path': '*', 'redirect': '/404', 'hidden': 'true' }) commit('SET_NAME', name) commit('SET_AVATAR', avatar) commit('SET_ROLES', roles) // 角色权限 commit('SET_MENUS', menus) // 菜单权限 resolve(data) }).catch(error => { reject(error) }) }) }, // 登出 logout({ commit, state }) { return new Promise((resolve, reject) => { // 如果后端有退出接口写在下面即可,这里直接退出也没问题 removeToken() // 必须先移除token resetRouter() commit('RESET_STATE') resolve() }) }, 第七步:修改getters.js存储信息 // store/getters.js const getters = { sidebar: state => state.app.sidebar, device: state => state.app.device, token: state => state.user.token, avatar: state => state.user.avatar, name: state => state.user.name, menus: state => state.user.menus, // 菜单权限 roles: state => state.user.roles // 角色权限控制按钮 } export default getters 第八步:修改request.js // utils/request.js import router from '@/router' const BASEURL = process.env.NODE_ENV === 'production' ? '' : '/api' // 创建axios 赋给变量service const service = axios.create({ baseURL: BASEURL, // url = base url + request url // withCredentials: true, // send cookies when cross-domain requests timeout: 5000 // 5s请求超时 }) // 请求拦截器 service.interceptors.request.use( config => { if (store.getters.token) { config.headers['Authorization'] = 'Bearer ' + getToken() // 改成后端要求的token键值 } return config }, error => { console.log(error) return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response => { const message = response.data.data.message const code = response.data.data.code if (code !== 200) { // 改成后端响应成功的状态码 switch (code) { // 响应错误判断 case 401: if (router.currentRoute.name === 'login') { return Promise.reject(new Error(message)) } else { Message({ message: '您没有权限访问该资源', type: 'error' }) } break case 403: Message({ message: message, type: 'error' }) break case 500: Message({ message: '服务异常,请联系管理员', type: 'error' }) break default: Message({ message: message, type: 'error' }) } // store.dispatch('user/resetToken').then(() => { // location.reload() // 重复登录的情况 // }) return Promise.reject(new Error(message || 'Error')) } else { return response } }, error => { console.log('err' + error) // 响应错误 Message({ message: error.message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) } ) 第九步:新增导入组件的方法

// 在router目录下新建_import_development.js文件

// 开发环境导入组件 module.exports = file => require('@/views/' + file + '.vue').default // vue-loader at least v13.0.0+

// 在router目录下新建_import_proudction.js文件

// 生产环境导入组件 module.exports = file => () => import('@/views/' + file + '.vue') 第十步:修改permission.js import Layout from '@/layout' // 引入Layout const _import = require('./router/_import_' + process.env.NODE_ENV) // 引入获取组件的方法 // 路由拦截器 router.beforeEach(async(to, from, next) => { // 进度条加载 NProgress.start() // 获取page标题 document.title = getPageTitle(to.meta.title) // 获取token决定用户是否可以登录 const hasToken = getToken() if (hasToken) { if (to.path === '/login') { // 如果已登录,则重定向到主页 next({ path: '/' }) NProgress.done() } else { const hasGetUserInfo = store.getters.name if (hasGetUserInfo) { next() } else { try { // 每次刷新都会执行try获取用户信息,所以getInfo必须要有,后端不提供怎么办?揍他 await store.dispatch('user/getInfo') // **在这里做动态路由** if (store.getters.menus.length < 1) { global.antRouter = [] next() } const menus = filterAsyncRouter(store.getters.menus) // 过滤路由 router.addRoutes(menus) // 动态添加路由 global.antRouter = menus // 将路由数据传递给全局变量,做侧边栏菜单渲染工作 next({ ...to, replace: true }) } catch (error) { // 移除token去登录页 await store.dispatch('user/resetToken') Message.error(error || 'Has Error') next(`/login?redirect=${to.path}`) NProgress.done() } } } } else { /* 没有token */ if (whiteList.indexOf(to.path) !== -1) { // 如果该路由在白名单内, 放行 next() } else { // 不在白名单内不允许通过重定向到登录页 next(`/login?redirect=${to.path}`) NProgress.done() } } }) // 遍历后台传来的路由字符串,转换为组件对象 function filterAsyncRouter(asyncRouterMap) { const accessedRouters = asyncRouterMap.filter(route => { if (route.component) { if (route.component === 'Layout') { // Layout组件特殊处理 route.component = Layout } else { route.component = _import(route.component) // 导入组件 } } if (route.children && route.children.length) { route.children = filterAsyncRouter(route.children) } return true }) return accessedRouters } 最后一步:替换路由 //layout目录下components下sidebar下index.vue routes() { return this.$router.options.routes.concat(global.antRouter) // 新路由连接 },

控制台执行npm run dev: 可以看到左侧菜单栏已经动态添加了菜单

600906f88404312cde38091e4f073ea.png

写在最后:

无偿提供接口地址:

基础地址: https://www.fastmock.site/mock/48611e3434449d37f501fc4a60f141a8/mock 登录api: /user/login 根据token获取用户信息api(包含姓名,头像,菜单权限,角色):/user/getUserInfoByToken username: admin/editor password: 123456 按钮权限控制(如果不需要做按钮权限这part不用看):

还是得看花裤衩大佬的原文;只有见过大佬写的code,才明白什么叫细到极致~

第一步:站在巨人的肩膀看世界

去花裤衩大佬githubsrc文件下找到directive文件并复制粘贴到自己的src文件下,保留permission文件,删除其他。

bd90292d317c31c66e0eab1b7adbfa3.png

第二步:测试按钮权限 //在dashboard/index.vue下新增两个测试按钮 admin editor // 当然你也可以为了方便使用,将它注册到全局 import permission from '@/directive/permission/index.js' // 权限判断指令 export default { name: 'Dashboard', computed: { ...mapGetters([ 'name' ]) }, directives: { permission } // 自定义指令 }

保存后看到登录admin账户时两个按钮都能显示,当登录editor账户时只能显示editor按钮。使用上面mock地址可以实现动态添加路由的需求,希望能够帮助到掘友萌。 image.png

gitee: gitee.com/unicorn-zbf…

master分支预览地址:unicorn-zbf.gitee.io/vue-admin-t…

master分支采用本地json文件模拟的数据;unicornZ分支使用fast mock平台模拟真实的接口请求,项目需要在本地运行预览。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3