You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
7.5 KiB
238 lines
7.5 KiB
<template> |
|
<div> |
|
<header |
|
class="z-1000 fixed left-0 right-0 top-[-1] w-full bg-transparent duration-300" |
|
:class="{ 'backdrop-blur-2xl': isScrolled || isNavbarOpen, 'h-full': isNavbarOpen }" |
|
> |
|
<div class="header-bg flex h-13 w-full items-center justify-between px-6 sm:px-4 md:px-8"> |
|
<h1 class="text-2xl font-bold text-[#52AC63]">BTDK</h1> |
|
<nav class="absolute left-0 right-0 top-0"> |
|
<ul class="flex justify-center gap-8 leading-13 text-white sm:hidden md:hidden"> |
|
<li |
|
v-for="nav in navItems" |
|
:key="nav.path" |
|
class="relative h-full text-inherit after:absolute after:bottom-2 after:left-0 after:right-0 after:h-[1px] after:w-full after:origin-top-right after:scale-x-0 after:bg-[#52AC63] after:transition-[transform] after:duration-300 after:content-[''] hover:after:origin-top-left hover:after:scale-x-100" |
|
> |
|
<NuxtLink :to="nav.path" class="text-inherit"> |
|
{{ nav.name }} |
|
</NuxtLink> |
|
</li> |
|
</ul> |
|
</nav> |
|
<Menu as="div" class="hidden h-full sm:block md:block" v-slot="{ open: menuOpen }"> |
|
<MenuButton class="h-full"> |
|
<div |
|
class="navbar-control" |
|
:class="{ open: isNavbarOpen }" |
|
@click="toggleNavbar(menuOpen)" |
|
> |
|
<span class="control-icon"></span> |
|
<span class="control-icon"></span> |
|
<span class="control-icon"></span> |
|
</div> |
|
</MenuButton> |
|
<transition |
|
enter-active-class="transition-all duration-300 overflow-hidden" |
|
enter-from-class="max-h-0 opacity-70" |
|
enter-to-class="h-full opacity-100" |
|
leave-active-class="transition-all duration-200 overflow-hidden" |
|
leave-from-class="h-full opacity-100" |
|
leave-to-class="max-h-0 opacity-70" |
|
> |
|
<!-- lg:ml-[-110px] flex justify-center md:justify-start md:flex-col md:text-center md:overflow-auto md:grow-[1] --> |
|
<div v-show="isNavbarOpen"> |
|
<MenuItems |
|
as="ul" |
|
class="header-bg z-1000 border-t-1 absolute inset-0 top-13 overflow-hidden border-t-[1px] border-[hsla(0,0%,100%,.06)] text-white backdrop-blur-2xl" |
|
static |
|
> |
|
<template v-for="nav in navItems" :key="nav.path"> |
|
<MenuItem |
|
as="li" |
|
v-slot="{ close }" |
|
class="cursor-pointer text-nowrap text-center" |
|
@click="onNavClick(nav, menuOpen)" |
|
> |
|
<Disclosure as="div" class="size-full" v-slot="{ open }"> |
|
<DisclosureButton as="p" class="relative py-7"> |
|
<span>{{ nav.name }} </span> |
|
<Icon |
|
name="mingcute:up-line" |
|
:class="open ? '' : 'rotate-180 transform'" |
|
class="absolute right-5 top-1/2 -translate-y-1/2 text-lg transition-transform duration-300" |
|
:ssr="true" |
|
v-if="!!nav.children?.length" |
|
/> |
|
</DisclosureButton> |
|
<transition |
|
enter-active-class="transition-all duration-700 overflow-hidden" |
|
enter-from-class="max-h-0 opacity-70" |
|
enter-to-class="max-h-[300px] opacity-100" |
|
leave-active-class="transition-all duration-200 overflow-hidden" |
|
leave-from-class="max-h-[300px] opacity-100" |
|
leave-to-class="max-h-0 opacity-70" |
|
> |
|
<DisclosurePanel as="div" v-if="!!nav.children?.length"> |
|
<ul class="flex flex-col bg-[hsla(0,0%,100%,.06)]"> |
|
<li |
|
class="text-nowrap py-7 text-center" |
|
v-for="child in nav.children" |
|
:key="child.path" |
|
@click="onNavClick(child, menuOpen)" |
|
> |
|
<span> |
|
{{ child.name }} |
|
</span> |
|
</li> |
|
</ul> |
|
</DisclosurePanel> |
|
</transition> |
|
</Disclosure> |
|
</MenuItem> |
|
</template> |
|
</MenuItems> |
|
</div> |
|
</transition> |
|
</Menu> |
|
</div> |
|
</header> |
|
<slot /> |
|
<footer> |
|
<p>版权所有 © 2025 比特电科</p> |
|
</footer> |
|
</div> |
|
</template> |
|
<script setup lang="ts"> |
|
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue' |
|
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue' |
|
|
|
const isScrolled = ref(false) |
|
const router = useRouter() |
|
const checkScroll = () => { |
|
isScrolled.value = window.scrollY > 20 |
|
} |
|
|
|
onMounted(() => { |
|
if (typeof window !== 'undefined') { |
|
checkScroll() |
|
window.addEventListener('scroll', checkScroll) |
|
} |
|
}) |
|
|
|
onUnmounted(() => { |
|
if (typeof window !== 'undefined') { |
|
window.removeEventListener('scroll', checkScroll) |
|
} |
|
}) |
|
|
|
const isNavbarOpen = ref(false) |
|
const toggleNavbar = (open: boolean) => { |
|
isNavbarOpen.value = !open |
|
} |
|
|
|
function onNavClick(nav: any, menuOpen: boolean) { |
|
if (!!nav.children?.length) { |
|
return |
|
} |
|
router.push(nav.path) |
|
isNavbarOpen.value = false |
|
} |
|
|
|
const navItems = [ |
|
{ |
|
name: '首页', |
|
path: '/', |
|
}, |
|
{ |
|
name: '产品中心', |
|
path: '/products', |
|
children: [ |
|
{ |
|
name: 'EM系列储能边缘智能网关', |
|
path: '/products/em-series-energy-storage-edge-intelligent-gateway', |
|
}, |
|
{ |
|
name: 'EM系列储能边缘智能网关', |
|
path: '/products/em-series-energy-storage-edge-intelligent-gateway', |
|
}, |
|
], |
|
}, |
|
{ |
|
name: '技术资料', |
|
path: '/technical-materials', |
|
}, |
|
{ |
|
name: '在线商城', |
|
path: '/online-store', |
|
}, |
|
{ |
|
name: '关于我们', |
|
path: '/about', |
|
}, |
|
] |
|
</script> |
|
<style scoped> |
|
.header-bg { |
|
@apply bg-[rgba(92,92,92,0.4)] bg-gradient-to-r from-black/40 to-black/40; |
|
} |
|
|
|
/* 子菜单展开收缩动画 */ |
|
.transition-all { |
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); |
|
} |
|
|
|
/* CSS */ |
|
.navbar-control { |
|
cursor: pointer; |
|
height: 100%; |
|
display: flex; |
|
flex-direction: column; |
|
gap: 6px; |
|
justify-content: center; |
|
} |
|
|
|
.control-icon { |
|
transition: all 0.3s ease; |
|
} |
|
|
|
/* 每个 control-icon 的伪元素 */ |
|
.control-icon:before { |
|
background-color: #fff; |
|
border-bottom-left-radius: 1px; |
|
border-top-right-radius: 1px; |
|
content: ''; |
|
display: block; |
|
height: 1px; |
|
transition: |
|
transform 0.3s ease 0.2s, |
|
background-color 0.4s ease 0s; |
|
width: 22px; |
|
opacity: 0.9; |
|
} |
|
.navbar-control.open .control-icon:before { |
|
/* background-color: #000; */ |
|
} |
|
.navbar-control.open .control-icon:nth-child(1) { |
|
transform: translateY(7px); |
|
} |
|
.navbar-control.open .control-icon:nth-child(2) { |
|
opacity: 0; |
|
transition-duration: 0.3s; |
|
} |
|
|
|
.navbar-control .control-icon:nth-child(2) { |
|
transition-duration: 0.6s; |
|
} |
|
|
|
.navbar-control.open .control-icon:nth-child(3) { |
|
transform: translateY(-7px); |
|
} |
|
|
|
/* open 状态下的动画 */ |
|
.navbar-control.open .control-icon:nth-child(1):before { |
|
transform: rotate(45deg); |
|
} |
|
.navbar-control.open .control-icon:nth-child(3):before { |
|
transform: rotate(-45deg); |
|
} |
|
</style>
|
|
|