最近再写一个vue3项目中,需要涉及页面以及按钮权限,在此做一个简单的记录。

一、页面权限:

有两种方案可以实现(本文采用的第二种方式):

1、匹配角色路由后,通过vue-router中的addRoutes方法添加。

2、在sidebar组件中使用工具函数,通过meta中定义的code与后端返回的codeList做对比,没有则隐藏菜单。

sidebar.vue

<template>
  <div :class="{ 'has-logo': showLogo }">
    <Logo v-if="showLogo === '1'" :collapse="isCollapse" />
    <el-scrollbar wrap-class="scrollbar-wrapper">
      <el-menu
        :default-active="activeMenu"
        :collapse="isCollapse"
        unique-opened
        :collapse-transition="false"
        mode="vertical"
        @select="menuSelect"
      >
        <sidebar-item
          v-for="route in routes"
          :key="route.path"
          :item="route"
          :base-path="route.path"
        />
      </el-menu>
    </el-scrollbar>
  </div>
</template>

<script lang="ts">
  import { computed, defineComponent, ref, onBeforeMount } from 'vue'
  import { useRoute, useRouter } from 'vue-router'
  import { useStore } from 'vuex'
  import SidebarItem from './SidebarItem.vue'
  import { algorithm } from '../../../utils/algorithm'
  import { useDynamicRoutesHook } from '../tag/tagsHook'
  import { emitter } from '~@/utils/mitt'
  import Logo from './Logo.vue'
  import { storageLocal, storageSession } from '~@/utils/storage'
  import { authAllot } from '~@/utils'

  export default defineComponent({
    name: 'Sidebar',
    components: { SidebarItem, Logo },
    setup() {
      // 调用工具函数authAllot方法,设置菜单
      const router = authAllot(storageSession.getItem('auth'))

      const store = useStore()

      const route = useRoute()

      const showLogo = ref(storageLocal.getItem('logoVal') || '1')

      const activeMenu = computed(() => {
        const { meta, path } = route
        if (meta.activeMenu) {
          return meta.activeMenu
        }
        return path
      })

      const { dynamicRouteTags } = useDynamicRoutesHook()

      const menuSelect = (indexPath: string): void => {
        let parentPath = ''
        let parentPathIndex = indexPath.lastIndexOf('/')
        if (parentPathIndex > 0) {
          parentPath = indexPath.slice(0, parentPathIndex)
        }
        // 找到当前路由的信息
        function findCurrentRoute(routes) {
          return routes.map((item, key) => {
            if (item.path === indexPath) {
              dynamicRouteTags(indexPath, parentPath, item)
            } else {
              if (item.children) findCurrentRoute(item.children)
            }
          })
          return
        }
        findCurrentRoute(algorithm.increaseIndexes(router))
        emitter.emit('changLayoutRoute', indexPath)
      }

      onBeforeMount(() => {
        emitter.on('logoChange', (key) => {
          showLogo.value = key
        })
      })

      return {
        routes: computed(() => algorithm.increaseIndexes(router)),
        activeMenu,
        isCollapse: computed(() => !store.getters.sidebar.opened),
        menuSelect,
        showLogo
      }
    }
  })
</script>

authAllot工具函数

/**
 * @description: 根据code或者拼接规则设置菜单权限
 * @param { any } authList
 * @return { Array }
 */
export const authAllot = (authList: any[]) => {
  const router = XEUtils.clone(useRouter().options.routes, true)
  const mapRouter = (routes: any) => {
    if (Object.prototype.toString.call(routes) === '[object Array]') {
      return routes.reduce((result: any[], route: any) => {
        if (route.meta && !route?.meta?.code) route.meta.code = route?.path
        const code = route.meta?.code
        if (code) {
          const allow: any = authList.findIndex((auth: any) => auth.code === code)
          if (allow == '-1') {
            route.meta && (route.meta.hidden = true)
          }
        }
        if (route?.children?.length && code) {
          route?.children.forEach((_: any) => {
            if (!_?.meta?.code) {
              !_.path.includes('/')
                ? (_.meta.code = route.meta.code + '/' + _.path)
                : (_.meta.code = route.meta.code + _.path)
            }
          })
          mapRouter(route.children)
        }
        return [...result, route]
      }, [])
    } else {
      return []
    }
  }
  return mapRouter(router)
}

二、按钮权限:

使用自定义命令实现

import { storageSession } from '~@/utils/storage'

const directives = [
  {
    name: 'permission',
    value: {
      mounted(el: any, binding: any) {
        const type = binding.value || ''
        let status = false
        // 获取当前角色codeList
        const permissionBtns = storageSession.getItem('auth')
        permissionBtns.forEach((item: any) => {
          if (type == item.code) {
            status = true
          }
        })
        // 没有匹配则隐藏按钮
        if (!status) {
          el.style.display = 'none'
        }
      }
    }
  }
]

export const useDirectives = (app: any) => {
  directives.forEach((directive) => app.directive(directive.name, directive.value))
}

Logo

前往低代码交流专区

更多推荐