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.
353 lines
11 KiB
353 lines
11 KiB
<template> |
|
<header |
|
class="fixed left-0 right-0 top-0 z-50 w-full bg-transparent" |
|
:class="{ 'h-full': isNavbarOpen }" |
|
> |
|
<div |
|
class="max-w-[1920px] mx-auto flex h-17 sm:h-13 w-full items-center justify-between px-28 sm:px-6 md:px-[88px] peer" |
|
> |
|
<h1 class="font-bold relative z-20"> |
|
<NuxtLink to="/"> |
|
<LetterPullup |
|
words="BTDK" |
|
:delay="0.05" |
|
class="text-[#52AC63] text-3xl md:text-2xl sm:text-base" |
|
/> |
|
</NuxtLink> |
|
</h1> |
|
<nav class="absolute inset-0 select-none"> |
|
<ul |
|
class="flex justify-center text-xl gap-x-4 leading-17 sm:leading-13 text-white sm:hidden md:hidden" |
|
> |
|
<li |
|
v-for="nav in navItems" |
|
:key="nav.path" |
|
class="w-32 text-center text-inherit cursor-pointer" |
|
:class="{ 'group/submenu': !!nav.children?.length }" |
|
@click="onNavPush(nav)" |
|
> |
|
<div |
|
class="relative h-full after:absolute after:bottom-0 after:left-0 after:right-0 after:h-1 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" |
|
> |
|
<span class="text-inherit"> |
|
{{ nav.name }} |
|
</span> |
|
</div> |
|
|
|
<div |
|
class="absolute top-17 left-0 right-0 grid grid-rows-[0fr] group-hover/submenu:grid-rows-[1fr] transition-all duration-[400ms]" |
|
> |
|
<ul |
|
class="h-0 overflow-hidden flex justify-center md:flex-col transition-[height] bg-[rgba(18,21,26,.6)] duration-[400ms] backdrop-blur-2xl group-hover/submenu:h-[72px]" |
|
> |
|
<li |
|
v-for="child in nav.children" |
|
:key="child.path" |
|
class="group/submenuitem mr-[120px] md:mr-[80px] cursor-pointer last:mr-0 text-[hsla(0,0%,100%,.9)]" |
|
@click="event => onChildNavPush(child, event)" |
|
> |
|
<div |
|
class="relative h-full after:absolute after:bottom-0 after:left-0 after:right-0 after:h-1 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" |
|
> |
|
<span class="text-inherit"> |
|
{{ child.name }} |
|
</span> |
|
</div> |
|
</li> |
|
</ul> |
|
</div> |
|
</li> |
|
</ul> |
|
</nav> |
|
<Menu |
|
as="div" |
|
class="hidden h-full sm:block md:block select-none" |
|
v-slot="{ open: menuOpen }" |
|
> |
|
<MenuButton class="h-full"> |
|
<div |
|
class="navbar-control select-none" |
|
: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-300 overflow-hidden" |
|
leave-from-class="h-full opacity-100" |
|
leave-to-class="max-h-0 opacity-70" |
|
> |
|
<div v-show="isNavbarOpen"> |
|
<MenuItems |
|
as="ul" |
|
class="header-bg select-none border-t-1 absolute inset-0 top-17 sm:top-13 z-50 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 text-base md:text-lg" |
|
@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 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-300 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> |
|
<div |
|
class="absolute mx-auto flex sm:h-13 items-center justify-between px-28 sm:px-6 md:px-[88px] h-17 top-0 w-full -z-10 peer-hover:backdrop-blur-2xl peer-hover:bg-[rgba(92,92,92,0.4)] peer-hover:bg-gradient-to-r peer-hover:from-black/50 peer-hover:to-black/50" |
|
:class="{ |
|
'backdrop-blur-2xl': isScrolled || isNavbarOpen, |
|
'header-bg': isScrolled, |
|
}" |
|
></div> |
|
</header> |
|
<slot /> |
|
<footer> |
|
<div |
|
class="relative flex flex-row justify-between sm:justify-center items-center text-sm font-regular bg-[#2D2D2F] md:flex-col p-4 sm:p-2 sm:text-xs" |
|
> |
|
<div> |
|
<!-- <span class="text-[#18AA56] text-[90px] leading-[100px] font-bold">BTDK</span> --> |
|
<div |
|
class="flex items-center text-sm sm:text-xs text-white opacity-60 pl-2 gap-x-2 sm:flex-col" |
|
> |
|
<p class="mr-2 lg:mr-0">©比特电科技有限公司</p> |
|
<p class="mr-2 flex items-center"> |
|
<NuxtImg |
|
class="size-4 object-cover" |
|
loading="lazy" |
|
src="/images/commons/beian.jpg" |
|
alt="beian" |
|
format="webp" |
|
/> |
|
<a |
|
href=" " |
|
rel="noreferrer" |
|
target="_blank" |
|
class="hover:no-underline inline-flex cursor-pointer ml-1" |
|
>京公网安备11010802045670号</a |
|
> |
|
</p> |
|
</div> |
|
</div> |
|
</div> |
|
</footer> |
|
</template> |
|
<script setup lang="ts"> |
|
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue' |
|
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue' |
|
import LetterPullup from '@/components/ui/letter-pullup/LetterPullup.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 = !isNavbarOpen.value |
|
} |
|
|
|
const updateStateNavbar = ref(false) |
|
|
|
function onNavPush(nav: any) { |
|
if (!!nav.break) { |
|
window.open(nav.url, '_blank') |
|
return |
|
} |
|
|
|
if (nav.path) { |
|
router.push(nav.path) |
|
updateStateNavbar.value = true |
|
nextTick(() => { |
|
updateStateNavbar.value = false |
|
}) |
|
} |
|
} |
|
|
|
function onChildNavPush(child: any, event: Event) { |
|
event.stopPropagation() |
|
event.preventDefault() |
|
|
|
if (!!child.break) { |
|
window.open(child.url, '_blank') |
|
return |
|
} |
|
|
|
if (child.path) { |
|
router.push(child.path) |
|
updateStateNavbar.value = true |
|
nextTick(() => { |
|
updateStateNavbar.value = false |
|
}) |
|
} |
|
} |
|
|
|
function onNavClick(nav: any, menuOpen: boolean) { |
|
if (!!nav.children?.length) { |
|
return |
|
} |
|
onNavPush(nav) |
|
isNavbarOpen.value = false |
|
} |
|
|
|
const navItems = [ |
|
{ |
|
name: '首页', |
|
path: '/', |
|
}, |
|
{ |
|
name: '产品中心', |
|
path: '', |
|
children: [ |
|
{ |
|
name: 'BK-1000', |
|
path: '/products/BK-1000', |
|
}, |
|
{ |
|
name: 'BK-2000', |
|
path: '/products/BK-2000', |
|
}, |
|
], |
|
}, |
|
{ |
|
name: '技术资料', |
|
path: '', |
|
break: true, |
|
url: 'http://doc.bitedianke.cn/', |
|
}, |
|
{ |
|
name: '在线商城', |
|
path: '', |
|
break: true, |
|
url: 'https://3ktcgr18h1x6x7uwnlob22lviaqfk6b.taobao.com', |
|
}, |
|
{ |
|
name: '关于我们', |
|
path: '/aboutUs', |
|
}, |
|
] |
|
</script> |
|
<style scoped> |
|
.header-bg { |
|
@apply bg-[rgba(92,92,92,0.4)] bg-gradient-to-r from-black/50 to-black/50; |
|
} |
|
|
|
/* 子菜单展开收缩动画 */ |
|
.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.3s 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>
|
|
|