前端样式第一版已完成
This commit is contained in:
266
src/layouts/Header.vue
Normal file
266
src/layouts/Header.vue
Normal file
@@ -0,0 +1,266 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user