瀏覽代碼

wip(menu): perf menu

vben 4 年之前
父節點
當前提交
cbcd909867

+ 2 - 1
src/components/Application/src/AppLogo.vue

@@ -66,8 +66,9 @@
   .@{prefix-cls} {
     display: flex;
     align-items: center;
-    padding-left: 12px;
+    padding-left: 7px;
     cursor: pointer;
+    transition: all 0.2s ease;
 
     &.collapsed-show-title {
       padding-left: 20px;

+ 3 - 1
src/components/Menu/index.ts

@@ -2,6 +2,8 @@ import { withInstall } from '../util';
 
 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
 
-export const BasicMenu = createAsyncComponent(() => import('./src/BasicMenu'), { loading: false });
+export const BasicMenu = createAsyncComponent(() => import('./src/BasicMenu.vue'), {
+  loading: false,
+});
 
 withInstall(BasicMenu);

+ 0 - 267
src/components/Menu/src/BasicMenu.tsx

@@ -1,267 +0,0 @@
-import './index.less';
-
-import type { MenuState } from './types';
-import type { Menu as MenuType } from '/@/router/types';
-
-import {
-  computed,
-  defineComponent,
-  unref,
-  reactive,
-  watch,
-  toRefs,
-  ComputedRef,
-  ref,
-  CSSProperties,
-} from 'vue';
-import { Menu } from 'ant-design-vue';
-import MenuContent from './MenuContent';
-// import { ScrollContainer } from '/@/components/Container';
-// import { BasicArrow } from '/@/components/Basic';
-
-import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
-import { ThemeEnum } from '/@/enums/appEnum';
-
-import { appStore } from '/@/store/modules/app';
-
-import { useOpenKeys } from './useOpenKeys';
-import { useRouter } from 'vue-router';
-
-import { isFunction } from '/@/utils/is';
-import { getSlot } from '/@/utils/helper/tsxHelper';
-import { menuHasChildren } from './helper';
-import { getCurrentParentPath } from '/@/router/menus';
-
-import { basicProps } from './props';
-import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
-import { REDIRECT_NAME } from '/@/router/constant';
-import { tabStore } from '/@/store/modules/tab';
-import { useDesign } from '/@/hooks/web/useDesign';
-export default defineComponent({
-  name: 'BasicMenu',
-  props: basicProps,
-  emits: ['menuClick'],
-  setup(props, { slots, emit }) {
-    const currentParentPath = ref('');
-    const isClickGo = ref(false);
-
-    const menuState = reactive<MenuState>({
-      defaultSelectedKeys: [],
-      mode: props.mode,
-      theme: computed(() => props.theme) as ComputedRef<ThemeEnum>,
-      openKeys: [],
-      selectedKeys: [],
-      collapsedOpenKeys: [],
-    });
-
-    const { prefixCls } = useDesign('basic-menu');
-
-    const { items, mode, accordion } = toRefs(props);
-
-    const { getCollapsed, getIsHorizontal, getTopMenuAlign, getSplit } = useMenuSetting();
-
-    const { currentRoute } = useRouter();
-
-    const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
-      menuState,
-      items,
-      mode,
-      accordion
-    );
-
-    const getMenuClass = computed(() => {
-      const { type } = props;
-      const { mode } = menuState;
-      return [
-        prefixCls,
-        `justify-${unref(getTopMenuAlign)}`,
-        {
-          [`${prefixCls}--hide-title`]: !unref(showTitle),
-          [`${prefixCls}--collapsed-show-title`]: props.collapsedShowTitle,
-          [`${prefixCls}__second`]:
-            !props.isHorizontal && appStore.getProjectConfig.menuSetting.split,
-          [`${prefixCls}__sidebar-hor`]:
-            type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL,
-        },
-      ];
-    });
-
-    const showTitle = computed(() => props.collapsedShowTitle && unref(getCollapsed));
-
-    const getInlineCollapseOptions = computed(() => {
-      const isInline = props.mode === MenuModeEnum.INLINE;
-
-      const inlineCollapseOptions: { inlineCollapsed?: boolean } = {};
-      if (isInline) {
-        inlineCollapseOptions.inlineCollapsed = unref(getCollapsed);
-      }
-      return inlineCollapseOptions;
-    });
-
-    const getWrapperStyle = computed(
-      (): CSSProperties => {
-        const isHorizontal = unref(getIsHorizontal) || getSplit.value;
-
-        return {
-          height: isHorizontal ? '100%' : `calc(100% - ${props.showLogo ? '48px' : '0px'})`,
-          overflowY: isHorizontal ? 'hidden' : 'auto',
-        };
-      }
-    );
-
-    watch(
-      () => tabStore.getCurrentTab,
-      () => {
-        if (unref(currentRoute).name === REDIRECT_NAME) return;
-        handleMenuChange();
-        unref(getSplit) && getParentPath();
-      }
-    );
-
-    watch(
-      () => props.items,
-      () => {
-        handleMenuChange();
-      },
-      {
-        immediate: true,
-      }
-    );
-
-    getParentPath();
-
-    async function getParentPath() {
-      const { appendClass } = props;
-      if (!appendClass) return '';
-      const parentPath = await getCurrentParentPath(unref(currentRoute).path);
-
-      currentParentPath.value = parentPath;
-    }
-
-    async function handleMenuClick({ key, keyPath }: { key: string; keyPath: string[] }) {
-      const { beforeClickFn } = props;
-      if (beforeClickFn && isFunction(beforeClickFn)) {
-        const flag = await beforeClickFn(key);
-        if (!flag) return;
-      }
-      emit('menuClick', key);
-
-      isClickGo.value = true;
-      menuState.openKeys = keyPath;
-      menuState.selectedKeys = [key];
-    }
-
-    function handleMenuChange() {
-      if (unref(isClickGo)) {
-        isClickGo.value = false;
-        return;
-      }
-      const path = unref(currentRoute).path;
-      if (menuState.mode !== MenuModeEnum.HORIZONTAL) {
-        setOpenKeys(path);
-      }
-      menuState.selectedKeys = [path];
-    }
-
-    // function renderExpandIcon({ key }: { key: string }) {
-    //   const isOpen = getOpenKeys.value.includes(key);
-    //   const collapsed = unref(getCollapsed);
-    //   return (
-    //     <BasicArrow
-    //       expand={isOpen}
-    //       bottom
-    //       inset
-    //       class={[
-    //         `${prefixCls}__expand-icon`,
-    //         {
-    //           [`${prefixCls}__expand-icon--collapsed`]: collapsed,
-    //         },
-    //       ]}
-    //     />
-    //   );
-    // }
-
-    function renderItem(menu: MenuType, level = 1) {
-      return !menuHasChildren(menu) ? renderMenuItem(menu, level) : renderSubMenu(menu, level);
-    }
-
-    function renderMenuItem(menu: MenuType, level: number) {
-      const { appendClass } = props;
-      const isAppendActiveCls =
-        appendClass && level === 1 && menu.path === unref(currentParentPath);
-
-      const levelCls = [
-        `${prefixCls}-item__level${level}`,
-        ` ${menuState.theme} `,
-        {
-          'top-active-menu': isAppendActiveCls,
-        },
-      ];
-      return (
-        <Menu.Item key={menu.path} class={levelCls}>
-          {() => [
-            <MenuContent
-              item={menu}
-              showTitle={unref(showTitle)}
-              isHorizontal={props.isHorizontal}
-            />,
-          ]}
-        </Menu.Item>
-      );
-    }
-
-    function renderSubMenu(menu: MenuType, level: number) {
-      const levelCls = `${prefixCls}-item__level${level} ${menuState.theme} `;
-      return (
-        <Menu.SubMenu key={menu.path} class={levelCls}>
-          {{
-            title: () => [
-              <MenuContent
-                showTitle={unref(showTitle)}
-                item={menu}
-                isHorizontal={props.isHorizontal}
-              />,
-            ],
-            // expandIcon: renderExpandIcon,
-            default: () => (menu.children || []).map((item) => renderItem(item, level + 1)),
-          }}
-        </Menu.SubMenu>
-      );
-    }
-
-    function renderMenu() {
-      const { selectedKeys, defaultSelectedKeys, mode, theme } = menuState;
-
-      return (
-        <Menu
-          selectedKeys={selectedKeys}
-          defaultSelectedKeys={defaultSelectedKeys}
-          mode={mode}
-          openKeys={unref(getOpenKeys)}
-          inlineIndent={props.inlineIndent}
-          theme={unref(theme)}
-          onOpenChange={handleOpenChange}
-          class={unref(getMenuClass)}
-          onClick={handleMenuClick}
-          subMenuOpenDelay={0.2}
-          {...unref(getInlineCollapseOptions)}
-        >
-          {{
-            default: () => unref(items).map((item) => renderItem(item)),
-          }}
-        </Menu>
-      );
-    }
-
-    return () => {
-      return (
-        <>
-          {!unref(getIsHorizontal) && getSlot(slots, 'header')}
-          <div class={`${prefixCls}-wrapper`} style={unref(getWrapperStyle)}>
-            {renderMenu()}
-          </div>
-        </>
-      );
-    };
-  },
-});

+ 209 - 0
src/components/Menu/src/BasicMenu.vue

@@ -0,0 +1,209 @@
+<template>
+  <slot name="header" v-if="!getIsHorizontal" />
+  <ScrollContainer :class="`${prefixCls}-wrapper`" :style="getWrapperStyle">
+    <Menu
+      :selectedKeys="selectedKeys"
+      :defaultSelectedKeys="defaultSelectedKeys"
+      :mode="mode"
+      :openKeys="getOpenKeys"
+      :inlineIndent="inlineIndent"
+      :theme="theme"
+      @openChange="handleOpenChange"
+      :class="getMenuClass"
+      @click="handleMenuClick"
+      :subMenuOpenDelay="0.2"
+      v-bind="getInlineCollapseOptions"
+    >
+      <template v-for="item in items" :key="item.path">
+        <BasicSubMenuItem
+          :item="item"
+          :theme="theme"
+          :level="1"
+          :appendClass="appendClass"
+          :parentPath="currentParentPath"
+          :showTitle="showTitle"
+          :isHorizontal="isHorizontal"
+        />
+      </template>
+    </Menu>
+  </ScrollContainer>
+</template>
+<script lang="ts">
+  import type { MenuState } from './types';
+
+  import {
+    computed,
+    defineComponent,
+    unref,
+    reactive,
+    watch,
+    toRefs,
+    ref,
+    CSSProperties,
+  } from 'vue';
+  import { Menu } from 'ant-design-vue';
+  import BasicSubMenuItem from './components/BasicSubMenuItem.vue';
+  import { ScrollContainer } from '/@/components/Container';
+
+  import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
+
+  import { appStore } from '/@/store/modules/app';
+
+  import { useOpenKeys } from './useOpenKeys';
+  import { useRouter } from 'vue-router';
+
+  import { isFunction } from '/@/utils/is';
+  import { getCurrentParentPath } from '/@/router/menus';
+
+  import { basicProps } from './props';
+  import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
+  import { REDIRECT_NAME } from '/@/router/constant';
+  import { tabStore } from '/@/store/modules/tab';
+  import { useDesign } from '/@/hooks/web/useDesign';
+  // import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
+
+  export default defineComponent({
+    name: 'BasicMenu',
+    components: {
+      Menu,
+      ScrollContainer,
+      BasicSubMenuItem,
+      // BasicSubMenuItem: createAsyncComponent(() => import('./components/BasicSubMenuItem.vue')),
+    },
+    props: basicProps,
+    emits: ['menuClick'],
+    setup(props, { emit }) {
+      const currentParentPath = ref('');
+      const isClickGo = ref(false);
+
+      const menuState = reactive<MenuState>({
+        defaultSelectedKeys: [],
+        openKeys: [],
+        selectedKeys: [],
+        collapsedOpenKeys: [],
+      });
+
+      const { prefixCls } = useDesign('basic-menu');
+      const { items, mode, accordion } = toRefs(props);
+
+      const { getCollapsed, getIsHorizontal, getTopMenuAlign, getSplit } = useMenuSetting();
+
+      const { currentRoute } = useRouter();
+
+      const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
+        menuState,
+        items,
+        mode,
+        accordion
+      );
+
+      const getMenuClass = computed(() => {
+        const { type, mode } = props;
+        return [
+          prefixCls,
+          `justify-${unref(getTopMenuAlign)}`,
+          {
+            [`${prefixCls}--hide-title`]: !unref(showTitle),
+            [`${prefixCls}--collapsed-show-title`]: props.collapsedShowTitle,
+            [`${prefixCls}__second`]:
+              !props.isHorizontal && appStore.getProjectConfig.menuSetting.split,
+            [`${prefixCls}__sidebar-hor`]:
+              type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL,
+          },
+        ];
+      });
+
+      const showTitle = computed(() => props.collapsedShowTitle && unref(getCollapsed));
+
+      const getInlineCollapseOptions = computed(() => {
+        const isInline = props.mode === MenuModeEnum.INLINE;
+
+        const inlineCollapseOptions: { inlineCollapsed?: boolean } = {};
+        if (isInline) {
+          inlineCollapseOptions.inlineCollapsed = unref(getCollapsed);
+        }
+        return inlineCollapseOptions;
+      });
+
+      const getWrapperStyle = computed(
+        (): CSSProperties => {
+          return {
+            height: `calc(100% - ${props.showLogo ? '48px' : '0px'})`,
+            overflowY: 'hidden',
+          };
+        }
+      );
+
+      watch(
+        () => tabStore.getCurrentTab,
+        () => {
+          if (unref(currentRoute).name === REDIRECT_NAME) return;
+          handleMenuChange();
+          unref(getSplit) && getParentPath();
+        }
+      );
+
+      watch(
+        () => props.items,
+        () => {
+          handleMenuChange();
+        },
+        {
+          immediate: true,
+        }
+      );
+
+      getParentPath();
+
+      async function getParentPath() {
+        const { appendClass } = props;
+        if (!appendClass) return '';
+        const parentPath = await getCurrentParentPath(unref(currentRoute).path);
+
+        currentParentPath.value = parentPath;
+      }
+
+      async function handleMenuClick({ key, keyPath }: { key: string; keyPath: string[] }) {
+        const { beforeClickFn } = props;
+        if (beforeClickFn && isFunction(beforeClickFn)) {
+          const flag = await beforeClickFn(key);
+          if (!flag) return;
+        }
+        emit('menuClick', key);
+
+        isClickGo.value = true;
+        menuState.openKeys = keyPath;
+        menuState.selectedKeys = [key];
+      }
+
+      function handleMenuChange() {
+        if (unref(isClickGo)) {
+          isClickGo.value = false;
+          return;
+        }
+        const path = unref(currentRoute).path;
+        if (props.mode !== MenuModeEnum.HORIZONTAL) {
+          setOpenKeys(path);
+        }
+        menuState.selectedKeys = [path];
+      }
+
+      return {
+        prefixCls,
+        getIsHorizontal,
+        getWrapperStyle,
+        handleMenuClick,
+        getInlineCollapseOptions,
+        getMenuClass,
+        handleOpenChange,
+        getOpenKeys,
+        currentParentPath,
+        showTitle,
+        ...toRefs(menuState),
+      };
+    },
+  });
+</script>
+<style lang="less">
+  @import './index.less';
+</style>

