| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- <template>
- <div class="user-page with-bottom-nav">
- <div class="user-header">
- <van-image
- :src="userStore.avatarUrl || 'https://picsum.photos/seed/avatar/200/200'"
- width="60"
- height="60"
- round
- fit="cover"
- />
- <h3>{{ userStore.isLoggedIn ? userStore.nickname : '游客' }}</h3>
- <p class="user-phone" v-if="userStore.phone">{{ userStore.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') }}</p>
- </div>
- <div class="user-stats">
- <div class="stat-item">
- <span class="stat-num">{{ wishCount }}</span>
- <span class="stat-label">许愿数</span>
- </div>
- <div class="stat-item">
- <span class="stat-num">{{ totalLikes }}</span>
- <span class="stat-label">收到的祝福</span>
- </div>
- </div>
- <van-cell-group inset>
- <van-cell title="我的愿望" icon="label-o" to="/my-wishes" is-link />
- <van-cell title="最近许愿" icon="clock-o" is-link @click="$router.push('/my-wishes')" />
- </van-cell-group>
- <div class="logout-section">
- <van-button
- v-if="userStore.isLoggedIn"
- type="danger"
- round
- plain
- block
- @click="handleLogout"
- >
- 退出登录
- </van-button>
- <van-button
- v-else
- type="primary"
- round
- block
- to="/login"
- >
- 登录 / 注册
- </van-button>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, onMounted } from 'vue'
- import { showConfirmDialog } from 'vant'
- import { useUserStore } from '@/stores/user'
- import { useRouter } from 'vue-router'
- import { logout as logoutApi, fetchUserSummary } from '@/api/auth'
- const userStore = useUserStore()
- const router = useRouter()
- const wishCount = ref(0)
- const totalLikes = ref(0)
- async function handleLogout() {
- await showConfirmDialog({
- title: '退出登录',
- message: '确定要退出当前账号吗?',
- confirmButtonText: '退出',
- confirmButtonColor: '#ee0a24',
- cancelButtonText: '取消',
- })
- try { await logoutApi() } catch { /* 即使后端调用失败也清除本地状态 */ }
- userStore.logout()
- router.push('/')
- }
- onMounted(async () => {
- if (userStore.isLoggedIn) {
- try {
- const summary = await fetchUserSummary()
- wishCount.value = summary.wishCount
- totalLikes.value = summary.receiveCount
- } catch { /* ignore */ }
- }
- })
- </script>
- <style scoped>
- .user-page {
- min-height: 100vh;
- background: #f7f8fa;
- }
- .user-header {
- background: linear-gradient(135deg, #07c160, #05a650);
- padding: 40px 20px 30px;
- text-align: center;
- color: #fff;
- }
- .user-header h3 {
- margin-top: 12px;
- font-size: 18px;
- }
- .user-phone {
- font-size: 13px;
- opacity: 0.8;
- margin-top: 4px;
- }
- .user-stats {
- display: flex;
- background: #fff;
- margin: -12px 16px 12px;
- border-radius: 12px;
- padding: 16px;
- box-shadow: 0 2px 8px rgba(0,0,0,0.06);
- }
- .stat-item {
- flex: 1;
- text-align: center;
- }
- .stat-num {
- display: block;
- font-size: 22px;
- font-weight: 700;
- color: #07c160;
- }
- .stat-label {
- font-size: 12px;
- color: #999;
- }
- .logout-section {
- padding: 30px 16px;
- }
- </style>
|