newfront/src/views/UserCenter.vue
2025-04-11 17:54:55 +08:00

315 lines
7.3 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="user-center">
<Navbar />
<div v-if="isLoading" class="loading-container">
<div class="loading-spinner">加载中...</div>
</div>
<div v-else-if="isAuthenticated" class="container">
<!-- 上部分用户信息和东币记录 -->
<div class="upper-section">
<div class="user-info-container">
<UserInfo ref="userInfo" />
</div>
<div class="coin-container">
<Coin ref="coin" />
</div>
</div>
<!-- 下部分投稿记录 -->
<div class="lower-section">
<SubmissionList @manage-works="handleManageWorks" />
</div>
</div>
<div v-else class="login-required-container">
<div class="login-required-message">
<h2>请先登录</h2>
<p>您需要登录后才能访问个人中心</p>
</div>
</div>
</div>
</template>
<script>
import Navbar from '@/components/NavBar.vue';
import UserInfo from '@/components/user_center/UserInfo.vue';
import Coin from '@/components/user_center/Coin.vue';
import SubmissionList from '@/components/user_center/SubmissionList.vue';
import Cookies from 'js-cookie';
import messageBox from '@/utils/messageBox.js';
import Login from '@/utils/login.js';
export default {
name: 'UserCenter',
components: {
Navbar,
UserInfo,
Coin,
SubmissionList
},
data() {
return {
isAuthenticated: false,
isLoading: true
};
},
created() {
document.title = '个人中心 - NEU小站';
},
mounted() {
this.checkAuthAndFetchUserInfo();
},
methods: {
async checkAuthAndFetchUserInfo() {
const token = Cookies.get('token');
if (!token) {
this.isLoading = false;
// 如果当前在user-center路径但没有登录态重定向到/login
if (this.$route.path === '/user-center') {
this.$router.replace('/login');
return;
}
// 如果是/login路由自动弹出登录框
if (this.$route.path === '/login') {
this.showLoginDialog();
}
return;
}
try {
// 使用 /islogin 接口快速验证 token
const response = await fetch('https://newfront.xn--xhq44jb2fzpc.com/user/islogin', {
method: 'GET',
headers: {
'Authorization': token
}
});
if (!response.ok) {
// 如果状态码不是 2xx (例如 401 Unauthorized)
throw new Error('Token 验证失败');
}
// 验证成功
const data = await response.json();
if (data && data.isLoggedIn) {
this.isAuthenticated = true;
} else {
// 理论上如果 response.ok 为 true这里不应该执行
// 但以防万一,处理逻辑上验证失败的情况
throw new Error('Token 验证成功但返回状态不正确');
}
this.isLoading = false;
// 如果登录成功且当前在/login路径重定向到/user-center
if (this.$route.path === '/login') {
this.$router.replace('/user-center');
}
} catch (error) {
console.error('获取用户信息出错:', error);
this.isLoading = false;
// 清除可能存在的无效token
Cookies.remove('token');
// 如果当前在user-center路径重定向到/login
if (this.$route.path === '/user-center') {
this.$router.replace('/login');
return;
}
// 如果是/login路由自动弹出登录框
if (this.$route.path === '/login') {
this.showLoginDialog();
}
}
},
showLoginDialog() {
Login()
.then(userData => {
console.log('登录成功:', userData);
this.isAuthenticated = true;
// 登录成功后重定向到/user-center
this.$router.replace('/user-center');
})
.catch(reason => {
console.log('登录取消:', reason);
});
},
handleManageWorks() {
// 检测是否为移动设备
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || window.innerWidth < 768;
if (isMobile) {
// 移动设备显示确认对话框
messageBox.confirm("建议在电脑端进行投稿以获得最佳体验。仍要继续吗?", "提示")
.then(() => {
// 用户确认,跳转到投稿页面
this.$router.push('/submit');
})
.catch(() => {
// 用户取消,不执行任何操作
console.log("用户取消了在移动端投稿");
});
} else {
// 电脑端直接跳转到投稿页面
this.$router.push('/submit');
}
}
}
};
</script>
<style scoped>
.user-center {
min-height: 100vh;
background-color: #f4f7fa;
padding-top: 60px; /* 为导航栏留出空间 */
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 24px 16px;
display: flex;
flex-direction: column;
gap: 24px;
}
/* 登录提示样式 */
.login-required-container {
display: flex;
justify-content: center;
align-items: center;
height: calc(100vh - 200px);
}
.login-required-message {
background-color: white;
padding: 30px 50px;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
text-align: center;
}
.login-required-message h2 {
font-size: 24px;
color: #333;
margin-bottom: 10px;
}
.login-required-message p {
font-size: 16px;
color: #666;
}
/* 上部分布局 */
.upper-section {
display: flex;
gap: 24px;
flex-wrap: wrap;
}
.user-info-container,
.coin-container {
flex: 1;
min-width: 300px;
}
/* 调整高度统一 */
@media (min-width: 769px) {
.upper-section {
align-items: stretch;
}
.user-info-container,
.coin-container {
display: flex;
flex-direction: column;
height: 350px; /* 固定高度 */
}
.coin-container > :first-child {
flex: 1;
overflow-y: auto; /* 允许内容滚动 */
display: flex;
flex-direction: column;
}
.coin-container ::-webkit-scrollbar {
width: 6px;
}
.coin-container ::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
.coin-container ::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 10px;
}
.coin-container ::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
}
/* 下部分布局 */
.lower-section {
width: 100%;
}
/* 响应式设计 */
@media (max-width: 768px) {
.upper-section {
flex-direction: column;
}
.user-info-container,
.coin-container {
width: 100%;
height: auto;
}
.container {
padding: 16px 12px;
}
}
/* 加载状态样式 */
.loading-container {
display: flex;
justify-content: center;
align-items: center;
height: calc(100vh - 60px);
}
.loading-spinner {
padding: 20px;
background-color: white;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
font-size: 16px;
color: #3182ce;
}
/* 添加一些过渡效果 */
.user-center {
transition: all 0.3s ease;
}
/* 确保在较小屏幕上内容不会溢出 */
@media (max-width: 480px) {
.container {
padding: 12px 8px;
}
}
</style>