最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解利用 Vue.js 實現(xiàn)前后端分離的RBAC角色權(quán)限管理

 更新時間:2017年09月15日 09:18:15   作者:52admln  
本篇文章主要介紹了利用 Vue.js 實現(xiàn)前后端分離的RBAC角色權(quán)限管理,非常具有實用價值,需要的朋友可以參考下

項目背景:物業(yè)管理后臺,不同角色擁有不同權(quán)限

采用技術(shù):Vue.js + Vuex + Element UI

實現(xiàn) RBAC 權(quán)限管理需要后端接口支持,這里僅提供前端解決方案。

因代碼篇幅較大,對代碼進(jìn)行了刪減,文中 “...” 即為省略的一部分代碼。

大致思路:
首先登錄成功后,從后臺拉取用戶當(dāng)前可顯示的菜單和可用權(quán)限列表,分別將其存入 store 的 nav(菜單導(dǎo)航) 和 auth(用戶可用權(quán)限) 中,在用戶切換路由時,判斷是否存在 auth ,如果不存在,則重新獲取,判斷當(dāng)前訪問地址 to.meta.alias 是否在用戶可用權(quán)限列表中,如果不存在,則提示無權(quán)限,否則進(jìn)入路由。

1. 路由與側(cè)邊菜單分離

側(cè)邊菜單相關(guān)代碼 Main.vue

<template>
<!-- ... -->
  <aside :class="collapsed?'menu-collapsed':'menu-expanded'">
    <!--導(dǎo)航菜單-->
    <el-menu :default-active="$route.path"
         class="el-menu-vertical-aliyun" 
         @open="handleopen"
         @close="handleclose"
         @select="handleselect"
         :collapse="collapsed"
         unique-opened router>
      <template v-for="(item,index) in nav">
        <!-- 二級菜單 -->
        <el-submenu :index="index+''"
              v-if="item.children && item.children.length > 0">
          <!-- 二級菜單頂級 -->
          <template slot="title">
            <i :class="['icon',item.iconCls]"></i>
            <span slot="title">{{item.name}}</span>
          </template>
          <!-- 二級菜單下級 -->
          <el-menu-item-group>
            <!--<span slot="title">{{item.name}}</span>-->
            <!-- && child.url-->
            <template v-for="child in item.children">
              <!--無三級菜單-->
              <el-menu-item
                  :index="child.url"
                  :key="child.url"
                  v-if="!child.children">
                {{child.name}}
              </el-menu-item>
              <!--有三級菜單-->
              <el-submenu
                  :index="child.url"
                  :key="child.url"
                  v-if="child.children">
                <span slot="title">{{child.name}}</span>
                <el-menu-item v-for="subChild in child.children"
                       :index="subChild.url"
                       :key="subChild.url">
                  {{subChild.name}}
                </el-menu-item>
              </el-submenu>
            </template>
          </el-menu-item-group>
        </el-submenu>
        <!-- 一級菜單 -->
        <el-menu-item v-if="!item.children"
               :index="item.url">
          <i :class="['icon',item.iconCls]"></i>
          <span slot="title">{{item.name}}</span>
        </el-menu-item>
  
      </template>
    </el-menu>
  </aside>
<!-- ... -->
</template>

<script>
  export default {
    // ...
    computed: {
     // 從 Vuex 中獲取導(dǎo)航菜單
     nav() {
      return this.$store.state.nav;
     }
    }
    // ...
  }
</script>

2. 路由切換前進(jìn)行鑒權(quán)

路由定義的部分代碼,對每個路由添加了 meta 屬性,用于鑒權(quán)。

這里 component 采用了異步引入的方式。

定義路由

