index修改

This commit is contained in:
Kunagisa 2025-06-05 21:36:55 +08:00
parent 60667511b4
commit b5c9aa67bf
2 changed files with 151 additions and 155 deletions

View File

@ -37,24 +37,6 @@
</div> </div>
</div> </div>
</div> </div>
<div v-else class="dashboard-content non-admin-view">
<div class="non-admin-card">
<div class="welcome-message">欢迎回来</div>
<div class="info-text">
您当前没有管理员权限请选择以下操作
</div>
<div class="button-group">
<button @click="goToHomePage" class="home-button">
<!-- Optional: Add an icon here -->
返回主页面
</button>
<button @click="handleLogout" class="logout-button">
<!-- Optional: Add an icon here -->
退出登录
</button>
</div>
</div>
</div>
</div> </div>
</template> </template>
@ -67,7 +49,7 @@ import ServiceHallView from '../../components/backend/ServiceHallView.vue'
const router = useRouter() const router = useRouter()
const hasToken = ref(false) const hasToken = ref(false)
const userId = ref(null) const userId = ref(localStorage.getItem('user_id'))
const currentAdminView = ref('event-management') const currentAdminView = ref('event-management')
const isMobileSidebarOpen = ref(false) const isMobileSidebarOpen = ref(false)
@ -79,19 +61,26 @@ onMounted(() => {
// token // token
const token = localStorage.getItem('access_token') const token = localStorage.getItem('access_token')
hasToken.value = !!token hasToken.value = !!token
console.log('检测到token')
if (!token) { if (!token) {
console.log('未检测到token')
router.push('/') router.push('/')
return;
} }
// ID // userId localStorage
const storedUserId = localStorage.getItem('user_id') // localStorage
if (storedUserId) { const currentStoredUserId = localStorage.getItem('user_id');
userId.value = storedUserId if (currentStoredUserId) {
console.log('当前用户ID:', userId.value) // ref localStorage null
if (userId.value !== currentStoredUserId) {
userId.value = currentStoredUserId;
console.log('Dashboard.vue - 用户ID已在 onMounted 中更新:', userId.value);
} else { } else {
console.log('未检测到用户ID') console.log('Dashboard.vue - 当前用户ID (onMounted, 与初始值一致):', userId.value);
}
} else {
// userId.value null null onMounted localStorage null
//
console.log('Dashboard.vue - 未在 localStorage 中检测到用户ID (onMounted)');
} }
}) })
@ -129,7 +118,7 @@ const selectAdminView = (viewName) => {
box-sizing: border-box; box-sizing: border-box;
} }
html, body, .dashboard-wrapper, .admin-layout { .dashboard-wrapper, .admin-layout {
height: 100%; height: 100%;
width: 100%; width: 100%;
overflow-x: hidden; /* Prevent horizontal scroll on body/wrapper */ overflow-x: hidden; /* Prevent horizontal scroll on body/wrapper */
@ -155,7 +144,7 @@ html, body, .dashboard-wrapper, .admin-layout {
height: 100%; /* Full height */ height: 100%; /* Full height */
position: fixed; /* Fixed position */ position: fixed; /* Fixed position */
left: 0; left: 0;
top: 0; top: 0px; /* Stick to the top of the webpage */
z-index: 1000; z-index: 1000;
transition: transform 0.3s ease; transition: transform 0.3s ease;
box-shadow: 2px 0 8px rgba(0,0,0,0.1); box-shadow: 2px 0 8px rgba(0,0,0,0.1);
@ -244,87 +233,6 @@ html, body, .dashboard-wrapper, .admin-layout {
transition: margin-left 0.3s ease; transition: margin-left 0.3s ease;
} }
/* Non-Admin View Enhancements */
.dashboard-content.non-admin-view {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh; /* Use min-height to ensure it covers viewport even if content is small */
width: 100%;
padding: 30px;
background-color: #f0f2f5; /* Consistent light background */
text-align: center; /* Center text for any messages */
}
.non-admin-view .non-admin-card {
background-color: #ffffff;
padding: 40px 50px;
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
max-width: 450px;
width: 100%;
display: flex;
flex-direction: column;
align-items: center; /* Center buttons if they are directly in this card */
}
.non-admin-view .welcome-message {
font-size: 1.5rem; /* Slightly larger welcome/info text */
color: #333;
margin-bottom: 15px;
font-weight: 500;
}
.non-admin-view .info-text {
font-size: 0.95rem;
color: #666;
margin-bottom: 30px;
line-height: 1.6;
}
.non-admin-view .button-group {
/* Removed background, padding, shadow from here as it's now on non-admin-card */
width: 100%; /* Button group takes full width of the card */
display: flex;
flex-direction: column; /* Stack buttons vertically */
gap: 15px; /* Space between buttons */
}
.non-admin-view .button-group button {
padding: 12px 25px; /* Slightly larger padding */
border-radius: 8px; /* Slightly more rounded */
font-weight: 500;
font-size: 1rem; /* Standardized font size */
transition: background-color 0.2s, transform 0.1s;
border: none;
color: #fff;
cursor: pointer;
width: 100%; /* Make buttons take full width of their container */
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.non-admin-view .button-group button:hover {
transform: translateY(-2px); /* Subtle lift on hover */
}
.non-admin-view .button-group .home-button {
background-color: #0ea5e9; /* Sky blue */
}
.non-admin-view .button-group .home-button:hover {
background-color: #0284c7; /* Darker sky blue */
}
.non-admin-view .button-group .logout-button {
background-color: #ef4444; /* Red */
}
.non-admin-view .button-group .logout-button:hover {
background-color: #dc2626; /* Darker Red */
}
/* Mobile Header Styles */ /* Mobile Header Styles */
.mobile-header { .mobile-header {
display: none; /* Hidden by default, shown on mobile */ display: none; /* Hidden by default, shown on mobile */
@ -333,7 +241,7 @@ html, body, .dashboard-wrapper, .admin-layout {
padding: 10px 15px; padding: 10px 15px;
align-items: center; align-items: center;
position: fixed; position: fixed;
top: 0; top: 0px; /* Stick to the top of the webpage */
left: 0; left: 0;
right: 0; right: 0;
z-index: 1001; /* Above sidebar when closed */ z-index: 1001; /* Above sidebar when closed */
@ -396,7 +304,7 @@ html, body, .dashboard-wrapper, .admin-layout {
.admin-main-content { .admin-main-content {
margin-left: 0; /* Content takes full width */ margin-left: 0; /* Content takes full width */
padding-top: 70px; /* Space for fixed mobile header */ padding-top: 55px; /* Space for fixed mobile header (now at top:0), adjusted from 70px */
} }
.mobile-header { .mobile-header {
@ -425,8 +333,9 @@ html, body, .dashboard-wrapper, .admin-layout {
} }
/* Styles for the placeholder non-admin page if it's not the main content area */ /* Styles for the placeholder non-admin page if it's not the main content area */
.dashboard-container { /* This class was used before, ensure it doesn't conflict or remove if not needed */ /*
/* If this is for the non-admin view specifically, and it's outside admin-layout */ .dashboard-container {
}
}
*/
</style> </style>

View File

@ -1,17 +1,28 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, onMounted } from 'vue' import { computed, ref, onMounted } from 'vue'
import { getUserInfo } from '../utils/jwt' import { getUserInfo } from '@/utils/jwt'
import { useRouter } from 'vue-router'
const isLoggedIn = computed(() => { const isLoggedIn = computed(() => {
return !!localStorage.getItem('access_token') && !!currentUserData.value return !!localStorage.getItem('access_token') && !!currentUserData.value
}) })
const isAdmin = computed(() => {
if (currentUserData.value && currentUserData.value.qq_code) {
const adminQQNumbers = ['1846172115', '1400429906', '3422054939'];
return adminQQNumbers.indexOf(String(currentUserData.value.qq_code)) !== -1;
}
return false;
})
const showMobileMenu = ref(false) const showMobileMenu = ref(false)
const currentUserData = ref(null) const currentUserData = ref(null)
const showDropdown = ref(false)
const router = useRouter()
const userAvatarUrl = computed(() => { const userAvatarUrl = computed(() => {
if (currentUserData.value && currentUserData.value.qq_code) { if (currentUserData.value && currentUserData.value.qq_code) {
return `http://q1.qlogo.cn/g?b=qq&nk=${currentUserData.value.qq_code}&s=40` return `https://q1.qlogo.cn/g?b=qq&nk=${currentUserData.value.qq_code}&s=40`
} }
return null return null
}) })
@ -20,14 +31,22 @@ const toggleMobileMenu = () => {
showMobileMenu.value = !showMobileMenu.value showMobileMenu.value = !showMobileMenu.value
} }
onMounted(async () => { const handleLogout = () => {
localStorage.removeItem('access_token')
currentUserData.value = null
showDropdown.value = false
router.push('/')
}
onMounted(() => {
if (localStorage.getItem('access_token')) { if (localStorage.getItem('access_token')) {
const userInfo = await getUserInfo() getUserInfo().then(userInfo => {
if (userInfo) { if (userInfo) {
currentUserData.value = userInfo currentUserData.value = userInfo
} else { } else {
console.log('Index.vue: Failed to get user info, token might be invalid.') console.log('Index.vue: Failed to get user info, token might be invalid.')
} }
})
} }
}) })
</script> </script>
@ -48,13 +67,24 @@ onMounted(async () => {
<router-link v-if="isLoggedIn" to="/demands" class="nav-link">办事大厅</router-link> <router-link v-if="isLoggedIn" to="/demands" class="nav-link">办事大厅</router-link>
</div> </div>
<div class="nav-right" :class="{ active: showMobileMenu }"> <div class="nav-right" :class="{ active: showMobileMenu }">
<router-link :to="isLoggedIn ? '/backend/dashboard' : '/backend/login'" class="nav-link login-btn"> <router-link v-if="!isLoggedIn" to="/backend/login" class="nav-link login-btn">
<i class="fas fa-user"></i> <i class="fas fa-user"></i>
{{ isLoggedIn ? '管理后台' : '登录' }} 登录
</router-link> </router-link>
<div v-if="isLoggedIn && currentUserData" class="user-info-nav"> <div v-if="isLoggedIn && currentUserData" class="user-info-nav" @click="showDropdown = !showDropdown">
<img v-if="userAvatarUrl" :src="userAvatarUrl" alt="User Avatar" class="nav-avatar" /> <img v-if="userAvatarUrl" :src="userAvatarUrl" alt="User Avatar" class="nav-avatar" />
<span class="nav-username">{{ currentUserData.username }}</span> <span class="nav-username">{{ currentUserData.username }}</span>
<i class="fas fa-chevron-down dropdown-icon"></i>
<div v-show="showDropdown" class="dropdown-menu">
<div v-if="isAdmin" class="dropdown-item" @click="router.push('/backend/dashboard'); showDropdown = false">
<i class="fas fa-cog"></i>
管理后台
</div>
<div class="dropdown-item" @click="handleLogout">
<i class="fas fa-sign-out-alt"></i>
退出登录
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -84,14 +114,11 @@ onMounted(async () => {
} }
.main-content { .main-content {
margin-top: 60px;
padding: 20px; padding: 20px;
flex: 1; flex: 1;
max-width: 1400px; max-width: 1400px;
width: 100%; width: 100%;
margin-left: auto; margin: 60px auto 0;
margin-right: auto;
margin-bottom: 0;
} }
.footer { .footer {
@ -132,7 +159,7 @@ onMounted(async () => {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
justify-content: space-between; justify-content: flex-start;
} }
.nav-brand { .nav-brand {
@ -142,12 +169,30 @@ onMounted(async () => {
text-decoration: none; text-decoration: none;
white-space: nowrap; white-space: nowrap;
padding: 15px 0; padding: 15px 0;
display: flex;
align-items: center;
margin-right: 8px;
} }
.nav-left { .nav-left {
width: auto;
flex-direction: row;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 15px; gap: 6px;
}
.nav-right {
margin-left: auto;
display: flex;
align-items: center;
gap: 6px;
}
.nav-left,
.nav-right {
align-items: center;
gap: 4px;
width: 100%; width: 100%;
flex-direction: column; flex-direction: column;
display: none; display: none;
@ -157,16 +202,6 @@ onMounted(async () => {
display: flex; display: flex;
} }
.nav-right {
display: flex;
align-items: center;
gap: 15px;
width: 100%;
justify-content: center;
display: none;
padding-bottom: 15px;
}
.nav-right.active { .nav-right.active {
display: flex; display: flex;
} }
@ -174,14 +209,14 @@ onMounted(async () => {
.nav-link { .nav-link {
color: rgba(255, 255, 255, 0.9); color: rgba(255, 255, 255, 0.9);
text-decoration: none; text-decoration: none;
padding: 10px 16px; padding: 8px 10px;
border-radius: 6px; border-radius: 6px;
transition: all 0.3s ease; transition: all 0.3s ease;
font-weight: 500; font-weight: 500;
position: relative; position: relative;
width: 100%; width: 100%;
text-align: center; text-align: center;
font-size: 1rem; font-size: 0.92rem;
} }
.nav-link:hover { .nav-link:hover {
@ -189,10 +224,16 @@ onMounted(async () => {
color: white; color: white;
} }
.router-link-active, .nav-link.router-link-exact-active,
.router-link-exact-active { .nav-link.router-link-active {
background-color: rgba(255, 255, 255, 0.2); background-color: rgba(255,255,255,0.18);
color: white; color: #fff;
font-weight: 700;
}
.nav-link:active {
background-color: rgba(255,255,255,0.28);
color: #fff;
} }
.login-btn { .login-btn {
@ -223,7 +264,52 @@ onMounted(async () => {
align-items: center; align-items: center;
gap: 10px; gap: 10px;
margin-left: 15px; margin-left: 15px;
padding: 5px 0; padding: 5px 10px;
cursor: pointer;
position: relative;
border-radius: 20px;
transition: background-color 0.3s;
}
.user-info-nav:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.dropdown-icon {
color: white;
font-size: 12px;
margin-left: 4px;
}
.dropdown-menu {
position: absolute;
top: 100%;
right: 0;
margin-top: 8px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
min-width: 160px;
z-index: 1000;
}
.dropdown-item {
padding: 12px 16px;
color: #333;
display: flex;
align-items: center;
gap: 8px;
transition: background-color 0.3s;
cursor: pointer;
}
.dropdown-item:hover {
background-color: #f5f5f5;
}
.dropdown-item i {
font-size: 14px;
color: #666;
} }
.nav-avatar { .nav-avatar {
@ -304,17 +390,18 @@ onMounted(async () => {
padding-bottom: 0; padding-bottom: 0;
} }
.nav-left {
}
.nav-link { .nav-link {
width: auto; width: auto;
padding: 15px 16px; padding: 10px 10px;
font-size: 0.95rem; font-size: 0.9rem;
} }
.nav-container { .nav-container {
flex-wrap: nowrap; flex-wrap: nowrap;
} }
.nav-left, .nav-right {
gap: 6px;
}
} }
</style> </style>