Browse Source

refactor: refactoring menu generation

vben 4 years ago
parent
commit
dc42d434f0

+ 4 - 0
.env

@@ -6,3 +6,7 @@ VITE_GLOB_APP_TITLE = Vben Admin
 
 # spa shortname
 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

+ 4 - 0
CHANGELOG.zh_CN.md

@@ -8,6 +8,10 @@
 - openModal 和 openDrawer 第二个参数可以代替`transferModalData`传参到内部
 - 带参路由可以被缓存
 
+### ✨ Refactor
+
+- 重构由后台生成菜单的逻辑
+
 ### ⚡ Performance Improvements
 
 - 菜单性能继续优化,更流畅

+ 55 - 0
build/vite/plugin/dynamicImport/index.ts

@@ -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;

+ 7 - 7
mock/sys/menu.ts

@@ -16,7 +16,7 @@ const dashboardRoute = {
     {
       path: '/welcome',
       name: 'Welcome',
-      component: '/dashboard/welcome/index.vue',
+      component: '/dashboard/welcome/index',
       meta: {
         title: '欢迎页',
         affix: true,
@@ -34,28 +34,28 @@ const frontRoute = {
   children: [
     {
       path: 'page',
-      component: '/demo/permission/front/index.vue',
+      component: '/demo/permission/front/index',
       meta: {
         title: '页面权限',
       },
     },
     {
       path: 'btn',
-      component: '/demo/permission/front/Btn.vue',
+      component: '/demo/permission/front/Btn',
       meta: {
         title: '按钮权限',
       },
     },
     {
       path: 'auth-pageA',
-      component: '/demo/permission/front/AuthPageA.vue',
+      component: '/demo/permission/front/AuthPageA',
       meta: {
         title: '权限测试页A',
       },
     },
     {
       path: 'auth-pageB',
-      component: '/demo/permission/front/AuthPageB.vue',
+      component: '/demo/permission/front/AuthPageB',
       meta: {
         title: '权限测试页B',
       },
@@ -71,14 +71,14 @@ const backRoute = {
   children: [
     {
       path: 'page',
-      component: 'demo/permission/back/index.vue',
+      component: '/demo/permission/back/index',
       meta: {
         title: '页面权限',
       },
     },
     {
       path: 'btn',
-      component: '/demo/permission/back/Btn.vue',
+      component: '/demo/permission/back/Btn',
       meta: {
         title: '按钮权限',
       },

+ 3 - 1
src/layouts/default/index.tsx

@@ -107,7 +107,9 @@ export default defineComponent({
                             unref(showHeaderRef) && <LayoutHeader />}
 
                           {showTabs && !unref(getFullContent) && (
-                            <MultipleTabs class={`default-layout__tabs`} />
+                            <Layout.Header class={`default-layout__tabs`}>
+                              {() => <MultipleTabs />}
+                            </Layout.Header>
                           )}
 
                           {useOpenBackTop && <BackTop target={getTarget} />}

+ 4 - 3
src/settings/projectSetting.ts

@@ -1,15 +1,16 @@
 import type { ProjectConfig } from '/@/types/config';
 
 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 { isProdMode } from '/@/utils/env';
+import { isProdMode, getRoleMode } from '/@/utils/env';
+
 // ! You need to clear the browser cache after the change
 const setting: ProjectConfig = {
   // Whether to show the configuration button
   showSettingButton: true,
   // 权限模式
-  permissionMode: PermissionModeEnum.ROLE,
+  permissionMode: getRoleMode(),
   // 网站灰色模式,用于可能悼念的日期开启
   grayMode: false,
   // 色弱模式

+ 4 - 4
src/store/modules/permission.ts

@@ -19,7 +19,7 @@ import { genRouteModule, transformObjToRoute } from '/@/utils/helper/routeHelper
 import { transformRouteToMenu } from '/@/utils/helper/menuHelper';
 
 import { useMessage } from '/@/hooks/web/useMessage';
-import { warn } from '/@/utils/log';
+// import { warn } from '/@/utils/log';
 
 const { createMessage } = useMessage();
 const NAME = 'permission';
@@ -99,9 +99,9 @@ class Permission extends VuexModule {
       });
       // this.commitRoutesState(routes);
       // Background permissions
-      warn(
-        `当前权限模式为:${PermissionModeEnum.ROLE},请将src/store/modules/permission.ts内的后台菜单获取函数注释,如果已注释可以忽略此信息!`
-      );
+      // warn(
+      //   `当前权限模式为:${PermissionModeEnum.ROLE},请将src/store/modules/permission.ts内的后台菜单获取函数注释,如果已注释可以忽略此信息!`
+      // );
       //  如果确定不需要做后台动态权限,请将下面整个判断注释
     } else if (permissionMode === PermissionModeEnum.BACK) {
       const messageKey = 'loadMenu';

+ 12 - 0
src/utils/env.ts

@@ -1,3 +1,4 @@
+import { PermissionModeEnum } from '../enums/appEnum';
 import type { GlobEnvConfig } from '/@/types/config';
 
 export const getGlobEnvConfig = (): GlobEnvConfig => {
@@ -46,3 +47,14 @@ export const isProdMode = (): boolean => import.meta.env.PROD;
  * @example:
  */
 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 - 0
src/utils/helper/dynamicImport.ts

@@ -0,0 +1,4 @@
+export default function (id: string) {
+  const dynamicImportModule: any = id;
+  return dynamicImportModule;
+}

+ 5 - 3
src/utils/helper/routeHelper.ts

@@ -6,6 +6,8 @@ import { tabStore } from '/@/store/modules/tab';
 import { createRouter, createWebHashHistory } from 'vue-router';
 import { toRaw } from 'vue';
 import { PAGE_LAYOUT_COMPONENT } from '/@/router/constant';
+// import { isDevMode } from '/@/utils/env';
+import dynamicImport from './dynamicImport';
 
 let currentTo: RouteLocationNormalized | null = null;
 
@@ -45,12 +47,12 @@ export function genRouteModule(moduleList: AppRouteModule[]) {
 // TODO  错误写法
 function asyncImportRoute(routes: AppRouteRecordRaw[]) {
   routes.forEach((item) => {
-    let { component } = item;
+    const { component } = item;
     const { children } = item;
     if (component) {
-      component = component.replace(/^\//, '');
-      item.component = () => import(`/@/views/${component}`);
+      item.component = dynamicImport(component);
     }
+
     children && asyncImportRoute(children);
   });
 }

+ 2 - 1
vite.config.ts

@@ -5,6 +5,7 @@ import { resolve } from 'path';
 import { modifyVars } from './build/config/lessModifyVars';
 import { createProxy } from './build/vite/proxy';
 import globbyTransform from './build/vite/plugin/context/transform';
+import dynamicImportTransform from './build/vite/plugin/dynamicImport/index';
 
 import { isDevFn, loadEnv } from './build/utils';
 
@@ -134,5 +135,5 @@ const viteConfig: UserConfig = {
 
 export default {
   ...viteConfig,
-  transforms: [globbyTransform(viteConfig)],
+  transforms: [globbyTransform(viteConfig), dynamicImportTransform(viteEnv)],
 } as UserConfig;