// ...
// 系統(tǒng)管理
{
path: '/system',
component: Main,
name: '系統(tǒng)管理',
redirect: '/system/organization',
children: [{
 path: '/system/organization',
 component: () => import ('@/views/System/Organization.vue'),
 name: '組織結(jié)構(gòu)',
 // requiresAuth 用于確認(rèn)此地址是否需要驗證
 // alias 用于獲取后端返回rbac權(quán)限對應(yīng)的前端路由地址和導(dǎo)航菜單圖標(biāo)
 meta: {requiresAuth: true, alias: 'Pmsadmin/Oragnize/list'}
},
 {
  path: '/system/user',
  component: () => import ('@/views/System/User.vue'),
  name: '人員管理',
  redirect: '/system/user/index',
  children: [
  {
   path: '/system/user/index',
   component: () => import ('@/views/System/UserList.vue'),
   name: '職員列表',
   meta: {requiresAuth: true, alias: 'Pmsadmin/Admin/list'}
  }
  ]
 },
 {
  path: '/system/auth',
  component: () => import ('@/views/System/Auth.vue'),
  name: '角色管理',
  meta: {requiresAuth: true, alias: 'Pmsadmin/Role/list'}
 }
]
}
// ...

路由鉤子 beforeEach

router.beforeEach((to, from, next) => {
 document.title = `${configs.title} - ${to.name}`;
 const {hasAuth, auth} = store.state.user;
 // 未拿到權(quán)限,則獲取
 if (!hasAuth) {
  store.dispatch('getUserAuth');
  console.log('重新獲取用戶權(quán)限');
  // next();
 }
 // 如果未登錄,跳轉(zhuǎn)
 if (window.localStorage.getItem('IS_LOGIN') === null && to.path !== '/login') {
  console.log('未登錄狀態(tài)');
  next({
   path: '/login',
   query: {redirect: to.fullPath}
   // 將跳轉(zhuǎn)的路由path作為參數(shù),登錄成功后跳轉(zhuǎn)到該路由
  })
 } else {
  // 需要鑒權(quán)的路由地址
  console.log(to, auth.indexOf(to.meta.alias), auth);
  if (to.meta.requiresAuth) {
   if (auth.indexOf(to.meta.alias) > -1) {
    console.log('有權(quán)限進(jìn)入');
    next();
   } else {
    if(auth.length > 0) {
     Message.error({
      message: '當(dāng)前用戶權(quán)限不足,無法訪問',
      showClose: true,
     });
    } else {
     next();
    }
   }
  } else {
   next();
  }
 }
});

在 Vuex 的 state 中,定義好 nav 對象

// 登錄用戶信息
const user = {
 name: '', // 用戶名
 avatar: '', // 用戶頭像
 auth: [], // 用戶權(quán)限
 hasAuth: false // 是否已經(jīng)加載用戶權(quán)限
};
// 導(dǎo)航菜單
const nav = [];

通過 action 異步獲取數(shù)據(jù)

// 獲取用戶權(quán)限
const getUserAuth = async ({commit}) => {
 const res = await http.post('YOUR_URL', {});
 if (res === null) return;
 console.log('getUserAuth', res.param);
 commit('SET_USER_AUTH', res.param.auth);
 commit('SET_SIDE_NAV', res.param.nav);
};

Vuex 中的 mutation 的相關(guān)代碼

