Commit dc42d434f0b2a3b269deb76d857b42340bd93e80

Authored by vben
1 parent 90b3fab2

refactor: refactoring menu generation

... ... @@ -6,3 +6,7 @@ VITE_GLOB_APP_TITLE = Vben Admin
6 6  
7 7 # spa shortname
8 8 VITE_GLOB_APP_SHORT_NAME = vue_vben_admin_2x
  9 +
  10 +# Menu generation mode BACK|ROLE
  11 +# Need to delete LocalStorage after modification
  12 +VITE_GEN_MENU_MODE=ROLE
... ...
CHANGELOG.zh_CN.md
... ... @@ -8,6 +8,10 @@
8 8 - openModal 和 openDrawer 第二个参数可以代替`transferModalData`传参到内部
9 9 - 带参路由可以被缓存
10 10  
  11 +### ✨ Refactor
  12 +
  13 +- 重构由后台生成菜单的逻辑
  14 +
11 15 ### ⚡ Performance Improvements
12 16  
13 17 - 菜单性能继续优化,更流畅
... ...
build/vite/plugin/dynamicImport/index.ts 0 → 100644
  1 +// Used to import all files under `src/views`
  2 +
  3 +// The built-in dynamic import of vite cannot meet the needs of importing all files under views
  4 +
  5 +import glob from 'glob';
  6 +import { Transform } from 'vite/dist/node/transform.js';
  7 +
  8 +function getPath(path: string) {
  9 + const lastIndex = path.lastIndexOf('.');
  10 + if (lastIndex !== -1) {
  11 + path = path.substring(0, lastIndex);
  12 + }
  13 + return path.replace('src/views', '');
  14 +}
  15 +
  16 +const dynamicImportTransform = function (env: any = {}): Transform {
  17 + return {
  18 + test({ path }) {
  19 + // Only convert the file
  20 + return path.includes('/src/utils/helper/dynamicImport.ts');
  21 + },
  22 + transform({ code }) {
  23 + const { VITE_GEN_MENU_MODE = '' } = env;
  24 + if (VITE_GEN_MENU_MODE !== 'BACK') {
  25 + return code;
  26 + }
  27 + // if (!isBuild) return code;
  28 + // Only convert the dir
  29 + try {
  30 + const files = glob.sync('src/views/**/**.{vue,tsx}', { cwd: process.cwd() });
  31 +
  32 + const _code = `
  33 + export default function (id) {
  34 + switch (id) {
  35 + ${files
  36 +
  37 + .map((p) =>
  38 + ` case '${getPath(p)}': return () => import('${p
  39 + .replace('src/views', '/@/views')
  40 + .replace(/\/\//g, '/')}');`.replace('.tsx', '')
  41 + )
  42 + .join('\n ')}
  43 + default: return Promise.reject(new Error("Unknown variable dynamic import: " + id));
  44 + }
  45 + }\n\n
  46 + `;
  47 + return _code;
  48 + } catch (error) {
  49 + console.error(error);
  50 + return code;
  51 + }
  52 + },
  53 + };
  54 +};
  55 +export default dynamicImportTransform;
... ...
mock/sys/menu.ts
... ... @@ -16,7 +16,7 @@ const dashboardRoute = {
16 16 {
17 17 path: '/welcome',
18 18 name: 'Welcome',
19   - component: '/dashboard/welcome/index.vue',
  19 + component: '/dashboard/welcome/index',
20 20 meta: {
21 21 title: '欢迎页',
22 22 affix: true,
... ... @@ -34,28 +34,28 @@ const frontRoute = {
34 34 children: [
35 35 {
36 36 path: 'page',
37   - component: '/demo/permission/front/index.vue',
  37 + component: '/demo/permission/front/index',
38 38 meta: {
39 39 title: '页面权限',
40 40 },
41 41 },
42 42 {
43 43 path: 'btn',
44   - component: '/demo/permission/front/Btn.vue',
  44 + component: '/demo/permission/front/Btn',
45 45 meta: {
46 46 title: '按钮权限',
47 47 },
48 48 },
49 49 {
50 50 path: 'auth-pageA',
51   - component: '/demo/permission/front/AuthPageA.vue',
  51 + component: '/demo/permission/front/AuthPageA',
52 52 meta: {
53 53 title: '权限测试页A',
54 54 },
55 55 },
56 56 {
57 57 path: 'auth-pageB',
58   - component: '/demo/permission/front/AuthPageB.vue',
  58 + component: '/demo/permission/front/AuthPageB',
59 59 meta: {
60 60 title: '权限测试页B',
61 61 },
... ... @@ -71,14 +71,14 @@ const backRoute = {
71 71 children: [
72 72 {
73 73 path: 'page',
74   - component: 'demo/permission/back/index.vue',
  74 + component: '/demo/permission/back/index',
75 75 meta: {
76 76 title: '页面权限',
77 77 },
78 78 },
79 79 {
80 80 path: 'btn',
81   - component: '/demo/permission/back/Btn.vue',
  81 + component: '/demo/permission/back/Btn',
82 82 meta: {
83 83 title: '按钮权限',
84 84 },
... ...
src/layouts/default/index.tsx
... ... @@ -107,7 +107,9 @@ export default defineComponent({
107 107 unref(showHeaderRef) && <LayoutHeader />}
108 108  
109 109 {showTabs && !unref(getFullContent) && (
110   - <MultipleTabs class={`default-layout__tabs`} />
  110 + <Layout.Header class={`default-layout__tabs`}>
  111 + {() => <MultipleTabs />}
  112 + </Layout.Header>
111 113 )}
112 114  
113 115 {useOpenBackTop && <BackTop target={getTarget} />}
... ...
src/settings/projectSetting.ts
1 1 import type { ProjectConfig } from '/@/types/config';
2 2  
3 3 import { MenuTypeEnum, MenuThemeEnum, MenuModeEnum, TriggerEnum } from '/@/enums/menuEnum';
4   -import { ContentEnum, PermissionModeEnum, RouterTransitionEnum } from '/@/enums/appEnum';
  4 +import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum';
5 5 import { primaryColor } from '../../build/config/lessModifyVars';
6   -import { isProdMode } from '/@/utils/env';
  6 +import { isProdMode, getRoleMode } from '/@/utils/env';
  7 +
7 8 // ! You need to clear the browser cache after the change
8 9 const setting: ProjectConfig = {
9 10 // Whether to show the configuration button
10 11 showSettingButton: true,
11 12 // 权限模式
12   - permissionMode: PermissionModeEnum.ROLE,
  13 + permissionMode: getRoleMode(),
13 14 // 网站灰色模式,用于可能悼念的日期开启
14 15 grayMode: false,
15 16 // 色弱模式
... ...
src/store/modules/permission.ts
... ... @@ -19,7 +19,7 @@ import { genRouteModule, transformObjToRoute } from &#39;/@/utils/helper/routeHelper
19 19 import { transformRouteToMenu } from '/@/utils/helper/menuHelper';
20 20  
21 21 import { useMessage } from '/@/hooks/web/useMessage';
22   -import { warn } from '/@/utils/log';
  22 +// import { warn } from '/@/utils/log';
23 23  
24 24 const { createMessage } = useMessage();
25 25 const NAME = 'permission';
... ... @@ -99,9 +99,9 @@ class Permission extends VuexModule {
99 99 });
100 100 // this.commitRoutesState(routes);
101 101 // Background permissions
102   - warn(
103   - `当前权限模式为:${PermissionModeEnum.ROLE},请将src/store/modules/permission.ts内的后台菜单获取函数注释,如果已注释可以忽略此信息!`
104   - );
  102 + // warn(
  103 + // `当前权限模式为:${PermissionModeEnum.ROLE},请将src/store/modules/permission.ts内的后台菜单获取函数注释,如果已注释可以忽略此信息!`
  104 + // );
105 105 // 如果确定不需要做后台动态权限,请将下面整个判断注释
106 106 } else if (permissionMode === PermissionModeEnum.BACK) {
107 107 const messageKey = 'loadMenu';
... ...
src/utils/env.ts
  1 +import { PermissionModeEnum } from '../enums/appEnum';
1 2 import type { GlobEnvConfig } from '/@/types/config';
2 3  
3 4 export const getGlobEnvConfig = (): GlobEnvConfig => {
... ... @@ -46,3 +47,14 @@ export const isProdMode = (): boolean =&gt; import.meta.env.PROD;
46 47 * @example:
47 48 */
48 49 export const isUseMock = (): boolean => import.meta.env.VITE_USE_MOCK === 'true';
  50 +
  51 +/**
  52 + * @description: 获取菜单生成方式
  53 + * @param {type}
  54 + * @returns:
  55 + * @example:
  56 + */
  57 +export const getRoleMode = (): PermissionModeEnum =>
  58 + import.meta.env.VITE_GEN_MENU_MODE === PermissionModeEnum.ROLE
  59 + ? PermissionModeEnum.ROLE
  60 + : PermissionModeEnum.BACK;
... ...
src/utils/helper/dynamicImport.ts 0 → 100644
  1 +export default function (id: string) {
  2 + const dynamicImportModule: any = id;
  3 + return dynamicImportModule;
  4 +}
... ...
src/utils/helper/routeHelper.ts
... ... @@ -6,6 +6,8 @@ import { tabStore } from &#39;/@/store/modules/tab&#39;;
6 6 import { createRouter, createWebHashHistory } from 'vue-router';
7 7 import { toRaw } from 'vue';
8 8 import { PAGE_LAYOUT_COMPONENT } from '/@/router/constant';
  9 +// import { isDevMode } from '/@/utils/env';
  10 +import dynamicImport from './dynamicImport';
9 11  
10 12 let currentTo: RouteLocationNormalized | null = null;
11 13  
... ... @@ -45,12 +47,12 @@ export function genRouteModule(moduleList: AppRouteModule[]) {
45 47 // TODO 错误写法
46 48 function asyncImportRoute(routes: AppRouteRecordRaw[]) {
47 49 routes.forEach((item) => {
48   - let { component } = item;
  50 + const { component } = item;
49 51 const { children } = item;
50 52 if (component) {
51   - component = component.replace(/^\//, '');
52   - item.component = () => import(`/@/views/${component}`);
  53 + item.component = dynamicImport(component);
53 54 }
  55 +
54 56 children && asyncImportRoute(children);
55 57 });
56 58 }
... ...
vite.config.ts
... ... @@ -5,6 +5,7 @@ import { resolve } from &#39;path&#39;;
5 5 import { modifyVars } from './build/config/lessModifyVars';
6 6 import { createProxy } from './build/vite/proxy';
7 7 import globbyTransform from './build/vite/plugin/context/transform';
  8 +import dynamicImportTransform from './build/vite/plugin/dynamicImport/index';
8 9  
9 10 import { isDevFn, loadEnv } from './build/utils';
10 11  
... ... @@ -134,5 +135,5 @@ const viteConfig: UserConfig = {
134 135  
135 136 export default {
136 137 ...viteConfig,
137   - transforms: [globbyTransform(viteConfig)],
  138 + transforms: [globbyTransform(viteConfig), dynamicImportTransform(viteEnv)],
138 139 } as UserConfig;
... ...