307 lines
10 KiB
Vue
307 lines
10 KiB
Vue
<template>
|
||
<header
|
||
class="fixed top-0 w-full z-50 transition-all duration-300"
|
||
:class="{
|
||
'bg-white/90 backdrop-blur-md shadow-sm py-3': isScrolled || isMenuOpen,
|
||
'bg-transparent py-5': !isScrolled && !isMenuOpen
|
||
}"
|
||
>
|
||
<!-- 关键修复:移动端布局优化 -->
|
||
<div class="px-3 sm:px-4">
|
||
<div class="flex justify-between items-center">
|
||
<router-link to="/" class="flex items-center shrink-0">
|
||
<img src="@/assets/images/logo.png" alt="Logo" class="w-8 h-8 md:w-10 md:h-10" />
|
||
<span class="ml-2 text-base sm:text-xl md:text-2xl font-bold text-primary whitespace-nowrap">
|
||
{{ currentLang === 'zh' ? '酉佰' : 'YouBaiBai' }}
|
||
</span>
|
||
</router-link>
|
||
|
||
<nav class="hidden md:flex space-x-8">
|
||
<router-link
|
||
v-for="item in menuItems"
|
||
:key="item.path"
|
||
:to="item.path"
|
||
class="font-medium transition-colors hover:text-primary"
|
||
active-class="text-primary"
|
||
:exact="item.exact"
|
||
>
|
||
{{ item.name }}
|
||
</router-link>
|
||
</nav>
|
||
|
||
<div class="hidden md:flex items-center space-x-4">
|
||
<!-- 语言切换按钮 -->
|
||
<button
|
||
@click="toggleLanguage"
|
||
class="flex items-center justify-center w-10 h-10 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-colors"
|
||
:title="currentLang === 'zh' ? '切换为英文' : 'Switch to Chinese'"
|
||
>
|
||
{{ currentLang === 'zh' ? 'EN' : '中' }}
|
||
</button>
|
||
|
||
<button
|
||
class="bg-gradient-to-r from-blue-500 to-indigo-600 hover:from-blue-600 hover:to-indigo-700 text-white font-medium py-2 px-4 md:py-3 md:px-6 rounded-lg flex items-center justify-center transition-all duration-300 transform hover:-translate-y-1 shadow-lg hover:shadow-xl active:translate-y-0 active:shadow-md"
|
||
@click="openModal"
|
||
>
|
||
{{ currentLang === 'zh' ? '联系我们' : 'Contact' }}
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 移动端菜单按钮 - 关键修复区域 -->
|
||
<div class="flex items-center space-x-2 md:hidden">
|
||
<!-- 移动端语言切换按钮 - 尺寸优化 -->
|
||
<button
|
||
@click="toggleLanguage"
|
||
class="shrink-0 flex items-center justify-center w-8 h-8 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-colors"
|
||
>
|
||
{{ currentLang === 'zh' ? 'EN' : '中' }}
|
||
</button>
|
||
|
||
<button @click="toggleMenu" class="shrink-0 text-gray-700">
|
||
<svg
|
||
xmlns="http://www.w3.org/2000/svg"
|
||
class="h-6 w-6"
|
||
fill="none"
|
||
viewBox="0 0 24 24"
|
||
stroke="currentColor"
|
||
>
|
||
<path
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
stroke-width="2"
|
||
d="M4 6h16M4 12h16m-7 6h7"
|
||
/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 移动端菜单 - 修复宽度问题 -->
|
||
<div
|
||
v-show="isMenuOpen"
|
||
class="w-full md:hidden fixed inset-x-0 z-50 bg-white/95 backdrop-blur-lg py-5 overflow-hidden"
|
||
:style="{ top: headerHeight + 'px', height: `calc(100vh - ${headerHeight}px)` }"
|
||
@click.self="closeMenu"
|
||
>
|
||
<div class="px-4 h-full flex flex-col">
|
||
<nav class="flex flex-col space-y-4 py-4 overflow-y-auto">
|
||
<router-link
|
||
v-for="item in menuItems"
|
||
:key="item.path"
|
||
:to="item.path"
|
||
class="font-medium text-lg py-2 transition-colors hover:text-primary"
|
||
active-class="text-primary"
|
||
@click="closeMenu"
|
||
>
|
||
{{ item.name }}
|
||
</router-link>
|
||
</nav>
|
||
<div class="pt-4 pb-8 mt-auto">
|
||
<button
|
||
class="w-full bg-primary hover:bg-blue-700 text-white font-semibold py-3 rounded-lg transition-colors"
|
||
@click="openModal(); closeMenu();"
|
||
>
|
||
{{ currentLang === 'zh' ? '联系我们' : 'Contact' }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- 模态框组件 -->
|
||
<!-- 模态框组件 - 移动端优化 -->
|
||
<transition name="modal-fade">
|
||
<div v-if="showModal" @click="closeModal" class="fixed inset-0 z-50 overflow-auto bg-black/50 flex items-start justify-center p-4 backdrop-blur-lg">
|
||
<div @click.stop class="bg-white rounded-2xl shadow-xl w-full max-w-md sm:max-w-2xl overflow-hidden transform transition-all sm:mt-20">
|
||
<!-- 模态框头部 -->
|
||
<div class="bg-gradient-to-r from-indigo-600 to-blue-700 p-4 sm:p-6 text-white">
|
||
<div class="flex justify-between items-center">
|
||
<h2 class="text-xl sm:text-2xl font-bold">{{ currentLang === 'zh' ? '留下您的联系方式' : 'Leave Your Contact' }}</h2>
|
||
<button @click="closeModal" class="text-white hover:text-gray-200">
|
||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 模态框内容 - 移动端优化 -->
|
||
<div class="p-4 sm:p-6 max-h-[70vh] overflow-y-auto bg-gradient-to-r from-indigo-600 to-blue-700">
|
||
<ContactForm :lang="currentLang" />
|
||
</div>
|
||
|
||
<!-- 模态框底部 - 移动端优化 -->
|
||
<div class="bg-gray-50 px-4 sm:px-6 py-4 flex flex-col sm:flex-row sm:flex-wrap justify-end gap-3">
|
||
<button
|
||
@click="closeModal"
|
||
class="w-full sm:w-auto px-5 py-2 text-gray-700 rounded-lg font-medium border border-gray-300 hover:bg-gray-100"
|
||
>
|
||
{{ currentLang === 'zh' ? '关闭' : 'Close' }}
|
||
</button>
|
||
<button
|
||
class="w-full sm:w-auto px-5 py-2 bg-indigo-600 text-white rounded-lg font-medium hover:bg-indigo-700"
|
||
>
|
||
{{ currentLang === 'zh' ? '立即申请' : 'Submit' }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</transition>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
|
||
import ContactForm from "@/components/ui/ContactForm.vue";
|
||
|
||
const isScrolled = ref(false);
|
||
const isMenuOpen = ref(false);
|
||
const showModal = ref(false);
|
||
const headerHeight = ref(0);
|
||
const currentLang = ref('zh'); // 默认中文
|
||
|
||
// 新增:视口和导航宽度变量
|
||
const viewportWidth = ref(0);
|
||
const navWidth = ref(0);
|
||
|
||
// 菜单项根据语言动态变化
|
||
const menuItems = computed(() => {
|
||
return [
|
||
{ path: '/', name: currentLang.value === 'zh' ? '首页' : 'Home', exact: true },
|
||
{ path: '/about', name: currentLang.value === 'zh' ? '公司介绍' : 'About' },
|
||
{ path: '/team', name: currentLang.value === 'zh' ? '团队介绍' : 'Team' },
|
||
{ path: '/features', name: currentLang.value === 'zh' ? '服务特色' : 'Features' },
|
||
{ path: '/careers', name: currentLang.value === 'zh' ? '加入我们' : 'Careers' }
|
||
];
|
||
});
|
||
|
||
// 新增:输出视口和导航宽度
|
||
const logDimensions = () => {
|
||
// 获取视口宽度
|
||
viewportWidth.value = window.innerWidth;
|
||
|
||
|
||
// 输出到控制台
|
||
console.log('视口宽度:', `${viewportWidth.value}px`);
|
||
console.log('----------------------');
|
||
// 获取导航元素宽度
|
||
const navElement = document.querySelector('header');
|
||
if (navElement) {
|
||
navWidth.value = navElement.offsetWidth;
|
||
}
|
||
console.log('导航宽度:', `${navWidth.value}px`);
|
||
console.log('----------------------');
|
||
// 修改header标签的宽度
|
||
navElement.style.width = `${navWidth.value}px`;
|
||
// 修改body的宽度
|
||
document.body.style.width = `${viewportWidth.value}px`;
|
||
};
|
||
|
||
const toggleLanguage = () => {
|
||
currentLang.value = currentLang.value === 'zh' ? 'en' : 'zh';
|
||
};
|
||
|
||
const openModal = () => {
|
||
showModal.value = true;
|
||
};
|
||
|
||
const closeModal = () => {
|
||
showModal.value = false;
|
||
};
|
||
|
||
const toggleMenu = () => {
|
||
isMenuOpen.value = !isMenuOpen.value;
|
||
if (isMenuOpen.value) {
|
||
document.body.style.overflow = 'hidden';
|
||
} else {
|
||
document.body.style.overflow = '';
|
||
}
|
||
};
|
||
|
||
const closeMenu = () => {
|
||
isMenuOpen.value = false;
|
||
document.body.style.overflow = '';
|
||
};
|
||
|
||
const handleScroll = () => {
|
||
isScrolled.value = window.scrollY > 20;
|
||
};
|
||
|
||
// 计算头部高度用于移动菜单定位
|
||
const calculateHeaderHeight = () => {
|
||
const header = document.querySelector('header');
|
||
if (header) {
|
||
headerHeight.value = header.offsetHeight;
|
||
}
|
||
};
|
||
|
||
onMounted(() => {
|
||
window.addEventListener('scroll', handleScroll);
|
||
calculateHeaderHeight();
|
||
window.addEventListener('resize', calculateHeaderHeight);
|
||
|
||
// 新增:添加尺寸输出功能
|
||
logDimensions(); // 初始输出
|
||
window.addEventListener('resize', logDimensions); // 窗口大小变化时输出
|
||
});
|
||
|
||
onBeforeUnmount(() => {
|
||
window.removeEventListener('scroll', handleScroll);
|
||
window.removeEventListener('resize', calculateHeaderHeight);
|
||
|
||
// 新增:移除尺寸输出监听器
|
||
window.removeEventListener('resize', logDimensions);
|
||
|
||
document.body.style.overflow = ''; // 确保卸载时恢复滚动
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
.router-link-exact-active {
|
||
position: relative;
|
||
}
|
||
|
||
.router-link-exact-active::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: -3px;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 2px;
|
||
background-color: #2563eb;
|
||
}
|
||
|
||
/* 模态框动画 */
|
||
.modal-fade-enter-active,
|
||
.modal-fade-leave-active {
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
|
||
.modal-fade-enter-from,
|
||
.modal-fade-leave-to {
|
||
opacity: 0;
|
||
}
|
||
|
||
/* 移动端菜单宽度修复 */
|
||
@media (max-width: 767px) {
|
||
.container {
|
||
padding-left: 1rem;
|
||
padding-right: 1rem;
|
||
}
|
||
|
||
/* 确保移动菜单不会超出视口 */
|
||
.overflow-hidden {
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* 防止路由链接换行 */
|
||
.router-link {
|
||
white-space: nowrap;
|
||
}
|
||
}
|
||
|
||
/* 增强模糊效果 */
|
||
.backdrop-blur-lg {
|
||
backdrop-filter: blur(12px);
|
||
}
|
||
</style> |