Browse Source

perf: perf menu mini style

vben 4 năm trước cách đây
mục cha
commit
66acb21edd

+ 10 - 8
src/components/Menu/src/BasicMenu.tsx

@@ -145,6 +145,15 @@ export default defineComponent({
         resetKeys();
       }
     }
+
+    const showTitle = computed(() => {
+      if (!props.isAppMenu) return true;
+      if (!props.collapsedShowTitle) {
+        return !menuStore.getCollapsedState;
+      }
+      return true;
+    });
+
     // render menu item
     function renderMenuItem(menuList?: MenuType[], index = 1) {
       if (!menuList) {
@@ -153,13 +162,6 @@ export default defineComponent({
       const { appendClass } = props;
       const levelCls = `basic-menu-item__level${index} ${menuState.theme} `;
 
-      const showTitle = computed(() => {
-        if (!props.isAppMenu) return true;
-        if (!props.collapsedShowTitle) {
-          return !menuStore.getCollapsedState;
-        }
-        return true;
-      });
       return menuList.map((menu) => {
         if (!menu) {
           return null;
@@ -249,7 +251,7 @@ export default defineComponent({
       return mode === MenuModeEnum.HORIZONTAL ? (
         renderMenu()
       ) : (
-        <section class={`basic-menu-wrap`}>
+        <section class={[`basic-menu-wrap`, !unref(showTitle) && 'hide-title']}>
           {getSlot(slots, 'header')}
           <SearchInput
             class={!props.search ? 'hidden' : ''}

+ 28 - 11
src/components/Menu/src/index.less

@@ -1,25 +1,37 @@
 @import (reference) '../../../design/index.less';
 
+.active-style() {
+  color: @white;
+  background: linear-gradient(
+    118deg,
+    rgba(@primary-color, 0.7),
+    rgba(@primary-color, 1)
+  ) !important;
+  border-radius: 2px;
+  box-shadow: 0 0 4px 1px rgba(@primary-color, 0.7);
+}
+
 .active-menu-style() {
   .ant-menu-item-selected,
   .ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected {
-    background: linear-gradient(
-      118deg,
-      rgba(@primary-color, 0.7),
-      rgba(@primary-color, 1)
-    ) !important;
-    border-radius: 2px;
-    box-shadow: 0 0 4px 1px rgba(@primary-color, 0.7);
+    .active-style();
   }
 }
 
 .basic-menu {
+  width: 100%;
+
   &.collapsed-show-title.ant-menu-inline-collapsed {
+    .basic-menu-item__level1 {
+      padding: 2px 0;
+    }
+
     & > li > .ant-menu-submenu-title {
       display: flex;
       margin-top: 12px;
       font-size: 12px;
       flex-direction: column;
+      line-height: 24px;
     }
 
     & > li[role='menuitem']:not(.ant-menu-submenu) {
@@ -106,7 +118,7 @@
         .ant-menu-submenu-open,
         .ant-menu-item-selected,
         .ant-menu-submenu-selected {
-          color: @primary-color;
+          color: @white !important;
           border-bottom: 3px solid @primary-color;
         }
 
@@ -115,7 +127,7 @@
         .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,
         .ant-menu-submenu-active,
         .ant-menu-submenu-title:hover {
-          color: @primary-color;
+          color: @white !important;
           border-bottom: 3px solid @primary-color;
         }
 
@@ -194,12 +206,12 @@
     }
 
     .basic-menu-item__level1 {
+      margin-bottom: 0;
+
       > .ant-menu-sub > li {
         background-color: @sub-menu-item-dark-bg-color;
       }
 
-      margin-bottom: 0;
-
       &.top-active-menu {
         color: @white;
         background: @top-menu-active-bg-color;
@@ -236,6 +248,11 @@
     }
 
     &.ant-menu-inline-collapsed {
+      .ant-menu-submenu-selected,
+      .ant-menu-item-selected {
+        .active-style();
+      }
+
       .ant-menu-item-selected {
         background: unset !important;
         box-shadow: none;

+ 1 - 1
src/components/Menu/src/props.ts

@@ -31,7 +31,7 @@ export const basicProps = {
   },
   // 菜单组件的mode属性
   mode: {
-    type: String as PropType<string>,
+    type: String as PropType<MenuModeEnum>,
     default: MenuModeEnum.INLINE,
   },
   type: {

+ 3 - 0
src/enums/appEnum.ts

@@ -1,3 +1,6 @@
+export const SIDE_BAR_MINI_WIDTH = 58;
+export const SIDE_BAR_SHOW_TIT_MINI_WIDTH = 80;
+
 export enum ContentEnum {
   // auto width
   FULL = 'full',

+ 7 - 0
src/hooks/core/useSetting.ts

@@ -4,6 +4,9 @@ import getProjectSetting from '/@/settings/projectSetting';
 
 import { getGlobEnvConfig, isDevMode } from '/@/utils/env';
 import { getShortName } from '../../../build/getShortName';
+import { warn } from '/@/utils/log';
+
+const reg = /[a-zA-Z\_]*/;
 
 const ENV_NAME = getShortName(import.meta.env);
 const ENV = ((isDevMode()
@@ -16,6 +19,10 @@ const {
   VITE_GLOB_API_URL_PREFIX,
 } = ENV;
 
+if (!reg.test(VITE_GLOB_APP_SHORT_NAME)) {
+  warn(`VITE_GLOB_APP_SHORT_NAME 变量只能是字符/下划线,请在环境变量中修改并重新运行。`);
+}
+
 export const useSetting = (): SettingWrap => {
   // Take global configuration
   const glob: Readonly<GlobConfig> = {

+ 14 - 5
src/layouts/default/LayoutSideBar.tsx

@@ -10,8 +10,10 @@ import darkImg from '/@/assets/images/sidebar/dark.png';
 import lightImg from '/@/assets/images/sidebar/light.png';
 import { appStore } from '/@/store/modules/app';
 import { MenuModeEnum, MenuSplitTyeEnum, MenuThemeEnum } from '/@/enums/menuEnum';
+import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum';
 import { useDebounce } from '/@/hooks/core/useDebounce';
 import LayoutMenu from './LayoutMenu';
+
 export default defineComponent({
   name: 'DefaultLayoutSideBar',
   setup() {
@@ -25,6 +27,13 @@ export default defineComponent({
       return appStore.getProjectConfig;
     });
 
+    const getMiniWidth = computed(() => {
+      const {
+        menuSetting: { collapsedShowTitle },
+      } = unref(getProjectConfigRef);
+      return collapsedShowTitle ? SIDE_BAR_SHOW_TIT_MINI_WIDTH : SIDE_BAR_MINI_WIDTH;
+    });
+
     // 根据展开状态设置背景图片
     const getStyle = computed((): any => {
       // const collapse = unref(collapseRef);
@@ -62,7 +71,7 @@ export default defineComponent({
         innerE = innerE || window.event;
         // let tarnameb = innerE.target || innerE.srcElement;
         const maxT = 600;
-        const minT = 80;
+        const minT = unref(getMiniWidth);
         iT < 0 && (iT = 0);
         iT > maxT && (iT = maxT);
         iT < minT && (iT = minT);
@@ -80,13 +89,13 @@ export default defineComponent({
         const width = parseInt(wrap.style.width);
         menuStore.commitDragStartState(false);
         if (!menuStore.getCollapsedState) {
-          if (width > 100) {
+          if (width > unref(getMiniWidth) + 20) {
             setMenuWidth(width);
           } else {
             menuStore.commitCollapsedState(true);
           }
         } else {
-          if (width > 80) {
+          if (width > unref(getMiniWidth)) {
             setMenuWidth(width);
             menuStore.commitCollapsedState(false);
           }
@@ -135,13 +144,13 @@ export default defineComponent({
 
     const getDragBarStyle = computed(() => {
       if (menuStore.getCollapsedState) {
-        return { left: '80px' };
+        return { left: `${unref(getMiniWidth)}px` };
       }
       return {};
     });
 
     const getCollapsedWidth = computed(() => {
-      return unref(brokenRef) ? 0 : 80;
+      return unref(brokenRef) ? 0 : unref(getMiniWidth);
     });
 
     function renderDragLine() {

+ 14 - 0
src/layouts/default/index.less

@@ -422,3 +422,17 @@
   height: 30px;
   line-height: 30px;
 }
+
+.hide-title {
+  .ant-menu-inline-collapsed > .ant-menu-item,
+  .ant-menu-inline-collapsed > .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-item,
+  .ant-menu-inline-collapsed
+    > .ant-menu-item-group
+    > .ant-menu-item-group-list
+    > .ant-menu-submenu
+    > .ant-menu-submenu-title,
+  .ant-menu-inline-collapsed > .ant-menu-submenu > .ant-menu-submenu-title {
+    padding-right: 20px !important;
+    padding-left: 20px !important;
+  }
+}

+ 2 - 1
src/store/modules/permission.ts

@@ -19,7 +19,8 @@ import { genRouteModule, transformObjToRoute } from '/@/utils/helper/routeHelper
 import { transformRouteToMenu } from '/@/utils/helper/menuHelper';
 
 import { useMessage } from '/@/hooks/web/useMessage';
-import { warn } from 'vue';
+import { warn } from '/@/utils/log';
+
 const { createMessage } = useMessage();
 const NAME = 'permission';
 hotModuleUnregisterModule(NAME);

+ 4 - 0
src/utils/log.ts

@@ -0,0 +1,4 @@
+const projectName = import.meta.env.VITE_GLOB_APP_TITLE;
+export function warn(message: string) {
+  console.warn(`[${projectName} warn]:${message}`);
+}

+ 1 - 1
vite.config.ts

@@ -80,7 +80,7 @@ const viteConfig: UserConfig = {
    *  boolean | 'terser' | 'esbuild'
    * @default 'terser'
    */
-  minify: 'terser',
+  minify: isDevFn() ? 'esbuild' : 'terser',
   /**
    * 基本公共路径
    * @default '/'