+ 39 - 0
src/components/Menu/src/components/BasicMenuItem.vue

@@ -0,0 +1,39 @@
+<template>
+  <MenuItem :class="getLevelClass">
+    <MenuContent v-bind="$props" :item="item" />
+  </MenuItem>
+</template>
+<script lang="ts">
+  import { defineComponent, computed } from 'vue';
+  import { Menu } from 'ant-design-vue';
+  import { useDesign } from '/@/hooks/web/useDesign';
+  import { itemProps } from '../props';
+
+  import MenuContent from '../MenuContent';
+  export default defineComponent({
+    name: 'BasicMenuItem',
+    components: { MenuItem: Menu.Item, MenuContent },
+    props: itemProps,
+    setup(props) {
+      const { prefixCls } = useDesign('basic-menu-item');
+
+      const getLevelClass = computed(() => {
+        const { appendClass, level, item, parentPath, theme } = props;
+        const isAppendActiveCls = appendClass && level === 1 && item.path === parentPath;
+
+        const levelCls = [
+          `${prefixCls}__level${level}`,
+          theme,
+          {
+            'top-active-menu': isAppendActiveCls,
+          },
+        ];
+        return levelCls;
+      });
+      return {
+        prefixCls,
+        getLevelClass,
+      };
+    },
+  });
+</script>

