[权限]基于角色的静态模式

发布时间 2023-04-08 18:16:16作者: Sherwin_szw

绝大多数,用户角色和功能固定时,推荐在这种方式。
开发简单,工作量少,可以快速交付。

1. 登录

当用户登录时,将用户角色写入到vuex,保存当前用户角色信息。

# store/index.js

import {createStore} from 'vuex'

export default createStore({
    state: {
        token: localStorage.getItem('token') || '',
        role: localStorage.getItem('role') || ''
    },
    getters: {},
    mutations: {
        login(state, {token, role}) {
            state.token = token
            state.role = role
            localStorage.setItem('token', token)
            localStorage.setItem('role', role)
        }
    },
    actions: {},
    modules: {}
})
# 登陆
const handleFinish = () => {
  const login_info = {
    token: '123',
    role: formState.role
  }
  store.commit('login', login_info)
  message.info(formState.user + "登陆成功")
  router.replace({name: "admin"})
};

2.定义路由

定义路由时,基于 meta 来指定哪些角色的用户可以访问此路由。

# router/index.js
const routes = [
    {
        path: '/login',
        name: 'login',
        component: () => import('../views/LoginView.vue'),
        meta: {is_menu: false}
    }, {
        path: '/admin',
        name: 'admin',
        component: () => import('../views/AdminView.vue'),
        meta: {is_menu: false},
        children:
            [
                {
                    path: 'user',
                    name: 'user',
                    component: () => import('../views/admin/UserView.vue'),
                    meta: {role: ['user'], is_menu: true, title: 'user'}
                },
                {
                    path: 'user2',
                    name: 'user2',
                    component: () => import('../views/admin/User2View.vue'),
                    meta: {role: ['admin'], is_menu: true, title: 'user2'}

                },
                {
                    path: 'all',
                    name: 'all',
                    component: () => import('../views/admin/AllView.vue'),
                    meta: {role: ['admin','user'], is_menu: true, title: 'all'}

                }]
    }]

3.路由导航守卫

用户访问页面时,在导航守卫中,进行判断,是否有权访问此路由。

  • 有权,继续访问
  • 无权,跳转登录页面
outer.beforeEach((to, from, next) => {
    let roles = to.meta.role
    if (roles) {
        console.log(store.state.role)
        // 在roles里找权限store.state.role,找不到返回-1
        if (roles.indexOf(store.state.role) != -1) {
            next()
        } else {
            next({name: "login"})
        }
    } else {
        next()
    }
})

4.菜单的加载

根据vuex中的角色,加载自己的路由,并添加在菜单中。

<template>
  <a-layout>
    <a-layout-sider :style="{ overflow: 'auto', height: '100vh', position: 'fixed', left: 0 }">
      <div class="logo"/>
      <a-menu theme="dark" mode="inline" v-model:selectedKeys="selectedKeys">
        <a-menu-item :key="item" v-for="item in routerlist">
          <user-outlined/>
          <router-link :to="{name:item.name}">{{ item.meta.title }}</router-link>
        </a-menu-item>
      </a-menu>
    </a-layout-sider>
    <a-layout :style="{ marginLeft: '200px' }">
      <a-layout-header :style="{ background: '#fff', padding: 0 }"/>
      <a-layout-content :style="{ margin: '24px 16px 0', overflow: 'initial' }">
        <div :style="{ padding: '24px', background: '#fff', textAlign: 'center' }">
          <router-view/>
        </div>
      </a-layout-content>
    </a-layout>
  </a-layout>
</template>
<script setup>
import {
  UserOutlined,
  // VideoCameraOutlined,
} from '@ant-design/icons-vue';
import {computed, ref} from 'vue';
import {useRouter} from "vue-router";
import {useStore} from "vuex";

const router = useRouter()
const store = useStore()
const selectedKeys = ref(['1'])
const routerlist = computed(
    () => {
      return router.getRoutes().filter(item => {
        if (item.meta.is_menu && item.meta.role.indexOf(store.state.role) != -1) {
          return true
        }
      })
    }
)
</script>