热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python权限管理系统_vue权限管理系统

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

vue权限系统

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

下面预览图是我写的一个后台管理系统,源码请点击链接 vuets-iview-admin 技术栈 - vue+typescript+iview

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

表的结构

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的外键。

这样就是一个账号 --> 角色 --> 权限的关系。

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

// 本地写好路由列表(需要进行动态匹配的)

export const routerList: Array = [

// 首页

{

path: '/',

name: '_home',

redirect: '/home',

component: Layout,

meta: {

hideInMenu: true,

notCache: true

},

children: [

{

path: 'home',

name: 'home',

meta: {

hideInMenu: true,

title: '首页',

notCache: true,

icon: 'md-home'

},

component: () => import('@/views/overview-operations/data-center/DataCenter.vue')

}

]

}

]

// 负责将后台返回的 菜单列表 转成vue-router所需要的 router list

export function toRouterComponent(menuList: Array) {

if (!menuList.length) return []

let routerArr = [];

for (let j = 0; j

let obj;

let firstIndex = routerList.findIndex(i => i.path === menuList[j].url); // 一级菜单

if (firstIndex !== -1) {

let children: Array = []

obj = {

path: routerList[firstIndex].path,

component: routerList[firstIndex].component,

redirect: routerList[firstIndex].redirect,

name: routerList[firstIndex].name,

meta: routerList[firstIndex].meta,

children

};

// 如果有子菜单

if (menuList[j].children && menuList[j].children.length) {

for (let k = 0; k

const _children = routerList[firstIndex].children!

let secondIndex = _children.findIndex(i => {

let fullpath = '';

if (routerList[firstIndex].path === '/') {

fullpath = `${routerList[firstIndex].path}${i.path}`;

} else {

fullpath = `${routerList[firstIndex].path}/${i.path}`;

}

return fullpath === menuList[j].children[k].url;

});

if (secondIndex !== -1) {

obj.children.push(_children[secondIndex]);

}

}

}

}

if (obj) {

routerArr.push(obj);

}

}

return routerArr;

}

// 根据菜单权限,获取路由数组

// 本地只保存后台返回的菜单,在页面刷新的时候从本地拿到菜单重新调用toRouterComponent生成 路由数组

export function getRouterList() {

if (!storage.get('username')) {

storage.set('menuTree', ''); // 清空菜单权限数据

}

let menuList = storage.get('menuTree') ? storage.get('menuTree') : [];

const routerArr = toRouterComponent(menuList);

return routerArr;

}

menuList,菜单数组(或对象), 由后台返回; routerList为前端定义的路由表;遍历routerList,如果routerList的path在menuMap里能找到的话,就表示该路由存在。最后生成一个过滤后的路由表,用vue提供的addRoutes方法动态添加到路由中,并把过滤后的路由表存到本地。

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

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

对于按钮的权限

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'

},

}

})

}

添加会员

// 通过方法来控制,更加灵活

添加会员

登出的问题

**登出后要清空缓存,routerArr,btnList 等。

由于之前登录,调用addRouter把权限上个账号的路由表加进去了,所以登出后要location.reload()一次,重新实例化路由表,去掉动态添加的路由,只保留基础路由。

location.reload()体验不是太好,但是vue-router没有提供动态删除路由的api,比如 deleteRouter。**

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

最简单的方法是存到localStorage里,只有登出才会清空缓存,只能登一个账号。

关于菜单和按钮的多语言放在前台还是后台

经过思考还是觉得放在前台好,有两点原因

放在前台方便前台操作,切换语言时不需要重新从后台获取菜单和按钮的名称

如果放在后台,新增语言的时候,后台还得加字段, 放在前台的话只需要更新一下语言包就行了

关于menutree 是否存到本地

之前一直是存在localstorage里,但是仔细一想还是有安全问题,用户可以通过api改变本地的menutree,刷新页面后还是会得到想要的权限,所以menutree 不能存到本地,只读到内存中,页面刷新后,再重新获取一次menutree,代价就是会牺牲一点用户体验。

关于左侧菜单栏重复push的问题

window.addEventListener('storage', () => {

// 当同时打开两个网页 其中一个网页退出登录的时候 通知另一个网页刷新 把之前的路由清掉

// 这样就不会重复push路由进去了

if (getLsCache('username') === '') {

window.location.reload();

setTimeout(() => {

this.$router.push('/login');

}, 200);

}

});

this.setLocal(this.$i18n.locale);



推荐阅读
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
  • CentOS7源码编译安装MySQL5.6
    2019独角兽企业重金招聘Python工程师标准一、先在cmake官网下个最新的cmake源码包cmake官网:https:www.cmake.org如此时最新 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文详细介绍如何使用Samba软件配置CIFS文件共享服务,涵盖安装、配置、权限管理及多用户挂载等关键步骤。通过具体示例和命令行操作,帮助读者快速搭建并优化Samba服务器。 ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本实验主要探讨了二叉排序树(BST)的基本操作,包括创建、查找和删除节点。通过具体实例和代码实现,详细介绍了如何使用递归和非递归方法进行关键字查找,并展示了删除特定节点后的树结构变化。 ... [详细]
  • SQLite 动态创建多个表的需求在网络上有不少讨论,但很少有详细的解决方案。本文将介绍如何在 Qt 环境中使用 QString 类轻松实现 SQLite 表的动态创建,并提供详细的步骤和示例代码。 ... [详细]
  • 本文详细介绍了C语言中链表的两种动态创建方法——头插法和尾插法,包括具体的实现代码和运行示例。通过这些内容,读者可以更好地理解和掌握链表的基本操作。 ... [详细]
  • 本文由瀚高PG实验室撰写,详细介绍了如何在PostgreSQL中创建、管理和删除模式。文章涵盖了创建模式的基本命令、public模式的特性、权限设置以及通过角色对象简化操作的方法。 ... [详细]
  • Linux设备驱动程序:异步时间操作与调度机制
    本文介绍了Linux内核中的几种异步延迟操作方法,包括内核定时器、tasklet机制和工作队列。这些机制允许在未来的某个时间点执行任务,而无需阻塞当前线程,从而提高系统的响应性和效率。 ... [详细]
  • 本文深入探讨了C++对象模型中的一些细节问题,特别是虚拟继承和析构函数的处理。通过具体代码示例和详细分析,揭示了书中某些观点的不足之处,并提供了更合理的解释。 ... [详细]
author-avatar
hola'thrme
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有