+ 53 - 0
src/components/Menu/src/components/BasicSubMenuItem.vue

@@ -0,0 +1,53 @@
+<template>
+  <BasicMenuItem v-if="!menuHasChildren(item)" v-bind="$props" />
+  <SubMenu v-else :class="[`${prefixCls}__level${level}`, theme]">
+    <template #title>
+      <MenuContent v-bind="$props" :item="item" />
+    </template>
+    <!-- <template #expandIcon="{ key }">
+      <ExpandIcon :key="key" />
+    </template> -->
+
+    <template v-for="childrenItem in item.children || []" :key="childrenItem.path">
+      <BasicSubMenuItem v-bind="$props" :item="childrenItem" :level="level + 1" />
+    </template>
+  </SubMenu>
+</template>
+<script lang="ts">
+  import type { Menu as MenuType } from '/@/router/types';
+
+  import { defineComponent } from 'vue';
+  import { Menu } from 'ant-design-vue';
+  import { useDesign } from '/@/hooks/web/useDesign';
+  import { itemProps } from '../props';
+  import BasicMenuItem from './BasicMenuItem.vue';
+  import MenuContent from '../MenuContent';
+  // import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
+
+  export default defineComponent({
+    name: 'BasicSubMenuItem',
+
+    components: {
+      BasicMenuItem,
+      SubMenu: Menu.SubMenu,
+      MenuItem: Menu.Item,
+      MenuContent,
+      // ExpandIcon: createAsyncComponent(() => import('./ExpandIcon.vue')),
+    },
+    props: itemProps,
+    setup() {
+      const { prefixCls } = useDesign('basic-menu-item');
+      function menuHasChildren(menuTreeItem: MenuType): boolean {
+        return (
+          Reflect.has(menuTreeItem, 'children') &&
+          !!menuTreeItem.children &&
+          menuTreeItem.children.length > 0
+        );
+      }
+      return {
+        prefixCls,
+        menuHasChildren,
+      };
+    },
+  });
+</script>

