基本功能实现
Change-Id: I4fb8dfa2eed093c13d7c1e4304c4b4d012512ba9
diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue
index a3f2d83..c4e0ec7 100644
--- a/src/views/HomeView.vue
+++ b/src/views/HomeView.vue
@@ -1,55 +1,208 @@
<template>
<div class="home-page">
<div class="home-container">
- <div class="welcome-section">
- <div class="welcome-card">
- <div class="welcome-header">
- <div class="user-avatar">
- <el-icon size="48" color="#667eea"><UserFilled /></el-icon>
- </div>
- <h1 class="welcome-title">🎉 欢迎来到 PT Tracker</h1>
- <p class="welcome-subtitle" v-if="userInfo.username">
- 欢迎回来,<strong>{{ userInfo.username }}</strong>!
- </p>
- <p class="login-time" v-if="userInfo.loginTime">
- 登录时间:{{ formatTime(userInfo.loginTime) }}
- </p>
+ <!-- 用户信息和导航 -->
+ <header class="site-header">
+ <div class="header-content">
+ <div class="logo-section">
+ <h2 class="site-logo">🚀 PT Tracker</h2>
</div>
-
- <div class="feature-grid">
- <div class="feature-item">
- <el-icon size="32" color="#67c23a"><Download /></el-icon>
- <h3>高速下载</h3>
- <p>享受极速下载体验</p>
+ <div class="user-section">
+ <div class="user-stats">
+ <div class="stat-item">
+ <span class="stat-label">上传:</span>
+ <span class="stat-value">{{ userStats.uploaded }}</span>
+ </div>
+ <div class="stat-item">
+ <span class="stat-label">下载:</span>
+ <span class="stat-value">{{ userStats.downloaded }}</span>
+ </div>
+ <div class="stat-item">
+ <span class="stat-label">分享率:</span>
+ <span class="stat-value ratio" :class="getRatioClass(userStats.ratio)">
+ {{ userStats.ratio }}
+ </span>
+ </div>
</div>
- <div class="feature-item">
- <el-icon size="32" color="#e6a23c"><Upload /></el-icon>
- <h3>资源分享</h3>
- <p>分享优质资源内容</p>
+ <div class="user-info">
+ <el-avatar :size="40" :icon="UserFilled" />
+ <span class="username">{{ userInfo.username }}</span>
+ <el-dropdown @command="handleUserCommand">
+ <el-icon class="dropdown-icon"><ArrowDown /></el-icon>
+ <template #dropdown>
+ <el-dropdown-menu>
+ <el-dropdown-item command="profile">个人资料</el-dropdown-item>
+ <el-dropdown-item command="settings">设置</el-dropdown-item>
+ <el-dropdown-item command="logout" divided>退出登录</el-dropdown-item>
+ </el-dropdown-menu>
+ </template>
+ </el-dropdown>
</div>
- <div class="feature-item">
- <el-icon size="32" color="#f56c6c"><ChatDotRound /></el-icon>
- <h3>社区交流</h3>
- <p>与志同道合的朋友交流</p>
- </div>
- </div>
-
- <div class="action-buttons">
- <el-button type="primary" size="large" :icon="Search">
- 浏览种子
- </el-button>
- <el-button type="success" size="large" :icon="Plus">
- 上传资源
- </el-button>
- <el-button type="info" size="large" :icon="Setting">
- 个人设置
- </el-button>
- <el-button type="danger" size="large" :icon="SwitchButton" @click="handleLogout">
- 退出登录
- </el-button>
</div>
</div>
- </div>
+ </header>
+
+ <!-- 主要内容区域 -->
+ <main class="main-content">
+ <!-- 统计概览 -->
+ <section class="stats-overview">
+ <div class="stats-grid">
+ <div class="stat-card">
+ <div class="stat-icon">
+ <el-icon size="32" color="#67c23a"><Download /></el-icon>
+ </div>
+ <div class="stat-info">
+ <h3>{{ siteStats.totalTorrents }}</h3>
+ <p>种子总数</p>
+ </div>
+ </div>
+ <div class="stat-card">
+ <div class="stat-icon">
+ <el-icon size="32" color="#409eff"><User /></el-icon>
+ </div>
+ <div class="stat-info">
+ <h3>{{ siteStats.totalUsers }}</h3>
+ <p>注册用户</p>
+ </div>
+ </div>
+ <div class="stat-card">
+ <div class="stat-icon">
+ <el-icon size="32" color="#f56c6c"><Upload /></el-icon>
+ </div>
+ <div class="stat-info">
+ <h3>{{ siteStats.totalSize }}</h3>
+ <p>数据总量</p>
+ </div>
+ </div>
+ </div>
+ </section>
+
+ <!-- 快速操作 -->
+ <section class="quick-actions">
+ <h2 class="section-title">快速操作</h2>
+ <div class="action-grid">
+ <div class="action-card" @click="navigateTo('/torrents')">
+ <el-icon size="48" color="#409eff"><Search /></el-icon>
+ <h3>浏览种子</h3>
+ <p>搜索和浏览所有可用的种子资源</p>
+ </div>
+ <div class="action-card" @click="navigateTo('/upload')">
+ <el-icon size="48" color="#67c23a"><Upload /></el-icon>
+ <h3>上传资源</h3>
+ <p>分享你的资源,为社区做贡献</p>
+ </div>
+ <div class="action-card" @click="navigateTo('/forum')">
+ <el-icon size="48" color="#e6a23c"><ChatDotRound /></el-icon>
+ <h3>论坛交流</h3>
+ <p>与其他用户交流讨论</p>
+ </div>
+ <div class="action-card" @click="navigateTo('/rankings')">
+ <el-icon size="48" color="#f56c6c"><TrophyBase /></el-icon>
+ <h3>排行榜</h3>
+ <p>查看用户和资源排行</p>
+ </div>
+ </div>
+ </section>
+
+ <!-- 最新种子 -->
+ <section class="latest-torrents">
+ <div class="section-header">
+ <h2 class="section-title">最新种子</h2>
+ <el-button type="primary" text @click="navigateTo('/torrents')">
+ 查看更多 <el-icon><ArrowRight /></el-icon>
+ </el-button>
+ </div>
+ <div class="torrents-list">
+ <div
+ v-for="torrent in latestTorrents"
+ :key="torrent.id"
+ class="torrent-item"
+ @click="navigateTo(`/torrent/${torrent.id}`)"
+ >
+ <div class="torrent-info">
+ <div class="torrent-category">
+ <el-tag :type="getCategoryType(torrent.category)" size="small">
+ {{ torrent.category }}
+ </el-tag>
+ </div>
+ <h4 class="torrent-title">{{ torrent.title }}</h4>
+ <div class="torrent-meta">
+ <span class="meta-item">
+ <el-icon><User /></el-icon>
+ {{ torrent.uploader }}
+ </span>
+ <span class="meta-item">
+ <el-icon><Clock /></el-icon>
+ {{ formatTime(torrent.uploadTime) }}
+ </span>
+ <span class="meta-item">
+ <el-icon><Coin /></el-icon>
+ {{ torrent.size }}
+ </span>
+ </div>
+ </div>
+ <div class="torrent-stats">
+ <div class="stat-group">
+ <span class="stat-number seeders">{{ torrent.seeders }}</span>
+ <span class="stat-label">做种</span>
+ </div>
+ <div class="stat-group">
+ <span class="stat-number leechers">{{ torrent.leechers }}</span>
+ <span class="stat-label">下载</span>
+ </div>
+ <div class="stat-group">
+ <span class="stat-number">{{ torrent.downloads }}</span>
+ <span class="stat-label">完成</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </section>
+
+ <!-- 个人活动 -->
+ <section class="user-activity">
+ <h2 class="section-title">我的活动</h2>
+ <div class="activity-grid">
+ <div class="activity-card">
+ <h3>我的种子</h3>
+ <div class="activity-stats">
+ <div class="activity-item">
+ <span class="activity-label">正在做种:</span>
+ <span class="activity-value">{{ userActivity.seeding }}</span>
+ </div>
+ <div class="activity-item">
+ <span class="activity-label">正在下载:</span>
+ <span class="activity-value">{{ userActivity.downloading }}</span>
+ </div>
+ <div class="activity-item">
+ <span class="activity-label">已上传:</span>
+ <span class="activity-value">{{ userActivity.uploaded }}</span>
+ </div>
+ </div>
+ <el-button type="primary" size="small" @click="navigateTo('/my-torrents')">
+ 查看详情
+ </el-button>
+ </div>
+
+ <div class="activity-card">
+ <h3>邀请管理</h3>
+ <div class="activity-stats">
+ <div class="activity-item">
+ <span class="activity-label">可用邀请:</span>
+ <span class="activity-value">{{ userActivity.invitations }}</span>
+ </div>
+ <div class="activity-item">
+ <span class="activity-label">已邀请:</span>
+ <span class="activity-value">{{ userActivity.invited }}</span>
+ </div>
+ </div>
+ <el-button type="success" size="small" @click="navigateTo('/invitations')">
+ 管理邀请
+ </el-button>
+ </div>
+ </div>
+ </section>
+ </main>
</div>
</div>
</template>
@@ -60,49 +213,154 @@
import { ElMessage, ElMessageBox } from 'element-plus'
import {
UserFilled,
+ ArrowDown,
Download,
Upload,
ChatDotRound,
Search,
- Plus,
- Setting,
- SwitchButton
+ User,
+ Connection,
+ TrophyBase,
+ ArrowRight,
+ Clock,
+ Coin
} from '@element-plus/icons-vue'
export default {
name: 'HomeView',
components: {
- UserFilled
+ UserFilled,
+ ArrowDown
},
setup() {
const router = useRouter()
+
const userInfo = ref({
username: '',
loginTime: ''
})
- // 获取用户信息
+ const userStats = ref({
+ uploaded: '128.5 GB',
+ downloaded: '45.2 GB',
+ ratio: '2.84'
+ })
+
+ const siteStats = ref({
+ totalTorrents: '12,458',
+ totalUsers: '8,924',
+ onlineUsers: '342',
+ totalSize: '45.2 TB'
+ })
+
+ const userActivity = ref({
+ seeding: 15,
+ downloading: 3,
+ uploaded: 8,
+ invitations: 5,
+ invited: 12
+ })
+
+ const latestTorrents = ref([
+ {
+ id: 1,
+ title: '[4K蓝光原盘] 阿凡达:水之道 Avatar: The Way of Water (2022)',
+ category: '电影',
+ uploader: 'MovieMaster',
+ uploadTime: '2025-06-03T10:30:00',
+ size: '85.6 GB',
+ seeders: 128,
+ leechers: 45,
+ downloads: 892
+ },
+ {
+ id: 2,
+ title: '[FLAC] Taylor Swift - Midnights (Deluxe Edition) [2022]',
+ category: '音乐',
+ uploader: 'MusicLover',
+ uploadTime: '2025-06-03T09:15:00',
+ size: '1.2 GB',
+ seeders: 67,
+ leechers: 12,
+ downloads: 456
+ },
+ {
+ id: 3,
+ title: '[合集] Adobe Creative Suite 2025 完整版',
+ category: '软件',
+ uploader: 'TechGuru',
+ uploadTime: '2025-06-03T08:45:00',
+ size: '12.8 GB',
+ seeders: 234,
+ leechers: 89,
+ downloads: 1205
+ }
+ ])
+
onMounted(() => {
userInfo.value = {
username: localStorage.getItem('username') || '用户',
loginTime: localStorage.getItem('loginTime') || ''
}
+
+ // 模拟获取用户数据
+ fetchUserData()
})
- // 格式化时间
+ const fetchUserData = () => {
+ // 这里应该是API调用,现在使用模拟数据
+ console.log('获取用户数据...')
+ }
+
const formatTime = (timeString) => {
if (!timeString) return ''
const date = new Date(timeString)
- return date.toLocaleString('zh-CN', {
- year: 'numeric',
- month: '2-digit',
- day: '2-digit',
- hour: '2-digit',
- minute: '2-digit'
- })
+ 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)
+ return `${days}天前`
}
- // 退出登录
+ const getRatioClass = (ratio) => {
+ const r = parseFloat(ratio)
+ if (r >= 2) return 'excellent'
+ if (r >= 1) return 'good'
+ return 'warning'
+ }
+
+ const getCategoryType = (category) => {
+ const types = {
+ '电影': 'primary',
+ '音乐': 'success',
+ '软件': 'warning',
+ '游戏': 'danger',
+ '电视剧': 'info'
+ }
+ return types[category] || 'default'
+ }
+
+ const navigateTo = (path) => {
+ router.push(path)
+ }
+
+ const handleUserCommand = async (command) => {
+ switch (command) {
+ case 'profile':
+ navigateTo('/profile')
+ break
+ case 'settings':
+ navigateTo('/settings')
+ break
+ case 'logout':
+ await handleLogout()
+ break
+ }
+ }
+
const handleLogout = async () => {
try {
await ElMessageBox.confirm(
@@ -115,7 +373,6 @@
}
)
- // 清除登录信息
localStorage.removeItem('isLoggedIn')
localStorage.removeItem('username')
localStorage.removeItem('loginTime')
@@ -131,15 +388,26 @@
return {
userInfo,
+ userStats,
+ siteStats,
+ userActivity,
+ latestTorrents,
formatTime,
+ getRatioClass,
+ getCategoryType,
+ navigateTo,
+ handleUserCommand,
handleLogout,
- Search,
- Plus,
- Setting,
- SwitchButton,
Download,
Upload,
- ChatDotRound
+ ChatDotRound,
+ Search,
+ User,
+ Connection,
+ TrophyBase,
+ ArrowRight,
+ Clock,
+ Coin
}
}
}
@@ -149,106 +417,323 @@
.home-page {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 20px;
+ padding: 0;
}
.home-container {
- width: 100%;
- max-width: 800px;
+ max-width: 1200px;
+ margin: 0 auto;
+ background: #fff;
+ min-height: 100vh;
}
-.welcome-section {
- .welcome-card {
- background: rgba(255, 255, 255, 0.95);
- backdrop-filter: blur(10px);
- border-radius: 20px;
- padding: 60px 40px;
- box-shadow: 0 25px 50px rgba(0, 0, 0, 0.1);
- border: 1px solid rgba(255, 255, 255, 0.2);
- text-align: center;
+// 网站头部
+.site-header {
+ background: #fff;
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+ position: sticky;
+ top: 0;
+ z-index: 100;
+
+ .header-content {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 16px 24px;
- .welcome-header {
- margin-bottom: 40px;
-
- .user-avatar {
- margin-bottom: 20px;
- }
-
- .welcome-title {
- font-size: 36px;
- font-weight: 700;
- color: #2c3e50;
- margin-bottom: 12px;
- letter-spacing: -0.5px;
- }
-
- .welcome-subtitle {
- font-size: 18px;
- color: #667eea;
- margin-bottom: 8px;
- font-weight: 500;
-
- strong {
- color: #2c3e50;
- }
- }
-
- .login-time {
- font-size: 14px;
- color: #909399;
+ .logo-section {
+ .site-logo {
margin: 0;
+ font-size: 24px;
+ font-weight: bold;
+ color: #667eea;
}
}
- .feature-grid {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
- gap: 30px;
- margin-bottom: 40px;
+ .user-section {
+ display: flex;
+ align-items: center;
+ gap: 24px;
- .feature-item {
- background: #f8f9fa;
- padding: 30px 20px;
- border-radius: 12px;
- transition: all 0.3s ease;
+ .user-stats {
+ display: flex;
+ gap: 16px;
- &:hover {
- transform: translateY(-5px);
- box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
+ .stat-item {
+ font-size: 14px;
+
+ .stat-label {
+ color: #909399;
+ margin-right: 4px;
+ }
+
+ .stat-value {
+ font-weight: 600;
+ color: #2c3e50;
+
+ &.ratio {
+ &.excellent { color: #67c23a; }
+ &.good { color: #e6a23c; }
+ &.warning { color: #f56c6c; }
+ }
+ }
+ }
+ }
+
+ .user-info {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ cursor: pointer;
+
+ .username {
+ font-weight: 500;
+ color: #2c3e50;
}
+ .dropdown-icon {
+ color: #909399;
+ transition: transform 0.3s ease;
+
+ &:hover {
+ transform: rotate(180deg);
+ }
+ }
+ }
+ }
+ }
+}
+
+// 主要内容
+.main-content {
+ padding: 24px;
+}
+
+.section-title {
+ font-size: 20px;
+ font-weight: 600;
+ color: #2c3e50;
+ margin-bottom: 16px;
+}
+
+.section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 16px;
+}
+
+// 统计概览
+.stats-overview {
+ margin-bottom: 32px;
+
+ .stats-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 16px;
+
+ .stat-card {
+ background: #fff;
+ border-radius: 12px;
+ padding: 24px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+ border: 1px solid #f0f0f0;
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ transition: all 0.3s ease;
+
+ &:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
+ }
+
+ .stat-info {
h3 {
- font-size: 18px;
+ font-size: 24px;
+ font-weight: bold;
color: #2c3e50;
- margin: 16px 0 8px 0;
- font-weight: 600;
+ margin: 0 0 4px 0;
}
p {
font-size: 14px;
- color: #7f8c8d;
+ color: #909399;
margin: 0;
- line-height: 1.5;
}
}
}
+ }
+}
+
+// 快速操作
+.quick-actions {
+ margin-bottom: 32px;
+
+ .action-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
+ gap: 20px;
- .action-buttons {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
- gap: 16px;
+ .action-card {
+ background: #fff;
+ border-radius: 12px;
+ padding: 32px 24px;
+ text-align: center;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+ border: 1px solid #f0f0f0;
+ cursor: pointer;
+ transition: all 0.3s ease;
- .el-button {
- height: 48px;
- font-size: 15px;
- font-weight: 500;
- border-radius: 10px;
+ &:hover {
+ transform: translateY(-4px);
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.15);
+ }
+
+ h3 {
+ font-size: 18px;
+ font-weight: 600;
+ color: #2c3e50;
+ margin: 16px 0 8px 0;
+ }
+
+ p {
+ font-size: 14px;
+ color: #7f8c8d;
+ line-height: 1.5;
+ margin: 0;
+ }
+ }
+ }
+}
+
+// 最新种子
+.latest-torrents {
+ margin-bottom: 32px;
+
+ .torrents-list {
+ background: #fff;
+ border-radius: 12px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+ border: 1px solid #f0f0f0;
+ overflow: hidden;
+
+ .torrent-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20px 24px;
+ border-bottom: 1px solid #f5f5f5;
+ cursor: pointer;
+ transition: background-color 0.3s ease;
+
+ &:hover {
+ background-color: #f8f9fa;
+ }
+
+ &:last-child {
+ border-bottom: none;
+ }
+
+ .torrent-info {
+ flex: 1;
- :deep(.el-icon) {
- margin-right: 8px;
+ .torrent-category {
+ margin-bottom: 8px;
+ }
+
+ .torrent-title {
+ font-size: 16px;
+ font-weight: 500;
+ color: #2c3e50;
+ margin: 0 0 8px 0;
+ line-height: 1.4;
+ }
+
+ .torrent-meta {
+ display: flex;
+ gap: 16px;
+
+ .meta-item {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ font-size: 12px;
+ color: #909399;
+
+ .el-icon {
+ font-size: 12px;
+ }
+ }
+ }
+ }
+
+ .torrent-stats {
+ display: flex;
+ gap: 24px;
+
+ .stat-group {
+ text-align: center;
+
+ .stat-number {
+ display: block;
+ font-size: 16px;
+ font-weight: 600;
+
+ &.seeders { color: #67c23a; }
+ &.leechers { color: #f56c6c; }
+ }
+
+ .stat-label {
+ font-size: 12px;
+ color: #909399;
+ }
+ }
+ }
+ }
+ }
+}
+
+// 用户活动
+.user-activity {
+ .activity-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
+ gap: 20px;
+
+ .activity-card {
+ background: #fff;
+ border-radius: 12px;
+ padding: 24px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+ border: 1px solid #f0f0f0;
+
+ h3 {
+ font-size: 18px;
+ font-weight: 600;
+ color: #2c3e50;
+ margin: 0 0 16px 0;
+ }
+
+ .activity-stats {
+ margin-bottom: 16px;
+
+ .activity-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 8px 0;
+
+ .activity-label {
+ font-size: 14px;
+ color: #7f8c8d;
+ }
+
+ .activity-value {
+ font-size: 14px;
+ font-weight: 600;
+ color: #2c3e50;
+ }
}
}
}
@@ -257,25 +742,35 @@
// 响应式设计
@media (max-width: 768px) {
- .home-page {
+ .header-content {
+ flex-direction: column;
+ gap: 16px;
+
+ .user-stats {
+ flex-direction: column;
+ gap: 8px;
+ text-align: center;
+ }
+ }
+
+ .main-content {
padding: 16px;
}
- .welcome-card {
- padding: 40px 24px !important;
+ .stats-grid,
+ .action-grid,
+ .activity-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .torrent-item {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 16px;
- .welcome-header .welcome-title {
- font-size: 28px;
- }
-
- .feature-grid {
- grid-template-columns: 1fr;
- gap: 20px;
- }
-
- .action-buttons {
- grid-template-columns: 1fr;
- gap: 12px;
+ .torrent-stats {
+ width: 100%;
+ justify-content: space-around;
}
}
}