GuDingZiChan/frontend/src/layouts/MainLayout.vue
2026-03-10 16:19:47 +08:00

97 lines
3.1 KiB
Vue

<template>
<div class="min-h-screen bg-system-background-secondary">
<!-- Navigation Bar - Apple Style -->
<nav class="nav-apple sticky top-0 z-50 px-6 py-4">
<div class="max-w-7xl mx-auto flex items-center justify-between">
<div class="flex items-center space-x-3">
<img
v-if="siteStore.logoUrl"
:src="siteStore.logoUrl"
alt="logo"
class="h-10 w-10 rounded-apple object-cover"
/>
<h1 class="text-apple-title text-system-label-primary">
{{ siteStore.siteName }}
</h1>
</div>
<div class="flex items-center space-x-4">
<GlobalSearch />
<button
@click="handleLogout"
class="btn-apple-secondary text-sm"
>
退出登录
</button>
</div>
</div>
</nav>
<!-- Sidebar Navigation - Apple Style -->
<div class="flex max-w-7xl mx-auto overflow-hidden">
<aside class="w-[220px] flex-shrink-0 bg-system-background-primary border-r border-system-gray-5 min-h-screen p-5">
<nav class="space-y-2">
<router-link
v-for="item in visibleNavItems"
:key="item.path"
:to="item.path"
class="nav-link flex items-center space-x-3 px-3 py-3 rounded-apple transition-colors text-system-label-secondary hover:bg-system-gray-6"
:class="{ 'nav-link--active': $route.path === item.path }"
>
<component :is="item.icon" class="w-5 h-5" />
<span class="text-apple-body">{{ item.title }}</span>
</router-link>
</nav>
</aside>
<!-- Main Content -->
<main class="flex-1 p-6 min-w-0 overflow-hidden">
<router-view />
</main>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import { useSiteStore } from '@/stores/site'
import { HomeIcon, CubeIcon, ArrowRightIcon, ChartBarIcon, Cog6ToothIcon } from '@heroicons/vue/24/outline'
import GlobalSearch from '@/components/GlobalSearch.vue'
const router = useRouter()
const authStore = useAuthStore()
const siteStore = useSiteStore()
const navItems = [
{ path: '/dashboard', title: '首页', icon: HomeIcon },
{ path: '/equipment', title: '资产管理', icon: CubeIcon, requiresAdmin: true },
{ path: '/borrow', title: '使用管理', icon: ArrowRightIcon },
{ path: '/statistics', title: '统计分析', icon: ChartBarIcon },
{ path: '/settings', title: '系统设置', icon: Cog6ToothIcon, requiresAdmin: true }
]
const visibleNavItems = computed(() => {
const isAdmin = authStore.user?.role === 'admin'
return navItems.filter((item) => !item.requiresAdmin || isAdmin)
})
const handleLogout = async () => {
await authStore.logout()
router.push('/login')
}
onMounted(() => {
siteStore.fetchSiteConfig()
})
</script>
<style scoped>
.nav-link--active {
background-color: var(--theme-primary);
color: #ffffff;
box-shadow: 0 6px 18px var(--theme-primary-ring);
}
</style>