• 【Vue 开发实战】实战篇 # 32:如何使用路由管理用户权限


    说明

    Vue 开发实战】学习笔记。

    效果

    访问没有权限的路由跳转到403页面

    在这里插入图片描述

    菜单也是根据权限进行展示,比如是user用户没有表单的权限访问

    在这里插入图片描述

    auth.js 权限校验文件

    export function getCurrentAuthority() {
        return ["user"];
    }
    
    export function check(authority) {
        const current = getCurrentAuthority();
        return current.some(item => authority.includes(item));
    }
    
    export function isLogin() {
        const current = getCurrentAuthority();
        return current && current[0] !== "guest";
    }
    

    403 页面

    <template>
        <div>403页面div>
    template>
    
    <script>
    export default {};
    script>
    
    <style>style>
    

    路由配置页面

    import Vue from "vue";
    import VueRouter from "vue-router";
    import NProgress from "nprogress";
    import "nprogress/nprogress.css";
    import { notification } from "ant-design-vue";
    import NotFound from "../views/404";
    import Forbidden from "../views/403";
    import findLast from "lodash/findLast";
    import { check, isLogin } from "../utils/auth";
    
    Vue.use(VueRouter);
    
    const routes = [
    	{
    		path: "/user",
            hideInMenu: true,
    		component: () =>
    			import(/* webpackChunkName: "layout" */ "../layouts/UserLayout"),
    		children: [
    			{
    				path: "/user",
    				redirect: "/user/login"
    			},
    			{
    				path: "/user/login",
    				name: "login",
    				component: () =>
    					import(/* webpackChunkName: "user" */ "../views/User/Login"),
    			},
    			{
    				path: "/user/register",
    				name: "register",
    				component: () =>
    					import(/* webpackChunkName: "user" */ "../views/User/Register"),
    			}
    		],
    	},
    	{
    		path: "/",
            meta: { authority: ["user", "admin"]},
    		component: () =>
    			import(/* webpackChunkName: "layout" */ "../layouts/BasicLayout"),
    		children: [
    			{
    				path: "/",
    				redirect: "/dashboard"
    			},
    			{
    				path: "/dashboard",
    				redirect: "/dashboard/analysis"
    			},
    			{
    				path: "/dashboard",
    				name: "dashboard",
                    meta: { icon: "dashboard", title: "仪表盘" },
    				component: { render: h => h("router-view")},
    				children: [
    					{
    						path: "/dashboard/analysis",
    						name: "analysis",
                            meta: { title: "分析页" },
    						component: () =>
    							import(/* webpackChunkName: "dashboard" */ "../views/Dashboard/Analysis"),
    					},
    				]
    			},
    			{
    				path: "/form",
    				name: "form",
                    meta: { icon: "form", title: "表单", authority: ["admin"] },
    				component: { render: h => h("router-view")},
    				children: [
    					{
    						path: "/form",
    						redirect: "/form/basic-form"
    					},
    					{
    						path: "/form/basic-form",
    						name: "basicform",
                            meta: { title: "基础表单" },
    						component: () =>
    							import(/* webpackChunkName: "form" */ "../views/Forms/BasicForm"),
    					},
    					{
    						path: "/form/step-form",
    						name: "stepform",
                            hideChildrenInMenu: true,
                            meta: { title: "分步表单" },
                            component: () =>
    							import(/* webpackChunkName: "form" */ "../views/Forms/StepForm"),
    						children: [
    							{
    								path: "/form/step-form",
    								redirect: "/form/step-form/info"
    							},
    							{
    								path: "/form/step-form/info",
    								name: "info",
    								component: () =>
    									import(/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step1"),
    							},
    							{
    								path: "/form/step-form/confirm",
    								name: "confirm",
    								component: () =>
    									import(/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step2"),
    							},
    							{
    								path: "/form/step-form/result",
    								name: "result",
    								component: () =>
    									import(/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step3"),
    							},
    						]
    					},
    				]
    			}
    		],
    	},
    	{
    		path: "/403",
    		name: "403",
            hideInMenu: true,
    		component: Forbidden
    	},
    	{
    		path: "*",
    		name: "404",
            hideInMenu: true,
    		component: NotFound
    	}
    ];
    
    const router = new VueRouter({
    	mode: "history",
    	base: process.env.BASE_URL,
    	routes
    });
    
    // 路由守卫
    router.beforeEach((to, from, next) => {
        if(to.path !== from.path) {
    	    NProgress.start();
        }
        // 找到最近匹配的那个
        const record = findLast(to.matched, record => record.meta.authority);
        if(record && !check(record.meta.authority)) {
            if(!isLogin() && to.path !== "/user/login") {
                next({
                    path: "/user/login"
                });
            }else if(to.path !== "/403"){
                notification.error({
                    message: "403",
                    description: "你没有权限访问,请联系管理员"
                });
                next({
                    path: "/403"
                });
            }
    	    NProgress.done();
        }
    	next();
    })
    
    router.afterEach((to, from) => {
    	NProgress.done();
    })
    
    export default router;
    

    侧边栏权限 SiderMenu.vue

    <template>
        <div style="width: 256px">
            <a-menu
                :selectedKeys="selectedKeys"
                :openKeys.sync="openKeys"
                mode="inline"
                :theme="theme"
            >
                <template v-for="item in menuData">
                    <a-menu-item v-if="!item.children"
                        :key="item.path"
                        @click="() => $router.push({path: item.path, query: $router.query})"
                    >
                        <a-icon v-if="item.meta.icon" :type="item.meta.icon" />
                        <span>{{ item.meta.title }}span>
                    a-menu-item>
                    <sub-menu v-else :key="item.path" :menu-info="item" />
                template>
            a-menu>
        div>
    template>
    
    <script>
    import SubMenu from "./SubMenu.vue";
    import { check } from "../utils/auth";
    export default {
        props: {
            theme: {
                type: String,
                default: "dark"
            }
        },
        components: {
            "sub-menu": SubMenu
        },
        data() {
            this.selectedKeysMap = {};
            this.openKeysMap = {};
            const menuData = this.getMenuData(this.$router.options.routes)
            return {
                collapsed: false,
                menuData,
                selectedKeys: this.selectedKeysMap[this.$route.path],
                openKeys: this.collapsed ? [] : this.openKeysMap[this.$route.path]
            };
        },
        watch: {
            "$route.path": function(val) {
                this.selectedKeys = this.selectedKeysMap[val];
                this.openKeys = this.collapsed ? [] : this.openKeysMap[val];
            }
        },
        methods: {
            getMenuData(routes = [], parentKeys = [], selectedKeys) {
                const menuData = [];
                for(let item of routes) {
                    if(item.meta && item.meta.authority && !check(item.meta.authority)) {
                        break;
                    }
                    if(item.name && !item.hideInMenu) {
                        this.openKeysMap[item.path] = parentKeys;
                        this.selectedKeysMap[item.path] = [selectedKeys || item.path];
                        const newItem = {...item};
                        delete newItem.children;
                        if(item.children && !item.hideChildrenInMenu) {
                            newItem.children = this.getMenuData(item.children, [...parentKeys, item.path]);
                        }else{
                            this.getMenuData(
                                item.children, 
                                selectedKeys ? parentKeys : [...parentKeys, item.path],
                                selectedKeys || item.path
                            );
                        }
                        menuData.push(newItem);
                    }else if(
                        !item.hideInMenu &&
                        !item.hideChildrenInMenu &&
                        item.children
                    ) {
                        menuData.push(...this.getMenuData(item.children, [...parentKeys, item.path]));
                    }
                }
                return menuData;
            }
        },
    };
    script>
    
    
  • 相关阅读:
    你真的了解Spring的依赖查找吗?
    shell脚本之数组元素排序
    目标检测技术概述
    【Windows】你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问,这些策略可帮助保护你的电脑
    主成分分析(机器学习)
    java计算机毕业设计志愿者管理系统演示录像2020源码+mysql数据库+系统+lw文档+部署
    香港金融交易解决方案提供商【移动财经】申请840美元纳斯达克IPO上市
    【计算机网络】数据链路层:点对点协议PPP
    记录一下一些卷积模块
    Nacos的使用记录
  • 原文地址:https://blog.csdn.net/kaimo313/article/details/126703975