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;

對於菜單的權限,通過路由表匹配

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等

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

對於按鈕的權限

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裏存在就顯示。

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__: {}
      }
    },
  })
}

<Button v-if="dataUri__[uri__.ADD_MEMBER]">添加會員</Button>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章