<script lang="ts" setup name="Header"> import Logo from '../Logo/index.vue' import Tools from '../Tools/index.vue' import TopMenu from '../TopMenu/topMenu.vue' import useSettingsStore from '@/store/modules/settings' import useMenuStore from '@/store/modules/menu' const settingsStore = useSettingsStore() const menuStore = useMenuStore() const { switchTo } = useMenu() const navRef = ref() // 顶部模式鼠标滚动 function handlerMouserScroll(event: WheelEvent) { navRef.value.scrollBy({ left: (event.deltaY || event.detail) > 0 ? 50 : -50, }) } </script> <template> <transition name="header"> <header v-if="settingsStore.mode === 'pc' && (settingsStore.menu.menuMode === 'head' || settingsStore.menu.menuMode === 'top')"> <div class="header-container"> <div class="main"> <logo :show-logo="settingsStore.app.enableLogo" /> <!-- 混合模式-主导航 --> <div v-if="settingsStore.menu.menuMode === 'head'" ref="navRef" class="nav" @wheel.prevent="handlerMouserScroll"> <template v-for="(item, index) in menuStore.allMenus" :key="index"> <div v-if="item.children && item.children.length !== 0" class="item-container" :class="{ active: index === menuStore.actived }"> <div class="item" :class="`${settingsStore.menu.hoverStyle}-item`" @click="switchTo(index)"> <el-icon v-if="settingsStore.menu.showIcon"> <svg-icon v-if="item.meta.icon" :name="item.meta.icon" /> </el-icon> <span v-if="item.meta.title">{{ item.meta.title }}</span> </div> </div> </template> </div> <!-- 顶部模式-菜单 --> <div v-if="settingsStore.menu.menuMode === 'top'" ref="navRef" class="nav" @wheel.prevent="handlerMouserScroll"> <top-menu /> </div> </div> <tools /> </div> </header> </transition> </template> <style lang="scss" scoped> header { position: fixed; z-index: 1000; top: 0; left: 0; right: 0; display: flex; align-items: center; padding: 0 20px; height: var(--g-header-height); color: var(--g-header-color); background-color: var(--g-header-bg); background-image: linear-gradient(90deg, #70b4ff 30%, #4384ff); transition: background-color 0.3s, var(--el-transition-color); .header-container { width: var(--g-header-width); height: 100%; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; .main { flex: 1; display: flex; flex-wrap: wrap; align-items: center; height: 100%; } } @media screen and (max-width: var(--g-header-width)) { .header-container { width: 100%; } } :deep(.title) { position: relative; width: inherit; height: inherit; padding: inherit; background-color: inherit; .logo { width: 50px; height: 50px; } span { font-size: 24px; letter-spacing: 1px; color: var(--g-header-color); } } .nav { flex: 1; display: flex; width: 0; height: 100%; margin: 0 30px; padding: 0 20px; overflow-x: auto; mask-image: linear-gradient(to right, transparent, #000 20px, #000 calc(100% - 20px), transparent); // firefox隐藏滚动条 scrollbar-width: none; // chrome隐藏滚动条 &::-webkit-scrollbar { display: none; } .item-container { position: relative; display: flex; width: initial; align-items: center; .item { display: flex; align-items: center; justify-content: center; flex-direction: column; padding: 10px; height: auto; cursor: pointer; color: var(--g-header-menu-color); background-color: var(--g-header-bg); transition: background-color 0.3s, var(--el-transition-color); &:hover { color: var(--g-header-menu-hover-color); background-color: var(--g-header-menu-hover-bg); } .el-icon { font-size: 24px; vertical-align: middle; } span { text-align: center; vertical-align: middle; word-break: break-all; @include text-overflow(1, false); } } .round-item { padding: 10px 20px; border-radius: 50px; } .square-item { height: 100%; } &.active .item { color: var(--g-header-menu-active-color); background-color: var(--g-header-menu-active-bg); } } } :deep(.tools) { padding: 0; .buttons .item .el-icon { color: var(--g-header-color); } .user-container { font-size: 16px; color: var(--g-header-color); } } } // 头部动画 .header-enter-active, .header-leave-active { transition: transform 0.3s; } .header-enter-from, .header-leave-to { transform: translateY(calc(var(--g-header-height) * -1)); } </style>