104 lines
3.1 KiB
Vue
104 lines
3.1 KiB
Vue
<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> |