266 lines
7.9 KiB
Vue
266 lines
7.9 KiB
Vue
<template>
|
|
<div>
|
|
<!-- 顶部导航栏 -->
|
|
<header class="bg-white shadow-sm sticky top-0 z-50">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div class="flex justify-between items-center h-16">
|
|
<!-- Logo和品牌 -->
|
|
<div class="flex items-center">
|
|
<router-link to="/" class="flex items-center">
|
|
<div class="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center mr-3">
|
|
<span class="text-white font-bold text-lg">C</span>
|
|
</div>
|
|
<span class="text-xl font-bold text-gray-900">CMS系统</span>
|
|
</router-link>
|
|
</div>
|
|
|
|
<!-- 桌面端导航菜单 -->
|
|
<nav class="hidden md:flex space-x-8">
|
|
<router-link
|
|
to="/"
|
|
class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors"
|
|
:class="{ 'text-blue-600': $route.path === '/' }"
|
|
>
|
|
首页
|
|
</router-link>
|
|
<router-link
|
|
to="/articles"
|
|
class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors"
|
|
:class="{ 'text-blue-600': $route.path.startsWith('/articles') }"
|
|
>
|
|
技术文章
|
|
</router-link>
|
|
<router-link
|
|
to="/news"
|
|
class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors"
|
|
:class="{ 'text-blue-600': $route.path.startsWith('/news') }"
|
|
>
|
|
新闻资讯
|
|
</router-link>
|
|
<router-link
|
|
to="/about"
|
|
class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors"
|
|
:class="{ 'text-blue-600': $route.path === '/about' }"
|
|
>
|
|
关于我们
|
|
</router-link>
|
|
<router-link
|
|
to="/contact"
|
|
class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors"
|
|
:class="{ 'text-blue-600': $route.path === '/contact' }"
|
|
>
|
|
联系我们
|
|
</router-link>
|
|
</nav>
|
|
|
|
<!-- 右侧操作区 -->
|
|
<div class="flex items-center space-x-4">
|
|
<!-- 搜索按钮 -->
|
|
<button
|
|
@click="searchOpen = !searchOpen"
|
|
class="text-gray-500 hover:text-gray-700 p-2 rounded-lg hover:bg-gray-100"
|
|
>
|
|
<SearchIcon class="w-5 h-5" />
|
|
</button>
|
|
|
|
<!-- 管理员入口 -->
|
|
<router-link
|
|
to="/admin"
|
|
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors"
|
|
>
|
|
管理后台
|
|
</router-link>
|
|
|
|
<!-- 移动端菜单按钮 -->
|
|
<button
|
|
@click="mobileMenuOpen = !mobileMenuOpen"
|
|
class="md:hidden text-gray-500 hover:text-gray-700 p-2 rounded-lg hover:bg-gray-100"
|
|
>
|
|
<MenuIcon v-if="!mobileMenuOpen" class="w-6 h-6" />
|
|
<XIcon v-else class="w-6 h-6" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 搜索栏 -->
|
|
<div v-if="searchOpen" class="py-4 border-t border-gray-200">
|
|
<div class="relative">
|
|
<SearchIcon class="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
|
|
<input
|
|
v-model="searchKeyword"
|
|
type="text"
|
|
placeholder="搜索文章、新闻..."
|
|
class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
@keyup.enter="handleSearch"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 移动端菜单 -->
|
|
<div v-if="mobileMenuOpen" class="md:hidden bg-white border-t border-gray-200">
|
|
<div class="px-2 pt-2 pb-3 space-y-1">
|
|
<router-link
|
|
to="/"
|
|
class="block px-3 py-2 text-base font-medium text-gray-700 hover:text-blue-600 hover:bg-gray-50 rounded-md"
|
|
@click="mobileMenuOpen = false"
|
|
>
|
|
首页
|
|
</router-link>
|
|
<router-link
|
|
to="/articles"
|
|
class="block px-3 py-2 text-base font-medium text-gray-700 hover:text-blue-600 hover:bg-gray-50 rounded-md"
|
|
@click="mobileMenuOpen = false"
|
|
>
|
|
技术文章
|
|
</router-link>
|
|
<router-link
|
|
to="/news"
|
|
class="block px-3 py-2 text-base font-medium text-gray-700 hover:text-blue-600 hover:bg-gray-50 rounded-md"
|
|
@click="mobileMenuOpen = false"
|
|
>
|
|
新闻资讯
|
|
</router-link>
|
|
<router-link
|
|
to="/about"
|
|
class="block px-3 py-2 text-base font-medium text-gray-700 hover:text-blue-600 hover:bg-gray-50 rounded-md"
|
|
@click="mobileMenuOpen = false"
|
|
>
|
|
关于我们
|
|
</router-link>
|
|
<router-link
|
|
to="/contact"
|
|
class="block px-3 py-2 text-base font-medium text-gray-700 hover:text-blue-600 hover:bg-gray-50 rounded-md"
|
|
@click="mobileMenuOpen = false"
|
|
>
|
|
联系我们
|
|
</router-link>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
|
|
const router = useRouter()
|
|
|
|
// 图标组件
|
|
const SearchIcon = {
|
|
template: `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>`
|
|
}
|
|
|
|
const MenuIcon = {
|
|
template: `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>`
|
|
}
|
|
|
|
const XIcon = {
|
|
template: `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>`
|
|
}
|
|
|
|
// 响应式数据
|
|
const searchOpen = ref(false)
|
|
const mobileMenuOpen = ref(false)
|
|
const searchKeyword = ref('')
|
|
|
|
// 处理搜索
|
|
const handleSearch = () => {
|
|
if (searchKeyword.value.trim()) {
|
|
router.push({
|
|
path: '/search',
|
|
query: { q: searchKeyword.value }
|
|
})
|
|
searchOpen.value = false
|
|
searchKeyword.value = ''
|
|
}
|
|
}
|
|
|
|
// 监听路由变化,关闭移动端菜单
|
|
import { watch } from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
|
|
const route = useRoute()
|
|
watch(() => route.path, () => {
|
|
mobileMenuOpen.value = false
|
|
searchOpen.value = false
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 导航链接激活状态 */
|
|
.router-link-active {
|
|
color: #2563eb;
|
|
}
|
|
|
|
/* 移动端菜单动画 */
|
|
.mobile-menu-enter-active,
|
|
.mobile-menu-leave-active {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.mobile-menu-enter-from,
|
|
.mobile-menu-leave-to {
|
|
opacity: 0;
|
|
transform: translateY(-10px);
|
|
}
|
|
|
|
/* 搜索栏动画 */
|
|
.search-enter-active,
|
|
.search-leave-active {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.search-enter-from,
|
|
.search-leave-to {
|
|
opacity: 0;
|
|
transform: translateY(-10px);
|
|
}
|
|
|
|
/* 响应式优化 */
|
|
@media (max-width: 768px) {
|
|
.hidden.md\:flex {
|
|
display: none;
|
|
}
|
|
|
|
.md\:hidden {
|
|
display: block;
|
|
}
|
|
}
|
|
|
|
/* 悬停效果 */
|
|
.hover\:bg-gray-100:hover {
|
|
background-color: #f3f4f6;
|
|
}
|
|
|
|
.hover\:text-blue-600:hover {
|
|
color: #2563eb;
|
|
}
|
|
|
|
.hover\:bg-blue-700:hover {
|
|
background-color: #1d4ed8;
|
|
}
|
|
|
|
/* 过渡动画 */
|
|
.transition-colors {
|
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
transition-duration: 150ms;
|
|
}
|
|
|
|
/* 粘性定位 */
|
|
.sticky {
|
|
position: sticky;
|
|
}
|
|
|
|
/* 阴影效果 */
|
|
.shadow-sm {
|
|
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
/* Z-index层级 */
|
|
.z-50 {
|
|
z-index: 50;
|
|
}
|
|
</style> |