website-vue/components/NavBar.vue

104 lines
3.1 KiB
Vue
Raw Normal View History

2025-04-22 15:57:06 +08:00
<template>
<nav :class="['bg-primary shadow-md fixed w-full z-50', { 'nav-scrolled': scrolled }]">
<div class="container">
<div class="flex items-center justify-between h-16">
<NuxtLink to="/" class="flex items-center text-white">
<i class="fas fa-cloud text-2xl mr-2"></i>
<span class="text-xl font-bold">{{ $t('common.appName') }}</span>
</NuxtLink>
<!-- 桌面端导航 -->
<div class="hidden md:flex items-center space-x-8">
<NuxtLink
v-for="(item, index) in navItems"
:key="index"
:to="item.path"
class="text-white/85 hover:text-secondary transition-colors duration-300"
:class="{ 'text-white': $route.path === item.path }"
>
{{ $t(item.i18nKey) }}
</NuxtLink>
<!-- 语言切换器 -->
<LanguageSwitcher />
</div>
<!-- 移动端菜单按钮 -->
<button
class="md:hidden text-white p-2 rounded-lg hover:bg-white/10 transition-colors duration-300"
aria-label="打开菜单"
@click="toggleMobileMenu"
>
<i class="fas fa-bars text-xl"></i>
</button>
</div>
<!-- 移动端菜单 -->
<div :class="['md:hidden bg-primary absolute top-16 left-0 right-0 shadow-lg', { 'hidden': !mobileMenuOpen }]">
<div class="container py-4">
<div class="flex flex-col space-y-4">
<NuxtLink
v-for="(item, index) in navItems"
:key="index"
:to="item.path"
class="text-white/85 hover:text-secondary transition-colors duration-300 py-2"
:class="{ 'text-white': $route.path === item.path }"
@click="mobileMenuOpen = false"
>
{{ $t(item.i18nKey) }}
</NuxtLink>
<!-- 移动端语言切换器 -->
<div class="py-2">
<LanguageSwitcher />
</div>
</div>
</div>
</div>
</div>
</nav>
<!-- 添加导航栏占位防止内容被导航栏遮挡 -->
<div class="h-16"></div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import LanguageSwitcher from './LanguageSwitcher.vue';
const route = useRoute();
const { t } = useI18n();
const mobileMenuOpen = ref(false);
const scrolled = ref(false);
const navItems = [
{ i18nKey: 'nav.home', path: '/' },
{ i18nKey: 'nav.products', path: '/products' },
{ i18nKey: 'nav.solutions', path: '/solutions' },
{ i18nKey: 'nav.cases', path: '/cases' },
{ i18nKey: 'nav.about', path: '/about' },
{ i18nKey: 'nav.contact', path: '/contact' }
];
const toggleMobileMenu = () => {
mobileMenuOpen.value = !mobileMenuOpen.value;
};
const handleScroll = () => {
if (window.scrollY > 100) {
scrolled.value = true;
} else {
scrolled.value = false;
}
};
onMounted(() => {
window.addEventListener('scroll', handleScroll);
});
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll);
});
</script>