+ 43 - 0
src/components/Menu/src/components/ExpandIcon.vue

@@ -0,0 +1,43 @@
+<template>
+  <BasicArrow :expand="getIsOpen" bottom inset :class="getWrapperClass" />
+</template>
+<script lang="ts">
+  import { defineComponent, PropType, computed } from 'vue';
+  import { useDesign } from '/@/hooks/web/useDesign';
+  import { BasicArrow } from '/@/components/Basic';
+
+  import { propTypes } from '/@/utils/propTypes';
+  export default defineComponent({
+    name: 'BasicMenuItem',
+    components: { BasicArrow },
+    props: {
+      key: propTypes.string,
+      openKeys: {
+        type: Array as PropType<string[]>,
+        default: [],
+      },
+      collapsed: propTypes.bool,
+    },
+    setup(props) {
+      const { prefixCls } = useDesign('basic-menu');
+
+      const getIsOpen = computed(() => {
+        return props.openKeys.includes(props.key);
+      });
+
+      const getWrapperClass = computed(() => {
+        return [
+          `${prefixCls}__expand-icon`,
+          {
+            [`${prefixCls}__expand-icon--collapsed`]: props.collapsed,
+          },
+        ];
+      });
+      return {
+        prefixCls,
+        getIsOpen,
+        getWrapperClass,
+      };
+    },
+  });
+</script>

