Files
gamegroup2/frontend/src/views/Layout.vue
T

198 lines
4.3 KiB
Vue
Raw Normal View History

<!-- src/views/Layout.vue -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useUserStore } from '@/stores/user'
import { useGroupStore } from '@/stores/group'
import { useTeamStore } from '@/stores/team'
import StatusToggle from '@/components/team/StatusToggle.vue'
import WorkScheduleModal from '@/components/team/WorkScheduleModal.vue'
import { ElBadge, ElButton, ElIcon } from 'element-plus'
const router = useRouter()
const userStore = useUserStore()
const groupStore = useGroupStore()
const teamStore = useTeamStore()
const showScheduleModal = ref(false)
const pendingCount = ref(0)
onMounted(async () => {
await userStore.initUser()
await groupStore.loadGroups()
await teamStore.loadActiveSession()
pendingCount.value = await teamStore.getPendingCount()
})
async function handleLogout() {
userStore.logout()
router.push({ name: 'Login' })
}
function showInviteModal() {
// TODO: 实现邀请模态框
}
</script>
<template>
<div class="layout">
<!-- 顶部导航 -->
<header class="header">
<div class="header-left">
<h1 class="logo">Game Group</h1>
</div>
<div class="header-center">
<nav class="nav">
<router-link to="/" class="nav-link" active-class="active">
首页
</router-link>
<router-link to="/games" class="nav-link" active-class="active">
游戏库
</router-link>
</nav>
</div>
<div class="header-right">
<el-badge :value="pendingCount" :hidden="pendingCount === 0">
<el-button circle @click="showInviteModal">
<el-icon>🔔</el-icon>
</el-button>
</el-badge>
<status-toggle />
<el-dropdown trigger="click">
<span class="user-dropdown">
<img
:src="userStore.user?.avatar || '/default-avatar.png'"
class="user-avatar"
/>
<span class="user-name">{{ userStore.user?.username }}</span>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="router.push('/profile')">
个人中心
</el-dropdown-item>
<el-dropdown-item @click="router.push('/settings')">
设置
</el-dropdown-item>
<el-dropdown-item divided @click="handleLogout">
退出登录
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</header>
<!-- 主体内容 -->
<main class="main">
<router-view />
</main>
<!-- 工作时间设置弹窗 -->
<work-schedule-modal v-model="showScheduleModal" />
</div>
</template>
<style scoped>
.layout {
min-height: 100vh;
background: var(--el-bg-color-page);
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
height: 60px;
background: var(--el-bg-color);
border-bottom: 1px solid var(--el-border-color);
position: sticky;
top: 0;
z-index: 100;
}
.header-left {
display: flex;
align-items: center;
}
.logo {
font-size: 20px;
font-weight: 700;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 0;
}
.header-center {
flex: 1;
display: flex;
justify-content: center;
}
.nav {
display: flex;
gap: 8px;
}
.nav-link {
padding: 8px 16px;
border-radius: 8px;
text-decoration: none;
color: var(--el-text-color-primary);
font-size: 14px;
transition: all 0.2s;
}
.nav-link:hover {
background: var(--el-fill-color-light);
}
.nav-link.active {
background: var(--el-color-primary-light-9);
color: var(--el-color-primary);
}
.header-right {
display: flex;
align-items: center;
gap: 16px;
}
.user-dropdown {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
padding: 4px 8px;
border-radius: 8px;
transition: background-color 0.2s;
}
.user-dropdown:hover {
background: var(--el-fill-color-light);
}
.user-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
}
.user-name {
font-size: 14px;
}
.main {
max-width: 1200px;
margin: 0 auto;
padding: 24px;
}
</style>