初始化
This commit is contained in:
512
src/views/Profile.vue
Normal file
512
src/views/Profile.vue
Normal file
@@ -0,0 +1,512 @@
|
||||
<template>
|
||||
<div class="profile-container">
|
||||
<!-- 深空背景 -->
|
||||
<div class="space-background">
|
||||
<div class="stars" ref="stars"></div>
|
||||
</div>
|
||||
|
||||
<!-- 顶部导航 -->
|
||||
<div class="header glass-card">
|
||||
<van-icon name="arrow-left" size="24" @click="goBack" />
|
||||
<h2>个人中心</h2>
|
||||
<van-icon name="setting-o" size="24" @click="goToSettings" />
|
||||
</div>
|
||||
|
||||
<!-- 用户信息卡片 -->
|
||||
<div class="user-card glass-card p-20">
|
||||
<div class="user-avatar">
|
||||
<img :src="userAvatar" alt="用户头像" />
|
||||
</div>
|
||||
<div class="user-info">
|
||||
<h3>{{ userName }}</h3>
|
||||
<p>{{ userEmail }}</p>
|
||||
<p class="user-motto">{{ userMotto }}</p>
|
||||
</div>
|
||||
<van-icon name="edit" size="20" @click="editProfile" />
|
||||
</div>
|
||||
|
||||
<!-- 核心数据卡片 -->
|
||||
<div class="stats-container">
|
||||
<div class="stats-card glass-card">
|
||||
<div class="stat-item">
|
||||
<div class="stat-number">{{ sentCount }}</div>
|
||||
<div class="stat-label">寄出的信</div>
|
||||
</div>
|
||||
<div class="stat-divider"></div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-number">{{ receivedCount }}</div>
|
||||
<div class="stat-label">收到的信</div>
|
||||
</div>
|
||||
<div class="stat-divider"></div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-number">{{ totalDays }}</div>
|
||||
<div class="stat-label">时间旅行(天)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 功能列表 -->
|
||||
<div class="function-list">
|
||||
<van-cell-group class="glass-card">
|
||||
<van-cell
|
||||
title="我的时间线"
|
||||
icon="chart-trending-o"
|
||||
is-link
|
||||
@click="goToTimeline"
|
||||
/>
|
||||
<van-cell
|
||||
title="数据统计"
|
||||
icon="bar-chart-o"
|
||||
is-link
|
||||
@click="goToStats"
|
||||
/>
|
||||
<van-cell
|
||||
title="AI助手"
|
||||
icon="bulb-o"
|
||||
is-link
|
||||
@click="goToAIAssistant"
|
||||
/>
|
||||
</van-cell-group>
|
||||
|
||||
<van-cell-group class="glass-card mt-20">
|
||||
<van-cell
|
||||
title="数据备份"
|
||||
icon="folder-o"
|
||||
is-link
|
||||
@click="goToBackup"
|
||||
/>
|
||||
<van-cell
|
||||
title="隐私设置"
|
||||
icon="shield-o"
|
||||
is-link
|
||||
@click="goToPrivacy"
|
||||
/>
|
||||
<van-cell
|
||||
title="通知管理"
|
||||
icon="bell"
|
||||
is-link
|
||||
@click="goToNotifications"
|
||||
/>
|
||||
</van-cell-group>
|
||||
|
||||
<van-cell-group class="glass-card mt-20">
|
||||
<van-cell
|
||||
title="帮助与反馈"
|
||||
icon="question-o"
|
||||
is-link
|
||||
@click="goToHelp"
|
||||
/>
|
||||
<van-cell
|
||||
title="关于ChronoMail"
|
||||
icon="info-o"
|
||||
is-link
|
||||
@click="showAbout"
|
||||
/>
|
||||
</van-cell-group>
|
||||
</div>
|
||||
|
||||
<!-- 退出登录按钮 -->
|
||||
<div class="logout-container">
|
||||
<van-button round block class="logout-button" @click="logout">
|
||||
退出登录
|
||||
</van-button>
|
||||
</div>
|
||||
|
||||
<!-- 底部导航 -->
|
||||
<van-tabbar v-model="active" class="custom-tabbar">
|
||||
<van-tabbar-item icon="home-o" to="/home">时光胶囊</van-tabbar-item>
|
||||
<van-tabbar-item icon="envelop-o" to="/inbox">收件箱</van-tabbar-item>
|
||||
<van-tabbar-item icon="send-o" to="/sent">发件箱</van-tabbar-item>
|
||||
<van-tabbar-item icon="user-o" to="/profile">个人中心</van-tabbar-item>
|
||||
</van-tabbar>
|
||||
|
||||
<!-- 关于弹窗 -->
|
||||
<van-popup v-model:show="showAboutPopup" position="bottom" :style="{ height: '40%' }">
|
||||
<div class="about-popup">
|
||||
<div class="about-logo">
|
||||
<div class="time-capsule"></div>
|
||||
<h3>ChronoMail</h3>
|
||||
<p>版本 1.0.0</p>
|
||||
</div>
|
||||
<div class="about-content">
|
||||
<p>ChronoMail 是一款可以发送邮件到未来的应用,帮助您与未来的自己进行对话,记录成长与蜕变。</p>
|
||||
<p class="about-slogan">"写给未来,不负当下"</p>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { showFailToast, showSuccessToast, Dialog } from 'vant'
|
||||
import { userActions, mailActions, userState } from '../store'
|
||||
|
||||
export default {
|
||||
name: 'Profile',
|
||||
setup() {
|
||||
const router = useRouter()
|
||||
const active = ref(3)
|
||||
const stars = ref(null)
|
||||
const showAboutPopup = ref(false)
|
||||
|
||||
// 使用直接导入的状态和操作
|
||||
const user = computed(() => userState.userInfo)
|
||||
|
||||
// 用户信息
|
||||
const userName = ref(user.value?.username || '时光旅人')
|
||||
const userEmail = ref(user.value?.email || 'traveler@chronomail.com')
|
||||
const userMotto = ref('穿越时空,与未来的自己对话')
|
||||
const userAvatar = ref(user.value?.avatar || 'https://picsum.photos/seed/user123/100/100.jpg')
|
||||
|
||||
// 统计数据
|
||||
const sentCount = ref(0)
|
||||
const receivedCount = ref(0)
|
||||
const totalDays = ref(0)
|
||||
|
||||
// 获取用户统计数据
|
||||
const fetchStatistics = async () => {
|
||||
try {
|
||||
const response = await mailActions.getStatistics()
|
||||
const data = response.data
|
||||
|
||||
sentCount.value = data.totalSent || 0
|
||||
receivedCount.value = data.totalReceived || 0
|
||||
totalDays.value = data.timeTravelDuration || 0
|
||||
} catch (error) {
|
||||
console.error('获取统计数据失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
const fetchUserProfile = async () => {
|
||||
try {
|
||||
const response = await userActions.getProfile()
|
||||
const userData = response.data
|
||||
|
||||
userName.value = userData.username || '时光旅人'
|
||||
userEmail.value = userData.email || 'traveler@chronomail.com'
|
||||
userAvatar.value = userData.avatar || 'https://picsum.photos/seed/user123/100/100.jpg'
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成星空背景
|
||||
const generateStars = () => {
|
||||
if (!stars.value) return
|
||||
|
||||
const starsContainer = stars.value
|
||||
const starCount = 100
|
||||
|
||||
for (let i = 0; i < starCount; i++) {
|
||||
const star = document.createElement('div')
|
||||
star.className = 'star'
|
||||
|
||||
// 随机位置
|
||||
const left = Math.random() * 100
|
||||
const top = Math.random() * 100
|
||||
|
||||
// 随机大小
|
||||
const size = Math.random() * 3 + 1
|
||||
|
||||
// 随机动画延迟
|
||||
const delay = Math.random() * 4
|
||||
|
||||
star.style.left = `${left}%`
|
||||
star.style.top = `${top}%`
|
||||
star.style.width = `${size}px`
|
||||
star.style.height = `${size}px`
|
||||
star.style.animationDelay = `${delay}s`
|
||||
|
||||
starsContainer.appendChild(star)
|
||||
}
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
// 跳转到设置页面
|
||||
const goToSettings = () => {
|
||||
showFailToast('设置页面开发中')
|
||||
}
|
||||
|
||||
// 编辑个人资料
|
||||
const editProfile = () => {
|
||||
showFailToast('编辑个人资料功能开发中')
|
||||
}
|
||||
|
||||
// 跳转到时间线
|
||||
const goToTimeline = () => {
|
||||
router.push('/timeline')
|
||||
}
|
||||
|
||||
// 跳转到数据统计
|
||||
const goToStats = () => {
|
||||
showFailToast('数据统计功能开发中')
|
||||
}
|
||||
|
||||
// 跳转到AI助手
|
||||
const goToAIAssistant = () => {
|
||||
showFailToast('AI助手功能开发中')
|
||||
}
|
||||
|
||||
// 跳转到数据备份
|
||||
const goToBackup = () => {
|
||||
showFailToast('数据备份功能开发中')
|
||||
}
|
||||
|
||||
// 跳转到隐私设置
|
||||
const goToPrivacy = () => {
|
||||
showFailToast('隐私设置功能开发中')
|
||||
}
|
||||
|
||||
// 跳转到通知管理
|
||||
const goToNotifications = () => {
|
||||
showFailToast('通知管理功能开发中')
|
||||
}
|
||||
|
||||
// 跳转到帮助与反馈
|
||||
const goToHelp = () => {
|
||||
showFailToast('帮助与反馈功能开发中')
|
||||
}
|
||||
|
||||
// 显示关于弹窗
|
||||
const showAbout = () => {
|
||||
showAboutPopup.value = true
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
const logout = () => {
|
||||
Dialog.confirm({
|
||||
title: '确认退出',
|
||||
message: '确定要退出登录吗?',
|
||||
})
|
||||
.then(() => {
|
||||
// 清除登录状态
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('user')
|
||||
|
||||
showSuccessToast('已退出登录')
|
||||
|
||||
// 跳转到登录页
|
||||
router.push('/login')
|
||||
})
|
||||
.catch(() => {
|
||||
// 取消操作
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
generateStars()
|
||||
fetchUserProfile()
|
||||
fetchStatistics()
|
||||
|
||||
// 获取用户信息
|
||||
const userStr = localStorage.getItem('user')
|
||||
if (userStr) {
|
||||
const user = JSON.parse(userStr)
|
||||
userName.value = user.name || '时光旅人'
|
||||
userEmail.value = user.email || 'traveler@chronomail.com'
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
active,
|
||||
stars,
|
||||
userName,
|
||||
userEmail,
|
||||
userMotto,
|
||||
userAvatar,
|
||||
sentCount,
|
||||
receivedCount,
|
||||
totalDays,
|
||||
showAboutPopup,
|
||||
goBack,
|
||||
goToSettings,
|
||||
editProfile,
|
||||
goToTimeline,
|
||||
goToStats,
|
||||
goToAIAssistant,
|
||||
goToBackup,
|
||||
goToPrivacy,
|
||||
goToNotifications,
|
||||
goToHelp,
|
||||
showAbout,
|
||||
logout
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.profile-container {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 15px 20px;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.user-avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.user-info h3 {
|
||||
margin: 0 0 5px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.user-info p {
|
||||
margin: 0 0 5px;
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.user-motto {
|
||||
font-style: italic;
|
||||
color: var(--accent-color) !important;
|
||||
}
|
||||
|
||||
.stats-container {
|
||||
margin: 0 15px 20px;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: var(--accent-color);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.stat-divider {
|
||||
width: 1px;
|
||||
height: 40px;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.function-list {
|
||||
margin: 0 15px 20px;
|
||||
}
|
||||
|
||||
.function-list .van-cell-group {
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.function-list .van-cell {
|
||||
background-color: transparent;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.function-list .van-cell::after {
|
||||
border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.logout-container {
|
||||
margin: 0 15px 20px;
|
||||
}
|
||||
|
||||
.logout-button {
|
||||
background: linear-gradient(135deg, #ff4d4f, #c41e3a);
|
||||
border: none;
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
box-shadow: 0 8px 20px rgba(255, 77, 79, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.logout-button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 12px 25px rgba(255, 77, 79, 0.4);
|
||||
}
|
||||
|
||||
.logout-button:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 5px 15px rgba(255, 77, 79, 0.3);
|
||||
}
|
||||
|
||||
.about-popup {
|
||||
padding: 30px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.about-logo {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.about-logo h3 {
|
||||
margin: 10px 0 5px;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
background: linear-gradient(135deg, #00D4FF, #ffffff);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.about-logo p {
|
||||
margin: 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.about-content {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.about-content p {
|
||||
margin: 10px 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.about-slogan {
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
color: var(--accent-color);
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user