前后端登录注册连接成功

Change-Id: Ib5f9282fe7217b3363e542ce5c4e1c0d32619dcb
diff --git a/src/views/auth/ProfileView.vue b/src/views/auth/ProfileView.vue
index e1e2544..5d11acc 100644
--- a/src/views/auth/ProfileView.vue
+++ b/src/views/auth/ProfileView.vue
@@ -1,1343 +1,1343 @@
-<template>
-  <div class="profile-page">
-    <div class="page-container">
-      <!-- 个人信息卡片 -->
-      <div class="profile-header">
-        <div class="user-avatar-section">
-          <div class="avatar-container">
-            <el-avatar :size="120" :src="userProfile.avatar">
-              {{ userProfile.username.charAt(0).toUpperCase() }}
-            </el-avatar>
-            <el-button 
-              type="primary" 
-              size="small" 
-              class="change-avatar-btn"
-              @click="showAvatarDialog = true"
-            >
-              更换头像
-            </el-button>
-          </div>
-          
-          <div class="user-basic-info">
-            <h1 class="username">{{ userProfile.username }}</h1>
-            <div class="user-title">
-              <el-tag :type="getUserTitleType(userProfile.userLevel)" size="large">
-                {{ userProfile.userTitle }}
-              </el-tag>
-            </div>
-            <div class="join-info">
-              <el-icon><Calendar /></el-icon>
-              <span>加入时间:{{ formatDate(userProfile.joinDate) }}</span>
-            </div>
-            <div class="last-login">
-              <el-icon><Clock /></el-icon>
-              <span>最后登录:{{ formatTime(userProfile.lastLogin) }}</span>
-            </div>
-          </div>
-        </div>
-        
-        <div class="user-stats-overview">
-          <div class="stats-grid">
-            <div class="stat-card">
-              <div class="stat-icon upload">
-                <el-icon size="32"><Upload /></el-icon>
-              </div>
-              <div class="stat-info">
-                <h3>{{ userProfile.stats.uploaded }}</h3>
-                <p>上传量</p>
-              </div>
-            </div>
-            
-            <div class="stat-card">
-              <div class="stat-icon download">
-                <el-icon size="32"><Download /></el-icon>
-              </div>
-              <div class="stat-info">
-                <h3>{{ userProfile.stats.downloaded }}</h3>
-                <p>下载量</p>
-              </div>
-            </div>
-            
-            <div class="stat-card">
-              <div class="stat-icon ratio" :class="getRatioClass(userProfile.stats.ratio)">
-                <el-icon size="32"><TrendCharts /></el-icon>
-              </div>
-              <div class="stat-info">
-                <h3>{{ userProfile.stats.ratio }}</h3>
-                <p>分享率</p>
-              </div>
-            </div>
-            
-            <div class="stat-card">
-              <div class="stat-icon points">
-                <el-icon size="32"><Star /></el-icon>
-              </div>
-              <div class="stat-info">
-                <h3>{{ userProfile.stats.points }}</h3>
-                <p>积分</p>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- 详细信息选项卡 -->
-      <div class="profile-content">
-        <el-tabs v-model="activeTab" type="border-card">
-          <!-- 个人信息 -->
-          <el-tab-pane label="个人信息" name="info">
-            <div class="info-section">
-              <el-form
-                ref="profileFormRef"
-                :model="editProfile"
-                :rules="profileRules"
-                label-width="120px"
-                size="large"
-              >
-                <div class="form-section">
-                  <h3>基本信息</h3>
-                  <el-form-item label="用户名">
-                    <el-input v-model="editProfile.username" disabled>
-                      <template #suffix>
-                        <el-tooltip content="用户名不可修改">
-                          <el-icon><QuestionFilled /></el-icon>
-                        </el-tooltip>
-                      </template>
-                    </el-input>
-                  </el-form-item>
-                  
-                  <el-form-item label="邮箱地址" prop="email">
-                    <el-input v-model="editProfile.email" type="email" />
-                  </el-form-item>
-                  
-                  <el-form-item label="真实姓名" prop="realName">
-                    <el-input v-model="editProfile.realName" placeholder="可选填写" />
-                  </el-form-item>
-                  
-                  <el-form-item label="所在地区">
-                    <el-cascader
-                      v-model="editProfile.location"
-                      :options="locationOptions"
-                      placeholder="请选择地区"
-                      clearable
-                    />
-                  </el-form-item>
-                </div>
-                
-                <div class="form-section">
-                  <h3>个人介绍</h3>
-                  <el-form-item label="个人签名">
-                    <el-input
-                      v-model="editProfile.signature"
-                      type="textarea"
-                      :rows="3"
-                      maxlength="200"
-                      show-word-limit
-                      placeholder="介绍一下自己吧..."
-                    />
-                  </el-form-item>
-                  
-                  <el-form-item label="个人网站">
-                    <el-input v-model="editProfile.website" placeholder="https://" />
-                  </el-form-item>
-                  
-                  <el-form-item label="兴趣爱好">
-                    <div class="interests-input">
-                      <el-tag
-                        v-for="interest in editProfile.interests"
-                        :key="interest"
-                        closable
-                        @close="removeInterest(interest)"
-                        class="interest-tag"
-                      >
-                        {{ interest }}
-                      </el-tag>
-                      <el-input
-                        v-if="interestInputVisible"
-                        ref="interestInputRef"
-                        v-model="interestInputValue"
-                        size="small"
-                        @keyup.enter="addInterest"
-                        @blur="addInterest"
-                        style="width: 120px;"
-                      />
-                      <el-button
-                        v-else
-                        size="small"
-                        @click="showInterestInput"
-                      >
-                        + 添加兴趣
-                      </el-button>
-                    </div>
-                  </el-form-item>
-                </div>
-                
-                <div class="form-section">
-                  <h3>隐私设置</h3>
-                  <el-form-item label="邮箱公开">
-                    <el-switch v-model="editProfile.emailPublic" />
-                    <span class="setting-tip">是否在个人资料中显示邮箱</span>
-                  </el-form-item>
-                  
-                  <el-form-item label="统计公开">
-                    <el-switch v-model="editProfile.statsPublic" />
-                    <span class="setting-tip">是否公开上传下载统计</span>
-                  </el-form-item>
-                  
-                  <el-form-item label="活动记录">
-                    <el-switch v-model="editProfile.activityPublic" />
-                    <span class="setting-tip">是否公开活动记录</span>
-                  </el-form-item>
-                </div>
-                
-                <div class="form-actions">
-                  <el-button @click="resetProfile">重置</el-button>
-                  <el-button type="primary" @click="saveProfile" :loading="saving">
-                    保存修改
-                  </el-button>
-                </div>
-              </el-form>
-            </div>
-          </el-tab-pane>
-          
-          <!-- 数据统计 -->
-          <el-tab-pane label="数据统计" name="stats">
-            <div class="stats-section">
-              <div class="stats-overview">
-                <div class="overview-grid">
-                  <div class="overview-card">
-                    <h3>上传统计</h3>
-                    <div class="stat-details">
-                      <div class="detail-item">
-                        <span class="label">总上传量:</span>
-                        <span class="value">{{ userProfile.detailedStats.totalUploaded }}</span>
-                      </div>
-                      <div class="detail-item">
-                        <span class="label">上传种子:</span>
-                        <span class="value">{{ userProfile.detailedStats.uploadedTorrents }} 个</span>
-                      </div>
-                      <div class="detail-item">
-                        <span class="label">平均大小:</span>
-                        <span class="value">{{ userProfile.detailedStats.avgUploadSize }}</span>
-                      </div>
-                    </div>
-                  </div>
-                  
-                  <div class="overview-card">
-                    <h3>下载统计</h3>
-                    <div class="stat-details">
-                      <div class="detail-item">
-                        <span class="label">总下载量:</span>
-                        <span class="value">{{ userProfile.detailedStats.totalDownloaded }}</span>
-                      </div>
-                      <div class="detail-item">
-                        <span class="label">下载种子:</span>
-                        <span class="value">{{ userProfile.detailedStats.downloadedTorrents }} 个</span>
-                      </div>
-                      <div class="detail-item">
-                        <span class="label">完成种子:</span>
-                        <span class="value">{{ userProfile.detailedStats.completedTorrents }} 个</span>
-                      </div>
-                    </div>
-                  </div>
-                  
-                  <div class="overview-card">
-                    <h3>做种统计</h3>
-                    <div class="stat-details">
-                      <div class="detail-item">
-                        <span class="label">正在做种:</span>
-                        <span class="value">{{ userProfile.detailedStats.seeding }} 个</span>
-                      </div>
-                      <div class="detail-item">
-                        <span class="label">做种时间:</span>
-                        <span class="value">{{ userProfile.detailedStats.seedingTime }}</span>
-                      </div>
-                      <div class="detail-item">
-                        <span class="label">做种排名:</span>
-                        <span class="value">第 {{ userProfile.detailedStats.seedingRank }} 名</span>
-                      </div>
-                    </div>
-                  </div>
-                  
-                  <div class="overview-card">
-                    <h3>积分记录</h3>
-                    <div class="stat-details">
-                      <div class="detail-item">
-                        <span class="label">当前积分:</span>
-                        <span class="value">{{ userProfile.stats.points }}</span>
-                      </div>
-                      <div class="detail-item">
-                        <span class="label">累计获得:</span>
-                        <span class="value">{{ userProfile.detailedStats.totalEarnedPoints }}</span>
-                      </div>
-                      <div class="detail-item">
-                        <span class="label">累计消费:</span>
-                        <span class="value">{{ userProfile.detailedStats.totalSpentPoints }}</span>
-                      </div>
-                    </div>
-                  </div>
-                </div>
-              </div>
-              
-              <!-- 数据图表 -->
-              <div class="charts-section">
-                <div class="chart-card">
-                  <h3>上传下载趋势</h3>
-                  <div class="chart-placeholder">
-                    <el-icon size="48" color="#e4e7ed"><TrendCharts /></el-icon>
-                    <p>图表功能开发中...</p>
-                  </div>
-                </div>
-              </div>
-            </div>
-          </el-tab-pane>
-          
-          <!-- 我的种子 -->
-          <el-tab-pane label="我的种子" name="torrents">
-            <div class="torrents-section">
-              <div class="section-header">
-                <h3>我上传的种子</h3>
-                <el-button type="primary" :icon="Upload" @click="$router.push('/upload')">
-                  上传新种子
-                </el-button>
-              </div>
-              
-              <el-table :data="userTorrents" stripe>
-                <el-table-column label="种子名称" min-width="300">
-                  <template #default="{ row }">
-                    <div class="torrent-info">
-                      <el-tag :type="getCategoryType(row.category)" size="small">
-                        {{ getCategoryName(row.category) }}
-                      </el-tag>
-                      <span class="torrent-title">{{ row.title }}</span>
-                    </div>
-                  </template>
-                </el-table-column>
-                
-                <el-table-column label="大小" prop="size" width="100" />
-                <el-table-column label="做种" prop="seeders" width="80" align="center" />
-                <el-table-column label="下载" prop="leechers" width="80" align="center" />
-                <el-table-column label="完成" prop="downloads" width="80" align="center" />
-                <el-table-column label="上传时间" width="120">
-                  <template #default="{ row }">
-                    {{ formatDate(row.uploadTime) }}
-                  </template>
-                </el-table-column>
-                
-                <el-table-column label="操作" width="120" align="center">
-                  <template #default="{ row }">
-                    <el-button 
-                      type="primary" 
-                      size="small" 
-                      @click="$router.push(`/torrent/${row.id}`)"
-                    >
-                      查看
-                    </el-button>
-                  </template>
-                </el-table-column>
-              </el-table>
-              
-              <div class="pagination-wrapper">
-                <el-pagination
-                  v-model:current-page="torrentsPage"
-                  :page-size="10"
-                  :total="userTorrents.length"
-                  layout="prev, pager, next"
-                  small
-                />
-              </div>
-            </div>
-          </el-tab-pane>
-          
-          <!-- 活动记录 -->
-          <el-tab-pane label="活动记录" name="activity">
-            <div class="activity-section">
-              <div class="activity-filters">
-                <el-select v-model="activityFilter" placeholder="活动类型">
-                  <el-option label="全部活动" value="" />
-                  <el-option label="上传种子" value="upload" />
-                  <el-option label="下载种子" value="download" />
-                  <el-option label="论坛发帖" value="post" />
-                  <el-option label="积分变动" value="points" />
-                </el-select>
-              </div>
-              
-              <div class="activity-timeline">
-                <el-timeline>
-                  <el-timeline-item
-                    v-for="activity in filteredActivities"
-                    :key="activity.id"
-                    :timestamp="formatTime(activity.time)"
-                    :type="getActivityType(activity.type)"
-                  >
-                    <div class="activity-content">
-                      <div class="activity-header">
-                        <el-icon>
-                          <component :is="getActivityIcon(activity.type)" />
-                        </el-icon>
-                        <span class="activity-title">{{ activity.title }}</span>
-                      </div>
-                      <div class="activity-description">{{ activity.description }}</div>
-                    </div>
-                  </el-timeline-item>
-                </el-timeline>
-              </div>
-            </div>
-          </el-tab-pane>
-          
-          <!-- 安全设置 -->
-          <el-tab-pane label="安全设置" name="security">
-            <div class="security-section">
-              <div class="security-card">
-                <h3>修改密码</h3>
-                <el-form
-                  ref="passwordFormRef"
-                  :model="passwordForm"
-                  :rules="passwordRules"
-                  label-width="120px"
-                >
-                  <el-form-item label="当前密码" prop="currentPassword">
-                    <el-input
-                      v-model="passwordForm.currentPassword"
-                      type="password"
-                      show-password
-                      placeholder="请输入当前密码"
-                    />
-                  </el-form-item>
-                  
-                  <el-form-item label="新密码" prop="newPassword">
-                    <el-input
-                      v-model="passwordForm.newPassword"
-                      type="password"
-                      show-password
-                      placeholder="请输入新密码"
-                    />
-                  </el-form-item>
-                  
-                  <el-form-item label="确认密码" prop="confirmPassword">
-                    <el-input
-                      v-model="passwordForm.confirmPassword"
-                      type="password"
-                      show-password
-                      placeholder="请再次输入新密码"
-                    />
-                  </el-form-item>
-                  
-                  <el-form-item>
-                    <el-button type="primary" @click="changePassword" :loading="changingPassword">
-                      修改密码
-                    </el-button>
-                  </el-form-item>
-                </el-form>
-              </div>
-              
-              <div class="security-card">
-                <h3>登录记录</h3>
-                <el-table :data="loginHistory" stripe>
-                  <el-table-column label="登录时间" width="180">
-                    <template #default="{ row }">
-                      {{ formatDateTime(row.time) }}
-                    </template>
-                  </el-table-column>
-                  <el-table-column label="IP地址" prop="ip" width="150" />
-                  <el-table-column label="设备信息" prop="device" />
-                  <el-table-column label="登录结果" width="100">
-                    <template #default="{ row }">
-                      <el-tag :type="row.success ? 'success' : 'danger'" size="small">
-                        {{ row.success ? '成功' : '失败' }}
-                      </el-tag>
-                    </template>
-                  </el-table-column>
-                </el-table>
-              </div>
-            </div>
-          </el-tab-pane>
-        </el-tabs>
-      </div>
-    </div>
-
-    <!-- 更换头像对话框 -->
-    <el-dialog v-model="showAvatarDialog" title="更换头像" width="400px">
-      <div class="avatar-upload">
-        <el-upload
-          ref="avatarUploadRef"
-          :auto-upload="false"
-          :limit="1"
-          accept="image/*"
-          :on-change="handleAvatarChange"
-          list-type="picture-card"
-          class="avatar-uploader"
-        >
-          <el-icon><Plus /></el-icon>
-        </el-upload>
-        <div class="upload-tips">
-          <p>支持 JPG、PNG 格式</p>
-          <p>建议尺寸 200x200 像素</p>
-          <p>文件大小不超过 2MB</p>
-        </div>
-      </div>
-      
-      <template #footer>
-        <el-button @click="showAvatarDialog = false">取消</el-button>
-        <el-button type="primary" @click="uploadAvatar" :loading="uploadingAvatar">
-          上传头像
-        </el-button>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import { ref, reactive, computed, onMounted, nextTick } from 'vue'
-import { useRouter } from 'vue-router'
-import { ElMessage } from 'element-plus'
-import {
-  Calendar,
-  Clock,
-  Upload,
-  Download,
-  TrendCharts,
-  Star,
-  QuestionFilled,
-  Plus,
-  ChatDotRound,
-  Flag,
-  Coin
-} from '@element-plus/icons-vue'
-
-export default {
-  name: 'ProfileView',
-  setup() {
-    const router = useRouter()
-    const profileFormRef = ref(null)
-    const passwordFormRef = ref(null)
-    const avatarUploadRef = ref(null)
-    const interestInputRef = ref(null)
-    
-    const activeTab = ref('info')
-    const showAvatarDialog = ref(false)
-    const saving = ref(false)
-    const changingPassword = ref(false)
-    const uploadingAvatar = ref(false)
-    const interestInputVisible = ref(false)
-    const interestInputValue = ref('')
-    const activityFilter = ref('')
-    const torrentsPage = ref(1)
-    
-    const userProfile = ref({
-      username: 'MovieExpert',
-      email: 'movieexpert@example.com',
-      realName: '',
-      avatar: '',
-      userLevel: 5,
-      userTitle: '资深会员',
-      joinDate: '2023-01-15T10:00:00',
-      lastLogin: '2025-06-03T14:30:00',
-      location: ['北京市', '朝阳区'],
-      signature: '热爱电影,分享快乐!',
-      website: 'https://movieblog.com',
-      interests: ['电影', '音乐', '科技', '摄影'],
-      emailPublic: false,
-      statsPublic: true,
-      activityPublic: true,
-      stats: {
-        uploaded: '256.8 GB',
-        downloaded: '89.6 GB',
-        ratio: '2.87',
-        points: '15,680'
-      },
-      detailedStats: {
-        totalUploaded: '256.8 GB',
-        uploadedTorrents: 45,
-        avgUploadSize: '5.7 GB',
-        totalDownloaded: '89.6 GB',
-        downloadedTorrents: 123,
-        completedTorrents: 118,
-        seeding: 32,
-        seedingTime: '1,245 小时',
-        seedingRank: 86,
-        totalEarnedPoints: '28,940',
-        totalSpentPoints: '13,260'
-      }
-    })
-    
-    const editProfile = reactive({
-      username: '',
-      email: '',
-      realName: '',
-      location: [],
-      signature: '',
-      website: '',
-      interests: [],
-      emailPublic: false,
-      statsPublic: true,
-      activityPublic: true
-    })
-    
-    const passwordForm = reactive({
-      currentPassword: '',
-      newPassword: '',
-      confirmPassword: ''
-    })
-    
-    const profileRules = {
-      email: [
-        { required: true, message: '请输入邮箱地址', trigger: 'blur' },
-        { type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }
-      ]
-    }
-    
-    const passwordRules = {
-      currentPassword: [
-        { required: true, message: '请输入当前密码', trigger: 'blur' }
-      ],
-      newPassword: [
-        { required: true, message: '请输入新密码', trigger: 'blur' },
-        { min: 6, message: '密码长度至少6个字符', trigger: 'blur' }
-      ],
-      confirmPassword: [
-        { required: true, message: '请确认新密码', trigger: 'blur' },
-        {
-          validator: (rule, value, callback) => {
-            if (value !== passwordForm.newPassword) {
-              callback(new Error('两次输入的密码不一致'))
-            } else {
-              callback()
-            }
-          },
-          trigger: 'blur'
-        }
-      ]
-    }
-    
-    const locationOptions = [
-      {
-        value: '北京市',
-        label: '北京市',
-        children: [
-          { value: '朝阳区', label: '朝阳区' },
-          { value: '海淀区', label: '海淀区' },
-          { value: '丰台区', label: '丰台区' }
-        ]
-      },
-      {
-        value: '上海市',
-        label: '上海市',
-        children: [
-          { value: '浦东新区', label: '浦东新区' },
-          { value: '黄浦区', label: '黄浦区' },
-          { value: '静安区', label: '静安区' }
-        ]
-      }
-    ]
-    
-    const userTorrents = ref([
-      {
-        id: 1,
-        title: '[4K蓝光原盘] 阿凡达:水之道',
-        category: 'movie',
-        size: '85.6 GB',
-        seeders: 45,
-        leechers: 12,
-        downloads: 234,
-        uploadTime: '2025-05-15T10:00:00'
-      },
-      {
-        id: 2,
-        title: '[FLAC] 古典音乐合集',
-        category: 'music',
-        size: '2.3 GB',
-        seeders: 23,
-        leechers: 5,
-        downloads: 89,
-        uploadTime: '2025-04-20T15:30:00'
-      }
-    ])
-    
-    const activities = ref([
-      {
-        id: 1,
-        type: 'upload',
-        title: '上传种子',
-        description: '上传了《阿凡达:水之道》4K蓝光原盘',
-        time: '2025-06-03T10:30:00'
-      },
-      {
-        id: 2,
-        type: 'download',
-        title: '下载种子',
-        description: '下载了《星际穿越》IMAX版本',
-        time: '2025-06-02T14:20:00'
-      },
-      {
-        id: 3,
-        type: 'post',
-        title: '发布主题',
-        description: '在电影讨论区发布了新主题',
-        time: '2025-06-01T16:45:00'
-      },
-      {
-        id: 4,
-        type: 'points',
-        title: '积分变动',
-        description: '做种奖励获得 +50 积分',
-        time: '2025-05-31T09:15:00'
-      }
-    ])
-    
-    const loginHistory = ref([
-      {
-        time: '2025-06-03T14:30:00',
-        ip: '192.168.1.100',
-        device: 'Windows 11 / Chrome 120',
-        success: true
-      },
-      {
-        time: '2025-06-02T09:15:00',
-        ip: '192.168.1.100',
-        device: 'Windows 11 / Chrome 120',
-        success: true
-      },
-      {
-        time: '2025-06-01T22:30:00',
-        ip: '192.168.1.100',
-        device: 'Android / Chrome Mobile',
-        success: true
-      }
-    ])
-    
-    const filteredActivities = computed(() => {
-      if (!activityFilter.value) return activities.value
-      return activities.value.filter(activity => activity.type === activityFilter.value)
-    })
-    
-    onMounted(() => {
-      loadUserProfile()
-    })
-    
-    const loadUserProfile = () => {
-      // 加载用户资料到编辑表单
-      Object.assign(editProfile, {
-        username: userProfile.value.username,
-        email: userProfile.value.email,
-        realName: userProfile.value.realName,
-        location: userProfile.value.location,
-        signature: userProfile.value.signature,
-        website: userProfile.value.website,
-        interests: [...userProfile.value.interests],
-        emailPublic: userProfile.value.emailPublic,
-        statsPublic: userProfile.value.statsPublic,
-        activityPublic: userProfile.value.activityPublic
-      })
-    }
-    
-    const formatDate = (dateString) => {
-      const date = new Date(dateString)
-      return date.toLocaleDateString('zh-CN')
-    }
-    
-    const formatTime = (timeString) => {
-      const date = new Date(timeString)
-      const now = new Date()
-      const diff = now - date
-      const hours = Math.floor(diff / (1000 * 60 * 60))
-      
-      if (hours < 1) return '刚刚'
-      if (hours < 24) return `${hours}小时前`
-      const days = Math.floor(hours / 24)
-      if (days < 7) return `${days}天前`
-      
-      return date.toLocaleDateString('zh-CN')
-    }
-    
-    const formatDateTime = (dateString) => {
-      const date = new Date(dateString)
-      return date.toLocaleString('zh-CN')
-    }
-    
-    const getUserTitleType = (level) => {
-      if (level >= 8) return 'danger'  // 管理员
-      if (level >= 6) return 'warning' // 资深会员
-      if (level >= 4) return 'success' // 正式会员
-      if (level >= 2) return 'info'    // 初级会员
-      return 'default' // 新手
-    }
-    
-    const getRatioClass = (ratio) => {
-      const r = parseFloat(ratio)
-      if (r >= 2) return 'excellent'
-      if (r >= 1) return 'good'
-      return 'warning'
-    }
-    
-    const getCategoryType = (category) => {
-      const types = {
-        'movie': 'primary',
-        'tv': 'info',
-        'music': 'success',
-        'software': 'warning',
-        'game': 'danger'
-      }
-      return types[category] || 'default'
-    }
-    
-    const getCategoryName = (category) => {
-      const names = {
-        'movie': '电影',
-        'tv': '电视剧',
-        'music': '音乐',
-        'software': '软件',
-        'game': '游戏'
-      }
-      return names[category] || category
-    }
-    
-    const getActivityType = (type) => {
-      const types = {
-        'upload': 'success',
-        'download': 'primary',
-        'post': 'warning',
-        'points': 'info'
-      }
-      return types[type] || 'primary'
-    }
-    
-    const getActivityIcon = (type) => {
-      const icons = {
-        'upload': 'Upload',
-        'download': 'Download',
-        'post': 'ChatDotRound',
-        'points': 'Coin'
-      }
-      return icons[type] || 'Star'
-    }
-    
-    const showInterestInput = () => {
-      interestInputVisible.value = true
-      nextTick(() => {
-        interestInputRef.value?.focus()
-      })
-    }
-    
-    const addInterest = () => {
-      const interest = interestInputValue.value.trim()
-      if (interest && !editProfile.interests.includes(interest)) {
-        editProfile.interests.push(interest)
-      }
-      interestInputVisible.value = false
-      interestInputValue.value = ''
-    }
-    
-    const removeInterest = (interest) => {
-      const index = editProfile.interests.indexOf(interest)
-      if (index > -1) {
-        editProfile.interests.splice(index, 1)
-      }
-    }
-    
-    const saveProfile = async () => {
-      try {
-        await profileFormRef.value?.validate()
-        
-        saving.value = true
-        
-        // 模拟保存过程
-        await new Promise(resolve => setTimeout(resolve, 1500))
-        
-        // 更新用户资料
-        Object.assign(userProfile.value, editProfile)
-        
-        ElMessage.success('个人资料保存成功')
-        
-      } catch (error) {
-        console.error('表单验证失败:', error)
-      } finally {
-        saving.value = false
-      }
-    }
-    
-    const resetProfile = () => {
-      loadUserProfile()
-      ElMessage.info('已重置为原始数据')
-    }
-    
-    const changePassword = async () => {
-      try {
-        await passwordFormRef.value?.validate()
-        
-        changingPassword.value = true
-        
-        // 模拟密码修改过程
-        await new Promise(resolve => setTimeout(resolve, 1500))
-        
-        // 重置表单
-        passwordFormRef.value?.resetFields()
-        Object.assign(passwordForm, {
-          currentPassword: '',
-          newPassword: '',
-          confirmPassword: ''
-        })
-        
-        ElMessage.success('密码修改成功')
-        
-      } catch (error) {
-        console.error('表单验证失败:', error)
-      } finally {
-        changingPassword.value = false
-      }
-    }
-    
-    const handleAvatarChange = (file) => {
-      const isImage = file.raw.type.startsWith('image/')
-      const isLt2M = file.raw.size / 1024 / 1024 < 2
-      
-      if (!isImage) {
-        ElMessage.error('只能上传图片文件!')
-        return false
-      }
-      if (!isLt2M) {
-        ElMessage.error('图片大小不能超过 2MB!')
-        return false
-      }
-      
-      return true
-    }
-    
-    const uploadAvatar = async () => {
-      const files = avatarUploadRef.value?.uploadFiles
-      if (!files || files.length === 0) {
-        ElMessage.warning('请选择头像文件')
-        return
-      }
-      
-      uploadingAvatar.value = true
-      try {
-        // 模拟上传过程
-        await new Promise(resolve => setTimeout(resolve, 2000))
-        
-        // 更新头像URL
-        userProfile.value.avatar = URL.createObjectURL(files[0].raw)
-        
-        ElMessage.success('头像上传成功')
-        showAvatarDialog.value = false
-        avatarUploadRef.value?.clearFiles()
-        
-      } catch (error) {
-        ElMessage.error('头像上传失败')
-      } finally {
-        uploadingAvatar.value = false
-      }
-    }
-    
-    return {
-      activeTab,
-      showAvatarDialog,
-      saving,
-      changingPassword,
-      uploadingAvatar,
-      interestInputVisible,
-      interestInputValue,
-      activityFilter,
-      torrentsPage,
-      userProfile,
-      editProfile,
-      passwordForm,
-      profileRules,
-      passwordRules,
-      locationOptions,
-      userTorrents,
-      filteredActivities,
-      loginHistory,
-      profileFormRef,
-      passwordFormRef,
-      avatarUploadRef,
-      interestInputRef,
-      formatDate,
-      formatTime,
-      formatDateTime,
-      getUserTitleType,
-      getRatioClass,
-      getCategoryType,
-      getCategoryName,
-      getActivityType,
-      getActivityIcon,
-      showInterestInput,
-      addInterest,
-      removeInterest,
-      saveProfile,
-      resetProfile,
-      changePassword,
-      handleAvatarChange,
-      uploadAvatar,
-      Calendar,
-      Clock,
-      Upload,
-      Download,
-      TrendCharts,
-      Star,
-      QuestionFilled,
-      Plus,
-      ChatDotRound,
-      Flag,
-      Coin
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.profile-page {
-  max-width: 1200px;
-  margin: 0 auto;
-  padding: 24px;
-  background: #f5f5f5;
-  min-height: 100vh;
-}
-
-.profile-header {
-  background: #fff;
-  border-radius: 12px;
-  padding: 32px;
-  margin-bottom: 24px;
-  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
-  
-  display: grid;
-  grid-template-columns: 1fr 1fr;
-  gap: 32px;
-  
-  .user-avatar-section {
-    display: flex;
-    gap: 24px;
-    
-    .avatar-container {
-      text-align: center;
-      
-      .change-avatar-btn {
-        margin-top: 12px;
-      }
-    }
-    
-    .user-basic-info {
-      flex: 1;
-      
-      .username {
-        font-size: 28px;
-        font-weight: 600;
-        color: #2c3e50;
-        margin: 0 0 12px 0;
-      }
-      
-      .user-title {
-        margin-bottom: 16px;
-      }
-      
-      .join-info, .last-login {
-        display: flex;
-        align-items: center;
-        gap: 8px;
-        font-size: 14px;
-        color: #7f8c8d;
-        margin-bottom: 8px;
-      }
-    }
-  }
-  
-  .user-stats-overview {
-    .stats-grid {
-      display: grid;
-      grid-template-columns: repeat(2, 1fr);
-      gap: 16px;
-      
-      .stat-card {
-        background: #f8f9fa;
-        border-radius: 8px;
-        padding: 20px;
-        display: flex;
-        align-items: center;
-        gap: 16px;
-        
-        .stat-icon {
-          width: 48px;
-          height: 48px;
-          border-radius: 50%;
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          
-          &.upload { background: rgba(103, 194, 58, 0.1); color: #67c23a; }
-          &.download { background: rgba(64, 158, 255, 0.1); color: #409eff; }
-          &.ratio {
-            &.excellent { background: rgba(103, 194, 58, 0.1); color: #67c23a; }
-            &.good { background: rgba(230, 162, 60, 0.1); color: #e6a23c; }
-            &.warning { background: rgba(245, 108, 108, 0.1); color: #f56c6c; }
-          }
-          &.points { background: rgba(245, 108, 108, 0.1); color: #f56c6c; }
-        }
-        
-        .stat-info {
-          h3 {
-            font-size: 20px;
-            font-weight: 600;
-            color: #2c3e50;
-            margin: 0 0 4px 0;
-          }
-          
-          p {
-            font-size: 14px;
-            color: #7f8c8d;
-            margin: 0;
-          }
-        }
-      }
-    }
-  }
-}
-
-.profile-content {
-  background: #fff;
-  border-radius: 12px;
-  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
-  
-  :deep(.el-tabs__content) {
-    padding: 24px;
-  }
-}
-
-.info-section {
-  .form-section {
-    margin-bottom: 32px;
-    
-    h3 {
-      font-size: 18px;
-      font-weight: 600;
-      color: #2c3e50;
-      margin: 0 0 20px 0;
-      padding-bottom: 8px;
-      border-bottom: 2px solid #f0f0f0;
-    }
-  }
-  
-  .interests-input {
-    display: flex;
-    flex-wrap: wrap;
-    gap: 8px;
-    align-items: center;
-    
-    .interest-tag {
-      margin: 0;
-    }
-  }
-  
-  .setting-tip {
-    margin-left: 12px;
-    font-size: 12px;
-    color: #909399;
-  }
-  
-  .form-actions {
-    text-align: center;
-    margin-top: 32px;
-    
-    .el-button {
-      margin: 0 8px;
-      min-width: 100px;
-    }
-  }
-}
-
-.stats-section {
-  .stats-overview {
-    margin-bottom: 32px;
-    
-    .overview-grid {
-      display: grid;
-      grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
-      gap: 20px;
-      
-      .overview-card {
-        background: #f8f9fa;
-        border-radius: 8px;
-        padding: 24px;
-        
-        h3 {
-          font-size: 16px;
-          font-weight: 600;
-          color: #2c3e50;
-          margin: 0 0 16px 0;
-        }
-        
-        .stat-details {
-          .detail-item {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            margin-bottom: 12px;
-            
-            .label {
-              font-size: 14px;
-              color: #7f8c8d;
-            }
-            
-            .value {
-              font-size: 14px;
-              font-weight: 600;
-              color: #2c3e50;
-            }
-          }
-        }
-      }
-    }
-  }
-  
-  .charts-section {
-    .chart-card {
-      background: #f8f9fa;
-      border-radius: 8px;
-      padding: 24px;
-      
-      h3 {
-        font-size: 16px;
-        font-weight: 600;
-        color: #2c3e50;
-        margin: 0 0 20px 0;
-      }
-      
-      .chart-placeholder {
-        text-align: center;
-        padding: 60px 0;
-        color: #909399;
-        
-        p {
-          margin: 12px 0 0 0;
-        }
-      }
-    }
-  }
-}
-
-.torrents-section {
-  .section-header {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    margin-bottom: 20px;
-    
-    h3 {
-      font-size: 18px;
-      font-weight: 600;
-      color: #2c3e50;
-      margin: 0;
-    }
-  }
-  
-  .torrent-info {
-    display: flex;
-    align-items: center;
-    gap: 12px;
-    
-    .torrent-title {
-      font-weight: 500;
-    }
-  }
-  
-  .pagination-wrapper {
-    margin-top: 16px;
-    text-align: center;
-  }
-}
-
-.activity-section {
-  .activity-filters {
-    margin-bottom: 24px;
-    
-    .el-select {
-      width: 150px;
-    }
-  }
-  
-  .activity-timeline {
-    .activity-content {
-      .activity-header {
-        display: flex;
-        align-items: center;
-        gap: 8px;
-        margin-bottom: 8px;
-        
-        .activity-title {
-          font-weight: 600;
-          color: #2c3e50;
-        }
-      }
-      
-      .activity-description {
-        font-size: 14px;
-        color: #7f8c8d;
-        line-height: 1.5;
-      }
-    }
-  }
-}
-
-.security-section {
-  .security-card {
-    background: #f8f9fa;
-    border-radius: 8px;
-    padding: 24px;
-    margin-bottom: 24px;
-    
-    h3 {
-      font-size: 18px;
-      font-weight: 600;
-      color: #2c3e50;
-      margin: 0 0 20px 0;
-    }
-  }
-}
-
-.avatar-upload {
-  text-align: center;
-  
-  .avatar-uploader {
-    margin-bottom: 16px;
-  }
-  
-  .upload-tips {
-    font-size: 12px;
-    color: #909399;
-    
-    p {
-      margin: 4px 0;
-    }
-  }
-}
-
-@media (max-width: 768px) {
-  .profile-page {
-    padding: 16px;
-  }
-  
-  .profile-header {
-    grid-template-columns: 1fr;
-    gap: 24px;
-    
-    .user-avatar-section {
-      flex-direction: column;
-      text-align: center;
-    }
-    
-    .user-stats-overview .stats-grid {
-      grid-template-columns: 1fr;
-    }
-  }
-  
-  .stats-overview .overview-grid {
-    grid-template-columns: 1fr;
-  }
-  
-  .torrents-section .section-header {
-    flex-direction: column;
-    gap: 16px;
-    align-items: flex-start;
-  }
-}
+<template>

+  <div class="profile-page">

+    <div class="page-container">

+      <!-- 个人信息卡片 -->

+      <div class="profile-header">

+        <div class="user-avatar-section">

+          <div class="avatar-container">

+            <el-avatar :size="120" :src="userProfile.avatar">

+              {{ userProfile.username.charAt(0).toUpperCase() }}

+            </el-avatar>

+            <el-button 

+              type="primary" 

+              size="small" 

+              class="change-avatar-btn"

+              @click="showAvatarDialog = true"

+            >

+              更换头像

+            </el-button>

+          </div>

+          

+          <div class="user-basic-info">

+            <h1 class="username">{{ userProfile.username }}</h1>

+            <div class="user-title">

+              <el-tag :type="getUserTitleType(userProfile.userLevel)" size="large">

+                {{ userProfile.userTitle }}

+              </el-tag>

+            </div>

+            <div class="join-info">

+              <el-icon><Calendar /></el-icon>

+              <span>加入时间:{{ formatDate(userProfile.joinDate) }}</span>

+            </div>

+            <div class="last-login">

+              <el-icon><Clock /></el-icon>

+              <span>最后登录:{{ formatTime(userProfile.lastLogin) }}</span>

+            </div>

+          </div>

+        </div>

+        

+        <div class="user-stats-overview">

+          <div class="stats-grid">

+            <div class="stat-card">

+              <div class="stat-icon upload">

+                <el-icon size="32"><Upload /></el-icon>

+              </div>

+              <div class="stat-info">

+                <h3>{{ userProfile.stats.uploaded }}</h3>

+                <p>上传量</p>

+              </div>

+            </div>

+            

+            <div class="stat-card">

+              <div class="stat-icon download">

+                <el-icon size="32"><Download /></el-icon>

+              </div>

+              <div class="stat-info">

+                <h3>{{ userProfile.stats.downloaded }}</h3>

+                <p>下载量</p>

+              </div>

+            </div>

+            

+            <div class="stat-card">

+              <div class="stat-icon ratio" :class="getRatioClass(userProfile.stats.ratio)">

+                <el-icon size="32"><TrendCharts /></el-icon>

+              </div>

+              <div class="stat-info">

+                <h3>{{ userProfile.stats.ratio }}</h3>

+                <p>分享率</p>

+              </div>

+            </div>

+            

+            <div class="stat-card">

+              <div class="stat-icon points">

+                <el-icon size="32"><Star /></el-icon>

+              </div>

+              <div class="stat-info">

+                <h3>{{ userProfile.stats.points }}</h3>

+                <p>积分</p>

+              </div>

+            </div>

+          </div>

+        </div>

+      </div>

+

+      <!-- 详细信息选项卡 -->

+      <div class="profile-content">

+        <el-tabs v-model="activeTab" type="border-card">

+          <!-- 个人信息 -->

+          <el-tab-pane label="个人信息" name="info">

+            <div class="info-section">

+              <el-form

+                ref="profileFormRef"

+                :model="editProfile"

+                :rules="profileRules"

+                label-width="120px"

+                size="large"

+              >

+                <div class="form-section">

+                  <h3>基本信息</h3>

+                  <el-form-item label="用户名">

+                    <el-input v-model="editProfile.username" disabled>

+                      <template #suffix>

+                        <el-tooltip content="用户名不可修改">

+                          <el-icon><QuestionFilled /></el-icon>

+                        </el-tooltip>

+                      </template>

+                    </el-input>

+                  </el-form-item>

+                  

+                  <el-form-item label="邮箱地址" prop="email">

+                    <el-input v-model="editProfile.email" type="email" />

+                  </el-form-item>

+                  

+                  <el-form-item label="真实姓名" prop="realName">

+                    <el-input v-model="editProfile.realName" placeholder="可选填写" />

+                  </el-form-item>

+                  

+                  <el-form-item label="所在地区">

+                    <el-cascader

+                      v-model="editProfile.location"

+                      :options="locationOptions"

+                      placeholder="请选择地区"

+                      clearable

+                    />

+                  </el-form-item>

+                </div>

+                

+                <div class="form-section">

+                  <h3>个人介绍</h3>

+                  <el-form-item label="个人签名">

+                    <el-input

+                      v-model="editProfile.signature"

+                      type="textarea"

+                      :rows="3"

+                      maxlength="200"

+                      show-word-limit

+                      placeholder="介绍一下自己吧..."

+                    />

+                  </el-form-item>

+                  

+                  <el-form-item label="个人网站">

+                    <el-input v-model="editProfile.website" placeholder="https://" />

+                  </el-form-item>

+                  

+                  <el-form-item label="兴趣爱好">

+                    <div class="interests-input">

+                      <el-tag

+                        v-for="interest in editProfile.interests"

+                        :key="interest"

+                        closable

+                        @close="removeInterest(interest)"

+                        class="interest-tag"

+                      >

+                        {{ interest }}

+                      </el-tag>

+                      <el-input

+                        v-if="interestInputVisible"

+                        ref="interestInputRef"

+                        v-model="interestInputValue"

+                        size="small"

+                        @keyup.enter="addInterest"

+                        @blur="addInterest"

+                        style="width: 120px;"

+                      />

+                      <el-button

+                        v-else

+                        size="small"

+                        @click="showInterestInput"

+                      >

+                        + 添加兴趣

+                      </el-button>

+                    </div>

+                  </el-form-item>

+                </div>

+                

+                <div class="form-section">

+                  <h3>隐私设置</h3>

+                  <el-form-item label="邮箱公开">

+                    <el-switch v-model="editProfile.emailPublic" />

+                    <span class="setting-tip">是否在个人资料中显示邮箱</span>

+                  </el-form-item>

+                  

+                  <el-form-item label="统计公开">

+                    <el-switch v-model="editProfile.statsPublic" />

+                    <span class="setting-tip">是否公开上传下载统计</span>

+                  </el-form-item>

+                  

+                  <el-form-item label="活动记录">

+                    <el-switch v-model="editProfile.activityPublic" />

+                    <span class="setting-tip">是否公开活动记录</span>

+                  </el-form-item>

+                </div>

+                

+                <div class="form-actions">

+                  <el-button @click="resetProfile">重置</el-button>

+                  <el-button type="primary" @click="saveProfile" :loading="saving">

+                    保存修改

+                  </el-button>

+                </div>

+              </el-form>

+            </div>

+          </el-tab-pane>

+          

+          <!-- 数据统计 -->

+          <el-tab-pane label="数据统计" name="stats">

+            <div class="stats-section">

+              <div class="stats-overview">

+                <div class="overview-grid">

+                  <div class="overview-card">

+                    <h3>上传统计</h3>

+                    <div class="stat-details">

+                      <div class="detail-item">

+                        <span class="label">总上传量:</span>

+                        <span class="value">{{ userProfile.detailedStats.totalUploaded }}</span>

+                      </div>

+                      <div class="detail-item">

+                        <span class="label">上传种子:</span>

+                        <span class="value">{{ userProfile.detailedStats.uploadedTorrents }} 个</span>

+                      </div>

+                      <div class="detail-item">

+                        <span class="label">平均大小:</span>

+                        <span class="value">{{ userProfile.detailedStats.avgUploadSize }}</span>

+                      </div>

+                    </div>

+                  </div>

+                  

+                  <div class="overview-card">

+                    <h3>下载统计</h3>

+                    <div class="stat-details">

+                      <div class="detail-item">

+                        <span class="label">总下载量:</span>

+                        <span class="value">{{ userProfile.detailedStats.totalDownloaded }}</span>

+                      </div>

+                      <div class="detail-item">

+                        <span class="label">下载种子:</span>

+                        <span class="value">{{ userProfile.detailedStats.downloadedTorrents }} 个</span>

+                      </div>

+                      <div class="detail-item">

+                        <span class="label">完成种子:</span>

+                        <span class="value">{{ userProfile.detailedStats.completedTorrents }} 个</span>

+                      </div>

+                    </div>

+                  </div>

+                  

+                  <div class="overview-card">

+                    <h3>做种统计</h3>

+                    <div class="stat-details">

+                      <div class="detail-item">

+                        <span class="label">正在做种:</span>

+                        <span class="value">{{ userProfile.detailedStats.seeding }} 个</span>

+                      </div>

+                      <div class="detail-item">

+                        <span class="label">做种时间:</span>

+                        <span class="value">{{ userProfile.detailedStats.seedingTime }}</span>

+                      </div>

+                      <div class="detail-item">

+                        <span class="label">做种排名:</span>

+                        <span class="value">第 {{ userProfile.detailedStats.seedingRank }} 名</span>

+                      </div>

+                    </div>

+                  </div>

+                  

+                  <div class="overview-card">

+                    <h3>积分记录</h3>

+                    <div class="stat-details">

+                      <div class="detail-item">

+                        <span class="label">当前积分:</span>

+                        <span class="value">{{ userProfile.stats.points }}</span>

+                      </div>

+                      <div class="detail-item">

+                        <span class="label">累计获得:</span>

+                        <span class="value">{{ userProfile.detailedStats.totalEarnedPoints }}</span>

+                      </div>

+                      <div class="detail-item">

+                        <span class="label">累计消费:</span>

+                        <span class="value">{{ userProfile.detailedStats.totalSpentPoints }}</span>

+                      </div>

+                    </div>

+                  </div>

+                </div>

+              </div>

+              

+              <!-- 数据图表 -->

+              <div class="charts-section">

+                <div class="chart-card">

+                  <h3>上传下载趋势</h3>

+                  <div class="chart-placeholder">

+                    <el-icon size="48" color="#e4e7ed"><TrendCharts /></el-icon>

+                    <p>图表功能开发中...</p>

+                  </div>

+                </div>

+              </div>

+            </div>

+          </el-tab-pane>

+          

+          <!-- 我的种子 -->

+          <el-tab-pane label="我的种子" name="torrents">

+            <div class="torrents-section">

+              <div class="section-header">

+                <h3>我上传的种子</h3>

+                <el-button type="primary" :icon="Upload" @click="$router.push('/upload')">

+                  上传新种子

+                </el-button>

+              </div>

+              

+              <el-table :data="userTorrents" stripe>

+                <el-table-column label="种子名称" min-width="300">

+                  <template #default="{ row }">

+                    <div class="torrent-info">

+                      <el-tag :type="getCategoryType(row.category)" size="small">

+                        {{ getCategoryName(row.category) }}

+                      </el-tag>

+                      <span class="torrent-title">{{ row.title }}</span>

+                    </div>

+                  </template>

+                </el-table-column>

+                

+                <el-table-column label="大小" prop="size" width="100" />

+                <el-table-column label="做种" prop="seeders" width="80" align="center" />

+                <el-table-column label="下载" prop="leechers" width="80" align="center" />

+                <el-table-column label="完成" prop="downloads" width="80" align="center" />

+                <el-table-column label="上传时间" width="120">

+                  <template #default="{ row }">

+                    {{ formatDate(row.uploadTime) }}

+                  </template>

+                </el-table-column>

+                

+                <el-table-column label="操作" width="120" align="center">

+                  <template #default="{ row }">

+                    <el-button 

+                      type="primary" 

+                      size="small" 

+                      @click="$router.push(`/torrent/${row.id}`)"

+                    >

+                      查看

+                    </el-button>

+                  </template>

+                </el-table-column>

+              </el-table>

+              

+              <div class="pagination-wrapper">

+                <el-pagination

+                  v-model:current-page="torrentsPage"

+                  :page-size="10"

+                  :total="userTorrents.length"

+                  layout="prev, pager, next"

+                  small

+                />

+              </div>

+            </div>

+          </el-tab-pane>

+          

+          <!-- 活动记录 -->

+          <el-tab-pane label="活动记录" name="activity">

+            <div class="activity-section">

+              <div class="activity-filters">

+                <el-select v-model="activityFilter" placeholder="活动类型">

+                  <el-option label="全部活动" value="" />

+                  <el-option label="上传种子" value="upload" />

+                  <el-option label="下载种子" value="download" />

+                  <el-option label="论坛发帖" value="post" />

+                  <el-option label="积分变动" value="points" />

+                </el-select>

+              </div>

+              

+              <div class="activity-timeline">

+                <el-timeline>

+                  <el-timeline-item

+                    v-for="activity in filteredActivities"

+                    :key="activity.id"

+                    :timestamp="formatTime(activity.time)"

+                    :type="getActivityType(activity.type)"

+                  >

+                    <div class="activity-content">

+                      <div class="activity-header">

+                        <el-icon>

+                          <component :is="getActivityIcon(activity.type)" />

+                        </el-icon>

+                        <span class="activity-title">{{ activity.title }}</span>

+                      </div>

+                      <div class="activity-description">{{ activity.description }}</div>

+                    </div>

+                  </el-timeline-item>

+                </el-timeline>

+              </div>

+            </div>

+          </el-tab-pane>

+          

+          <!-- 安全设置 -->

+          <el-tab-pane label="安全设置" name="security">

+            <div class="security-section">

+              <div class="security-card">

+                <h3>修改密码</h3>

+                <el-form

+                  ref="passwordFormRef"

+                  :model="passwordForm"

+                  :rules="passwordRules"

+                  label-width="120px"

+                >

+                  <el-form-item label="当前密码" prop="currentPassword">

+                    <el-input

+                      v-model="passwordForm.currentPassword"

+                      type="password"

+                      show-password

+                      placeholder="请输入当前密码"

+                    />

+                  </el-form-item>

+                  

+                  <el-form-item label="新密码" prop="newPassword">

+                    <el-input

+                      v-model="passwordForm.newPassword"

+                      type="password"

+                      show-password

+                      placeholder="请输入新密码"

+                    />

+                  </el-form-item>

+                  

+                  <el-form-item label="确认密码" prop="confirmPassword">

+                    <el-input

+                      v-model="passwordForm.confirmPassword"

+                      type="password"

+                      show-password

+                      placeholder="请再次输入新密码"

+                    />

+                  </el-form-item>

+                  

+                  <el-form-item>

+                    <el-button type="primary" @click="changePassword" :loading="changingPassword">

+                      修改密码

+                    </el-button>

+                  </el-form-item>

+                </el-form>

+              </div>

+              

+              <div class="security-card">

+                <h3>登录记录</h3>

+                <el-table :data="loginHistory" stripe>

+                  <el-table-column label="登录时间" width="180">

+                    <template #default="{ row }">

+                      {{ formatDateTime(row.time) }}

+                    </template>

+                  </el-table-column>

+                  <el-table-column label="IP地址" prop="ip" width="150" />

+                  <el-table-column label="设备信息" prop="device" />

+                  <el-table-column label="登录结果" width="100">

+                    <template #default="{ row }">

+                      <el-tag :type="row.success ? 'success' : 'danger'" size="small">

+                        {{ row.success ? '成功' : '失败' }}

+                      </el-tag>

+                    </template>

+                  </el-table-column>

+                </el-table>

+              </div>

+            </div>

+          </el-tab-pane>

+        </el-tabs>

+      </div>

+    </div>

+

+    <!-- 更换头像对话框 -->

+    <el-dialog v-model="showAvatarDialog" title="更换头像" width="400px">

+      <div class="avatar-upload">

+        <el-upload

+          ref="avatarUploadRef"

+          :auto-upload="false"

+          :limit="1"

+          accept="image/*"

+          :on-change="handleAvatarChange"

+          list-type="picture-card"

+          class="avatar-uploader"

+        >

+          <el-icon><Plus /></el-icon>

+        </el-upload>

+        <div class="upload-tips">

+          <p>支持 JPG、PNG 格式</p>

+          <p>建议尺寸 200x200 像素</p>

+          <p>文件大小不超过 2MB</p>

+        </div>

+      </div>

+      

+      <template #footer>

+        <el-button @click="showAvatarDialog = false">取消</el-button>

+        <el-button type="primary" @click="uploadAvatar" :loading="uploadingAvatar">

+          上传头像

+        </el-button>

+      </template>

+    </el-dialog>

+  </div>

+</template>

+

+<script>

+import { ref, reactive, computed, onMounted, nextTick } from 'vue'

+import { useRouter } from 'vue-router'

+import { ElMessage } from 'element-plus'

+import {

+  Calendar,

+  Clock,

+  Upload,

+  Download,

+  TrendCharts,

+  Star,

+  QuestionFilled,

+  Plus,

+  ChatDotRound,

+  Flag,

+  Coin

+} from '@element-plus/icons-vue'

+

+export default {

+  name: 'ProfileView',

+  setup() {

+    const router = useRouter()

+    const profileFormRef = ref(null)

+    const passwordFormRef = ref(null)

+    const avatarUploadRef = ref(null)

+    const interestInputRef = ref(null)

+    

+    const activeTab = ref('info')

+    const showAvatarDialog = ref(false)

+    const saving = ref(false)

+    const changingPassword = ref(false)

+    const uploadingAvatar = ref(false)

+    const interestInputVisible = ref(false)

+    const interestInputValue = ref('')

+    const activityFilter = ref('')

+    const torrentsPage = ref(1)

+    

+    const userProfile = ref({

+      username: 'MovieExpert',

+      email: 'movieexpert@example.com',

+      realName: '',

+      avatar: '',

+      userLevel: 5,

+      userTitle: '资深会员',

+      joinDate: '2023-01-15T10:00:00',

+      lastLogin: '2025-06-03T14:30:00',

+      location: ['北京市', '朝阳区'],

+      signature: '热爱电影,分享快乐!',

+      website: 'https://movieblog.com',

+      interests: ['电影', '音乐', '科技', '摄影'],

+      emailPublic: false,

+      statsPublic: true,

+      activityPublic: true,

+      stats: {

+        uploaded: '256.8 GB',

+        downloaded: '89.6 GB',

+        ratio: '2.87',

+        points: '15,680'

+      },

+      detailedStats: {

+        totalUploaded: '256.8 GB',

+        uploadedTorrents: 45,

+        avgUploadSize: '5.7 GB',

+        totalDownloaded: '89.6 GB',

+        downloadedTorrents: 123,

+        completedTorrents: 118,

+        seeding: 32,

+        seedingTime: '1,245 小时',

+        seedingRank: 86,

+        totalEarnedPoints: '28,940',

+        totalSpentPoints: '13,260'

+      }

+    })

+    

+    const editProfile = reactive({

+      username: '',

+      email: '',

+      realName: '',

+      location: [],

+      signature: '',

+      website: '',

+      interests: [],

+      emailPublic: false,

+      statsPublic: true,

+      activityPublic: true

+    })

+    

+    const passwordForm = reactive({

+      currentPassword: '',

+      newPassword: '',

+      confirmPassword: ''

+    })

+    

+    const profileRules = {

+      email: [

+        { required: true, message: '请输入邮箱地址', trigger: 'blur' },

+        { type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }

+      ]

+    }

+    

+    const passwordRules = {

+      currentPassword: [

+        { required: true, message: '请输入当前密码', trigger: 'blur' }

+      ],

+      newPassword: [

+        { required: true, message: '请输入新密码', trigger: 'blur' },

+        { min: 6, message: '密码长度至少6个字符', trigger: 'blur' }

+      ],

+      confirmPassword: [

+        { required: true, message: '请确认新密码', trigger: 'blur' },

+        {

+          validator: (rule, value, callback) => {

+            if (value !== passwordForm.newPassword) {

+              callback(new Error('两次输入的密码不一致'))

+            } else {

+              callback()

+            }

+          },

+          trigger: 'blur'

+        }

+      ]

+    }

+    

+    const locationOptions = [

+      {

+        value: '北京市',

+        label: '北京市',

+        children: [

+          { value: '朝阳区', label: '朝阳区' },

+          { value: '海淀区', label: '海淀区' },

+          { value: '丰台区', label: '丰台区' }

+        ]

+      },

+      {

+        value: '上海市',

+        label: '上海市',

+        children: [

+          { value: '浦东新区', label: '浦东新区' },

+          { value: '黄浦区', label: '黄浦区' },

+          { value: '静安区', label: '静安区' }

+        ]

+      }

+    ]

+    

+    const userTorrents = ref([

+      {

+        id: 1,

+        title: '[4K蓝光原盘] 阿凡达:水之道',

+        category: 'movie',

+        size: '85.6 GB',

+        seeders: 45,

+        leechers: 12,

+        downloads: 234,

+        uploadTime: '2025-05-15T10:00:00'

+      },

+      {

+        id: 2,

+        title: '[FLAC] 古典音乐合集',

+        category: 'music',

+        size: '2.3 GB',

+        seeders: 23,

+        leechers: 5,

+        downloads: 89,

+        uploadTime: '2025-04-20T15:30:00'

+      }

+    ])

+    

+    const activities = ref([

+      {

+        id: 1,

+        type: 'upload',

+        title: '上传种子',

+        description: '上传了《阿凡达:水之道》4K蓝光原盘',

+        time: '2025-06-03T10:30:00'

+      },

+      {

+        id: 2,

+        type: 'download',

+        title: '下载种子',

+        description: '下载了《星际穿越》IMAX版本',

+        time: '2025-06-02T14:20:00'

+      },

+      {

+        id: 3,

+        type: 'post',

+        title: '发布主题',

+        description: '在电影讨论区发布了新主题',

+        time: '2025-06-01T16:45:00'

+      },

+      {

+        id: 4,

+        type: 'points',

+        title: '积分变动',

+        description: '做种奖励获得 +50 积分',

+        time: '2025-05-31T09:15:00'

+      }

+    ])

+    

+    const loginHistory = ref([

+      {

+        time: '2025-06-03T14:30:00',

+        ip: '192.168.1.100',

+        device: 'Windows 11 / Chrome 120',

+        success: true

+      },

+      {

+        time: '2025-06-02T09:15:00',

+        ip: '192.168.1.100',

+        device: 'Windows 11 / Chrome 120',

+        success: true

+      },

+      {

+        time: '2025-06-01T22:30:00',

+        ip: '192.168.1.100',

+        device: 'Android / Chrome Mobile',

+        success: true

+      }

+    ])

+    

+    const filteredActivities = computed(() => {

+      if (!activityFilter.value) return activities.value

+      return activities.value.filter(activity => activity.type === activityFilter.value)

+    })

+    

+    onMounted(() => {

+      loadUserProfile()

+    })

+    

+    const loadUserProfile = () => {

+      // 加载用户资料到编辑表单

+      Object.assign(editProfile, {

+        username: userProfile.value.username,

+        email: userProfile.value.email,

+        realName: userProfile.value.realName,

+        location: userProfile.value.location,

+        signature: userProfile.value.signature,

+        website: userProfile.value.website,

+        interests: [...userProfile.value.interests],

+        emailPublic: userProfile.value.emailPublic,

+        statsPublic: userProfile.value.statsPublic,

+        activityPublic: userProfile.value.activityPublic

+      })

+    }

+    

+    const formatDate = (dateString) => {

+      const date = new Date(dateString)

+      return date.toLocaleDateString('zh-CN')

+    }

+    

+    const formatTime = (timeString) => {

+      const date = new Date(timeString)

+      const now = new Date()

+      const diff = now - date

+      const hours = Math.floor(diff / (1000 * 60 * 60))

+      

+      if (hours < 1) return '刚刚'

+      if (hours < 24) return `${hours}小时前`

+      const days = Math.floor(hours / 24)

+      if (days < 7) return `${days}天前`

+      

+      return date.toLocaleDateString('zh-CN')

+    }

+    

+    const formatDateTime = (dateString) => {

+      const date = new Date(dateString)

+      return date.toLocaleString('zh-CN')

+    }

+    

+    const getUserTitleType = (level) => {

+      if (level >= 8) return 'danger'  // 管理员

+      if (level >= 6) return 'warning' // 资深会员

+      if (level >= 4) return 'success' // 正式会员

+      if (level >= 2) return 'info'    // 初级会员

+      return 'default' // 新手

+    }

+    

+    const getRatioClass = (ratio) => {

+      const r = parseFloat(ratio)

+      if (r >= 2) return 'excellent'

+      if (r >= 1) return 'good'

+      return 'warning'

+    }

+    

+    const getCategoryType = (category) => {

+      const types = {

+        'movie': 'primary',

+        'tv': 'info',

+        'music': 'success',

+        'software': 'warning',

+        'game': 'danger'

+      }

+      return types[category] || 'default'

+    }

+    

+    const getCategoryName = (category) => {

+      const names = {

+        'movie': '电影',

+        'tv': '电视剧',

+        'music': '音乐',

+        'software': '软件',

+        'game': '游戏'

+      }

+      return names[category] || category

+    }

+    

+    const getActivityType = (type) => {

+      const types = {

+        'upload': 'success',

+        'download': 'primary',

+        'post': 'warning',

+        'points': 'info'

+      }

+      return types[type] || 'primary'

+    }

+    

+    const getActivityIcon = (type) => {

+      const icons = {

+        'upload': 'Upload',

+        'download': 'Download',

+        'post': 'ChatDotRound',

+        'points': 'Coin'

+      }

+      return icons[type] || 'Star'

+    }

+    

+    const showInterestInput = () => {

+      interestInputVisible.value = true

+      nextTick(() => {

+        interestInputRef.value?.focus()

+      })

+    }

+    

+    const addInterest = () => {

+      const interest = interestInputValue.value.trim()

+      if (interest && !editProfile.interests.includes(interest)) {

+        editProfile.interests.push(interest)

+      }

+      interestInputVisible.value = false

+      interestInputValue.value = ''

+    }

+    

+    const removeInterest = (interest) => {

+      const index = editProfile.interests.indexOf(interest)

+      if (index > -1) {

+        editProfile.interests.splice(index, 1)

+      }

+    }

+    

+    const saveProfile = async () => {

+      try {

+        await profileFormRef.value?.validate()

+        

+        saving.value = true

+        

+        // 模拟保存过程

+        await new Promise(resolve => setTimeout(resolve, 1500))

+        

+        // 更新用户资料

+        Object.assign(userProfile.value, editProfile)

+        

+        ElMessage.success('个人资料保存成功')

+        

+      } catch (error) {

+        console.error('表单验证失败:', error)

+      } finally {

+        saving.value = false

+      }

+    }

+    

+    const resetProfile = () => {

+      loadUserProfile()

+      ElMessage.info('已重置为原始数据')

+    }

+    

+    const changePassword = async () => {

+      try {

+        await passwordFormRef.value?.validate()

+        

+        changingPassword.value = true

+        

+        // 模拟密码修改过程

+        await new Promise(resolve => setTimeout(resolve, 1500))

+        

+        // 重置表单

+        passwordFormRef.value?.resetFields()

+        Object.assign(passwordForm, {

+          currentPassword: '',

+          newPassword: '',

+          confirmPassword: ''

+        })

+        

+        ElMessage.success('密码修改成功')

+        

+      } catch (error) {

+        console.error('表单验证失败:', error)

+      } finally {

+        changingPassword.value = false

+      }

+    }

+    

+    const handleAvatarChange = (file) => {

+      const isImage = file.raw.type.startsWith('image/')

+      const isLt2M = file.raw.size / 1024 / 1024 < 2

+      

+      if (!isImage) {

+        ElMessage.error('只能上传图片文件!')

+        return false

+      }

+      if (!isLt2M) {

+        ElMessage.error('图片大小不能超过 2MB!')

+        return false

+      }

+      

+      return true

+    }

+    

+    const uploadAvatar = async () => {

+      const files = avatarUploadRef.value?.uploadFiles

+      if (!files || files.length === 0) {

+        ElMessage.warning('请选择头像文件')

+        return

+      }

+      

+      uploadingAvatar.value = true

+      try {

+        // 模拟上传过程

+        await new Promise(resolve => setTimeout(resolve, 2000))

+        

+        // 更新头像URL

+        userProfile.value.avatar = URL.createObjectURL(files[0].raw)

+        

+        ElMessage.success('头像上传成功')

+        showAvatarDialog.value = false

+        avatarUploadRef.value?.clearFiles()

+        

+      } catch (error) {

+        ElMessage.error('头像上传失败')

+      } finally {

+        uploadingAvatar.value = false

+      }

+    }

+    

+    return {

+      activeTab,

+      showAvatarDialog,

+      saving,

+      changingPassword,

+      uploadingAvatar,

+      interestInputVisible,

+      interestInputValue,

+      activityFilter,

+      torrentsPage,

+      userProfile,

+      editProfile,

+      passwordForm,

+      profileRules,

+      passwordRules,

+      locationOptions,

+      userTorrents,

+      filteredActivities,

+      loginHistory,

+      profileFormRef,

+      passwordFormRef,

+      avatarUploadRef,

+      interestInputRef,

+      formatDate,

+      formatTime,

+      formatDateTime,

+      getUserTitleType,

+      getRatioClass,

+      getCategoryType,

+      getCategoryName,

+      getActivityType,

+      getActivityIcon,

+      showInterestInput,

+      addInterest,

+      removeInterest,

+      saveProfile,

+      resetProfile,

+      changePassword,

+      handleAvatarChange,

+      uploadAvatar,

+      Calendar,

+      Clock,

+      Upload,

+      Download,

+      TrendCharts,

+      Star,

+      QuestionFilled,

+      Plus,

+      ChatDotRound,

+      Flag,

+      Coin

+    }

+  }

+}

+</script>

+

+<style lang="scss" scoped>

+.profile-page {

+  max-width: 1200px;

+  margin: 0 auto;

+  padding: 24px;

+  background: #f5f5f5;

+  min-height: 100vh;

+}

+

+.profile-header {

+  background: #fff;

+  border-radius: 12px;

+  padding: 32px;

+  margin-bottom: 24px;

+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);

+  

+  display: grid;

+  grid-template-columns: 1fr 1fr;

+  gap: 32px;

+  

+  .user-avatar-section {

+    display: flex;

+    gap: 24px;

+    

+    .avatar-container {

+      text-align: center;

+      

+      .change-avatar-btn {

+        margin-top: 12px;

+      }

+    }

+    

+    .user-basic-info {

+      flex: 1;

+      

+      .username {

+        font-size: 28px;

+        font-weight: 600;

+        color: #2c3e50;

+        margin: 0 0 12px 0;

+      }

+      

+      .user-title {

+        margin-bottom: 16px;

+      }

+      

+      .join-info, .last-login {

+        display: flex;

+        align-items: center;

+        gap: 8px;

+        font-size: 14px;

+        color: #7f8c8d;

+        margin-bottom: 8px;

+      }

+    }

+  }

+  

+  .user-stats-overview {

+    .stats-grid {

+      display: grid;

+      grid-template-columns: repeat(2, 1fr);

+      gap: 16px;

+      

+      .stat-card {

+        background: #f8f9fa;

+        border-radius: 8px;

+        padding: 20px;

+        display: flex;

+        align-items: center;

+        gap: 16px;

+        

+        .stat-icon {

+          width: 48px;

+          height: 48px;

+          border-radius: 50%;

+          display: flex;

+          align-items: center;

+          justify-content: center;

+          

+          &.upload { background: rgba(103, 194, 58, 0.1); color: #67c23a; }

+          &.download { background: rgba(64, 158, 255, 0.1); color: #409eff; }

+          &.ratio {

+            &.excellent { background: rgba(103, 194, 58, 0.1); color: #67c23a; }

+            &.good { background: rgba(230, 162, 60, 0.1); color: #e6a23c; }

+            &.warning { background: rgba(245, 108, 108, 0.1); color: #f56c6c; }

+          }

+          &.points { background: rgba(245, 108, 108, 0.1); color: #f56c6c; }

+        }

+        

+        .stat-info {

+          h3 {

+            font-size: 20px;

+            font-weight: 600;

+            color: #2c3e50;

+            margin: 0 0 4px 0;

+          }

+          

+          p {

+            font-size: 14px;

+            color: #7f8c8d;

+            margin: 0;

+          }

+        }

+      }

+    }

+  }

+}

+

+.profile-content {

+  background: #fff;

+  border-radius: 12px;

+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);

+  

+  :deep(.el-tabs__content) {

+    padding: 24px;

+  }

+}

+

+.info-section {

+  .form-section {

+    margin-bottom: 32px;

+    

+    h3 {

+      font-size: 18px;

+      font-weight: 600;

+      color: #2c3e50;

+      margin: 0 0 20px 0;

+      padding-bottom: 8px;

+      border-bottom: 2px solid #f0f0f0;

+    }

+  }

+  

+  .interests-input {

+    display: flex;

+    flex-wrap: wrap;

+    gap: 8px;

+    align-items: center;

+    

+    .interest-tag {

+      margin: 0;

+    }

+  }

+  

+  .setting-tip {

+    margin-left: 12px;

+    font-size: 12px;

+    color: #909399;

+  }

+  

+  .form-actions {

+    text-align: center;

+    margin-top: 32px;

+    

+    .el-button {

+      margin: 0 8px;

+      min-width: 100px;

+    }

+  }

+}

+

+.stats-section {

+  .stats-overview {

+    margin-bottom: 32px;

+    

+    .overview-grid {

+      display: grid;

+      grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));

+      gap: 20px;

+      

+      .overview-card {

+        background: #f8f9fa;

+        border-radius: 8px;

+        padding: 24px;

+        

+        h3 {

+          font-size: 16px;

+          font-weight: 600;

+          color: #2c3e50;

+          margin: 0 0 16px 0;

+        }

+        

+        .stat-details {

+          .detail-item {

+            display: flex;

+            justify-content: space-between;

+            align-items: center;

+            margin-bottom: 12px;

+            

+            .label {

+              font-size: 14px;

+              color: #7f8c8d;

+            }

+            

+            .value {

+              font-size: 14px;

+              font-weight: 600;

+              color: #2c3e50;

+            }

+          }

+        }

+      }

+    }

+  }

+  

+  .charts-section {

+    .chart-card {

+      background: #f8f9fa;

+      border-radius: 8px;

+      padding: 24px;

+      

+      h3 {

+        font-size: 16px;

+        font-weight: 600;

+        color: #2c3e50;

+        margin: 0 0 20px 0;

+      }

+      

+      .chart-placeholder {

+        text-align: center;

+        padding: 60px 0;

+        color: #909399;

+        

+        p {

+          margin: 12px 0 0 0;

+        }

+      }

+    }

+  }

+}

+

+.torrents-section {

+  .section-header {

+    display: flex;

+    justify-content: space-between;

+    align-items: center;

+    margin-bottom: 20px;

+    

+    h3 {

+      font-size: 18px;

+      font-weight: 600;

+      color: #2c3e50;

+      margin: 0;

+    }

+  }

+  

+  .torrent-info {

+    display: flex;

+    align-items: center;

+    gap: 12px;

+    

+    .torrent-title {

+      font-weight: 500;

+    }

+  }

+  

+  .pagination-wrapper {

+    margin-top: 16px;

+    text-align: center;

+  }

+}

+

+.activity-section {

+  .activity-filters {

+    margin-bottom: 24px;

+    

+    .el-select {

+      width: 150px;

+    }

+  }

+  

+  .activity-timeline {

+    .activity-content {

+      .activity-header {

+        display: flex;

+        align-items: center;

+        gap: 8px;

+        margin-bottom: 8px;

+        

+        .activity-title {

+          font-weight: 600;

+          color: #2c3e50;

+        }

+      }

+      

+      .activity-description {

+        font-size: 14px;

+        color: #7f8c8d;

+        line-height: 1.5;

+      }

+    }

+  }

+}

+

+.security-section {

+  .security-card {

+    background: #f8f9fa;

+    border-radius: 8px;

+    padding: 24px;

+    margin-bottom: 24px;

+    

+    h3 {

+      font-size: 18px;

+      font-weight: 600;

+      color: #2c3e50;

+      margin: 0 0 20px 0;

+    }

+  }

+}

+

+.avatar-upload {

+  text-align: center;

+  

+  .avatar-uploader {

+    margin-bottom: 16px;

+  }

+  

+  .upload-tips {

+    font-size: 12px;

+    color: #909399;

+    

+    p {

+      margin: 4px 0;

+    }

+  }

+}

+

+@media (max-width: 768px) {

+  .profile-page {

+    padding: 16px;

+  }

+  

+  .profile-header {

+    grid-template-columns: 1fr;

+    gap: 24px;

+    

+    .user-avatar-section {

+      flex-direction: column;

+      text-align: center;

+    }

+    

+    .user-stats-overview .stats-grid {

+      grid-template-columns: 1fr;

+    }

+  }

+  

+  .stats-overview .overview-grid {

+    grid-template-columns: 1fr;

+  }

+  

+  .torrents-section .section-header {

+    flex-direction: column;

+    gap: 16px;

+    align-items: flex-start;

+  }

+}

 </style>
\ No newline at end of file