+ 0 - 12
src/components/Menu/src/helper.ts

@@ -1,12 +0,0 @@
-import type { Menu as MenuType } from '/@/router/types';
-
-/**
- * @description: Whether the menu has child nodes
- */
-export function menuHasChildren(menuTreeItem: MenuType): boolean {
-  return (
-    Reflect.has(menuTreeItem, 'children') &&
-    !!menuTreeItem.children &&
-    menuTreeItem.children.length > 0
-  );
-}

+ 42 - 41
src/components/Menu/src/index.less

@@ -4,6 +4,7 @@
 
 .active-style() {
   color: @white;
+  // background: @primary-color !important;
   background: linear-gradient(
     118deg,
     rgba(@primary-color, 0.8),
@@ -27,6 +28,7 @@
   //   right: 16px;
   //   width: 10px;
   //   transform-origin: none;
+  //   opacity: 0.45;
 
   //   span[role='img'] {
   //     margin-right: 0;
@@ -52,9 +54,9 @@
       > .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;
+    &.ant-menu-inline-collapsed .ant-menu-submenu-title {
+      padding-right: 16px !important;
+      padding-left: 16px !important;
     }
   }
 
@@ -87,32 +89,33 @@
     }
   }
 
-  // .ant-menu-item {
-  //   transition: unset;
-  // }
+  .ant-menu-item {
+    transition: unset;
+  }
 
   // scrollbar -s tart