// 設(shè)置用戶權(quán)限
const SET_USER_AUTH = (state, auth) => {
 state.user.auth = auth.concat('歡迎使用');
 state.user.hasAuth = true;
};
// 設(shè)置導(dǎo)航菜單
const SET_SIDE_NAV = (state, nav) => {
 // 導(dǎo)航菜單
 let _nav = [{
  name: '歡迎使用',
  url: "/main",
  iconCls: 'fa fa-bookmark'
 }];
 // 權(quán)限菜單對應(yīng)的路由地址
 const route = {
  "系統(tǒng)管理": {iconCls: 'fa fa-archive', url: ''},
  "Pmsadmin/Oragnize/list": {iconCls: '', url: '/system/organization'},
  "Pmsadmin/Admin/list": {iconCls: '', url: '/system/user/index'},
  "Pmsadmin/Role/list": {iconCls: '', url: '/system/auth'},
  "Pmsadmin/Log/record": {iconCls: '', url: '/system/logs'},
  "項目管理": {iconCls: 'fa fa-unlock-alt', url: ''},
  "Pmsadmin/Project/list": {iconCls: '', url: '/project/list/index'},
  "Pmsadmin/House/list": {iconCls: '', url: '/project/house'},
  "Pmsadmin/Pack/list": {iconCls: '', url: '/project/pack'},
  "廣告位": {iconCls: 'fa fa-edit', url: ''},
  "Pmsadmin/Place/list": {iconCls: '', url: '/adsplace/list'},
  "投訴建議": {iconCls: 'fa fa-tasks', url: ''},
  "Pmsadmin/Scategory/list": {iconCls: '', url: '/complain/type'},
  "Pmsadmin/Complain/list": {iconCls: '', url: '/complain/list'},
  "Pmsadmin/Suggest/list": {iconCls: '', url: '/complain/suggestion'},
  "報事報修": {iconCls: 'fa fa-user', url: ''},
  "Pmsadmin/Rcategory/list": {iconCls: '', url: '/rcategory/type'},
  "Pmsadmin/Rcategory/info": {iconCls: '', url: '/rcategory/public'},
  "Pmsadmin/Repair/list": {iconCls: '', url: '/rcategory/personal'},
  "便民服務(wù)": {iconCls: 'fa fa-external-link', url: ''},
  "Pmsadmin/Bcategory/list": {iconCls: '', url: '/bcategory/type'},
  "Pmsadmin/Service/list": {iconCls: '', url: '/bcategory/list'},
  "首座推薦": {iconCls: 'fa fa-file-text', url: ''},
  "Pmsadmin/stcategory/list": {iconCls: '', url: '/stcategory/type'},
  "Pmsadmin/Store/list": {iconCls: '', url: '/stcategory/list'},
  "招商租賃": {iconCls: 'fa fa-leaf', url: ''},
  "Pmsadmin/Bussiness/list": {iconCls: '', url: '/bussiness/list'},
  "Pmsadmin/Company/list": {iconCls: '', url: '/bussiness/company'},
  "Pmsadmin/Question/list": {iconCls: '', url: '/bussiness/question'},
  "停車找車": {iconCls: 'fa fa-ra', url: ''},
  "Pmsadmin/Cplace/list": {iconCls: '', url: '/cplace/cmanage'},
  "Pmsadmin/Clist/list": {iconCls: '', url: '/cplace/clist'},
  "Pmsadmin/Cquestion/list": {iconCls: '', url: '/cplace/cquestion'},
 };
 for (let key in nav) {
  let item = nav[key];
  let _temp = {};
  let subItems = []; // 二級菜單臨時數(shù)組
  if (item.children && item.children.length > 0) {
   // 二級菜單
   item.children.forEach(subItem => {
    subItems.push(Object.assign({}, {
     name: subItem.name || '',
     url: route[subItem.url].url || '',
     iconCls: route[subItem.url].iconCls || '',
    }))
   });
   // 一級菜單
   _temp = Object.assign({}, {
    name: item.name || '',
    url: item.url || '',
    iconCls: route[item.name].iconCls || '',
    children: subItems.slice(0)
   });
   _nav.push(_temp);
  }
 }
 state.nav = _nav;
};

3. 后端接口返回內(nèi)容

{
  "status": 200,
  "info": "數(shù)據(jù)查詢成功!",
  "param": {
    "nav": {
      "1": {
        "name": "系統(tǒng)管理",
        "url": "",
        "children": [
          {
            "name": "組織結(jié)構(gòu)",
            "url": "Pmsadmin/Oragnize/list"
          },
          {
            "name": "人員管理",
            "url": "Pmsadmin/Admin/list"
          },
          {
            "name": "角色管理",
            "url": "Pmsadmin/Role/list"
          },
          {
            "name": "日志管理",
            "url": "Pmsadmin/Log/record"
          }
        ]
      },
      "61": {
        "name": "廣告位",
        "url": "",
        "children": [
          {
            "name": "廣告位列表",
            "url": "Pmsadmin/Place/list"
          }
        ]
      }
    },
    "auth": [
      "系統(tǒng)管理",
      "Pmsadmin/Oragnize/list",
      "Pmsadmin/Admin/list",
      "Pmsadmin/Role/list",
      "Pmsadmin/Log/record",
      "廣告位",
      "Pmsadmin/Place/list"
    ]
  }
}

