161 lines
5.1 KiB
Vue
161 lines
5.1 KiB
Vue
<script setup>
|
|
|
|
import { ref, onMounted } from 'vue'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import { UserOutlined, MenuOutlined } from '@ant-design/icons-vue'
|
|
import { useUserStore } from '@/stores/user'
|
|
import AuthModal from '@/components/common/AuthModal.vue'
|
|
|
|
// 合并后的状态管理
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const userStore = useUserStore()
|
|
const authModal = ref(null)
|
|
const isScrolled = ref(false)
|
|
const mobileMenuVisible = ref(false)
|
|
|
|
const menuItems = [
|
|
{ path: '/', title: '首页', icon: 'HomeOutlined' },
|
|
{ path: '/projects', title: '项目列表', icon: 'InfoCircleOutlined' },
|
|
{ path: '/about', title: '关于我们', icon: 'InfoCircleOutlined' },
|
|
{ path: '/services', title: '服务项目', icon: 'AppstoreOutlined' },
|
|
]
|
|
|
|
// 滚动监听逻辑
|
|
onMounted(() => {
|
|
window.addEventListener('scroll', () => {
|
|
isScrolled.value = window.scrollY > 0
|
|
})
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<a-layout class="min-h-screen body-box">
|
|
<!-- 顶部导航栏 -->
|
|
<header class="sticky top-0 z-50 bg-gradient-to-r from-blue-600 to-purple-700 transition-shadow duration-300" :class="{ 'shadow-lg': isScrolled }">
|
|
<div class="flex items-center justify-between px-6 py-4">
|
|
<div class="flex items-center space-x-4">
|
|
<img src="@/assets/nl-logo.png" alt="Logo" class="h-10 w-10 transition-transform hover:scale-110">
|
|
<span class="text-2xl font-extrabold tracking-wide bg-gradient-to-r from-white to-blue-100 bg-clip-text text-transparent">AppStop</span>
|
|
</div>
|
|
|
|
<nav class="hidden md:flex space-x-4">
|
|
<a
|
|
href="javascript:;"
|
|
v-for="item in menuItems"
|
|
:key="item.path"
|
|
type="text"
|
|
:class="`${route.path === item.path? 'router-link-active': 'router-link'} flex items-center p-3 rounded-lg hover:bg-opacity-10 hover:bg-white transition-colors text-white text-lg`"
|
|
@click="router.push(item.path)"
|
|
>
|
|
<component :is="item.icon" class="mr-3" />
|
|
{{ item.title }}
|
|
</a>
|
|
</nav>
|
|
|
|
<div class="flex items-center space-x-4">
|
|
<AuthModal ref="authModal" />
|
|
<a-button
|
|
v-if="!userStore.isAuthenticated"
|
|
type="primary"
|
|
class="text-sm"
|
|
@click="authModal?.show()"
|
|
>
|
|
登录/注册
|
|
</a-button>
|
|
<div v-else>
|
|
<a-dropdown>
|
|
<a class="ant-dropdown-link" @click.prevent>
|
|
<img src="https://pic.rmb.bdstatic.com/bjh/80852bfe7c321988191838517ba64e309354.jpeg@h_1280" alt="User Avatar" class="h-8 w-8 rounded-full cursor-pointer">
|
|
</a>
|
|
<template #overlay>
|
|
<a-menu>
|
|
<a-menu-item>
|
|
<a href="/personal">个人中心</a>
|
|
</a-menu-item>
|
|
<a-menu-item v-if="userStore.user?.role === 'admin'">
|
|
<a href="/admin">后台管理</a>
|
|
</a-menu-item>
|
|
</a-menu>
|
|
</template>
|
|
</a-dropdown>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- 移动端菜单 -->
|
|
<a-drawer
|
|
v-model:visible="mobileMenuVisible"
|
|
placement="left"
|
|
:width="280"
|
|
class="md:hidden"
|
|
>
|
|
<div class="p-4 space-y-4">
|
|
<a-button
|
|
v-for="item in menuItems"
|
|
:key="item.path"
|
|
type="link"
|
|
:class="`${route.path === item.path? 'router-link-active': 'router-link'} flex items-center p-3 rounded-lg hover:bg-opacity-10 hover:bg-white transition-colors text-white text-lg`"
|
|
@click="router.push(item.path)"
|
|
>
|
|
<component :is="item.icon" class="mr-4" />
|
|
{{ item.title }}
|
|
</a-button>
|
|
</div>
|
|
</a-drawer>
|
|
|
|
<!-- 移动端菜单开关 -->
|
|
<div class="fixed bottom-6 right-6 z-50 md:hidden">
|
|
<a-button
|
|
shape="circle"
|
|
type="primary"
|
|
size="large"
|
|
class="!w-14 !h-14 shadow-xl hover:scale-110 transition-transform"
|
|
@click="mobileMenuVisible = true"
|
|
>
|
|
<template #icon><MenuOutlined class="text-2xl" /></template>
|
|
</a-button>
|
|
</div>
|
|
|
|
<a-layout-content class="pt-16 body-box">
|
|
<router-view />
|
|
</a-layout-content>
|
|
</a-layout>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');
|
|
|
|
body {
|
|
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
}
|
|
.body-box {
|
|
background-color: #111 !important;
|
|
min-height: 100vh;
|
|
}
|
|
:deep(.ant-menu-horizontal) {
|
|
border-bottom: none !important;
|
|
}
|
|
|
|
:deep(.ant-drawer-body) {
|
|
background: linear-gradient(135deg, #2d3748 0%, #1a202c 100%);
|
|
}
|
|
|
|
header {
|
|
backdrop-filter: blur(10px);
|
|
background-image: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
// 激活状态样式增强
|
|
.router-link {
|
|
color: #fff !important;
|
|
}
|
|
// 激活状态样式增强
|
|
.router-link-active {
|
|
color: #fff !important;
|
|
background-color: rgba(255, 255, 255, 0.1) !important;
|
|
}
|
|
}
|
|
</style> |