-  &-wrapper {
-    /* 滚动槽 */
-    &::-webkit-scrollbar {
-      width: 5px;
-      height: 5px;
-    }
+  // &-wrapper {
 
-    &::-webkit-scrollbar-track {
-      background: rgba(0, 0, 0, 0);
-    }
+  /* 滚动槽 */
+  // &::-webkit-scrollbar {
+  //   width: 5px;
+  //   height: 5px;
+  // }
 
-    &::-webkit-scrollbar-thumb {
-      background: rgba(255, 255, 255, 0.2);
-      border-radius: 3px;
-      box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1);
-    }
+  // &::-webkit-scrollbar-track {
+  //   background: rgba(0, 0, 0, 0);
+  // }
 
-    ::-webkit-scrollbar-thumb:hover {
-      background: @border-color-dark;
-    }
-  }
+  // &::-webkit-scrollbar-thumb {
+  //   background: rgba(255, 255, 255, 0.2);
+  //   border-radius: 3px;
+  //   box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1);
+  // }
+
+  // ::-webkit-scrollbar-thumb:hover {
+  //   background: @border-color-dark;
+  // }
+  // }
 
   // scrollbar  end
 
@@ -225,14 +228,6 @@
     }
   }
 
-  &:not(.@{basic-menu-prefix-cls}__sidebar-hor).ant-menu-inline-collapsed {
-    .@{basic-menu-prefix-cls}-item__level1 {
-      > div {
-        align-items: center;
-      }
-    }
-  }
-
   &.ant-menu-dark:not(.@{basic-menu-prefix-cls}__sidebar-hor):not(.@{basic-menu-prefix-cls}__second) {
     // Reset menu item row height
     .ant-menu-item:not(.@{basic-menu-prefix-cls}-item__level1),
@@ -255,10 +250,6 @@
     background: @sider-dark-bg-color;
     .active-menu-style();
 
-    // .menu-item-icon.app-iconify {
-    //   display: inline-block !important;
-    // }
-
     .ant-menu-item.ant-menu-item-selected.@{basic-menu-prefix-cls}-menu-item__level1,
     .ant-menu-submenu-selected.@{basic-menu-prefix-cls}-menu-item__level1 {
       color: @white;
@@ -304,10 +295,6 @@
     overflow: hidden;
     border-right: none;
 
-    // .menu-item-icon.app-iconify {
-    //   display: inline-block !important;
-    // }
-
     .ant-menu-item.ant-menu-item-selected.@{basic-menu-prefix-cls}-menu-item__level1,
     .ant-menu-submenu-selected.@{basic-menu-prefix-cls}-menu-item__level1 {
       color: @primary-color;
@@ -332,6 +319,7 @@
       align-items: center;
     }
   }
+
   .@{basic-menu-prefix-cls}__tag {
     position: absolute;
     top: calc(50% - 8px);
@@ -368,6 +356,20 @@
       background: @warning-color;
     }
   }
+
+  .ant-menu-submenu,
+  .ant-menu-submenu-inline {
+    transition: unset;
+  }
+
+  // .ant-menu-submenu-arrow {
+  //   transition: all 0.15s ease 0s;
+  // }
+
+  .ant-menu-inline.ant-menu-sub {
+    box-shadow: unset !important;
+    transition: unset;
+  }
 }
 
 .ant-menu-dark {
@@ -375,7 +377,6 @@
     > ul {
       background: @sider-dark-bg-color;
     }
-
     .active-menu-style();
   }
 }

+ 22 - 32
src/components/Menu/src/props.ts

@@ -3,57 +3,47 @@ import type { PropType } from 'vue';
 
 import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
 import { ThemeEnum } from '/@/enums/appEnum';
