feat: 完成移动端适配和项目文档
This commit is contained in:
111
src/components/layout/MobileLayout.vue
Normal file
111
src/components/layout/MobileLayout.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div class="mobile-layout">
|
||||
<!-- 顶部栏 -->
|
||||
<div class="mobile-header">
|
||||
<el-button icon="Menu" @click="sidebarVisible = true" />
|
||||
<h1 class="logo">GameGroup</h1>
|
||||
<div class="header-actions">
|
||||
<el-badge :value="unreadCount">
|
||||
<el-button circle icon="Bell" />
|
||||
</el-badge>
|
||||
<el-avatar :src="userInfo?.avatar" size="small" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主内容区 -->
|
||||
<div class="mobile-content">
|
||||
<RouterView />
|
||||
</div>
|
||||
|
||||
<!-- 底部Tab导航 -->
|
||||
<div class="mobile-tabs">
|
||||
<div
|
||||
v-for="tab in tabs"
|
||||
:key="tab.path"
|
||||
:class="['tab-item', { active: isActive(tab.path) }]"
|
||||
@click="navigate(tab.path)"
|
||||
>
|
||||
<el-icon>
|
||||
<component :is="tab.icon" />
|
||||
</el-icon>
|
||||
<span>{{ tab.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 侧边栏抽屉 -->
|
||||
<el-drawer v-model="sidebarVisible" direction="ltr" size="280px">
|
||||
<AppSidebar />
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import AppSidebar from './AppSidebar.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const sidebarVisible = ref(false)
|
||||
const unreadCount = ref(0)
|
||||
|
||||
const userInfo = computed(() => authStore.userInfo)
|
||||
|
||||
const tabs = [
|
||||
{ path: '/', icon: 'HomeFilled', label: '首页' },
|
||||
{ path: '/groups', icon: 'UserFilled', label: '小组' },
|
||||
{ path: '/games', icon: 'Grid', label: '游戏' },
|
||||
{ path: '/appointments', icon: 'Calendar', label: '预约' }
|
||||
]
|
||||
|
||||
const isActive = (path: string) => {
|
||||
return route.path.startsWith(path)
|
||||
}
|
||||
|
||||
const navigate = (path: string) => {
|
||||
router.push(path)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mobile-layout {
|
||||
@apply flex flex-col h-screen bg-gray-50;
|
||||
}
|
||||
|
||||
.mobile-header {
|
||||
@apply flex items-center justify-between px-4 py-3 bg-white shadow-sm sticky top-0 z-50;
|
||||
}
|
||||
|
||||
.logo {
|
||||
@apply text-lg font-bold bg-gradient-to-r from-primary-500 to-accent-500 bg-clip-text text-transparent;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
@apply flex items-center gap-3;
|
||||
}
|
||||
|
||||
.mobile-content {
|
||||
@apply flex-1 overflow-y-auto pb-20;
|
||||
}
|
||||
|
||||
.mobile-tabs {
|
||||
@apply flex justify-around items-center py-2 bg-white border-t fixed bottom-0 left-0 right-0 z-50;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
@apply flex flex-col items-center gap-1 py-2 px-4 text-gray-400 transition-colors;
|
||||
|
||||
&.active {
|
||||
@apply text-primary-500;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.mobile-layout {
|
||||
@apply hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user