mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-28 05:39:34 +08:00
feat(layout): added setting. Used to fix the left mixed mode menu
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
### ✨ Features
|
### ✨ Features
|
||||||
|
|
||||||
- 新增`mixSideTrigger`配置。用于配置左侧混合模式菜单打开方式。可选`hover`,默认`click`
|
- 新增`mixSideTrigger`配置。用于配置左侧混合模式菜单打开方式。可选`hover`,默认`click`
|
||||||
|
- 新增`mixSideFixed`配置。用于固定左侧混合模式菜单
|
||||||
|
- modal 组件新增`height`和`min-height`属性
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
"build": "cross-env vite build --mode=production && esno ./build/script/postBuild.ts",
|
"build": "cross-env vite build --mode=production && esno ./build/script/postBuild.ts",
|
||||||
"build:site": "cross-env SITE=true npm run build ",
|
"build:site": "cross-env SITE=true npm run build ",
|
||||||
"build:no-cache": "yarn clean:cache && npm run build",
|
"build:no-cache": "yarn clean:cache && npm run build",
|
||||||
"typecheck": "typecheck .",
|
"typecheck": "vuedx-typecheck .",
|
||||||
"report": "cross-env REPORT=true npm run build ",
|
"report": "cross-env REPORT=true npm run build ",
|
||||||
"preview": "npm run build && esno ./build/script/preview.ts",
|
"preview": "npm run build && esno ./build/script/preview.ts",
|
||||||
"preview:dist": "esno ./build/script/preview.ts",
|
"preview:dist": "esno ./build/script/preview.ts",
|
||||||
|
@@ -125,15 +125,13 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
!props.mixSider &&
|
||||||
() => props.items,
|
watch(
|
||||||
() => {
|
() => props.items,
|
||||||
handleMenuChange();
|
() => {
|
||||||
}
|
handleMenuChange();
|
||||||
// {
|
}
|
||||||
// immediate: true,
|
);
|
||||||
// }
|
|
||||||
);
|
|
||||||
|
|
||||||
async function handleMenuClick({ key, keyPath }: { key: string; keyPath: string[] }) {
|
async function handleMenuClick({ key, keyPath }: { key: string; keyPath: string[] }) {
|
||||||
const { beforeClickFn } = props;
|
const { beforeClickFn } = props;
|
||||||
|
@@ -8,6 +8,7 @@ import { unref } from 'vue';
|
|||||||
import { es6Unique } from '/@/utils';
|
import { es6Unique } from '/@/utils';
|
||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||||
import { getAllParentPath } from '/@/router/helper/menuHelper';
|
import { getAllParentPath } from '/@/router/helper/menuHelper';
|
||||||
|
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
|
||||||
|
|
||||||
export function useOpenKeys(
|
export function useOpenKeys(
|
||||||
menuState: MenuState,
|
menuState: MenuState,
|
||||||
@@ -15,18 +16,29 @@ export function useOpenKeys(
|
|||||||
mode: Ref<MenuModeEnum>,
|
mode: Ref<MenuModeEnum>,
|
||||||
accordion: Ref<boolean>
|
accordion: Ref<boolean>
|
||||||
) {
|
) {
|
||||||
const { getCollapsed, getIsMixSidebar } = useMenuSetting();
|
const { getCollapsed, getIsMixSidebar, getMixSideFixed } = useMenuSetting();
|
||||||
|
|
||||||
function setOpenKeys(path: string) {
|
async function setOpenKeys(path: string) {
|
||||||
if (mode.value === MenuModeEnum.HORIZONTAL) {
|
if (mode.value === MenuModeEnum.HORIZONTAL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const menuList = toRaw(menus.value);
|
const native = unref(getIsMixSidebar) && unref(getMixSideFixed);
|
||||||
if (!unref(accordion)) {
|
|
||||||
menuState.openKeys = es6Unique([...menuState.openKeys, ...getAllParentPath(menuList, path)]);
|
useTimeoutFn(
|
||||||
} else {
|
() => {
|
||||||
menuState.openKeys = getAllParentPath(menuList, path);
|
const menuList = toRaw(menus.value);
|
||||||
}
|
if (!unref(accordion)) {
|
||||||
|
menuState.openKeys = es6Unique([
|
||||||
|
...menuState.openKeys,
|
||||||
|
...getAllParentPath(menuList, path),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
menuState.openKeys = getAllParentPath(menuList, path);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
16,
|
||||||
|
native
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getOpenKeys = computed(() => {
|
const getOpenKeys = computed(() => {
|
||||||
|
@@ -218,7 +218,7 @@ export function useDataSource(
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
useTimeoutFn(() => {
|
useTimeoutFn(() => {
|
||||||
unref(propsRef).immediate && fetch();
|
unref(propsRef).immediate && fetch();
|
||||||
}, 0);
|
}, 16);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@@ -3,20 +3,23 @@ import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
|
|||||||
|
|
||||||
import { isFunction } from '/@/utils/is';
|
import { isFunction } from '/@/utils/is';
|
||||||
|
|
||||||
export function useTimeoutFn(handle: Fn<any>, wait: number) {
|
export function useTimeoutFn(handle: Fn<any>, wait: number, native = false) {
|
||||||
if (!isFunction(handle)) {
|
if (!isFunction(handle)) {
|
||||||
throw new Error('handle is not Function!');
|
throw new Error('handle is not Function!');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { readyRef, stop, start } = useTimeoutRef(wait);
|
const { readyRef, stop, start } = useTimeoutRef(wait);
|
||||||
|
if (native) {
|
||||||
watch(
|
handle();
|
||||||
readyRef,
|
} else {
|
||||||
(maturity) => {
|
watch(
|
||||||
maturity && handle();
|
readyRef,
|
||||||
},
|
(maturity) => {
|
||||||
{ immediate: false }
|
maturity && handle();
|
||||||
);
|
},
|
||||||
|
{ immediate: false }
|
||||||
|
);
|
||||||
|
}
|
||||||
return { readyRef, stop, start };
|
return { readyRef, stop, start };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import type { MenuSetting } from '/@/types/config';
|
import type { MenuSetting } from '/@/types/config';
|
||||||
|
|
||||||
import { computed, unref } from 'vue';
|
import { computed, unref, ref } from 'vue';
|
||||||
|
|
||||||
import { appStore } from '/@/store/modules/app';
|
import { appStore } from '/@/store/modules/app';
|
||||||
|
|
||||||
@@ -8,6 +8,8 @@ import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appE
|
|||||||
import { MenuModeEnum, MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum';
|
import { MenuModeEnum, MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||||
import { useFullContent } from '/@/hooks/web/useFullContent';
|
import { useFullContent } from '/@/hooks/web/useFullContent';
|
||||||
|
|
||||||
|
const mixSideHasChildren = ref(false);
|
||||||
|
|
||||||
// Get menu configuration
|
// Get menu configuration
|
||||||
const getMenuSetting = computed(() => appStore.getProjectConfig.menuSetting);
|
const getMenuSetting = computed(() => appStore.getProjectConfig.menuSetting);
|
||||||
|
|
||||||
@@ -39,6 +41,8 @@ const getCanDrag = computed(() => unref(getMenuSetting).canDrag);
|
|||||||
|
|
||||||
const getAccordion = computed(() => unref(getMenuSetting).accordion);
|
const getAccordion = computed(() => unref(getMenuSetting).accordion);
|
||||||
|
|
||||||
|
const getMixSideFixed = computed(() => unref(getMenuSetting).mixSideFixed);
|
||||||
|
|
||||||
const getTopMenuAlign = computed(() => unref(getMenuSetting).topMenuAlign);
|
const getTopMenuAlign = computed(() => unref(getMenuSetting).topMenuAlign);
|
||||||
|
|
||||||
const getCloseMixSidebarOnChange = computed(() => unref(getMenuSetting).closeMixSidebarOnChange);
|
const getCloseMixSidebarOnChange = computed(() => unref(getMenuSetting).closeMixSidebarOnChange);
|
||||||
@@ -87,7 +91,8 @@ const getCalcContentWidth = computed(() => {
|
|||||||
unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && unref(getMenuHidden))
|
unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && unref(getMenuHidden))
|
||||||
? 0
|
? 0
|
||||||
: unref(getIsMixSidebar)
|
: unref(getIsMixSidebar)
|
||||||
? SIDE_BAR_SHOW_TIT_MINI_WIDTH
|
? SIDE_BAR_SHOW_TIT_MINI_WIDTH +
|
||||||
|
(unref(getMixSideFixed) && unref(mixSideHasChildren) ? unref(getRealWidth) : 0)
|
||||||
: unref(getRealWidth);
|
: unref(getRealWidth);
|
||||||
|
|
||||||
return `calc(100% - ${unref(width)}px)`;
|
return `calc(100% - ${unref(width)}px)`;
|
||||||
@@ -148,5 +153,7 @@ export function useMenuSetting() {
|
|||||||
getIsMixSidebar,
|
getIsMixSidebar,
|
||||||
getCloseMixSidebarOnChange,
|
getCloseMixSidebarOnChange,
|
||||||
getMixSideTrigger,
|
getMixSideTrigger,
|
||||||
|
getMixSideFixed,
|
||||||
|
mixSideHasChildren,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -75,6 +75,7 @@ export default defineComponent({
|
|||||||
getIsMixSidebar,
|
getIsMixSidebar,
|
||||||
getCloseMixSidebarOnChange,
|
getCloseMixSidebarOnChange,
|
||||||
getMixSideTrigger,
|
getMixSideTrigger,
|
||||||
|
getMixSideFixed,
|
||||||
} = useMenuSetting();
|
} = useMenuSetting();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -110,6 +111,12 @@ export default defineComponent({
|
|||||||
def={unref(getSplit)}
|
def={unref(getSplit)}
|
||||||
disabled={!unref(getShowMenuRef) || unref(getMenuType) !== MenuTypeEnum.MIX}
|
disabled={!unref(getShowMenuRef) || unref(getMenuType) !== MenuTypeEnum.MIX}
|
||||||
/>
|
/>
|
||||||
|
<SwitchItem
|
||||||
|
title={t('layout.setting.mixSidebarFixed')}
|
||||||
|
event={HandlerEnum.MENU_FIXED_MIX_SIDEBAR}
|
||||||
|
def={unref(getMixSideFixed)}
|
||||||
|
disabled={!unref(getIsMixSidebar)}
|
||||||
|
/>
|
||||||
|
|
||||||
<SwitchItem
|
<SwitchItem
|
||||||
title={t('layout.setting.closeMixSidebarOnChange')}
|
title={t('layout.setting.closeMixSidebarOnChange')}
|
||||||
|
@@ -27,6 +27,7 @@ export enum HandlerEnum {
|
|||||||
MENU_FIXED,
|
MENU_FIXED,
|
||||||
MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE,
|
MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE,
|
||||||
MENU_TRIGGER_MIX_SIDEBAR,
|
MENU_TRIGGER_MIX_SIDEBAR,
|
||||||
|
MENU_FIXED_MIX_SIDEBAR,
|
||||||
|
|
||||||
// header
|
// header
|
||||||
HEADER_SHOW,
|
HEADER_SHOW,
|
||||||
|
@@ -70,6 +70,9 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
|
|||||||
case HandlerEnum.MENU_TRIGGER_MIX_SIDEBAR:
|
case HandlerEnum.MENU_TRIGGER_MIX_SIDEBAR:
|
||||||
return { menuSetting: { mixSideTrigger: value } };
|
return { menuSetting: { mixSideTrigger: value } };
|
||||||
|
|
||||||
|
case HandlerEnum.MENU_FIXED_MIX_SIDEBAR:
|
||||||
|
return { menuSetting: { mixSideTrigger: value } };
|
||||||
|
|
||||||
// ============transition==================
|
// ============transition==================
|
||||||
case HandlerEnum.OPEN_PAGE_LOADING:
|
case HandlerEnum.OPEN_PAGE_LOADING:
|
||||||
appStore.commitPageLoadingState(false);
|
appStore.commitPageLoadingState(false);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="`${prefixCls}-dom`" />
|
<div :class="`${prefixCls}-dom`" :style="getDomStyle" />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-click-outside="handleClickOutside"
|
v-click-outside="handleClickOutside"
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
v-bind="getItemEvents(item)"
|
v-bind="getItemEvents(item)"
|
||||||
>
|
>
|
||||||
<MenuTag :item="item" :showTitle="false" :isHorizontal="false" />
|
<MenuTag :item="item" :showTitle="false" :isHorizontal="false" />
|
||||||
<g-icon
|
<Icon
|
||||||
:class="`${prefixCls}-module__icon`"
|
:class="`${prefixCls}-module__icon`"
|
||||||
:size="22"
|
:size="22"
|
||||||
:icon="item.meta && item.meta.icon"
|
:icon="item.meta && item.meta.icon"
|
||||||
@@ -48,6 +48,14 @@
|
|||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<span class="text"> {{ title }}</span>
|
<span class="text"> {{ title }}</span>
|
||||||
|
<Icon
|
||||||
|
:size="16"
|
||||||
|
v-if="getMixSideFixed"
|
||||||
|
icon="ri:pushpin-2-fill"
|
||||||
|
class="pushpin"
|
||||||
|
@click="handleFixedMenu"
|
||||||
|
/>
|
||||||
|
<Icon :size="16" v-else icon="ri:pushpin-2-line" class="pushpin" @click="handleFixedMenu" />
|
||||||
</div>
|
</div>
|
||||||
<ScrollContainer :class="`${prefixCls}-menu-list__content`">
|
<ScrollContainer :class="`${prefixCls}-menu-list__content`">
|
||||||
<BasicMenu
|
<BasicMenu
|
||||||
@@ -70,20 +78,23 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, onMounted, ref, computed, CSSProperties, unref } from 'vue';
|
import { defineComponent, onMounted, ref, computed, CSSProperties, unref } from 'vue';
|
||||||
import type { Menu } from '/@/router/types';
|
import type { Menu } from '/@/router/types';
|
||||||
import type { RouteLocationNormalized } from 'vue-router';
|
import { RouteLocationNormalized } from 'vue-router';
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign';
|
||||||
import { getShallowMenus, getChildrenMenus, getCurrentParentPath } from '/@/router/menus';
|
import { getShallowMenus, getChildrenMenus, getCurrentParentPath } from '/@/router/menus';
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import { ScrollContainer } from '/@/components/Container';
|
import { ScrollContainer } from '/@/components/Container';
|
||||||
|
import Icon from '/@/components/Icon';
|
||||||
import { AppLogo } from '/@/components/Application';
|
import { AppLogo } from '/@/components/Application';
|
||||||
import { useGo } from '/@/hooks/web/usePage';
|
import { useGo } from '/@/hooks/web/usePage';
|
||||||
import { BasicMenu, MenuTag } from '/@/components/Menu';
|
import { BasicMenu, MenuTag } from '/@/components/Menu';
|
||||||
import { listenerLastChangeTab } from '/@/logics/mitt/tabChange';
|
import { listenerLastChangeTab } from '/@/logics/mitt/tabChange';
|
||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||||
import { useDragLine } from './useLayoutSider';
|
import { useDragLine } from './useLayoutSider';
|
||||||
|
import { useGlobSetting } from '/@/hooks/setting';
|
||||||
|
|
||||||
|
import { SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum';
|
||||||
|
|
||||||
import clickOutside from '/@/directives/clickOutside';
|
import clickOutside from '/@/directives/clickOutside';
|
||||||
import { useGlobSetting } from '/@/hooks/setting';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LayoutMixSider',
|
name: 'LayoutMixSider',
|
||||||
@@ -92,6 +103,7 @@
|
|||||||
AppLogo,
|
AppLogo,
|
||||||
BasicMenu,
|
BasicMenu,
|
||||||
MenuTag,
|
MenuTag,
|
||||||
|
Icon,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
clickOutside,
|
clickOutside,
|
||||||
@@ -101,6 +113,7 @@
|
|||||||
const activePath = ref('');
|
const activePath = ref('');
|
||||||
const chilrenMenus = ref<Menu[]>([]);
|
const chilrenMenus = ref<Menu[]>([]);
|
||||||
const openMenu = ref(false);
|
const openMenu = ref(false);
|
||||||
|
const isInit = ref(false);
|
||||||
const dragBarRef = ref<ElRef>(null);
|
const dragBarRef = ref<ElRef>(null);
|
||||||
const sideRef = ref<ElRef>(null);
|
const sideRef = ref<ElRef>(null);
|
||||||
const currentRoute = ref<Nullable<RouteLocationNormalized>>(null);
|
const currentRoute = ref<Nullable<RouteLocationNormalized>>(null);
|
||||||
@@ -114,7 +127,12 @@
|
|||||||
getCloseMixSidebarOnChange,
|
getCloseMixSidebarOnChange,
|
||||||
getMenuTheme,
|
getMenuTheme,
|
||||||
getMixSideTrigger,
|
getMixSideTrigger,
|
||||||
|
getRealWidth,
|
||||||
|
getMixSideFixed,
|
||||||
|
mixSideHasChildren,
|
||||||
|
setMenuSetting,
|
||||||
} = useMenuSetting();
|
} = useMenuSetting();
|
||||||
|
|
||||||
const { title } = useGlobSetting();
|
const { title } = useGlobSetting();
|
||||||
|
|
||||||
useDragLine(sideRef, dragBarRef, true);
|
useDragLine(sideRef, dragBarRef, true);
|
||||||
@@ -127,14 +145,41 @@
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getIsFixed = computed(() => {
|
||||||
|
mixSideHasChildren.value = unref(chilrenMenus).length > 0;
|
||||||
|
const isFixed = unref(getMixSideFixed) && unref(mixSideHasChildren);
|
||||||
|
if (isFixed) {
|
||||||
|
openMenu.value = true;
|
||||||
|
}
|
||||||
|
return isFixed;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getDomStyle = computed(
|
||||||
|
(): CSSProperties => {
|
||||||
|
const fixedWidth = unref(getIsFixed) ? unref(getRealWidth) : 0;
|
||||||
|
const width = `${SIDE_BAR_SHOW_TIT_MINI_WIDTH + fixedWidth}px`;
|
||||||
|
return {
|
||||||
|
width,
|
||||||
|
maxWidth: width,
|
||||||
|
minWidth: width,
|
||||||
|
flex: `0 0 ${width}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const getMenuEvents = computed(() => {
|
const getMenuEvents = computed(() => {
|
||||||
return unref(getMixSideTrigger) === 'hover'
|
// return unref(getMixSideTrigger) === 'hover'
|
||||||
? {
|
// ? {
|
||||||
onMouseleave: () => {
|
// onMouseleave: () => {
|
||||||
openMenu.value = false;
|
// closeMenu();
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
: {};
|
// : {};
|
||||||
|
return {
|
||||||
|
onMouseleave: () => {
|
||||||
|
closeMenu();
|
||||||
|
},
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const getShowDragBar = computed(() => unref(getCanDrag));
|
const getShowDragBar = computed(() => unref(getCanDrag));
|
||||||
@@ -145,9 +190,9 @@
|
|||||||
|
|
||||||
listenerLastChangeTab((route) => {
|
listenerLastChangeTab((route) => {
|
||||||
currentRoute.value = route;
|
currentRoute.value = route;
|
||||||
setActive();
|
setActive(true);
|
||||||
if (unref(getCloseMixSidebarOnChange)) {
|
if (unref(getCloseMixSidebarOnChange)) {
|
||||||
openMenu.value = false;
|
closeMenu();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -156,7 +201,11 @@
|
|||||||
|
|
||||||
if (unref(activePath) === path) {
|
if (unref(activePath) === path) {
|
||||||
if (!hover) {
|
if (!hover) {
|
||||||
openMenu.value = !unref(openMenu);
|
if (!unref(openMenu)) {
|
||||||
|
openMenu.value = true;
|
||||||
|
} else {
|
||||||
|
closeMenu();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!unref(openMenu)) {
|
if (!unref(openMenu)) {
|
||||||
setActive();
|
setActive();
|
||||||
@@ -169,18 +218,32 @@
|
|||||||
if (!children || children.length === 0) {
|
if (!children || children.length === 0) {
|
||||||
go(path);
|
go(path);
|
||||||
chilrenMenus.value = [];
|
chilrenMenus.value = [];
|
||||||
openMenu.value = false;
|
closeMenu();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
chilrenMenus.value = children;
|
chilrenMenus.value = children;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setActive() {
|
async function setActive(setChildren = false) {
|
||||||
const path = currentRoute.value?.path;
|
const path = currentRoute.value?.path;
|
||||||
if (!path) return;
|
if (!path) return;
|
||||||
const parentPath = await getCurrentParentPath(path);
|
const parentPath = await getCurrentParentPath(path);
|
||||||
activePath.value = parentPath;
|
activePath.value = parentPath;
|
||||||
// hanldeModuleClick(parentPath);
|
// hanldeModuleClick(parentPath);
|
||||||
|
if (unref(getMixSideFixed)) {
|
||||||
|
const activeMenu = unref(menuModules).find((item) => item.path === unref(activePath));
|
||||||
|
const p = activeMenu?.path;
|
||||||
|
if (p) {
|
||||||
|
const children = await getChildrenMenus(p);
|
||||||
|
if (setChildren) {
|
||||||
|
chilrenMenus.value = children;
|
||||||
|
openMenu.value = children.length > 0;
|
||||||
|
}
|
||||||
|
if (children.length === 0) {
|
||||||
|
chilrenMenus.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMenuClick(path: string) {
|
function handleMenuClick(path: string) {
|
||||||
@@ -188,7 +251,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleClickOutside() {
|
function handleClickOutside() {
|
||||||
openMenu.value = false;
|
closeMenu();
|
||||||
setActive();
|
setActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,6 +266,18 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleFixedMenu() {
|
||||||
|
setMenuSetting({
|
||||||
|
mixSideFixed: !unref(getIsFixed),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeMenu() {
|
||||||
|
if (!unref(getIsFixed)) {
|
||||||
|
openMenu.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
t,
|
t,
|
||||||
prefixCls,
|
prefixCls,
|
||||||
@@ -221,6 +296,9 @@
|
|||||||
getMenuTheme,
|
getMenuTheme,
|
||||||
getItemEvents,
|
getItemEvents,
|
||||||
getMenuEvents,
|
getMenuEvents,
|
||||||
|
getDomStyle,
|
||||||
|
handleFixedMenu,
|
||||||
|
getMixSideFixed,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -241,7 +319,7 @@
|
|||||||
min-width: @width;
|
min-width: @width;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: @sider-dark-bg-color;
|
background: @sider-dark-bg-color;
|
||||||
transition: all 0.2s ease 0s;
|
transition: all 0.3s ease 0s;
|
||||||
flex: 0 0 @width;
|
flex: 0 0 @width;
|
||||||
.@{tag-prefix-cls} {
|
.@{tag-prefix-cls} {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -293,6 +371,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.@{prefix-cls}-menu-list {
|
||||||
|
&__title {
|
||||||
|
.pushpin {
|
||||||
|
color: rgba(0, 0, 0, 0.35);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@border-color: @sider-dark-lighten-1-bg-color;
|
@border-color: @sider-dark-lighten-1-bg-color;
|
||||||
|
|
||||||
@@ -388,20 +477,30 @@
|
|||||||
&__title {
|
&__title {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: @header-height;
|
height: @header-height;
|
||||||
margin-left: -6px;
|
// margin-left: -6px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
color: @primary-color;
|
color: @primary-color;
|
||||||
border-bottom: 1px solid rgb(238, 238, 238);
|
border-bottom: 1px solid rgb(238, 238, 238);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: unset;
|
transition: unset;
|
||||||
// justify-content: center;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: start;
|
justify-content: space-between;
|
||||||
|
|
||||||
&.show {
|
&.show {
|
||||||
|
min-width: 130px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: all 0.5s ease;
|
transition: all 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pushpin {
|
||||||
|
margin-right: 6px;
|
||||||
|
color: rgba(255, 255, 255, 0.65);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
|
@@ -77,4 +77,6 @@ export default {
|
|||||||
mixSidebarTrigger: 'Mixed menu Trigger',
|
mixSidebarTrigger: 'Mixed menu Trigger',
|
||||||
triggerHover: 'Hover',
|
triggerHover: 'Hover',
|
||||||
triggerClick: 'Click',
|
triggerClick: 'Click',
|
||||||
|
|
||||||
|
mixSidebarFixed: 'Fixed expanded menu',
|
||||||
};
|
};
|
||||||
|
@@ -76,4 +76,6 @@ export default {
|
|||||||
mixSidebarTrigger: '混合菜单触发方式',
|
mixSidebarTrigger: '混合菜单触发方式',
|
||||||
triggerHover: '悬停',
|
triggerHover: '悬停',
|
||||||
triggerClick: '点击',
|
triggerClick: '点击',
|
||||||
|
|
||||||
|
mixSidebarFixed: '固定展开菜单',
|
||||||
};
|
};
|
||||||
|
@@ -110,6 +110,8 @@ const setting: ProjectConfig = {
|
|||||||
closeMixSidebarOnChange: false,
|
closeMixSidebarOnChange: false,
|
||||||
// Module opening method ‘click’ |'hover'
|
// Module opening method ‘click’ |'hover'
|
||||||
mixSideTrigger: MixSidebarTriggerEnum.CLICK,
|
mixSideTrigger: MixSidebarTriggerEnum.CLICK,
|
||||||
|
// Fixed expanded menu
|
||||||
|
mixSideFixed: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Multi-label
|
// Multi-label
|
||||||
|
1
src/types/config.d.ts
vendored
1
src/types/config.d.ts
vendored
@@ -21,6 +21,7 @@ export interface MenuSetting {
|
|||||||
closeMixSidebarOnChange: boolean;
|
closeMixSidebarOnChange: boolean;
|
||||||
collapsedShowTitle: boolean;
|
collapsedShowTitle: boolean;
|
||||||
mixSideTrigger: MixSidebarTriggerEnum;
|
mixSideTrigger: MixSidebarTriggerEnum;
|
||||||
|
mixSideFixed: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MultiTabsSetting {
|
export interface MultiTabsSetting {
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2016",
|
"target": "esnext",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"strictFunctionTypes": false,
|
"strictFunctionTypes": false,
|
||||||
"jsx": "react",
|
"jsx": "preserve",
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
|
Reference in New Issue
Block a user