fix(projects): 修复vertical-mix导航模式的二级菜单显示问题

This commit is contained in:
Soybean
2021-09-29 08:49:28 +08:00
parent c7e6b86a5b
commit 6f286e6747
10 changed files with 1443 additions and 979 deletions

View File

@ -21,10 +21,12 @@
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import { computed } from 'vue';
import type { PropType, VNodeChild } from 'vue';
import { useRouter } from 'vue-router';
import { useAppStore } from '@/store';
import { useBoolean } from '@/hooks';
import { useVerticalMixSiderContext } from '@/context';
const props = defineProps({
routeName: {
@ -39,51 +41,50 @@ const props = defineProps({
type: Function as PropType<() => VNodeChild>,
required: true
},
isActive: {
type: Boolean,
default: false
activeRouteName: {
type: String,
required: true
},
isMini: {
type: Boolean,
default: false
},
hoverRoute: {
type: String,
default: ''
}
});
const emit = defineEmits(['update:hoverRoute']);
const app = useAppStore();
const router = useRouter();
const { useVerticalMixSiderInject } = useVerticalMixSiderContext();
const { bool: isHover, setTrue, setFalse } = useBoolean();
const { bool: isMouseEnterMenu, setTrue: setMouseEnterMenu, setFalse: setMouseLeaveMenu } = useBoolean();
const hoverRouteName = ref(props.hoverRoute);
function setHoverRouteName(name: string) {
hoverRouteName.value = name;
}
const { setHoverRouteName, showChildMenu, hideChildMenu, isMouseEnterChildMenu } = useVerticalMixSiderInject();
const isActive = computed(() => props.routeName === props.activeRouteName);
function handleRouter() {
router.push({ name: props.routeName });
}
function handleMouseEvent(type: 'enter' | 'leave') {
if (type === 'enter') {
setTrue();
setHoverRouteName(props.routeName);
} else {
setFalse();
}
async function setActiveHoverRouteName() {
setTimeout(() => {
if (app.menu.fixedMix && !isMouseEnterChildMenu.value && !isMouseEnterMenu.value) {
setHoverRouteName(props.activeRouteName);
}
setMouseLeaveMenu();
}, 100);
}
watch(
() => props.hoverRoute,
newValue => {
setHoverRouteName(newValue);
function handleMouseEvent(type: 'enter' | 'leave') {
if (type === 'enter') {
setMouseEnterMenu();
setTrue();
setHoverRouteName(props.routeName);
showChildMenu();
} else {
setFalse();
hideChildMenu();
setActiveHoverRouteName();
}
);
watch(hoverRouteName, newValue => {
emit('update:hoverRoute', newValue);
});
}
</script>
<style scoped></style>

View File

@ -13,7 +13,8 @@
dark:bg-[#18181c]
"
:style="{ width: showDrawer ? theme.menuStyle.width + 'px' : '0px' }"
@mouseleave="handleResetHoverRoute"
@mouseenter="handleMouseEvent('enter')"
@mouseleave="handleMouseEvent('leave')"
>
<header class="header-height flex-y-center justify-between">
<h2 class="pl-8px text-16px text-primary font-bold">{{ title }}</h2>
@ -38,29 +39,39 @@ import { NScrollbar, NMenu } from 'naive-ui';
import type { MenuOption } from 'naive-ui';
import { useThemeStore, useAppStore } from '@/store';
import { useAppTitle } from '@/hooks';
import { useVerticalMixSiderContext } from '@/context';
import { menus } from '@/router';
import type { GlobalMenuOption } from '@/interface';
const props = defineProps({
hoverRoute: {
activeRouteName: {
type: String,
default: ''
required: true
}
});
const emit = defineEmits(['reset-hover-route']);
const router = useRouter();
const route = useRoute();
const theme = useThemeStore();
const app = useAppStore();
const { toggleFixedMixMenu } = useAppStore();
const { useVerticalMixSiderInject } = useVerticalMixSiderContext();
const title = useAppTitle();
const {
childMenuVisible,
hoverRouteName,
setHoverRouteName,
showChildMenu,
hideChildMenu,
setMouseEnterChildMenu,
setMouseLeaveChildMenu
} = useVerticalMixSiderInject();
const childMenus = computed(() => {
const children: MenuOption[] = [];
menus.some(item => {
const flag = item.routeName === props.hoverRoute && Boolean(item.children?.length);
const flag = item.routeName === hoverRouteName.value && Boolean(item.children?.length);
if (flag) {
children.push(...item.children!);
}
@ -69,17 +80,9 @@ const childMenus = computed(() => {
return children;
});
const showDrawer = computed(() => childMenus.value.length || app.menu.fixedMix);
const showDrawer = computed(() => (childMenuVisible.value && childMenus.value.length) || app.menu.fixedMix);
const activeKey = computed(() => getActiveKey());
function getActiveKey() {
return route.name as string;
}
function handleResetHoverRoute() {
emit('reset-hover-route');
}
const activeKey = computed(() => route.name as string);
function handleUpdateMenu(key: string, item: MenuOption) {
const menuItem = item as GlobalMenuOption;
@ -90,6 +93,17 @@ const headerHeight = computed(() => {
const { height } = theme.headerStyle;
return `${height}px`;
});
function handleMouseEvent(type: 'enter' | 'leave') {
if (type === 'enter') {
showChildMenu();
setMouseEnterChildMenu();
} else {
hideChildMenu();
setMouseLeaveChildMenu();
setHoverRouteName(props.activeRouteName);
}
}
</script>
<style scoped>
.drawer-shadow {

View File

@ -10,11 +10,10 @@
<mix-menu
v-for="item in firstDegreeMenus"
:key="item.routeName"
v-model:hover-route="hoverRoute"
:route-name="item.routeName"
:label="item.label"
:icon="item.icon"
:is-active="activeParentRouteName === item.routeName"
:active-route-name="activeParentRouteName"
:is-mini="app.menu.collapsed"
/>
</n-scrollbar>
@ -25,17 +24,18 @@
class="relative h-full transition-width duration-300 ease-in-out"
:style="{ width: app.menu.fixedMix ? theme.menuStyle.width + 'px' : '0px' }"
>
<mix-menu-drawer :hover-route="hoverRoute" @reset-hover-route="resetHoverRoute" />
<mix-menu-drawer :active-route-name="activeParentRouteName" />
</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { computed } from 'vue';
import type { VNodeChild } from 'vue';
import { NScrollbar } from 'naive-ui';
import { useRoute } from 'vue-router';
import { useAppStore, useThemeStore } from '@/store';
import { useVerticalMixSiderContext } from '@/context';
import { menus } from '@/router';
import { MixMenu, MixMenuCollapse, MixMenuDrawer } from './components';
import { GlobalLogo } from '../../../common';
@ -43,6 +43,7 @@ import { GlobalLogo } from '../../../common';
const theme = useThemeStore();
const app = useAppStore();
const route = useRoute();
const { useVerticalMixSiderProvide } = useVerticalMixSiderContext();
const mixMenuWidth = computed(() => `${theme.menuStyle.mixWidth}px`);
const mixMenuCollapsedWidth = computed(() => `${theme.menuStyle.mixCollapsedWidth}px`);
@ -68,10 +69,7 @@ const activeParentRouteName = computed(() => {
return name;
});
const hoverRoute = ref('');
function resetHoverRoute() {
hoverRoute.value = '';
}
useVerticalMixSiderProvide();
</script>
<style scoped>
.mix-menu-width {