Commit dc42d434f0b2a3b269deb76d857b42340bd93e80
1 parent
90b3fab2
refactor: refactoring menu generation
Showing
11 changed files
with
104 additions
and
19 deletions
.env
CHANGELOG.zh_CN.md
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 '/@/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 => 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
src/utils/helper/routeHelper.ts
... | ... | @@ -6,6 +6,8 @@ import { tabStore } from '/@/store/modules/tab'; |
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 'path'; |
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; | ... | ... |