精华内容
下载资源
问答
  • vue权限管理

    2017-12-25 15:32:41
    vue权限管理,vue实战,vue学习,vue页面权限控制,vue项目实战
  • 后台管理系统一般都会有权限模块,用来控制用户能访问哪些页面和哪些数据接口。大多数管理系统的页面都长这样。 左边为菜单,分为两级,右边为图表显示区域,有增删改查的按钮。 表的结构 SET NAMES utf8mb4; SET ...
  • 后端返回用户权限,前端根据用户权限处理得到左侧菜单;所有路由在前端定义好,根据后端返回的用户权限筛选出需要挂载的路由,然后使用 addRoutes 动态挂载路由。 二、实现要点 (1)路由定义,分为初始路由和动态...
  • Vue权限管理

    千次阅读 2018-11-28 12:17:49
    Vue权限管理前言我们首先去定义一个路由表下面就是我们的各个组件的定义了 前言 博主最近刚刚上手一个图书管理系统的小Demo,在编写的过程中遇到了许多的问题,尤其是对于我这样的新手来说权限管理是一个难点,...

    前言

    博主最近刚刚上手一个图书管理系统的小Demo,在编写的过程中遇到了许多的问题,尤其是对于我这样的新手来说权限管理是一个难点,本身对Vue就不是很理解,所以查阅了许多的文章后才有一点点思路,所以在这里记录下来,也希望其他的小白也能够少走一些弯路。

    我大概的思路是这样的

    首先,我们我们有两种用户,一个admin(管理员),一个user(普通用户),他们所看到的界面都是不一样的
    第一步:我们将一些公用的组件提取出来制作成一个静态路由表,其他需要有权限的展示的组件我们把他制作成动态的路由表
    第二步:当我们登录的时候获取用户的身份,然后我们遍历动态路由表,动态的生成路由表

    是不是这样就感觉简单很多了呢,下面我们来建立一个一个简单的demo吧!先看一下我的结构图


    error------错误组件(当路径错误时显示)
    login------登录组件
    home------普通用户界面
    home--------管理员界面

    我们首先去定义一个路由表

    import Vue from 'vue'
    import Router from 'vue-router'
    
    Vue.use(Router)
    
    const router = new Router({
      routes: [
        {
          path: '/',
          name: 'login',
          component: (resolve) => require(['../components/login.vue'], resolve)
        },
        {
          path: '/login',
          name: 'login',
          component: (resolve) => require(['../components/login.vue'], resolve)
        },
        {
          path: '/404',
          name: 'err',
          component: (resolve) => require(['../components/error.vue'], resolve)
        }
      ]
    })
    export default router;//我们把静态的路由表导出去
    
    //我们使用meta标签来定义里面的权限
    export const dynamicRouter = [
      {
        path: '/home',
        name: 'home',
        meta: {
          roles:['user']//表示只有user的权限才能够访问这个界面
        },
        component: (resolve) => require(['../components/home.vue'], resolve)
      },
      {
        path: '/home',
        name: 'home2',
        meta: {
          roles:['admin']
        },
        component: (resolve) => require(['../components/home2.vue'], resolve)
      },
    ];
    
    

    下面就是我们的各个组件的定义了

    在这里插入图片描述

    最后就是我们的login组件了

    <template>
      <div>
        <form>
          账户:<input type="text" :model="user">
          密码:<input type="text" :model="pass">
          <button @click="updateR">修改权限</button>
          <input type="button" value="登录" @click="Login">
        </form>
      </div>
    </template>
    
    <script>
      import {router,dynamicRouter} from '../router/index' //获取路由配置文件里的两个路由表
      export default {
        name: "login",
        data(){
          return{
            user:'',
            pass:'',
            roles:'user'
          }
        },
        methods:{
          Login(){
            let dR = new Array(); //创建一个数组用来存储符合权限的路由
            for (let i=0;i<dynamicRouter.length;i++){ //第一层循环遍历动态路由表的每一个路由
              for (let j=0;j<dynamicRouter[i].meta.roles.length;j++){ //第二次循环遍历每一个路由里的roles设置的权限并和当前登录账号的权限比较
                if (dynamicRouter[i].meta.roles[j] == this.roles){//此处因为没有后台我就把权限写死在data里面了
                  dR.push(dynamicRouter[i]); //符合条件的路由信息就放进数组里
                }
              }
            }
            console.log(dR);
            this.$router.addRoutes(dR.concat([{ //动态添加符合条件的路由
              path: '*',
              redirect: '/404' //所有不匹配路径(*)都重定向到404
            }]));
            this.$router.push({path:'/home'}); //登录验证后跳转到主页home页面
          }
        },
        updateR(){
          if (this.roles === 'admin'){
            this.roles === 'user'
          } else{
            this.roles === 'admin'
          }
        }
      }
    </script>
    
    <style scoped>
    
    </style>
    
    
    展开全文
  • vue 权限管理

    万次阅读 2018-10-31 21:33:43
    首先需要了解的就是纯前端是无法实现权限管理的,vue权限管理主要是基于路由实现的,当然这样的权限管理完全可以被绕过去的,而之所以在前端这么做,更多是为了用户体验,节省不必要的加载开销等等。 用vue来实现...

    今天来说说权限管理,因为网上已经有很多关于这方面的很多内容,博主也是借鉴了网上的一些逻辑来写的,主要也是说说前端实现权限管理的一个思路,也是作为自己日后面对这样的问题的一个解决方案。
    首先需要了解的就是纯前端是无法实现权限管理的,vue的权限管理主要是基于路由实现的,当然这样的权限管理完全可以被绕过去的,而之所以在前端这么做,更多是为了用户体验,节省不必要的加载开销等等。
    用vue来实现权限管理,主要就是基于这个新的vue的api,addRoutes的方法来实现的,当然权限管理也分为几个方面,博主今天主要就是说的页面级的权限,思路就是利用刚刚说的api来动态加载路由,我们将路由分为两个部分,一个是公共部分,即所有人都能看到的路由,另外一部分则是动态加载部分,这里也简单的将代码贴出来,大家参考一下就可以,网上的代码也是有很多

    import Vue from 'vue'
    import Router from 'vue-router'
    
    Vue.use(Router)
    
    export const constRouterMap = [
      {
        path: '/login',
        name: 'Login',
        meta: {
          title: '登录',
          keepAlive: false
        },
        component: () => import('@/views/Login.vue')
      },
      {
        path: '/layout',
        component: () => import('@/views/Layout.vue'),
        // redirect: '/login',
        // redirect: '/index',
        children: [
          {
            path: '/index',
            name: 'index',
            meta: {
              title: '首页',
              keepAlive: false
            },
            component: () => import('@/views/HomePage.vue')
          },
          {
            path: '/about',
            name: 'about',
            meta: {
              title: '开发备忘',
              keepAlive: false
            },
            component: () => import('@/views/About.vue')
          },
          {
            path: '/author',
            name: 'author',
            meta: {
              title: '关于作者',
              keepAlive: false
            },
            component: () => import('@/views/AboutAuthor.vue')
          },
          {
            path: '/weather',
            name: 'wether-fore',
            meta: {
              title: '天气预报',
              keepAlive: true
            },
            component: () => import('@/views/WeatherFore.vue')
          },
          {
            path: '/dynamic',
            name: 'dynamic-table',
            meta: {
              title: '动态表格',
              keepAlive: false
            },
            component: () => import('@/views/DynamicTable.vue')
          },
          {
            path: '/editable',
            name: 'editable',
            meta: {
              title: '可编辑表格',
              keepAlive: true
            },
            component: () => import('@/views/TableGrid.vue')
          }
        ]
      }    
    ]
    
    export const asyncRouterMap = [
      {
        path: '/layout',
        component: () => import('@/views/Layout.vue'),
        children: [
          {
            path: '/access',
            name: 'access',
            component: () => import('@/views/AccessTest.vue'),
            meta: {
              title: '权限控制',
              roles: ['admin'],
              keepAlive: false
            }
          },
          {
            path: '/cube',
            name: 'cube',
            component: () => import('@/views/MagicCube.vue'),
            meta: {
              title: '魔幻立方',
              roles: ['admin'],
              keepAlive: false
            }
          }
        ]
      },
      {
        path: '/error',
        component: () => import('@/views/NotFound.vue')
      },
      {
        path: '*', redirect: '/error', hidden: true
      }
    ]
    
    export default new Router({
      mode: 'history',
      routes: constRouterMap
    })
    
    

    看到这个代码应该知道,我们首先是先加载公共路由部分,然后再根据vue-router提供的路由导航钩子,当路由进行跳转的时候,向服务器请求用户的角色权限

    import router from './router'
    import store from '@/store/index'
    import { Message } from 'element-ui'
    const whiteList = ['/login']
    
    router.beforeEach((to, from, next) => {
      if (sessionStorage.getItem('token')) {
        if (to.path === '/') {
          next('/index')
        } else {
          if (store.getters.roles.length === 0) {
            const roles = sessionStorage.getItem('roles')
            store.dispatch('permission/generateRoute', { roles })
              .then(() => {
                console.log(store.getters.addRoutes[0].children.length)
                router.addRoutes(store.getters.addRoutes)
                next({ ...to, replace: true })
              })
              .catch(err => {
                Message.error({ message: err })
              })
          } else {
            next()
          }
        }
      } else {
        if (whiteList.indexOf(to.path) !== -1) {
          next()
        } else {
          next('/login')
        }
      }
    })
    
    

    这里后台博主用了thinkjs的框架,博主现在还在整理,后续整理好,也会上传到github上面。在这个导航钩子上,我们利用了vuex来存储角色信息,每次登陆会进行判断,如果没有角色信息,就会去触发action来请求服务器,服务器返回角色字段后,我们将他存在store里面。另外根据上面的路由,我们将页面权限需要的角色放在路由的meta字段中,所以当我们拿到角色信息后,会和动态路由中的meta进行一一对比,需要注意的是,当路由有嵌套的children属性时,我们还需要将children里面的路由拿出来一一进行递归对比,这样如果服务器的角色信息,符合路由需要的权限,我们就将这个路由记录下来,最后组成需要添加的路由,利用addRoutes来形成最终的路由。

    generateRoute ({ commit }, data) {
          return new Promise((resolve, reject) => {
            const roles = []
            roles.push(data.roles)
            let accessRouters
            console.log(roles.indexOf('admin') >= 0)
            if (roles.indexOf('admin') >= 0) {
              accessRouters = asyncRouterMap
            } else {
              accessRouters = filterAsyncRouter(asyncRouterMap, roles)
            }
            // console.log(accessRouters)
            commit('SET_ROUTERS', accessRouters)
            commit('SET_ROLES', roles)
            resolve()
          })
        },
    
    function hasPermission (roles, route) {
      if (route.meta && route.meta.roles) {
        return roles.some(role => route.meta.roles.indexOf(role) >= 0)
      } else {
        return true
      }
    }
    
    function filterAsyncRouter (asyncRouter, roles) {
      const accessRouters = asyncRouter.filter(route => {
        if (hasPermission(roles, route)) {
          if (route.children && route.children.length) {
            route.children = filterAsyncRouter(route.children, roles)
          }
          return true
        }
        return false
      })
      // console.log(accessRouters)
      return accessRouters
    }
    

    结合前面的导航钩子就形成了最终的路由,当用户试图访问不存在的路由的时候,则会返回404页面,另外也简单的说下按钮及页面中视图显示的权限,其实也是利用了vue的自定义指令,我们给自定义指令传入需要的角色权限数组,然后和存储在store中的权限作对比,如果没有权限,则移除当前的DOM元素

    import store from '@/store/index'
    
    const permission = {
      inserted (el, binding, vnode) {
        const { value } = binding
        const roles = store.getters && store.getters.roles
        if (value && value instanceof Array && value.length > 0) {
          const permissionRoles = value
          const hasPermission = roles.some(role => {
            return permissionRoles.includes(role)
          })
          if (!hasPermission) {
            el.parentNode && el.parentNode.removeChild(el)
          }
        } else {
          throw new Error('roles is must be Array!')
        }
      }
    }
    export default permission
    
    

    这些代码都是博主自己写的项目中的片段,完整的代码,大家有兴趣可以去GitHub上面查看。之前写的权限没有问题,但是重新整理的时候,突然发现权限需要刷新的时候才会生效,技术有限,所以要是有同学发现代码有什么问题,可以随时告诉博主,当然博主也是会继续踩坑下去,解决这个问题。

    展开全文
  • 主要介绍了浅谈vue后台管理系统权限控制思考与实践,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 为了帮助企业方便快捷地管理商品信息的后台数据,开发了一个企业权限管理系统。该系统包括用户管理、角色管理、资源权限管理、基本数据管理模块;用户管理模块基于Spring Security的用户登录、退出操作,以及用户查询...
  • 主要介绍了vue实现后台管理权限系统及顶栏三级菜单显示功能,本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 包含了成熟的后台管理功能和手机端h5内容站点系统 部门管理 用户管理 ...cms内容管理,配合flash-vue-h5提供了手机端内容展示系统 消息管理:配置消息模板,发送短信,邮件消息 基于idea插件的代码生成
  • 该项目主要介绍了权限管理系统的用户管理功能、角色管理功能、角色资源功能、角色权限功能、日志管理、回收站、都能实现用户的增删查改
  • 前后端分离的权限管理综合demo,包含技术点:springboot、mybatis(使用tkmapper)、shiro、vue、bootstrap、axios、sweetalert、webpack
  • 包括图形展示、权限管理、用户管理等功能。【后端技术】技术说明Spring?Boot2MVC框架?开发的一站式解决方案Spring?Security5?认证和授权框架MyBatisPlus3.3.1?基于?MyBatis?框架的快速研发框架MyBatisCode工具生成?...
  • vue权限管理系统

    千次阅读 2019-01-17 19:54:23
    vue权限系统 后台管理系统一般都会有权限模块,用来控制用户能访问哪些页面和哪些数据接口。大多数管理系统的页面都长这样。 左边为菜单,分为两级,右边为图表显示区域,有增删改查的按钮。 表的结构 SET NAMES ...

    vue权限系统

    后台管理系统一般都会有权限模块,用来控制用户能访问哪些页面和哪些数据接口。大多数管理系统的页面都长这样。

    image

    左边为菜单,分为两级,右边为图表显示区域,有增删改查的按钮。

    表的结构

    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for t_auth_rule
    -- ----------------------------
    DROP TABLE IF EXISTS `t_auth_rule`;
    CREATE TABLE `t_auth_rule` (
      `id_pk` bigint(20) NOT NULL AUTO_INCREMENT,
      `auth_id` varchar(128) NOT NULL COMMENT '权限Id',
      `pauth_id` varchar(128) DEFAULT NULL COMMENT '父级Id',
      `auth_name` varchar(255) NOT NULL COMMENT '权限名称',
      `auth_icon` varchar(255) NOT NULL COMMENT '权限图标',
      `auth_type` smallint(6) NOT NULL COMMENT '权限类型,BIT表示其属性\r\n            0x00表示可显示的菜单权限节点;\r\n            0x01表示普通节点',
      `auth_condition` text COMMENT '条件',
      `remark` varchar(255) DEFAULT NULL COMMENT '备注',
      `is_menu` smallint(255) DEFAULT '0' COMMENT '是否为菜单,0表示非,1表示是',
      `weight` int(11) NOT NULL DEFAULT '0' COMMENT '权重',
      `rule` varchar(256) DEFAULT NULL COMMENT '规则路径主要对应菜单或方法的路径名称',
      `cr_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
      `up_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
      PRIMARY KEY (`id_pk`),
      UNIQUE KEY `AK_auth_id` (`auth_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=264 DEFAULT CHARSET=utf8 COMMENT='权限规则表,记录权限相关的信息,权限以父子关系存在,菜单是权限的一种。';
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for t_role_auth
    -- ----------------------------
    DROP TABLE IF EXISTS `t_role_auth`;
    CREATE TABLE `t_role_auth` (
      `id_pk` bigint(20) NOT NULL AUTO_INCREMENT,
      `role_id_fk` varchar(32) DEFAULT NULL COMMENT '角色id',
      `auth_id_fk` varchar(128) DEFAULT NULL COMMENT '权限id',
      `aa` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`id_pk`)
    ) ENGINE=InnoDB AUTO_INCREMENT=77 DEFAULT CHARSET=utf8 COMMENT='角色与权限的关系表';
    
    SET FOREIGN_KEY_CHECKS = 1;

    稍微解释一下表结构,t_auth_rule 表用来存储对应的权限菜单,一般来说,菜单分为一级和二级菜单,rule字段对应前端的路由规则;而按钮为第三级,rule对应的是接口url地址。
    t_role_auth 表为角色权限关联表,一个角色拥有哪些权限是通过这张表查出来的。当然还有一个role表,还有一个账号表,账号表里有一个role的外键。
    这样就是一个账号 --> 角色 --> 权限的关系。

    对于菜单的权限,通过路由表匹配

    addRouters(menuMap) {
        let routerArr = [];
        for (let j = 0; j < routerList.length; j++) {
            let obj;
            if (menuMap['AuthRule::' + routerList[j].path]) {     // 找到一级菜单
                obj = {
                    path: routerList[j].path,
                    component: routerList[j].component,
                    redirect: routerList[j].redirect,
                    name: routerList[j].name,
                    meta: routerList[j].meta,
                    children: []
                };
    
                if (routerList[j].children.length) {
                    for (let k = 0; k < routerList[j].children.length; k++) {
                        let _fullpath = routerList[j].children[k].path
                        if (routerList[j].children[k].meta) {
                            _fullpath = routerList[j].children[k].meta.parentPath + '/' + _fullpath 
                        }
                        if (menuMap['AuthRule::' + _fullpath]) {  // 找到二级菜单
                            obj.children.push(routerList[j].children[k]);
                        }
                    }
                }
            }
            if (obj) {
                routerArr.push(obj);
                this.$router.options.routes.push(obj);
            }
        }
    
        storage.set("routerArr", routerArr);
        this.$router.addRoutes(routerArr);
        this.$router.push({ path: "/" });
    },

    menuMap为登录时获取的权限菜单,是一个对象; routerList为前端定义的路由表;遍历routerList,如果routerList的key在menuMap里能找到的话,就表示该路由存在。最后生成一个过滤后的路由表,用vue提供的addRoutes方法动态添加到路由中,并把过滤后的路由表存到本地。

    const menuMap = {
        '/dashboard': {path: '/dashboard', name: '首页'}
    }
    const routerList = [
        {path: '/dashboard', name: '首页', component: ..}
    ]

    在页面刷新的时候,从本地获取路由表,添加到路由表中,代码如下,constRouterArr为基础路由表,比如登录,404等

    注意这一步有个问题,由于我写的storage库用了JSON.stringify,把路由表中的component(实际为一个函数)丢失了,所以在从本地获取路由的时候,还要重新生成一个新的路由表,重新把component加上去,即把上面的addrouters重新执行一遍

    ~~const routerList = storage.get('routerArr')
    const routerArr = constRouterArr.concat(routerList);~~

    export function getRouterList() {
      if (!sessionStorage.getItem('user_info')) {
        storage.set('menuTree', ''); // 清空菜单权限数据
        storage.set('routerArr', ''); 
      }
        let menuMap = storage.get('menuTree') ? storage.get('menuTree') : [];
        
        let routerArr = [];
        for (let j = 0; j < routerList.length; j++) {
            let obj;
            if (menuMap['AuthRule::' + routerList[j].path]) {  // 找到一级菜单
                // console.log(routerList[j].component)
                obj = {
                    path: routerList[j].path,
                    component: routerList[j].component,  // 从本地获取的数据被丢失了,需要重新组装
                    redirect: routerList[j].redirect,
                    name: routerList[j].name,
                    meta: routerList[j].meta,
                    children: []
                };
                // console.log(routerList[j].children, routerList[j])
                if (routerList[j].children && routerList[j].children.length) {
                    for (let k = 0; k < routerList[j].children.length; k++) {
                        let _fullpath = routerList[j].children[k].path
                        if (routerList[j].children[k].meta) {
                            _fullpath = routerList[j].children[k].meta.parentPath + '/' + _fullpath 
                        }
                        if (menuMap['AuthRule::' + _fullpath]) {  // 找到二级菜单
                            obj.children.push(routerList[j].children[k]);
                        }
                    }
                }
            }
            if (obj) {
                routerArr.push(obj);
            }
        }
        
      return routerArr; 
    }

    对于按钮的权限

    if (res.data.auth_rule_map) {
        let obj = {}
        Object.keys(res.data.auth_rule_map).forEach(i => {
          // 将所有的按钮放到一个obj里 key 为接口地址  
          if (res.data.auth_rule_map[i].is_menu === 0) {  // 如果是按钮
            obj[res.data.auth_rule_map[i].rule] = 1
          }             
        })
        storage.set("btnList", obj);
        storage.set("menuTree", res.data.auth_rule_map);
    }

    auth_rule_map为接口返回权限map,把按钮的权限过滤出来存到本地
    将map添加到每个路由组件的data里,(这里有一个问题,怎么判断一个组件是否是路由组件),目前想到的是通过组件name来判断,把所有的路由组件放到一个数组里做判断。

    在组件内部的按钮上加上v-if,如果this.uri__里的uri在uriMap里存在就显示。
    也可以通过方法来判断,如下面的__isBtnShow,不仅可以控制按钮的显示隐藏,还可以控制其样式,比如颜色等,更加灵活,推荐使用方法来控制

    uri = {
        ADD_MEMBER: '/api/add_member'
    }
    
    export default function install (Vue) {
      const uriMap = storage.get('btnList')
      //uriMap['/admin/api/auth_rule/update_auth_rule.action'] = 1
      Vue.mixin({
        created() {
          const arr = ['MemberManage', 'PayManage', '...']
          if (arr.indexOf(this.$options.name) !== -1) {
            this.dataUri__ = uriMap
            this.uri__ = uri  
          }
        },
        data() {
          return {
            dataUri__: {}
          }
        },
        methods: {
          __isBtnShow(uri) {
            return uriMap[uri] ? 'display: inline-block' : 'display: none'
          },
        }
      })
    }
    
    <Button v-if="dataUri__[uri__.ADD_MEMBER]">添加会员</Button>
    
    // 通过方法来控制,更加灵活
    <Button :style="__isBtnShow(uri__.ADD_MEMBER)">添加会员</Button>

    登出的问题

    登出后要清空缓存,routerArr,btnList 等。
    由于之前登录,调用addRouter把权限上个账号的路由表加进去了,所以登出后要location.reload()一次,重新实例化路由表,去掉动态添加的路由,只保留基础路由。
    location.reload()体验不是太好,但是vue-router没有提供动态删除路由的api,比如 deleteRouter。

    同时登两个账号,导致刷新页面的时候,前者页面的本地缓存被覆盖,权限菜单等数据发生变化,路由表也发生变化

    能想到的解决方法是存一个loginIndex 来表示登录账号的个数,比如第一次登录的时候存一个loginIndex=0, 后面存数据的时候都把这个参数带上;后面登多个账号的时候个loginIndex++,这样localStorage的key就是一个动态的(这样还是不行)
    最简单的方法是存到localStorage里,只有登出才会清空缓存,只能登一个账号。

    展开全文
  • 1.通过权限管理调用后台的数据,在登录用户之后动态加载路由与菜单 并通过vuex 将路由信息及菜单信息保存到stroe中去 export default { state: { perms: [], // 用户权限标识集合 }, getters: { }, mutations: { ...

    1.通过权限管理调用后台的数据,在登录用户之后动态加载路由与菜单 并通过vuex 将路由信息及菜单信息保存到stroe中去

    export default {
        state: {
            perms: [],  // 用户权限标识集合
        },
        getters: {
       
        },
        mutations: {
            setPerms(state, perms){  // 用户权限标识集合
                state.perms = perms;
            }
        },
        actions: {
        }
    }
     api.user.findPermissions({'username': userName}).then(res => {
          // 保存用户权限标识集合
          // console.info(JSON.stringify(res.data))
          store.commit('setPerms', res.data)
        })

    后台数据表

    回传数据

    [
      {
        "menuId": 18,
        "parentId": 5,
        "menuName": "修改菜单",
        "path": "",
        "component": "",
        "perms": "menu:edit",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:08:02.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 19,
        "parentId": 5,
        "menuName": "删除菜单",
        "path": "",
        "component": "",
        "perms": "menu:delete",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:08:02.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 21,
        "parentId": 6,
        "menuName": "修改部门",
        "path": "",
        "component": "",
        "perms": "dept:edit",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:09:24.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 65,
        "parentId": 64,
        "menuName": "新增字典",
        "path": "",
        "component": "",
        "perms": "dict:add",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2018-01-18T11:10:08.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 14,
        "parentId": 4,
        "menuName": "新增角色",
        "path": "",
        "component": "",
        "perms": "role:add",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:06:38.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 67,
        "parentId": 64,
        "menuName": "删除字典",
        "path": "",
        "component": "",
        "perms": "dict:delete",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2018-01-18T11:10:47.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 22,
        "parentId": 6,
        "menuName": "删除部门",
        "path": "",
        "component": "",
        "perms": "dept:delete",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:09:24.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 17,
        "parentId": 5,
        "menuName": "新增菜单",
        "path": "",
        "component": "",
        "perms": "menu:add",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:08:02.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 13,
        "parentId": 3,
        "menuName": "删除用户",
        "path": "",
        "component": "",
        "perms": "user:delete",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:04:58.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 20,
        "parentId": 6,
        "menuName": "新增部门",
        "path": "",
        "component": "",
        "perms": "dept:add",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:09:24.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 15,
        "parentId": 4,
        "menuName": "修改角色",
        "path": "",
        "component": "",
        "perms": "role:edit",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:06:38.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 66,
        "parentId": 64,
        "menuName": "修改字典",
        "path": "",
        "component": "",
        "perms": "dict:edit",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2018-01-18T11:10:27.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 16,
        "parentId": 4,
        "menuName": "删除角色",
        "path": "",
        "component": "",
        "perms": "role:delete",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:06:38.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 11,
        "parentId": 3,
        "menuName": "新增用户",
        "path": "",
        "component": "",
        "perms": "user:add",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:02:58.000+0000",
        "modifyTime": null,
        "menuChild": null
      },
      {
        "menuId": 12,
        "parentId": 3,
        "menuName": "修改用户",
        "path": "",
        "component": "",
        "perms": "user:edit",
        "icon": null,
        "type": "1",
        "orderNum": null,
        "createTime": "2017-12-27T09:04:07.000+0000",
        "modifyTime": null,
        "menuChild": null
      }
    ]

     自定义一个带有权限的按钮

    <template>
      <el-button :size="size" :type="type" :icon="icon"
        :loading="loading" :disabled="!hasPerms(perms)" @click="handleClick">
        {{label}}
      </el-button>
    </template>
    
    <script>
    import { hasPermission } from '@/permission/permission.js'
    export default {
      name: 'SkyButton',
      props: {
        label: {  // 按钮显示文本
          type: String,
          default: 'Button'
        },
        icon: {  // 按钮显示图标
          type: String,
          default: ''
        },
        size: {  // 按钮尺寸
          type: String,
          default: 'mini'
        },
        type: {  // 按钮类型
          type: String,
          default: null
        },
        loading: {  // 按钮加载标识
          type: Boolean,
          default: false
        },
        disabled: {  // 按钮是否禁用
          type: Boolean,
          default: false
        },
        perms: {  // 按钮权限标识,外部使用者传入
          type: String,
          default: null
        }
      },
      data() {
        return {
        }
      },
      methods: {
        handleClick: function () {
          // 按钮操作处理函数
          this.$emit('click', {})
        },
        hasPerms: function (perms) {
          // 根据权限标识和外部指示状态进行权限判断
          return hasPermission(perms) & !this.disabled
        }
      },
      mounted() {
      }
    }
    </script>
    
    <style scoped>
    
    </style>
    

     编辑权限管理的js  通过按钮中呈现的 权限例 user:add 来匹配从后台调用的数据 返回菜单时候可点击调用

    import store from '@/store'
    
    /**
     * 判断用户是否拥有操作权限
     * 根据传入的权限标识,查看是否存在用户权限标识集合
     * @param perms
     */
    export function hasPermission(perms) {
      let hasPermission = false
      let permissions = store.state.user.perms
      for (let i = 0, len = permissions.length; i < len; i++) {
        if (permissions[i].perms=== perms||perms==='all:reload') {
          hasPermission = true;
          break
        }
      }
      // console.info(hasPermission)
      return hasPermission
    }
    
    
    

    最后在应用改路由的的页面中调用

    <template>
      <div class="myContainer">
        <!--工具栏-->
        <div class="toolbar">
          <el-form :inline="true" :model="filters" label-width="120px">
            <el-form-item label="角色名称">
              <el-input v-model="filters.name" placeholder="角色名" size="mini"></el-input>
            </el-form-item>
            <el-form-item label="角色名称">
              <el-input v-model="filters.name" placeholder="角色名" size="mini"></el-input>
            </el-form-item>
            <el-form-item>
              <sky-button icon="fa fa-search" :label="$t('action.search')" perms="role:view" type="primary"/>
            </el-form-item>
            <el-form-item>
              <sky-button icon="fa fa-search" label="重置" perms="all:reload" type="primary"/>
            </el-form-item>
          </el-form>
          <el-row :gutter="10" class="mb8" type="flex" justify="end">
            <el-col :span="1.5">
              <sky-button icon="el-icon-plus" @click="drawer = true" label="新增" perms="role:add" type="primary"
                          size="mini"/>
            </el-col>
            <el-col :span="1.5">
              <sky-button icon="el-icon-delete" label="批量删除" perms="role:delete" type="danger" size="mini"/>
            </el-col>
            <el-col :span="1.5">
              <sky-button icon="el-icon-upload2" label="导入" perms="role:import" type="danger" size="mini"/>
            </el-col>
            <el-col :span="1.5">
              <sky-button icon="el-icon-download" label="导出" perms="role:export" type="warning" size="mini"/>
            </el-col>
          </el-row>
        </div>
        <!--表格内容栏-->
        <div class="contentbar"></div>
        <sky-table :height="350" rowkey="name" permsEdit="role:edit" permsDelete="role:delete"
                   :data="pageResult" :columns="filterColumns"
                   @findPage="findPage" @handleEdit="handleEdit" @handleDelete="handleDelete">
        </sky-table>
        <el-drawer
          title="我是标题"
          :visible.sync="drawer"
          :with-header="false">
          <div class="demo-drawer__content">
            <el-form :model="dataForm">
              <el-form-item label="活动名称">
                <el-input v-model="dataForm.name" autocomplete="off"></el-input>
              </el-form-item>
              <el-form-item label="活动区域">
                <el-select v-model="dataForm.id" placeholder="请选择活动区域">
                  <el-option label="区域一" value="shanghai"></el-option>
                  <el-option label="区域二" value="beijing"></el-option>
                </el-select>
              </el-form-item>
            </el-form>
            <div class="demo-drawer__footer">
              <el-button @click="cancelForm">取 消</el-button>
              <el-button type="primary" @click="$refs.drawer.closeDrawer()" :loading="loading">{{ loading ? '提交中 ...' : '确定'
                }}
              </el-button>
            </div>
          </div>
        </el-drawer>
      </div>
    </template>
    
    <script>
      import SkyButton from "@/components/SkyButton/SkyButton.vue"
      import SkyTable from "@/components/SkyTable/SkyTable.vue"
    
      export default {
        name: "role",
        components: {
          SkyButton,
          SkyTable,
        },
        data() {
          return {
            drawer: false,
            size: 'small',
            filters: {
              name: ''
            },
            columns: [],
            filterColumns: [
              {prop: "id", label: "ID", minWidth: 50},
              {prop: "name", label: "用户名", minWidth: 120},
              {prop: "deptName", label: "机构", minWidth: 120},
              {prop: "roleNames", label: "角色", minWidth: 100},
              {prop: "email", label: "邮箱", minWidth: 120},
              {prop: "mobile", label: "手机", minWidth: 100},
              {prop: "status", label: "状态", minWidth: 70},
            ],
            loading: true,
            pageRequest: {pageNum: 1, pageSize: 10},
            pageResult: {
              content: [{
                id: '1',
                name: '王小虎2',
                deptName: '上海市普陀区金沙江路 1518 弄',
                roleNames: '上海市普陀区金沙江路 1518 弄',
                email: '上海市普陀区金沙江路 1518 弄',
                mobile: '上海市普陀区金沙江路 1518 弄',
                status: '上海市普陀区金沙江路 1518 弄',
              }, {
                id: '2',
                name: '王小虎3',
                deptName: '上海市普陀区金沙江路 1518 弄',
                roleNames: '上海市普陀区金沙江路 1518 弄',
                email: '上海市普陀区金沙江路 1518 弄',
                mobile: '上海市普陀区金沙江路 1518 弄',
                status: '上海市普陀区金沙江路 1518 弄',
                children: [
                  {
                    id: '3',
                    name: '王小虎534',
                    deptName: '上海市普陀区金沙江路 1518 弄',
                    roleNames: '上海市普陀区金沙江路 1518 弄',
                    email: '上海市普陀区金沙江路 1518 弄',
                    mobile: '上海市普陀区金沙江路 1518 弄',
                    status: '上海市普陀区金沙江路 1518 弄',
                  }, {
                    id: '4',
                    name: '王小虎51',
                    deptName: '上海市普陀区金沙江路 1518 弄',
                    roleNames: '上海市普陀区金沙江路 1518 弄',
                    email: '上海市普陀区金沙江路 1518 弄',
                    mobile: '上海市普陀区金沙江路 1518 弄',
                    status: '上海市普陀区金沙江路 1518 弄',
                  }, {
                    id: '5',
                    name: '王小虎52',
                    deptName: '上海市普陀区金沙江路 1518 弄',
                    roleNames: '上海市普陀区金沙江路 1518 弄',
                    email: '上海市普陀区金沙江路 1518 弄',
                    mobile: '上海市普陀区金沙江路 1518 弄',
                    status: '上海市普陀区金沙江路 1518 弄',
                  }, {
                    id: '6',
                    name: '王小虎53',
                    deptName: '上海市普陀区金沙江路 1518 弄',
                    roleNames: '上海市普陀区金沙江路 1518 弄',
                    email: '上海市普陀区金沙江路 1518 弄',
                    mobile: '上海市普陀区金沙江路 1518 弄',
                    status: '上海市普陀区金沙江路 1518 弄',
                  }, {
                    id: '7',
                    name: '王小虎54',
                    deptName: '上海市普陀区金沙江路 1518 弄',
                    roleNames: '上海市普陀区金沙江路 1518 弄',
                    email: '上海市普陀区金沙江路 1518 弄',
                    mobile: '上海市普陀区金沙江路 1518 弄',
                    status: '上海市普陀区金沙江路 1518 弄',
                  }, {
                    id: '8',
                    name: '王小虎55',
                    deptName: '上海市普陀区金沙江路 1518 弄',
                    roleNames: '上海市普陀区金沙江路 1518 弄',
                    email: '上海市普陀区金沙江路 1518 弄',
                    mobile: '上海市普陀区金沙江路 1518 弄',
                    status: '上海市普陀区金沙江路 1518 弄',
                  },
                ],
              }, {
                id: '10',
                name: '王小虎6',
                deptName: '上海市普陀区金沙江路 1518 弄',
                roleNames: '上海市普陀区金沙江路 1518 弄',
                email: '上海市普陀区金沙江路 1518 弄',
                mobile: '上海市普陀区金沙江路 1518 弄',
                status: '上海市普陀区金沙江路 1518 弄',
              }]
            },
            operation: false, // true:新增, false:编辑
            dialogVisible: false, // 新增编辑界面是否显示
            editLoading: false,
            dataFormRules: {
              name: [
                {required: true, message: '请输入用户名', trigger: 'blur'}
              ]
            },
            // 新增编辑界面数据
            dataForm: {
              id: 0,
              name: '',
              password: '123456',
              deptId: 1,
              deptName: '',
              email: 'test@qq.com',
              mobile: '13889700023',
              status: 1,
              userRoles: []
            },
            deptData: [],
            deptTreeProps: {
              label: 'name',
              children: 'children'
            },
            roles: []
          }
        },
        methods: {
          findPage() {
          },
          handleEdit() {
          },
          handleDelete() {
          },
          cancelForm() {
          },
        }
      }
    </script>
    
    <style scoped>
      .toolbar {
        /*width: 98%;*/
        background: #F7F7F7;
        padding: 10px 5px 10px;
        margin: auto;
      }
    </style>
    

     

    <sky-button icon="el-icon-plus" @click="drawer = true" label="新增" perms="role:add" type="primary"
                          size="mini"/>

     显示效果

    展开全文
  • VUE权限管理,精确控制到按钮级别

    千次阅读 2019-11-07 16:42:28
    VUE权限管理,精确控制到按钮级别 一个完整的权限系统必不可少的两个部分是: 控制页面元素的渲染 动态注册路由 控制页面元素的渲染 肯定不能用v-if来控制页面元素的渲染,太繁琐,每个页面都得去获取用户的权限,...
  • vue 权限管理 状态模块封装 (4)

    千次阅读 2020-01-14 13:20:09
    1. 在src目录下新建一个store...import Vue from 'vue' import vuex from 'vuex' Vue.use(vuex); import app from './modules/app' import tab from './modules/tab' import iframe from './modules/iframe' i...
  • 角色支持遗传,类型:共有ABCD四个功能权限,分配了AB 2个权限给超级管理员角色的用户,支持让超级管理员用户可以自己创建角色。但是只能选择AB 2个。无法看到光盘! 遇到问题可有加群咨询 如何使用Wiki: : 代码...
  • vue+element实现的后台管理权限,拿来即用!
  • springboot+vue 权限管理系统

    千次阅读 2019-01-24 10:37:13
    权限管理系统 demo http://permission.yuanjy.com 前端 github地址:https://github.com/yjysanshu/vue--authority 后端 github地址:https://github.com/yjysanshu/springboot-authority 简介 该权限管理项目是...
  • springboot+Vue权限管理项目(一)

    千次阅读 2020-03-04 15:11:12
    Mango后台权限管理系统是基于Springboot,SpringCloud,vue.js,Element UI,等 主流前后端技术实现的。 1.2系统架构 本系统采用前后端分离架构实现,前后端通过JSON格式进行交互,前后端皆可独立分开部署,前端...
  • 基于SpringBoot + Vue的前后端分离权限管理系统,可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。 技术...
  • RBAC权限管理系统 项目简介 一个基于Django,Django REST框架(DRF),Vue的前布局分离的后台管理系统,可轻松添加业务页面及功能。 系统预览 特别鸣谢 感谢提供的非商业开源软件开发授权 感谢提供一级Django框架 ...
  • 配置文件及数据库 位于 src/resources 文件夹下面 前端页面地址:
  • RXThinkCMF_EVTP6_PRO前后端分离开发框架是基于 ThinkPhp6+ElementUI+Vue 开发的权限架构及内容管理框架,采用全新的前端UI框架,支持多主题切换,前端UI框架完全适配手机端、PAD终端以及PC电脑终端,框架内置完整的...
  • Laravel-Admin是用laravel + elementUi前端框架前首先分离写入成的后台脚手架,自带用户组权限系统。 安装 作曲家安装 配置nginx本地域名local.admin.com(如需更换域名,需要在webpack.mix.js替换配置域名)指向/ ...
  • 前端技术主要使用Vue.js和Element UI框架。 2.1.3 项目结构 mango-ui –build:项目编译相关模块,项目模板自动生成 –config:项目配置相关模块,项目模板自动生成 –src:项目源码模块,前端开发工作集中在此目录 ...
  • java版oa源码下载 平台简介 一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间...角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 字典管理:对系统中经

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 28,754
精华内容 11,501
关键字:

vue权限管理

vue 订阅