Skip to content

Commit

Permalink
refactor(projects): perf code
Browse files Browse the repository at this point in the history
  • Loading branch information
honghuangdc committed Oct 24, 2023
1 parent 542e5d3 commit 0b2e046
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 58 deletions.
5 changes: 4 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ VITE_ICON_LOCAL_PREFIX=icon-local
VITE_AUTH_ROUTE_MODE=static

# static auth route home
VITE_ROUTE_HOME=home
VITE_ROUTE_HOME=home

# default menu icon
VITE_MENU_ICON=mdi:menu
5 changes: 3 additions & 2 deletions packages/hooks/src/use-svg-icon-render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import type { Component } from 'vue';
/**
* svg icon render hook
* @param SvgIcon svg icon component
* @param defaultIcon default icon name (iconify icon name)
*/
export default function useSvgIconRender(SvgIcon: Component) {
export default function useSvgIconRender(SvgIcon: Component, defaultIcon: string) {
interface IconConfig {
/**
* iconify icon name
Expand All @@ -32,7 +33,7 @@ export default function useSvgIconRender(SvgIcon: Component) {
* @param config
*/
const SvgIconVNode = (config: IconConfig) => {
const { color, fontSize, icon, localIcon } = config;
const { color, fontSize, icon = defaultIcon, localIcon } = config;

const style: IconStyle = {};

Expand Down
1 change: 1 addition & 0 deletions src/enum/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export enum SetupStoreId {
App = 'app-store',
Theme = 'theme-store',
Auth = 'auth-store',
Route = 'route-store'
Expand Down
5 changes: 4 additions & 1 deletion src/layouts/base-layout/index.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { AdminLayout } from '@sa/materials';
import { useAppStore } from '@/store/modules/app';
import GlobalHeader from '../modules/global-header/index.vue';
import GlobalSider from '../modules/global-sider/index.vue';
import GlobalTab from '../modules/global-tab/index.vue';
Expand All @@ -9,10 +10,12 @@ import GlobalFooter from '../modules/global-footer/index.vue';
defineOptions({
name: 'BaseLayout'
});
const app = useAppStore();
</script>

<template>
<AdminLayout>
<AdminLayout :sider-collapse="app.siderCollapse">
<template #header>
<GlobalHeader />
</template>
Expand Down
11 changes: 10 additions & 1 deletion src/layouts/components/global-logo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@ import { $t } from '@/locales';
defineOptions({
name: 'GlobalLogo'
});
interface Props {
/**
* whether to show the title
*/
showTitle: boolean;
}
defineProps<Props>();
</script>

<template>
<RouterLink to="/" class="flex-center w-full nowrap-hidden">
<SystemLogo class="text-32px text-primary" />
<h2 class="pl-8px text-16px font-bold text-primary transition duration-300 ease-in-out">
<h2 v-show="showTitle" class="pl-8px text-16px font-bold text-primary transition duration-300 ease-in-out">
{{ $t('system.title') }}
</h2>
</RouterLink>
Expand Down
16 changes: 4 additions & 12 deletions src/layouts/modules/global-header/components/switch-lang.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
<script setup lang="ts">
import { ref } from 'vue';
import { setLocale } from '@/locales';
import { localStg } from '@/utils/storage';
import { useAppStore } from '@/store/modules/app';
defineOptions({
name: 'SwitchLang'
});
const locale = ref<App.I18n.LangType>(localStg.get('lang') || 'zh-CN');
const app = useAppStore();
type LocaleOption = {
label: string;
Expand All @@ -24,12 +22,6 @@ const options: LocaleOption[] = [
key: 'en'
}
];
function handleSelect(key: App.I18n.LangType) {
locale.value = key;
setLocale(key);
localStg.set('lang', key);
}
</script>

<template>
Expand All @@ -40,8 +32,8 @@ function handleSelect(key: App.I18n.LangType) {
</div>
</AButton>
<template #overlay>
<AMenu :selected-keys="[locale]">
<AMenuItem v-for="option in options" :key="option.key" @click="handleSelect(option.key)">
<AMenu :selected-keys="[app.locale]">
<AMenuItem v-for="option in options" :key="option.key" @click="app.changeLocale(option.key)">
{{ option.label }}
</AMenuItem>
</AMenu>
Expand Down
4 changes: 3 additions & 1 deletion src/layouts/modules/global-header/index.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<script setup lang="ts">
import { useAppStore } from '@/store/modules/app';
import { useThemeStore } from '@/store/modules/theme';
// import GlobalLogo from '../../components/global-logo.vue';
import SwitchLang from './components/switch-lang.vue';
import UserAvatar from './components/user-avatar.vue';
const app = useAppStore();
const themeStore = useThemeStore();
defineOptions({
Expand All @@ -14,7 +16,7 @@ defineOptions({
<template>
<DarkModeContainer class="flex-y-center h-full shadow-header">
<div class="flex-1-hidden flex-y-center h-full">
<MenuToggler />
<MenuToggler :collapsed="app.siderCollapse" @click="app.toggleSiderCollapse" />
</div>
<div class="flex justify-end h-full">
<SwitchLang />
Expand Down
6 changes: 4 additions & 2 deletions src/layouts/modules/global-sider/index.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
<script setup lang="ts">
import { useAppStore } from '@/store/modules/app';
import { useRouteStore } from '@/store/modules/route';
import GlobalLogo from '../../components/global-logo.vue';
defineOptions({
name: 'GlobalSider'
});
const app = useAppStore();
const route = useRouteStore();
</script>

<template>
<DarkModeContainer class="flex-vertical-stretch wh-full shadow-sider">
<GlobalLogo :show-title="true" class="h-48px" />
<GlobalLogo :show-title="!app.siderCollapse" class="h-48px" />
<div class="flex-1-hidden">
<AMenu mode="inline" :items="route.antdMenus" />
<AMenu mode="inline" :inline-collapsed="app.siderCollapse" :items="route.antdMenus" class="w-full" />
</div>
</DarkModeContainer>
</template>
Expand Down
3 changes: 2 additions & 1 deletion src/router/elegant/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ export const autoRoutes: ElegantRoute[] = [
meta: {
title: 'user-center',
i18nKey: 'route.user-center',
requiresAuth: true
requiresAuth: true,
hideInMenu: true
}
}
]
Expand Down
25 changes: 25 additions & 0 deletions src/store/modules/app/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ref } from 'vue';
import { defineStore } from 'pinia';
import { useBoolean } from '@sa/hooks';
import { SetupStoreId } from '@/enum';
import { setLocale } from '@/locales';
import { localStg } from '@/utils/storage';

export const useAppStore = defineStore(SetupStoreId.App, () => {
const locale = ref<App.I18n.LangType>(localStg.get('lang') || 'zh-CN');

function changeLocale(lang: App.I18n.LangType) {
locale.value = lang;
setLocale(lang);
localStg.set('lang', lang);
}

const { bool: siderCollapse, toggle: toggleSiderCollapse } = useBoolean();

return {
locale,
changeLocale,
siderCollapse,
toggleSiderCollapse
};
});
40 changes: 34 additions & 6 deletions src/store/modules/route/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ref } from 'vue';
import { ref, watch, effectScope, onScopeDispose } from 'vue';
import type { RouteRecordRaw } from 'vue-router';
import { defineStore } from 'pinia';
import { useBoolean } from '@sa/hooks';
Expand All @@ -7,8 +7,12 @@ import { SetupStoreId } from '@/enum';
import { router } from '@/router';
import { createRoutes } from '@/router/routes';
import { getGlobalMenusByAuthRoutes, getAntdMenuByGlobalMenus, getCacheRouteNames } from './shared';
import { useAppStore } from '../app';

export const useRouteStore = defineStore(SetupStoreId.Route, () => {
const app = useAppStore();
const scope = effectScope();

const { bool: isInitAuthRoute, setBool: setIsInitAuthRoute } = useBoolean();

/**
Expand All @@ -28,20 +32,26 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
*/
const globalMenus = ref<App.Global.Menu[]>([]);

/**
* get global menus
*/
function getGlobalMenus() {
const { treeRoutes } = createRoutes();
globalMenus.value = getGlobalMenusByAuthRoutes(treeRoutes);
getAntdMenus();
}

/**
* antd menus
*/
const antdMenus = ref<App.Global.AntdMenu[]>([]);

/**
* get global menus
* get antd menus
*/
function getGlobalMenus() {
const { treeRoutes } = createRoutes();
globalMenus.value = getGlobalMenusByAuthRoutes(treeRoutes);
function getAntdMenus() {
antdMenus.value = getAntdMenuByGlobalMenus(globalMenus.value);
}

/**
* cache routes
*/
Expand Down Expand Up @@ -95,6 +105,24 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
});
}

// watch store
scope.run(() => {
// update menus when locale changed
watch(
() => app.locale,
() => {
getAntdMenus();
}
);
});

/**
* on scope dispose
*/
onScopeDispose(() => {
scope.stop();
});

return {
antdMenus,
cacheRoutes,
Expand Down
66 changes: 35 additions & 31 deletions src/store/modules/route/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,42 @@ export function getGlobalMenusByAuthRoutes(routes: ElegantRoute[]) {
if (isFirstLevelRoute(route)) {
const child = route.children[0];

const { title, i18nKey, icon, localIcon } = child.meta ?? {};

const menu: App.Global.Menu = {
key: child.name,
title,
i18nKey,
routeKey: child.name,
routePath: route.path,
icon,
localIcon
};

menus.push(menu);
const { title, i18nKey, icon, localIcon, hideInMenu } = child.meta ?? {};

if (!hideInMenu) {
const menu: App.Global.Menu = {
key: child.name,
title,
i18nKey,
routeKey: child.name,
routePath: route.path,
icon,
localIcon
};

menus.push(menu);
}
} else {
const { name, path } = route;
const { title, i18nKey, icon, localIcon } = route.meta ?? {};

const menu: App.Global.Menu = {
key: name,
title,
i18nKey,
routeKey: name,
routePath: path,
icon,
localIcon
};

if (hasChildren(route)) {
menu.children = getGlobalMenusByAuthRoutes(route.children);
}
const { title, i18nKey, icon, localIcon, hideInMenu } = route.meta ?? {};

if (!hideInMenu) {
const menu: App.Global.Menu = {
key: name,
title,
i18nKey,
routeKey: name,
routePath: path,
icon,
localIcon
};

if (hasChildren(route)) {
menu.children = getGlobalMenusByAuthRoutes(route.children);
}

menus.push(menu);
menus.push(menu);
}
}
});

Expand Down Expand Up @@ -82,7 +86,7 @@ export function getCacheRouteNames(routes: ElegantRoute[]) {
}

export function getAntdMenuByGlobalMenus(globalMenus: App.Global.Menu[]) {
const { SvgIconVNode } = useSvgIconRender(SvgIcon);
const { SvgIconVNode } = useSvgIconRender(SvgIcon, import.meta.env.VITE_MENU_ICON);

const menus: App.Global.AntdMenu[] = [];

Expand All @@ -99,7 +103,7 @@ export function getAntdMenuByGlobalMenus(globalMenus: App.Global.Menu[]) {
};

if (children?.length) {
(antdMenu as any).children = getAntdMenuByGlobalMenus(children);
(antdMenu as App.Global.AntSubMenu).children = getAntdMenuByGlobalMenus(children);
}

menus.push(antdMenu);
Expand Down
1 change: 1 addition & 0 deletions src/typings/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ declare namespace App {

namespace Global {
type AntdMenu = NonNullable<import('ant-design-vue').ItemType>;
type AntSubMenu = import('ant-design-vue/es/menu/src/interface').SubMenuType;
type RouteKey = import('@elegant-router/types').RouteKey;
type RouteMap = import('@elegant-router/types').RouteMap;

Expand Down
5 changes: 5 additions & 0 deletions src/typings/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,10 @@ declare namespace Env {
* @description it only has effect when the auth route mode is static, if the route mode is dynamic, the home route key is defined in the back-end
*/
readonly VITE_ROUTE_HOME: import('@elegant-router/types').AutoRouteKey;
/**
* default menu icon if menu icon is not set
* @description iconify icon name
*/
readonly VITE_MENU_ICON: string;
}
}

0 comments on commit 0b2e046

Please sign in to comment.