|
|
@@ -7,6 +7,9 @@ import { computed, ref } from 'vue'
|
|
|
const route = useRoute()
|
|
|
const isDocView = computed(() => route.name === 'doc')
|
|
|
|
|
|
+// 计算当前激活的菜单索引
|
|
|
+defineOptions({ name: 'NewHeader' })
|
|
|
+
|
|
|
// 组件属性
|
|
|
defineProps({
|
|
|
title: {
|
|
|
@@ -47,14 +50,35 @@ const handleMenuHover = (index: number) => {
|
|
|
activeIndex.value = index
|
|
|
}
|
|
|
|
|
|
-// 处理菜单离开
|
|
|
+// 处理整个菜单区域离开
|
|
|
const handleMenuLeave = () => {
|
|
|
- activeIndex.value = -1
|
|
|
+ // 添加一个小延迟,防止意外关闭
|
|
|
+ setTimeout(() => {
|
|
|
+ activeIndex.value = -1
|
|
|
+ }, 100)
|
|
|
+}
|
|
|
+
|
|
|
+// 处理子菜单悬停,防止子菜单消失
|
|
|
+const handleSubmenuHover = (index: number) => {
|
|
|
+ activeIndex.value = index
|
|
|
+}
|
|
|
+
|
|
|
+// 处理菜单项点击
|
|
|
+const handleMenuClick = (index: number) => {
|
|
|
+ if (activeIndex.value === index) {
|
|
|
+ activeIndex.value = -1
|
|
|
+ } else {
|
|
|
+ activeIndex.value = index
|
|
|
+ }
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
- <header class="new-header" :class="{ 'new-header-doc': isDocView }">
|
|
|
+ <header
|
|
|
+ class="new-header"
|
|
|
+ :class="{ 'new-header-doc': isDocView }"
|
|
|
+ @mouseleave="handleMenuLeave"
|
|
|
+ >
|
|
|
<div class="header-container">
|
|
|
<!-- Logo 区域 -->
|
|
|
<div class="logo-section">
|
|
|
@@ -72,22 +96,28 @@ const handleMenuLeave = () => {
|
|
|
:key="item.name"
|
|
|
class="menu-item"
|
|
|
@mouseenter="handleMenuHover(index)"
|
|
|
- @mouseleave="handleMenuLeave"
|
|
|
+ @click="handleMenuClick(index)"
|
|
|
:class="{ active: activeIndex === index }"
|
|
|
>
|
|
|
- <RouterLink :to="item.path" class="menu-link">{{ item.title }}</RouterLink>
|
|
|
- <!-- 添加二级菜单 -->
|
|
|
- <ul v-if="item.children && item.children.length > 0" class="submenu">
|
|
|
- <li v-for="subItem in item.children" :key="subItem.name" class="submenu-item">
|
|
|
- <RouterLink :to="`${item.path}/${subItem.path}`" class="submenu-link">{{ subItem.title }}</RouterLink>
|
|
|
- <!-- 添加三级菜单 -->
|
|
|
- <ul v-if="subItem.children && subItem.children.length > 0" class="sub-submenu">
|
|
|
- <li v-for="subSubItem in subItem.children" :key="subSubItem.name" class="sub-submenu-item">
|
|
|
- <RouterLink :to="`${item.path}/${subItem.path}/${subSubItem.path}`" class="sub-submenu-link">{{ subSubItem.title }}</RouterLink>
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
+ <RouterLink :to="item.path" class="menu-link" @click.prevent>{{ item.title }}</RouterLink>
|
|
|
+ <!-- 添加二级和三级菜单 -->
|
|
|
+ <div
|
|
|
+ v-if="item.children && item.children.length > 0"
|
|
|
+ class="submenu"
|
|
|
+ @mouseenter="handleSubmenuHover(index)"
|
|
|
+ >
|
|
|
+ <div class="submenu-content">
|
|
|
+ <div v-for="subItem in item.children" :key="subItem.name" class="submenu-item">
|
|
|
+ <RouterLink :to="`${item.path}/${subItem.path}`" class="submenu-link">{{ subItem.title }}</RouterLink>
|
|
|
+ <!-- 添加三级菜单 -->
|
|
|
+ <div v-if="subItem.children && subItem.children.length > 0" class="sub-submenu">
|
|
|
+ <div v-for="subSubItem in subItem.children" :key="subSubItem.name" class="sub-submenu-item">
|
|
|
+ <RouterLink :to="`${item.path}/${subItem.path}/${subSubItem.path}`" class="sub-submenu-link">{{ subSubItem.title }}</RouterLink>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</li>
|
|
|
</ul>
|
|
|
</nav>
|
|
|
@@ -107,20 +137,17 @@ const handleMenuLeave = () => {
|
|
|
@use "sass:color";
|
|
|
|
|
|
.new-header {
|
|
|
- position: fixed;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- height: v.$header-height;
|
|
|
+ position: relative;
|
|
|
+ width: 100%;
|
|
|
background-color: v.$background-light;
|
|
|
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
|
|
- z-index: v.$z-index-fixed;
|
|
|
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
|
+ z-index: 1001; // 确保header在submenu之上
|
|
|
}
|
|
|
|
|
|
.header-container {
|
|
|
@include m.container;
|
|
|
@include m.flex-between;
|
|
|
- height: 100%;
|
|
|
+ padding: 0 v.$spacing-lg;
|
|
|
}
|
|
|
|
|
|
// Logo 区域样式
|
|
|
@@ -128,16 +155,18 @@ const handleMenuLeave = () => {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: v.$spacing-sm;
|
|
|
+ //height: 100%; // 确保logo区域填满header高度
|
|
|
|
|
|
a {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
text-decoration: none;
|
|
|
gap: v.$spacing-sm;
|
|
|
+ height: 100%; // 确保链接区域填满header高度
|
|
|
}
|
|
|
|
|
|
.logo {
|
|
|
- height: 42px;
|
|
|
+ height: 42px; // 保持logo高度不变
|
|
|
width: auto;
|
|
|
transition: transform 0.3s ease;
|
|
|
transform-origin: center;
|
|
|
@@ -159,6 +188,7 @@ const handleMenuLeave = () => {
|
|
|
.nav-menu {
|
|
|
flex: 1;
|
|
|
margin: 0 v.$spacing-xl;
|
|
|
+ height: 100%; // 确保导航菜单填满header高度
|
|
|
|
|
|
.menu-list {
|
|
|
display: flex;
|
|
|
@@ -170,7 +200,7 @@ const handleMenuLeave = () => {
|
|
|
|
|
|
.menu-item {
|
|
|
position: relative;
|
|
|
- height: 100%;
|
|
|
+ height: 64px; // 确保菜单项高度与header一致
|
|
|
padding: 0 v.$spacing-lg;
|
|
|
|
|
|
&:hover, &.active {
|
|
|
@@ -193,18 +223,30 @@ const handleMenuLeave = () => {
|
|
|
// 添加二级菜单样式
|
|
|
.submenu {
|
|
|
display: none;
|
|
|
- position: absolute;
|
|
|
- top: 100%;
|
|
|
+ position: fixed;
|
|
|
+ top: 64px; // 直接使用固定的header高度
|
|
|
left: 0;
|
|
|
+ width: 100%;
|
|
|
background-color: v.$background-light;
|
|
|
- border: 1px solid rgba(0, 0, 0, 0.1);
|
|
|
- border-radius: v.$border-radius-md;
|
|
|
- padding: v.$spacing-sm 0;
|
|
|
- min-width: 200px;
|
|
|
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
|
|
+ padding: v.$spacing-lg 0;
|
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
|
+ animation: slideDown 0.3s ease;
|
|
|
+ z-index: 1000;
|
|
|
+ pointer-events: auto; // 确保可以接收鼠标事件
|
|
|
+ }
|
|
|
+ @keyframes slideDown {
|
|
|
+ from {
|
|
|
+ opacity: 0;
|
|
|
+ transform: translateY(-10px);
|
|
|
+ }
|
|
|
+ to {
|
|
|
+ opacity: 1;
|
|
|
+ transform: translateY(0);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .menu-item:hover .submenu {
|
|
|
+ .menu-item.active .submenu {
|
|
|
display: block;
|
|
|
}
|
|
|
|
|
|
@@ -212,41 +254,73 @@ const handleMenuLeave = () => {
|
|
|
position: relative;
|
|
|
}
|
|
|
|
|
|
+ .submenu-content {
|
|
|
+ max-width: v.$container-width;
|
|
|
+ margin: 0 auto;
|
|
|
+ padding: 0 v.$spacing-lg;
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
|
+ gap: v.$spacing-xl;
|
|
|
+ }
|
|
|
+
|
|
|
+ .submenu-item {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
.submenu-link {
|
|
|
display: block;
|
|
|
- padding: v.$spacing-sm v.$spacing-lg;
|
|
|
+ padding: v.$spacing-sm 0;
|
|
|
color: v.$text-primary;
|
|
|
text-decoration: none;
|
|
|
- font-size: v.$font-size-sm;
|
|
|
- transition: background-color v.$transition-fast;
|
|
|
+ font-size: v.$font-size-md;
|
|
|
+ font-weight: v.$font-weight-medium;
|
|
|
+ border-bottom: 2px solid v.$primary-color;
|
|
|
+ margin-bottom: v.$spacing-md;
|
|
|
+ transition: all v.$transition-fast;
|
|
|
|
|
|
&:hover {
|
|
|
- background-color: rgba(v.$primary-color, 0.1);
|
|
|
color: v.$primary-color;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 添加三级菜单样式
|
|
|
.sub-submenu {
|
|
|
- display: none;
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 100%;
|
|
|
- background-color: v.$background-light;
|
|
|
- border: 1px solid rgba(0, 0, 0, 0.1);
|
|
|
- border-radius: v.$border-radius-md;
|
|
|
- padding: v.$spacing-sm 0;
|
|
|
- min-width: 200px;
|
|
|
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ margin-top: v.$spacing-xs;
|
|
|
}
|
|
|
|
|
|
- .submenu-item:hover .sub-submenu {
|
|
|
+ .sub-submenu-item {
|
|
|
+ margin-bottom: v.$spacing-xs;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-submenu-link {
|
|
|
display: block;
|
|
|
+ padding: v.$spacing-xs v.$spacing-sm v.$spacing-xs v.$spacing-md;
|
|
|
+ color: v.$text-secondary;
|
|
|
+ text-decoration: none;
|
|
|
+ font-size: v.$font-size-sm;
|
|
|
+ transition: all v.$transition-fast;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &:before {
|
|
|
+ content: "•";
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ color: v.$primary-color;
|
|
|
+ opacity: 0.7;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: v.$primary-color;
|
|
|
+ transform: translateX(5px);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.sub-submenu-link {
|
|
|
display: block;
|
|
|
- padding: v.$spacing-sm v.$spacing-lg;
|
|
|
+ padding: v.$spacing-sm v.$spacing-lg v.$spacing-sm v.$spacing-lg;
|
|
|
color: v.$text-primary;
|
|
|
text-decoration: none;
|
|
|
font-size: v.$font-size-sm;
|
|
|
@@ -264,6 +338,7 @@ const handleMenuLeave = () => {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: v.$spacing-md;
|
|
|
+ height: 100%; // 确保操作区域填满header高度
|
|
|
}
|
|
|
|
|
|
.action-link {
|