Files
spa-view/src/layouts/MainLayout.vue
2025-04-24 17:01:44 +08:00

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>