+import { propTypes } from '/@/utils/propTypes';
 export const basicProps = {
   items: {
     type: Array as PropType<Menu[]>,
     default: () => [],
   },
-  appendClass: {
-    type: Boolean as PropType<boolean>,
-    default: false,
-  },
+  appendClass: propTypes.bool,
 
-  collapsedShowTitle: {
-    type: Boolean as PropType<boolean>,
-    default: false,
-  },
+  collapsedShowTitle: propTypes.bool,
 
   // 最好是4 倍数
-  inlineIndent: {
-    type: Number as PropType<number>,
-    default: 20,
-  },
+  inlineIndent: propTypes.number.def(20),
   // 菜单组件的mode属性
   mode: {
     type: String as PropType<MenuModeEnum>,
     default: MenuModeEnum.INLINE,
   },
-  showLogo: {
-    type: Boolean as PropType<boolean>,
-    default: false,
-  },
+  showLogo: propTypes.bool,
   type: {
     type: String as PropType<MenuTypeEnum>,
     default: MenuTypeEnum.MIX,
   },
-  theme: {
-    type: String as PropType<string>,
-    default: ThemeEnum.DARK,
-  },
-  inlineCollapsed: {
-    type: Boolean as PropType<boolean>,
-    default: false,
-  },
+  theme: propTypes.string.def(ThemeEnum.DARK),
+  inlineCollapsed: propTypes.bool,
 
-  isHorizontal: {
-    type: Boolean as PropType<boolean>,
-    default: false,
-  },
-  accordion: {
-    type: Boolean as PropType<boolean>,
-    default: true,
-  },
+  isHorizontal: propTypes.bool,
+  accordion: propTypes.bool.def(true),
   beforeClickFn: {
     type: Function as PropType<(key: string) => Promise<boolean>>,
   },
 };
+
+export const itemProps = {
+  item: {
+    type: Object as PropType<Menu>,
+    default: {},
+  },
+  level: propTypes.number,
+  theme: propTypes.oneOf(['dark', 'light']),
+  appendClass: propTypes.bool,
+  parentPath: propTypes.string,
+  showTitle: propTypes.bool,
+  isHorizontal: propTypes.bool,
+};

+ 6 - 6
src/components/Menu/src/types.ts

@@ -1,15 +1,15 @@
-import { ComputedRef } from 'vue';
-import { ThemeEnum } from '/@/enums/appEnum';
-import { MenuModeEnum } from '/@/enums/menuEnum';
+// import { ComputedRef } from 'vue';
+// import { ThemeEnum } from '/@/enums/appEnum';
+// import { MenuModeEnum } from '/@/enums/menuEnum';
 export interface MenuState {
   // 默认选中的列表
   defaultSelectedKeys: string[];
 
   // 模式
-  mode: MenuModeEnum;
+  // mode: MenuModeEnum;
 
-  // 主题
-  theme: ComputedRef<ThemeEnum> | ThemeEnum;
+  // // 主题
+  // theme: ComputedRef<ThemeEnum> | ThemeEnum;
 
   // 缩进
   inlineIndent?: number;

+ 1 - 1
src/enums/appEnum.ts

@@ -1,4 +1,4 @@
-export const SIDE_BAR_MINI_WIDTH = 58;
+export const SIDE_BAR_MINI_WIDTH = 48;
 export const SIDE_BAR_SHOW_TIT_MINI_WIDTH = 80;
 
 export enum ContentEnum {

+ 3 - 3
src/layouts/default/tabs/index.less

@@ -34,9 +34,9 @@
         border: 1px solid darken(@border-color-light, 6%);
         transition: none;
 
-        &:not(.ant-tabs-tab-active)::before {
+        &:not(.ant-tabs-tab-active)::after {
           position: absolute;
-          top: -1px;
+          bottom: -1px;
           left: 50%;
           width: 100%;
           height: 2px;
@@ -53,7 +53,7 @@
             opacity: 1;
           }
 
-          &:not(.ant-tabs-tab-active)::before {
+          &:not(.ant-tabs-tab-active)::after {
             opacity: 1;
             transform: translate(-50%, 0) scaleX(1);
             transition: all 0.3s ease-in-out;

+ 1 - 0
src/router/helper/menuHelper.ts

@@ -42,6 +42,7 @@ export function transformMenuModule(menuModule: MenuModule): Menu {
   forEach(menuList, (m) => {
     !isUrl(m.path) && joinParentPath(menuList, m);
   });
+
   return menuList[0];
 }