feat: Dynamically get the menu from the back end

This commit is contained in:
vben
2024-06-30 15:03:37 +08:00
parent 1d70d71537
commit 9572d1a1c5
71 changed files with 1033 additions and 509 deletions

View File

@@ -3,16 +3,14 @@ import type { Router } from 'vue-router';
import { LOGIN_PATH } from '@vben/constants';
import { $t } from '@vben/locales';
import { startProgress, stopProgress } from '@vben/utils';
import { generatorMenus, generatorRoutes } from '@vben-core/helpers';
import { preferences } from '@vben-core/preferences';
import { useAccessStore } from '@vben-core/stores';
import { useTitle } from '@vueuse/core';
import { generateAccess } from '#/forward/access';
import { dynamicRoutes, essentialsRouteNames } from '#/router/routes';
const forbiddenPage = () => import('#/views/_essential/fallback/forbidden.vue');
/**
* 通用守卫配置
* @param router
@@ -96,22 +94,16 @@ function setupAccessGuard(router: Router) {
// 当前登录用户拥有的角色标识列表
const userRoles = accessStore.getUserRoles;
const accessibleRoutes = await generatorRoutes(
dynamicRoutes,
userRoles,
// 如果 route.meta.menuVisibleWithForbidden = true
// 生成菜单和路由
const { accessibleMenus, accessibleRoutes } = await generateAccess({
roles: userRoles,
router,
// 则会在菜单中显示但是访问会被重定向到403
// 这里可以指定403页面
forbiddenPage,
);
// 动态添加到router实例内
accessibleRoutes.forEach((route) => router.addRoute(route));
// 生成菜单
const menus = await generatorMenus(accessibleRoutes, router);
routes: dynamicRoutes,
});
// 保存菜单信息和路由信息
accessStore.setAccessMenus(menus);
accessStore.setAccessMenus(accessibleMenus);
accessStore.setAccessRoutes(accessibleRoutes);
const redirectPath = (from.query.redirect ?? to.path) as string;

View File

@@ -15,7 +15,7 @@ const fallbackNotFoundRoute: RouteRecordRaw = {
hideInTab: true,
title: '404',
},
name: 'Fallback',
name: 'FallbackNotFound',
path: '/:path(.*)*',
};

View File

@@ -15,14 +15,108 @@ const routes: RouteRecordRaw[] = [
},
name: 'Demos',
path: '/demos',
redirect: '/demos/fallback/403',
redirect: '/demos/access/frontend',
children: [
{
meta: {
icon: 'mdi:shield-key-outline',
title: $t('page.demos.access.title'),
},
name: 'Access',
path: '/access',
redirect: '/access/frontend',
children: [
{
name: 'AccessFrontend',
path: 'frontend',
meta: {
icon: 'mdi:table-key',
title: $t('page.demos.access.frontend-control'),
},
children: [
{
name: 'AccessFrontendPageControl',
path: 'page-control',
component: () =>
import('#/views/demos/access/frontend/index.vue'),
meta: {
icon: 'mdi:page-previous-outline',
title: $t('page.demos.access.page'),
},
},
{
name: 'AccessFrontendButtonControl',
path: 'button-control',
component: () =>
import('#/views/demos/access/frontend/button-control.vue'),
meta: {
icon: 'mdi:button-cursor',
title: $t('page.demos.access.button'),
},
},
{
name: 'AccessFrontendTest1',
path: 'access-test-1',
component: () =>
import('#/views/demos/access/frontend/access-test-1.vue'),
meta: {
authority: ['admin'],
icon: 'mdi:button-cursor',
title: $t('page.demos.access.access-test-1'),
},
},
{
name: 'AccessFrontendTest2',
path: 'access-test-2',
component: () =>
import('#/views/demos/access/frontend/access-test-2.vue'),
meta: {
authority: ['user'],
icon: 'mdi:button-cursor',
title: $t('page.demos.access.access-test-2'),
},
},
],
},
{
name: 'AccessBackend',
path: 'backend',
component: () => import('#/views/demos/access/backend/index.vue'),
meta: {
icon: 'mdi:cloud-key-outline',
title: $t('page.demos.access.backend-control'),
},
children: [
{
name: 'AccessBackendPageControl',
path: 'page-control',
component: () =>
import('#/views/demos/access/frontend/index.vue'),
meta: {
icon: 'mdi:page-previous-outline',
title: $t('page.demos.access.page'),
},
},
{
name: 'AccessBackendButtonControl',
path: 'button-control',
component: () =>
import('#/views/demos/access/frontend/button-control.vue'),
meta: {
icon: 'mdi:button-cursor',
title: $t('page.demos.access.button'),
},
},
],
},
],
},
{
meta: {
icon: 'mdi:lightbulb-error-outline',
title: $t('page.demos.fallback.title'),
},
name: 'FallbackLayout',
name: 'Fallback',
path: '/fallback',
redirect: '/fallback/403',
children: [