存在的問題

  • 新增 修改 刪除 按鈕還無法實現(xiàn)根據(jù)用戶權(quán)限控制其顯示
  • 代碼上還存在著不足,期待大神能夠有更優(yōu)的解決方案。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue3文件下載方法實現(xiàn)的簡單代碼

    Vue3文件下載方法實現(xiàn)的簡單代碼

    在Web開發(fā)中,文件下載可通過多種方式實現(xiàn),下面這篇文章主要介紹了Vue3文件下載方法實現(xiàn)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-10-10
  • vue學(xué)習(xí)之mintui picker選擇器實現(xiàn)省市二級聯(lián)動示例

    vue學(xué)習(xí)之mintui picker選擇器實現(xiàn)省市二級聯(lián)動示例

    本篇文章主要介紹了vue學(xué)習(xí)之mintui picker選擇器實現(xiàn)省市二級聯(lián)動示例,非常具有實用價值,需要的朋友可以參考下
    2017-10-10
  • vue項目頁面嵌入代碼塊vue-prism-editor的實現(xiàn)

    vue項目頁面嵌入代碼塊vue-prism-editor的實現(xiàn)

    這篇文章主要介紹了vue項目頁面嵌入代碼塊vue-prism-editor的實現(xiàn),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • vue項目如何實現(xiàn)ip和localhost同時訪問

    vue項目如何實現(xiàn)ip和localhost同時訪問

    這篇文章主要介紹了vue項目如何實現(xiàn)ip和localhost同時訪問,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 在Flask項目中集成并訪問Vue前端項目的流程步驟

    在Flask項目中集成并訪問Vue前端項目的流程步驟

    在現(xiàn)代?Web?開發(fā)中,前后端分離的架構(gòu)模式越來越流行,前端通常使用?Vue、React?等框架開發(fā),而后端則使用?Flask、Django?等框架提供?API?服務(wù),本文將詳細(xì)介紹如何在一個?Flask?項目中集成?Vue?前端項目,并確保能夠正確訪問和運(yùn)行,需要的朋友可以參考下
    2025-03-03
  • VUE2.0+ElementUI2.0表格el-table循環(huán)動態(tài)列渲染的寫法詳解

    VUE2.0+ElementUI2.0表格el-table循環(huán)動態(tài)列渲染的寫法詳解

    這篇文章主要介紹了VUE2.0+ElementUI2.0表格el-table循環(huán)動態(tài)列渲染的寫法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • 如何理解Vue前后端數(shù)據(jù)交互與顯示

    如何理解Vue前后端數(shù)據(jù)交互與顯示

    這篇文章主要介紹了如何理解Vue前后端數(shù)據(jù)交互與顯示,對Vue感興趣的同學(xué),可以參考下
    2021-05-05
  • Vue3新狀態(tài)管理工具實例詳解

    Vue3新狀態(tài)管理工具實例詳解

    Vue3公布曾經(jīng)有一段時間了,它采納了新的響應(yīng)式零碎,而且構(gòu)建了一套全新的 Composition API,下面這篇文章主要給大家介紹了關(guān)于Vue3新狀態(tài)管理工具的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • vue中調(diào)用百度地圖獲取經(jīng)緯度的實現(xiàn)

    vue中調(diào)用百度地圖獲取經(jīng)緯度的實現(xiàn)

    最近做個項目,需要實現(xiàn)獲取當(dāng)前位置的經(jīng)緯度,所以本文主要介紹了vue中調(diào)用百度地圖獲取經(jīng)緯度的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • vue滾動tab跟隨切換效果

    vue滾動tab跟隨切換效果

    這篇文章主要為大家詳細(xì)介紹了vue滾動tab跟隨切換效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07

最新評論

新蔡县| 普洱| 洪湖市| 安丘市| 蓬安县| 改则县| 汾阳市| 五寨县| 安国市| 灵石县| 民勤县| 奈曼旗| 金坛市| 杭锦旗| 武清区| 阿拉尔市| 乳山市| 永吉县| 河北省| 仪陇县| 邹平县| 家居| 萨嘎县| 防城港市| 汶上县| 博野县| 尖扎县| 浦北县| 乌拉特前旗| 松江区| 太保市| 永嘉县| 彩票| 恩施市| 乌兰浩特市| 宝坻区| 玉山县| 宁夏| 海南省| 桃园市| 浙江省|