DCFronted/src/views/backend/Dashboard.vue
2025-06-09 23:53:23 +08:00

359 lines
9.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="dashboard-wrapper">
<div v-if="isAdmin" class="admin-layout" :class="{ 'sidebar-open': isMobileSidebarOpen }">
<div class="mobile-header">
<button @click="isMobileSidebarOpen = !isMobileSidebarOpen" class="hamburger-button">
<span class="hamburger-icon"></span>
</button>
<span class="mobile-header-title">后台管理</span>
</div>
<div class="admin-sidebar">
<div class="sidebar-header">
<h3>后台管理</h3>
</div>
<ul class="sidebar-nav">
<li @click="selectAdminView('event-management')" :class="{ active: currentAdminView === 'event-management' }"><a>赛事管理</a></li>
<li @click="selectAdminView('player-management')" :class="{ active: currentAdminView === 'player-management' }"><a>赛事玩家管理</a></li>
<li @click="selectAdminView('service-hall')" :class="{ active: currentAdminView === 'service-hall' }"><a>办事大厅</a></li>
</ul>
<div class="sidebar-footer">
<button @click="selectAdminView('code-generator')" :class="['sidebar-button', 'code-generator-button', { 'active': currentAdminView === 'code-generator' }]">
代码生成器
</button>
<button @click="goToHomePage" class="home-button sidebar-button">
返回主界面
</button>
<button @click="handleLogout" class="logout-button sidebar-button">
退出登录
</button>
</div>
</div>
<div class="admin-main-content">
<div v-if="currentAdminView === 'event-management'">
<TournamentList />
</div>
<div v-else-if="currentAdminView === 'player-management'">
<PlayerList />
</div>
<div v-else-if="currentAdminView === 'service-hall'">
<ServiceHallView />
</div>
<div v-else-if="currentAdminView === 'code-generator'">
<CodeGenerator />
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import TournamentList from '../../components/backend/TournamentList.vue'
import PlayerList from '../../components/backend/PlayerList.vue'
import ServiceHallView from '../../components/backend/ServiceHallView.vue'
import CodeGenerator from '../../components/backend/CodeGenerator.vue'
const router = useRouter()
const hasToken = ref(false)
const userId = ref(localStorage.getItem('user_id'))
const currentAdminView = ref('event-management')
const isMobileSidebarOpen = ref(false)
const isAdmin = computed(() => {
return userId.value === '1846172115' || userId.value === '1400429906' || userId.value === '3422054939'
})
onMounted(() => {
// 检查是否有token
const token = localStorage.getItem('access_token')
hasToken.value = !!token
if (!token) {
router.push('/')
return;
}
// userId 应该已经从 localStorage 初始化了
// 可以在这里再次检查或记录,以防 localStorage 在组件加载后发生变化
const currentStoredUserId = localStorage.getItem('user_id');
if (currentStoredUserId) {
// 如果 ref 中的值与当前 localStorage 中的值不同(例如,初始为 null现在有值了
if (userId.value !== currentStoredUserId) {
userId.value = currentStoredUserId;
console.log('Dashboard.vue - 用户ID已在 onMounted 中更新:', userId.value);
} else {
console.log('Dashboard.vue - 当前用户ID (onMounted, 与初始值一致):', userId.value);
}
} else {
// 如果 userId.value 为 null初始即为 null 且 onMounted 时 localStorage 仍为 null
// 并且我们删除了非管理员视图,管理员内容将不会显示
console.log('Dashboard.vue - 未在 localStorage 中检测到用户ID (onMounted)');
}
})
const handleLogout = () => {
// 清除本地存储的 token
localStorage.removeItem('access_token')
// 可选清除用户ID
localStorage.removeItem('user_id')
// 清除当前视图状态 (如果需要)
currentAdminView.value = 'event-management'
isMobileSidebarOpen.value = false; // 退出时关闭侧边栏
// 跳转到登录页面
router.push('/')
}
const goToHomePage = () => {
router.push('/') // 假设主页路由是 '/'
isMobileSidebarOpen.value = false; // 返回主页时关闭侧边栏
}
// 新增:选择管理员视图的方法
const selectAdminView = (viewName) => {
currentAdminView.value = viewName
if (window.innerWidth <= 768) {
isMobileSidebarOpen.value = false
}
}
</script>
<style scoped>
/* Global reset and base styles (optional, but good for consistency) */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.dashboard-wrapper, .admin-layout {
height: 100%;
width: 100%;
overflow-x: hidden; /* Prevent horizontal scroll on body/wrapper */
}
.dashboard-wrapper {
font-family: 'Arial', sans-serif;
background-color: #f0f2f5; /* Default background for non-admin or loading states */
}
/* Admin Layout Styles */
.admin-layout {
display: flex;
position: relative; /* For mobile sidebar positioning */
}
.admin-sidebar {
width: 240px; /* Sidebar width */
background-color: #e0f2fe; /* 淡蓝色 - light sky blue, adjust as needed */
color: #075985; /* Darker blue for text for contrast */
display: flex;
flex-direction: column;
height: 100%; /* Full height */
position: fixed; /* Fixed position */
left: 0;
top: 0px; /* Stick to the top of the webpage */
z-index: 1000;
transition: transform 0.3s ease;
box-shadow: 2px 0 8px rgba(0,0,0,0.1);
}
.sidebar-header {
padding: 20px;
text-align: center;
border-bottom: 1px solid #bae6fd; /* Lighter blue for border */
}
.sidebar-header h3 {
color: #0c4a6e; /* Even darker blue for header */
margin: 0;
font-size: 1.6rem;
}
.sidebar-nav {
list-style: none;
flex-grow: 1;
overflow-y: auto; /* Allow scrolling for many nav items */
}
.sidebar-nav li a {
display: block;
padding: 15px 20px;
color: #075985;
text-decoration: none;
transition: background-color 0.2s, color 0.2s;
cursor: pointer;
font-weight: 500;
}
.sidebar-nav li a:hover {
background-color: #7dd3fc; /* Lighter blue for hover */
color: #0c4a6e;
}
.sidebar-nav li.active a {
background-color: #38bdf8; /* Medium blue for active */
color: #ffffff;
font-weight: 600;
}
.sidebar-footer {
padding: 20px;
border-top: 1px solid #bae6fd;
display: flex;
flex-direction: column;
gap: 12px;
}
.sidebar-button {
width: 100%;
padding: 12px 15px;
border-radius: 6px;
text-align: center;
font-weight: 500;
transition: background-color 0.2s, opacity 0.2s;
border: none;
color: #fff;
cursor: pointer;
}
.sidebar-button.home-button {
background-color: #0ea5e9; /* Sky blue */
}
.sidebar-button.home-button:hover {
background-color: #0284c7; /* Darker sky blue */
}
.sidebar-button.code-generator-button {
background-color: #10b981; /* Emerald green */
}
.sidebar-button.code-generator-button:hover {
background-color: #059669; /* Darker emerald green */
}
.sidebar-button.code-generator-button.active {
background-color: #047857;
color: #ffffff;
}
.sidebar-button.logout-button {
background-color: #ef4444; /* Red */
}
.sidebar-button.logout-button:hover {
background-color: #dc2626; /* Darker Red */
}
.admin-main-content {
flex-grow: 1;
background-color: #ffffff; /* White background for content */
padding: 20px;
margin-left: 240px; /* Same as sidebar width */
height: 100%;
overflow-y: auto;
transition: margin-left 0.3s ease;
}
/* Mobile Header Styles */
.mobile-header {
display: none; /* Hidden by default, shown on mobile */
background-color: #e0f2fe; /* Same as sidebar */
color: #0c4a6e;
padding: 10px 15px;
align-items: center;
position: fixed;
top: 0px; /* Stick to the top of the webpage */
left: 0;
right: 0;
z-index: 1001; /* Above sidebar when closed */
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.hamburger-button {
background: none;
border: none;
cursor: pointer;
padding: 10px;
display: flex; /* For centering span inside */
align-items: center;
justify-content: center;
}
.hamburger-icon {
display: block;
width: 24px;
height: 2px;
background-color: #0c4a6e;
position: relative;
}
.hamburger-icon::before,
.hamburger-icon::after {
content: '';
position: absolute;
width: 24px;
height: 2px;
background-color: #0c4a6e;
left: 0;
}
.hamburger-icon::before {
top: -7px;
}
.hamburger-icon::after {
bottom: -7px;
}
.mobile-header-title {
margin-left: 15px;
font-size: 1.2rem;
font-weight: 600;
}
/* Mobile Responsiveness */
@media (max-width: 768px) {
.admin-sidebar {
transform: translateX(-100%); /* Hide sidebar off-screen */
box-shadow: none; /* Hide shadow when off-screen or covered */
}
.admin-layout.sidebar-open .admin-sidebar {
transform: translateX(0); /* Show sidebar */
box-shadow: 2px 0 8px rgba(0,0,0,0.15); /* Shadow for open sidebar on mobile */
}
.admin-main-content {
margin-left: 0; /* Content takes full width */
padding-top: 55px; /* Space for fixed mobile header (now at top:0), adjusted from 70px */
}
.mobile-header {
display: flex;
}
.sidebar-header h3 {
font-size: 1.3rem; /* Slightly smaller header for mobile sidebar */
}
.sidebar-nav li a {
padding: 12px 20px; /* Adjust padding if needed */
}
/* Overlay for when mobile sidebar is open */
.admin-layout.sidebar-open::after {
content: '';
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.3);
z-index: 999; /* Below sidebar, above content */
}
}
/* Styles for the placeholder non-admin page if it's not the main content area */
/*
.dashboard-container {
}
*/
</style>