mirror of
https://github.com/vbenjs/vben-admin-thin-next.git
synced 2025-02-02 18:08:40 +08:00
refactor: refactoring menu generation
This commit is contained in:
parent
90b3fab28e
commit
dc42d434f0
4
.env
4
.env
@ -6,3 +6,7 @@ VITE_GLOB_APP_TITLE = Vben Admin
|
|||||||
|
|
||||||
# spa shortname
|
# spa shortname
|
||||||
VITE_GLOB_APP_SHORT_NAME = vue_vben_admin_2x
|
VITE_GLOB_APP_SHORT_NAME = vue_vben_admin_2x
|
||||||
|
|
||||||
|
# Menu generation mode BACK|ROLE
|
||||||
|
# Need to delete LocalStorage after modification
|
||||||
|
VITE_GEN_MENU_MODE=ROLE
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
- openModal 和 openDrawer 第二个参数可以代替`transferModalData`传参到内部
|
- openModal 和 openDrawer 第二个参数可以代替`transferModalData`传参到内部
|
||||||
- 带参路由可以被缓存
|
- 带参路由可以被缓存
|
||||||
|
|
||||||
|
### ✨ Refactor
|
||||||
|
|
||||||
|
- 重构由后台生成菜单的逻辑
|
||||||
|
|
||||||
### ⚡ Performance Improvements
|
### ⚡ Performance Improvements
|
||||||
|
|
||||||
- 菜单性能继续优化,更流畅
|
- 菜单性能继续优化,更流畅
|
||||||
|
55
build/vite/plugin/dynamicImport/index.ts
Normal file
55
build/vite/plugin/dynamicImport/index.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// Used to import all files under `src/views`
|
||||||
|
|
||||||
|
// The built-in dynamic import of vite cannot meet the needs of importing all files under views
|
||||||
|
|
||||||
|
import glob from 'glob';
|
||||||
|
import { Transform } from 'vite/dist/node/transform.js';
|
||||||
|
|
||||||
|
function getPath(path: string) {
|
||||||
|
const lastIndex = path.lastIndexOf('.');
|
||||||
|
if (lastIndex !== -1) {
|
||||||
|
path = path.substring(0, lastIndex);
|
||||||
|
}
|
||||||
|
return path.replace('src/views', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
const dynamicImportTransform = function (env: any = {}): Transform {
|
||||||
|
return {
|
||||||
|
test({ path }) {
|
||||||
|
// Only convert the file
|
||||||
|
return path.includes('/src/utils/helper/dynamicImport.ts');
|
||||||
|
},
|
||||||
|
transform({ code }) {
|
||||||
|
const { VITE_GEN_MENU_MODE = '' } = env;
|
||||||
|
if (VITE_GEN_MENU_MODE !== 'BACK') {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
// if (!isBuild) return code;
|
||||||
|
// Only convert the dir
|
||||||
|
try {
|
||||||
|
const files = glob.sync('src/views/**/**.{vue,tsx}', { cwd: process.cwd() });
|
||||||
|
|
||||||
|
const _code = `
|
||||||
|
export default function (id) {
|
||||||
|
switch (id) {
|
||||||
|
${files
|
||||||
|
|
||||||
|
.map((p) =>
|
||||||
|
` case '${getPath(p)}': return () => import('${p
|
||||||
|
.replace('src/views', '/@/views')
|
||||||
|
.replace(/\/\//g, '/')}');`.replace('.tsx', '')
|
||||||
|
)
|
||||||
|
.join('\n ')}
|
||||||
|
default: return Promise.reject(new Error("Unknown variable dynamic import: " + id));
|
||||||
|
}
|
||||||
|
}\n\n
|
||||||
|
`;
|
||||||
|
return _code;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default dynamicImportTransform;
|
@ -16,7 +16,7 @@ const dashboardRoute = {
|
|||||||
{
|
{
|
||||||
path: '/welcome',
|
path: '/welcome',
|
||||||
name: 'Welcome',
|
name: 'Welcome',
|
||||||
component: '/dashboard/welcome/index.vue',
|
component: '/dashboard/welcome/index',
|
||||||
meta: {
|
meta: {
|
||||||
title: '欢迎页',
|
title: '欢迎页',
|
||||||
affix: true,
|
affix: true,
|
||||||
@ -34,28 +34,28 @@ const frontRoute = {
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'page',
|
path: 'page',
|
||||||
component: '/demo/permission/front/index.vue',
|
component: '/demo/permission/front/index',
|
||||||
meta: {
|
meta: {
|
||||||
title: '页面权限',
|
title: '页面权限',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'btn',
|
path: 'btn',
|
||||||
component: '/demo/permission/front/Btn.vue',
|
component: '/demo/permission/front/Btn',
|
||||||
meta: {
|
meta: {
|
||||||
title: '按钮权限',
|
title: '按钮权限',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'auth-pageA',
|
path: 'auth-pageA',
|
||||||
component: '/demo/permission/front/AuthPageA.vue',
|
component: '/demo/permission/front/AuthPageA',
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限测试页A',
|
title: '权限测试页A',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'auth-pageB',
|
path: 'auth-pageB',
|
||||||
component: '/demo/permission/front/AuthPageB.vue',
|
component: '/demo/permission/front/AuthPageB',
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限测试页B',
|
title: '权限测试页B',
|
||||||
},
|
},
|
||||||
@ -71,14 +71,14 @@ const backRoute = {
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'page',
|
path: 'page',
|
||||||
component: 'demo/permission/back/index.vue',
|
component: '/demo/permission/back/index',
|
||||||
meta: {
|
meta: {
|
||||||
title: '页面权限',
|
title: '页面权限',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'btn',
|
path: 'btn',
|
||||||
component: '/demo/permission/back/Btn.vue',
|
component: '/demo/permission/back/Btn',
|
||||||
meta: {
|
meta: {
|
||||||
title: '按钮权限',
|
title: '按钮权限',
|
||||||
},
|
},
|
||||||
|
@ -107,7 +107,9 @@ export default defineComponent({
|
|||||||
unref(showHeaderRef) && <LayoutHeader />}
|
unref(showHeaderRef) && <LayoutHeader />}
|
||||||
|
|
||||||
{showTabs && !unref(getFullContent) && (
|
{showTabs && !unref(getFullContent) && (
|
||||||
<MultipleTabs class={`default-layout__tabs`} />
|
<Layout.Header class={`default-layout__tabs`}>
|
||||||
|
{() => <MultipleTabs />}
|
||||||
|
</Layout.Header>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{useOpenBackTop && <BackTop target={getTarget} />}
|
{useOpenBackTop && <BackTop target={getTarget} />}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import type { ProjectConfig } from '/@/types/config';
|
import type { ProjectConfig } from '/@/types/config';
|
||||||
|
|
||||||
import { MenuTypeEnum, MenuThemeEnum, MenuModeEnum, TriggerEnum } from '/@/enums/menuEnum';
|
import { MenuTypeEnum, MenuThemeEnum, MenuModeEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||||
import { ContentEnum, PermissionModeEnum, RouterTransitionEnum } from '/@/enums/appEnum';
|
import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum';
|
||||||
import { primaryColor } from '../../build/config/lessModifyVars';
|
import { primaryColor } from '../../build/config/lessModifyVars';
|
||||||
import { isProdMode } from '/@/utils/env';
|
import { isProdMode, getRoleMode } from '/@/utils/env';
|
||||||
|
|
||||||
// ! You need to clear the browser cache after the change
|
// ! You need to clear the browser cache after the change
|
||||||
const setting: ProjectConfig = {
|
const setting: ProjectConfig = {
|
||||||
// Whether to show the configuration button
|
// Whether to show the configuration button
|
||||||
showSettingButton: true,
|
showSettingButton: true,
|
||||||
// 权限模式
|
// 权限模式
|
||||||
permissionMode: PermissionModeEnum.ROLE,
|
permissionMode: getRoleMode(),
|
||||||
// 网站灰色模式,用于可能悼念的日期开启
|
// 网站灰色模式,用于可能悼念的日期开启
|
||||||
grayMode: false,
|
grayMode: false,
|
||||||
// 色弱模式
|
// 色弱模式
|
||||||
|
@ -19,7 +19,7 @@ import { genRouteModule, transformObjToRoute } from '/@/utils/helper/routeHelper
|
|||||||
import { transformRouteToMenu } from '/@/utils/helper/menuHelper';
|
import { transformRouteToMenu } from '/@/utils/helper/menuHelper';
|
||||||
|
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
import { warn } from '/@/utils/log';
|
// import { warn } from '/@/utils/log';
|
||||||
|
|
||||||
const { createMessage } = useMessage();
|
const { createMessage } = useMessage();
|
||||||
const NAME = 'permission';
|
const NAME = 'permission';
|
||||||
@ -99,9 +99,9 @@ class Permission extends VuexModule {
|
|||||||
});
|
});
|
||||||
// this.commitRoutesState(routes);
|
// this.commitRoutesState(routes);
|
||||||
// Background permissions
|
// Background permissions
|
||||||
warn(
|
// warn(
|
||||||
`当前权限模式为:${PermissionModeEnum.ROLE},请将src/store/modules/permission.ts内的后台菜单获取函数注释,如果已注释可以忽略此信息!`
|
// `当前权限模式为:${PermissionModeEnum.ROLE},请将src/store/modules/permission.ts内的后台菜单获取函数注释,如果已注释可以忽略此信息!`
|
||||||
);
|
// );
|
||||||
// 如果确定不需要做后台动态权限,请将下面整个判断注释
|
// 如果确定不需要做后台动态权限,请将下面整个判断注释
|
||||||
} else if (permissionMode === PermissionModeEnum.BACK) {
|
} else if (permissionMode === PermissionModeEnum.BACK) {
|
||||||
const messageKey = 'loadMenu';
|
const messageKey = 'loadMenu';
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { PermissionModeEnum } from '../enums/appEnum';
|
||||||
import type { GlobEnvConfig } from '/@/types/config';
|
import type { GlobEnvConfig } from '/@/types/config';
|
||||||
|
|
||||||
export const getGlobEnvConfig = (): GlobEnvConfig => {
|
export const getGlobEnvConfig = (): GlobEnvConfig => {
|
||||||
@ -46,3 +47,14 @@ export const isProdMode = (): boolean => import.meta.env.PROD;
|
|||||||
* @example:
|
* @example:
|
||||||
*/
|
*/
|
||||||
export const isUseMock = (): boolean => import.meta.env.VITE_USE_MOCK === 'true';
|
export const isUseMock = (): boolean => import.meta.env.VITE_USE_MOCK === 'true';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 获取菜单生成方式
|
||||||
|
* @param {type}
|
||||||
|
* @returns:
|
||||||
|
* @example:
|
||||||
|
*/
|
||||||
|
export const getRoleMode = (): PermissionModeEnum =>
|
||||||
|
import.meta.env.VITE_GEN_MENU_MODE === PermissionModeEnum.ROLE
|
||||||
|
? PermissionModeEnum.ROLE
|
||||||
|
: PermissionModeEnum.BACK;
|
||||||
|
4
src/utils/helper/dynamicImport.ts
Normal file
4
src/utils/helper/dynamicImport.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export default function (id: string) {
|
||||||
|
const dynamicImportModule: any = id;
|
||||||
|
return dynamicImportModule;
|
||||||
|
}
|
@ -6,6 +6,8 @@ import { tabStore } from '/@/store/modules/tab';
|
|||||||
import { createRouter, createWebHashHistory } from 'vue-router';
|
import { createRouter, createWebHashHistory } from 'vue-router';
|
||||||
import { toRaw } from 'vue';
|
import { toRaw } from 'vue';
|
||||||
import { PAGE_LAYOUT_COMPONENT } from '/@/router/constant';
|
import { PAGE_LAYOUT_COMPONENT } from '/@/router/constant';
|
||||||
|
// import { isDevMode } from '/@/utils/env';
|
||||||
|
import dynamicImport from './dynamicImport';
|
||||||
|
|
||||||
let currentTo: RouteLocationNormalized | null = null;
|
let currentTo: RouteLocationNormalized | null = null;
|
||||||
|
|
||||||
@ -45,12 +47,12 @@ export function genRouteModule(moduleList: AppRouteModule[]) {
|
|||||||
// TODO 错误写法
|
// TODO 错误写法
|
||||||
function asyncImportRoute(routes: AppRouteRecordRaw[]) {
|
function asyncImportRoute(routes: AppRouteRecordRaw[]) {
|
||||||
routes.forEach((item) => {
|
routes.forEach((item) => {
|
||||||
let { component } = item;
|
const { component } = item;
|
||||||
const { children } = item;
|
const { children } = item;
|
||||||
if (component) {
|
if (component) {
|
||||||
component = component.replace(/^\//, '');
|
item.component = dynamicImport(component);
|
||||||
item.component = () => import(`/@/views/${component}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
children && asyncImportRoute(children);
|
children && asyncImportRoute(children);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import { resolve } from 'path';
|
|||||||
import { modifyVars } from './build/config/lessModifyVars';
|
import { modifyVars } from './build/config/lessModifyVars';
|
||||||
import { createProxy } from './build/vite/proxy';
|
import { createProxy } from './build/vite/proxy';
|
||||||
import globbyTransform from './build/vite/plugin/context/transform';
|
import globbyTransform from './build/vite/plugin/context/transform';
|
||||||
|
import dynamicImportTransform from './build/vite/plugin/dynamicImport/index';
|
||||||
|
|
||||||
import { isDevFn, loadEnv } from './build/utils';
|
import { isDevFn, loadEnv } from './build/utils';
|
||||||
|
|
||||||
@ -134,5 +135,5 @@ const viteConfig: UserConfig = {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
...viteConfig,
|
...viteConfig,
|
||||||
transforms: [globbyTransform(viteConfig)],
|
transforms: [globbyTransform(viteConfig), dynamicImportTransform(viteEnv)],
|
||||||
} as UserConfig;
|
} as UserConfig;
|
||||||
|
Loading…
Reference in New Issue
Block a user