vue权限管理系统

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: SpringBoot Vue权限管理系统是一种基于SpringBoot和Vue框架开发的权限管理系统。它可以帮助开发者快速搭建一个具有权限管理功能的Web应用程序。该系统采用前后端分离的架构,前端使用Vue框架,后端使用SpringBoot框架。通过该系统,用户可以进行用户管理、角色管理、权限管理等操作,实现对系统的全面控制和管理。 ### 回答2: Spring Boot和Vue两个非常流行的开源框架,结合起来可以构建起一个强大的权限管理系统。下面就介绍一下如何实现这个系统。 1. 数据库设计 权限管理系统的核心就是对用户和角色的管理,因此需要设计一个包含用户、角色和权限的数据库结构。用户表包含用户名、密码、邮箱、电话等基本信息;角色表包含角色名称、角色描述等信息;权限表包含权限名称、权限描述、URL地址等信息。此外,还需要建立角色权限和用户角色之间的关系表。这些表的设计需要根据实际需求进行定制化,以满足系统的业务需求。 2. 后端开发 采用Spring Boot框架进行后端开发,实现以下功能: 1)用户登录,使用Jwt Token验证用户身份,给前端返回Token。 2)角色管理,包括添加、删除、修改角色信息。 3)权限管理,包括添加、删除、修改权限信息。 4)用户角色管理,包括为用户分配角色和撤销角色。 5)角色权限管理,包括为角色分配权限和撤销权限。 6)数据接口管理,使用Spring Security框架实现数据接口权限控制。 3. 前端开发 采用Vue框架进行前端开发,实现以下功能: 1)登录页面,实现用户登录功能。 2)用户管理页面,展示用户信息,包括用户名、邮箱、电话等信息。 3)角色管理页面,展示角色信息,包括角色名称、角色描述等信息。 4)权限管理页面,展示权限信息,包括权限名称、权限描述、URL地址等信息。 5)用户角色管理页面,实现为用户分配角色和撤销角色功能。 6)角色权限管理页面,实现为角色分配权限和撤销权限功能。 7)数据接口管理页面,实现数据接口访问权限控制功能。 4. 集成部署 将前后端分别打包成jar和静态文件,将其部署到服务器上。前端静态文件采用nginx作为反向代理服务器进行访问控制,后端服务则采用Tomcat容器运行。 总之,Spring Boot与Vue的结合为权限管理系统的开发带来了很大的便利性。通过选择合适的工具和技术,可以开发出高效、稳定且易于维护的权限管理系统。 ### 回答3: Springboot 和 Vue 都是非常流行的开发框架,一起使用可以构建出非常好的应用程序。权限管理系统是 Web 应用程序中非常重要的一个方面,它可以为不同的用户分配不同的权限,从而保证数据和用户的安全。在这篇文章中,我将谈谈如何使用 Springboot 和 Vue 来构建一个权限管理系统。 首先,我们需要创建一个基于 Springboot 的后端 API,用于处理用户、角色和权限的管理。我们可以使用 Spring Security 来提供身份验证和授权。Spring Security 是一个强大的安全框架,可以提供身份验证、授权、角色管理、过滤器等功能。我们可以使用 Spring Security 的注解来定义不同的角色和权限,并在我们的代码中使用这些注解来保护 API 接口。 接下来,我们需要创建一个 Vue 前端界面来管理用户、角色和权限。我们可以使用 Element UI 或其他类似库来使用 Vue 编写漂亮的界面。我们需要使用 Vue Router 来管理应用程序的不同页面,并使用 Vuex 来管理我们的应用状态。在我们的前端应用程序中,我们可以使用 Axios 或其他类似的库来与后端 API 进行通信。 最后,我们需要使用一些工具来将我们的应用程序部署到云上。我们可以使用 Docker 来打包我们的应用程序,然后使用 Kubernetes 或其他类似工具来部署应用程序到云上。我们也可以使用一些 CI/CD 工具来自动化部署过程,例如 Jenkins 或 CircleCI。 总之,Springboot 和 Vue 可以一起构建一个强大的权限管理系统,这个系统可以为不同的用户分配不同的角色和权限,从而保证应用程序的安全和用户的隐私。使用这个系统可以让我们更快、更安全地开发和部署我们的应用程序,为我们的用户提供更好的服务。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值