index.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <template>
  2. <view class="page-profile">
  3. <!-- User info card -->
  4. <view class="user-card" @click="goLogin">
  5. <view class="avatar">
  6. <image :src="userStore.avatarUrl || '/static/default-avatar.png'" mode="aspectFill" />
  7. </view>
  8. <text class="nickname">{{ userStore.nickname || '未登录' }}</text>
  9. <text v-if="!userStore.isLoggedIn" class="login-hint">点击登录</text>
  10. <view v-if="userStore.isVip" class="vip-badge">VIP 会员</view>
  11. </view>
  12. <!-- VIP status -->
  13. <view class="vip-card" @click="goPayment">
  14. <view class="vip-info">
  15. <text class="vip-title">VIP 会员</text>
  16. <text class="vip-desc">
  17. {{ userStore.isVip ? `有效期至: ${userStore.vipEndTime?.slice(0, 10)}` : '开通VIP获取完整分析' }}
  18. </text>
  19. </view>
  20. <text class="vip-action">{{ userStore.isVip ? '续费' : '立即开通' }}</text>
  21. </view>
  22. <!-- Daily quota (non-VIP) -->
  23. <view v-if="!userStore.isVip" class="quota-card">
  24. <view class="quota-item">
  25. <text class="quota-label">今日分析</text>
  26. <text class="quota-value">{{ userStore.usedCharts }}/{{ userStore.maxCharts }}</text>
  27. </view>
  28. <view class="quota-divider"></view>
  29. <view class="quota-item">
  30. <text class="quota-label">今日解读</text>
  31. <text class="quota-value">{{ userStore.usedChats }}/{{ userStore.maxChats }}</text>
  32. </view>
  33. </view>
  34. <!-- Menu list -->
  35. <view class="menu-section">
  36. <view class="menu-item" @click="goRecords">
  37. <text>📋 我的分析</text>
  38. <text class="menu-arrow">›</text>
  39. </view>
  40. <view class="menu-item" @click="goCommission">
  41. <text>💰 我的推广</text>
  42. <text class="menu-arrow">›</text>
  43. </view>
  44. <view class="menu-item" @click="copyReferral">
  45. <text>🔗 推广码: {{ userStore.referralCode || '加载中' }}</text>
  46. <text class="menu-tip">点击复制</text>
  47. </view>
  48. </view>
  49. <!-- Actions -->
  50. <view class="menu-section">
  51. <view class="menu-item" @click="handleLogout">
  52. <text style="color: #EF4444;">退出登录</text>
  53. </view>
  54. </view>
  55. </view>
  56. </template>
  57. <script setup>
  58. import { onShow } from '@dcloudio/uni-app'
  59. import { useUserStore } from '@/stores/user'
  60. const userStore = useUserStore()
  61. onShow(() => {
  62. if (userStore.isLoggedIn) {
  63. userStore.fetchProfile()
  64. userStore.fetchQuota()
  65. userStore.fetchCommissionSummary()
  66. }
  67. })
  68. function goLogin() {
  69. if (!userStore.isLoggedIn) {
  70. uni.navigateTo({ url: '/pages/login/index' })
  71. }
  72. }
  73. function goPayment() {
  74. uni.navigateTo({ url: '/pages/payment/index' })
  75. }
  76. function goRecords() {
  77. uni.switchTab({ url: '/pages/records/index' })
  78. }
  79. function goCommission() {
  80. uni.showToast({ title: '推广功能开发中', icon: 'none' })
  81. }
  82. function copyReferral() {
  83. if (userStore.referralCode) {
  84. uni.setClipboardData({
  85. data: userStore.referralCode,
  86. success: () => uni.showToast({ title: '已复制推广码', icon: 'success' })
  87. })
  88. }
  89. }
  90. function handleLogout() {
  91. uni.showModal({
  92. title: '确认退出',
  93. content: '确定要退出登录吗?',
  94. success: (res) => {
  95. if (res.confirm) {
  96. userStore.logout()
  97. uni.showToast({ title: '已退出', icon: 'success' })
  98. }
  99. }
  100. })
  101. }
  102. </script>
  103. <style scoped lang="scss">
  104. .page-profile { padding: 16px; }
  105. .user-card {
  106. text-align: center; padding: 30px 0; background: #fff;
  107. border-radius: 12px; margin-bottom: 16px;
  108. }
  109. .avatar {
  110. width: 64px; height: 64px; border-radius: 50%; overflow: hidden;
  111. margin: 0 auto 12px;
  112. }
  113. .avatar image { width: 100%; height: 100%; }
  114. .nickname { font-size: 18px; font-weight: 600; display: block; color: #1F2937; }
  115. .login-hint { font-size: 12px; color: #3B82F6; display: block; margin-top: 4px; }
  116. .vip-badge {
  117. display: inline-block; background: #FEF3C7; color: #D97706;
  118. padding: 2px 12px; border-radius: 12px; font-size: 12px; margin-top: 8px;
  119. }
  120. .vip-card {
  121. background: linear-gradient(135deg, #3B82F6, #2563EB); border-radius: 12px;
  122. padding: 16px; display: flex; justify-content: space-between;
  123. align-items: center; margin-bottom: 16px;
  124. }
  125. .vip-title { color: #fff; font-weight: 600; font-size: 16px; display: block; }
  126. .vip-desc { color: rgba(255,255,255,0.8); font-size: 12px; display: block; margin-top: 4px; }
  127. .vip-action { color: #fff; font-size: 14px; font-weight: 500; }
  128. .menu-section { background: #fff; border-radius: 12px; margin-bottom: 16px; overflow: hidden; }
  129. .menu-item {
  130. display: flex; justify-content: space-between; align-items: center;
  131. padding: 14px 16px; border-bottom: 1px solid #F3F4F6;
  132. }
  133. .menu-item:last-child { border-bottom: none; }
  134. .menu-arrow { color: #9CA3AF; font-size: 18px; }
  135. .menu-tip { color: #3B82F6; font-size: 12px; }
  136. .quota-card {
  137. background: #fff; border-radius: 12px; padding: 16px; margin-bottom: 16px;
  138. display: flex; align-items: center; justify-content: space-around;
  139. }
  140. .quota-item { text-align: center; }
  141. .quota-label { font-size: 12px; color: #6B7280; display: block; margin-bottom: 4px; }
  142. .quota-value { font-size: 20px; font-weight: 700; color: #1F2937; }
  143. .quota-divider { width: 1px; height: 36px; background: #E5E7EB; }
  144. </style>