Skip to content

路由权限

本文档介绍前端路由权限的配置和使用。

路由配置

基础路由

typescript
// src/router/routes/modules/dashboard.ts
export default {
  path: '/dashboard',
  name: 'Dashboard',
  component: () => import('@/views/dashboard/index.vue'),
  meta: {
    title: '仪表盘',
    icon: 'lucide:home',
    requiresAuth: true
  }
};

权限路由

typescript
export default {
  path: '/system',
  name: 'System',
  meta: {
    title: '系统管理',
    icon: 'lucide:settings',
    requiresAuth: true,
    permissions: ['system:view']
  },
  children: [
    {
      path: 'user',
      name: 'SystemUser',
      component: () => import('@/views/system/user/index.vue'),
      meta: {
        title: '用户管理',
        permissions: ['system:user:view']
      }
    }
  ]
};

路由守卫

权限检查

typescript
// src/router/guard/permission.ts
router.beforeEach(async (to, from, next) => {
  const userStore = useUserStore();
  
  // 检查是否需要登录
  if (to.meta.requiresAuth && !userStore.isLogin) {
    next('/login');
    return;
  }
  
  // 检查权限
  if (to.meta.permissions) {
    const hasPermission = userStore.hasPermissions(to.meta.permissions);
    if (!hasPermission) {
      next('/403');
      return;
    }
  }
  
  next();
});

动态路由

后端返回路由

typescript
// src/api/auth/menu.ts
export function getMenuListApi() {
  return request.get('/system/menu/list');
}

生成路由

typescript
// src/store/modules/permission.ts
export const usePermissionStore = defineStore('permission', () => {
  const routes = ref<RouteRecordRaw[]>([]);
  
  async function generateRoutes() {
    const menuList = await getMenuListApi();
    routes.value = transformMenuToRoutes(menuList);
    
    // 动态添加路由
    routes.value.forEach(route => {
      router.addRoute(route);
    });
  }
  
  return {
    routes,
    generateRoutes
  };
});

按钮权限

指令方式

vue
<template>
  <a-button v-permission="['system:user:add']">
    新增
  </a-button>
</template>

函数方式

vue
<script setup lang="ts">
import { usePermission } from '@/hooks/usePermission';

const { hasPermission } = usePermission();

const canAdd = hasPermission(['system:user:add']);
</script>

<template>
  <a-button v-if="canAdd">新增</a-button>
</template>

权限工具

typescript
// src/hooks/usePermission.ts
export function usePermission() {
  const userStore = useUserStore();
  
  function hasPermission(permissions: string[]) {
    return permissions.some(permission => 
      userStore.permissions.includes(permission)
    );
  }
  
  function hasRole(roles: string[]) {
    return roles.some(role => 
      userStore.roles.includes(role)
    );
  }
  
  return {
    hasPermission,
    hasRole
  };
}

参考资源

MIT License