vue 權限管理



核心想法:

登陸后獲得用戶角色,通過角色獲得用戶的權限,注入權限對應的路由。刷新頁面,從localStorage用角色(更好的方式是通過token)再次獲得所屬權限,再次注入路由。在管理界面左端循環權限對應的路由菜單
localStorage存用戶的信息(token),權限路由不會存。

所有的路由分為2種:
  • 公共路由:所有用戶可以查看。
  • 權限路由:當前用戶權限所屬的路由。
實現控制的方式分兩種:
  • 通過 vue-router addRoutes 方法注入路由實現控制
  • 通過 vue-router beforeEach 鈎子限制路由跳轉
一般來講,需要采用第一種方式,addRoutes注入的方式,第二種每次判斷,開銷比較大,而且一次性拿不到角色對應的所有路由列表。這個列表需要再登陸后立即渲染在左邊。

 

 



權限的控制分為好幾種:
  • 一級菜單的權限控制,
  • 二級菜單的權限控制,
  • 按鈕級別的權限控制。
控制方式有2種:
  • 后端返回路由控制列表
  • 前后端約定路由控制列表

代碼:一級菜單的權限控制,前后端約定的方式確定角色能訪問的路由。
routers/index.js

 

import Vue from 'vue'
import Router from 'vue-router'
import loginRoute from './modules/login.js';
import homeRoute from './modules/home.js'
import productionRoute from './modules/production.js';
import store from '../stores/index.js';


Vue.use(Router)

//不需要權限的路由
export const constantRoutes = [loginRoute];
//需要權限的路由
//這里只是導出。實際上添加到router里在在store的permission里
export const asyncRoutes = [
    homeRoute,
    productionRoute,
];
console.log(asyncRoutes);
const router = new Router({
    mode: 'history',
    base: process.env.BASE_URL,
    routes: [
        ...constantRoutes,
    ]
})
router.beforeEach((to,from,next)=>{
    let user = store.state.user.user;
    let permissionRoutes= store.state.permission.permissionRoutes;
    console.log(store.state);
    console.log(user);
    if(!user && to.path!=='/'){
        next({
            path:'/'
        });
    }else{
        //刷新頁面的情況
        if(!permissionRoutes && user){
            store.dispatch('generateRoutes',{
                role:user.role
            })

            console.log(router);
            console.log(to);
            //這里寫next沒用
            next({...to})
        }else{
            next();
        }


        // next({...to, replace: true })
    }
});
export default  router;

  其中,productionRoute:

import Layout from '../../layouts/Index.vue'
const productionAdd = () => import('../../pages/production/Add.vue')
const productionList = () => import('../../pages/production/List.vue')
const productionTemplateComplete  = () => import('../../pages/production/TemplateComplete.vue')
let routes = {
    path: '/production',
    component: Layout,
    meta: {
        title: '產品管理',
        roles: [0, 1]
    },
    children: [
        {
            path: 'add',
            component: productionAdd,
            beforeEnter (to, from, next) {
                console.log('router beforeEnter');
                next();
            },
            meta: {
                title: '產品新增'
            }
        },
        {
            path: 'list',
            component: productionList,
            meta: {
                title: '產品列表'
            }
        },
        {
            path: 'templateComplete',
            component: productionTemplateComplete,
            meta: {
                title: '產品新增完善'
            }
        }
    ]
}

export default routes

  

stores/index.js
import Vue from 'vue'
import Vuex from 'vuex'

import user from './modules/user.js'
import permission from './modules/permission.js'


Vue.use(Vuex)

export default new Vuex.Store({
    modules: {
        user,
        permission,
    }
})

  



stores/modules/user.js
const SET_USER = 'SET_USER' //登錄成功
const CLEAR_USER = 'CLEAR_USER' //退出登錄
import $ajax from '../../axios/index.js';
import store from '../index.js';
export default {
    state: {
        user:JSON.parse(localStorage.getItem('user')) || null
    },
    mutations: {
        [SET_USER](state, user) {
            state.user = user;
            localStorage.setItem('user', JSON.stringify(user))
        },

        [CLEAR_USER](state) {
            state.user = null;
            localStorage.removeItem('user');
        }
    },
    actions: {
        login({commit}, param) {
            console.log('action');
            console.log(param);
            return new Promise((resolve, reject) => {
                //一期不做后台登陸,前端判斷
                // $ajax({
                //     url:api.login,
                //     data:{
                //         ...param
                //     }
                // }).then(res=>{
                //     let user = res.data.data;
                //     commit(SET_USER, user);
                //     resolve();
                // }).catch(res=>{
                //     reject();
                // })
                //前端驗證用戶名,密碼
                window.setTimeout(()=>{
                    if(param.username === 'huainanju' && param.password === 'huainanju123'){
                        let user = {
                            username:'管理員',
                            role:0
                        }
                        commit(SET_USER, user);
                        store.dispatch('generateRoutes',{
                            role:user.role
                        })
                        resolve();
                    }else{
                        reject();
                    }
                },1000)
            });
        },
        logout({commit}) {
            commit(CLEAR_USER)
        }
    }
}

  



stores/modules/permisson.js
import {asyncRoutes} from '../../routers/index';
import router from '../../routers/index';
/**
 * 遞歸過濾異步路由表,返回符合用戶角色權限的路由表
 * @param role
 */
function filterAsyncRoutes(role) {
    const res = asyncRoutes.filter(route => {
        return route.meta.roles.includes(role)
    });
    return res
}

const permisssion = {
    state:{
        permissionRoutes:null
    },
    getter:{

    },
    mutations:{
        SET_ROUTERS: (state, routes) => {
            //添加路由
            console.log('添加路由');
            router.addRoutes(routes);
            state.permissionRoutes = routes // 權限路由
        },
    },
    actions:{
        generateRoutes({ commit }, data) {
            let {role} = data;
            let routes = filterAsyncRoutes(role);
            console.log(routes);
            commit('SET_ROUTERS', routes)
        }
    }
}

export default permisssion;

  

layouts/Left.vue

<template>
    <el-aside style="min-height:100%;min-width:250px;" width="250px">
        <el-menu :default-active="defaultActive"
                 background-color="#324157"
                 text-color="#bfcbd9"
                 active-text-color="#409EFF"
                 style="position:fixed;top:0;left:0;min-height: 100%;width:250px;z-index:100"
                 router>
            <template v-for="(item,index) in permissionRoutes">
                <!--一級菜單-->
                <el-menu-item :index="item.path" v-if="item.children.length === 1 ">
                    <i class="el-icon-menu"></i>
<!--                    <div>我是</div>-->
                    <span>{{item.meta.title}}</span>
                </el-menu-item>
                <!--多級菜單-->
                <el-submenu :index="index+''" v-else>
                    <template slot="title">
                        <i class="el-icon-menu"></i>
                        <span>{{item.meta.title}}</span>
                    </template>
                    <template v-for="child in item.children">
                        <el-menu-item :index="item.path+'/'+child.path">{{child.meta.title}}</el-menu-item>
                    </template>
                </el-submenu>
            </template>
        </el-menu>
    </el-aside>
</template>
<script>
    import {mapState} from 'vuex'

    export default {
        data() {
            return {
            }
        },
        computed: {
            ...mapState({
                'permissionRoutes':state=>state.permission.permissionRoutes
            }),
            defaultActive: function () {
                if (this.$route.path.indexOf('/classInfo') >= 0) {
                    return 'classList'
                }
                return this.$route.path.replace('/org/', '');
            }
        },
        created() {
            window.setTimeout(()=>{
                console.log(this.permissionRoutes);
            },1000)
        }
    }
</script>

  











免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM