blob: f3231daae5b14e502abc602a5c2241a1d62ce7c4 [file] [log] [blame]
<template>
<div class="torrents-page">
<div class="page-header">
<h1>种子资源</h1>
<div class="header-actions">
<el-button type="primary" :icon="Upload" @click="$router.push('/upload')">
上传种子
</el-button>
</div>
</div>
<!-- 搜索和筛选 -->
<div class="search-section">
<div class="search-bar">
<el-input
v-model="searchQuery"
placeholder="搜索种子..."
:prefix-icon="Search"
size="large"
@keyup.enter="handleSearch"
clearable
/>
<el-button type="primary" size="large" @click="handleSearch">
搜索
</el-button>
</div>
<div class="filters">
<el-select v-model="selectedCategory" placeholder="分类" @change="handleFilter">
<el-option label="全部" value="" />
<el-option label="电影" value="movie" />
<el-option label="电视剧" value="tv" />
<el-option label="音乐" value="music" />
<el-option label="软件" value="software" />
<el-option label="游戏" value="game" />
</el-select>
<el-select v-model="sortBy" placeholder="排序方式" @change="handleFilter">
<el-option label="上传时间" value="upload_time" />
<el-option label="文件大小" value="size" />
<el-option label="做种数" value="seeders" />
<el-option label="下载数" value="leechers" />
<el-option label="完成数" value="downloads" />
</el-select>
<el-radio-group v-model="sortOrder" @change="handleFilter">
<el-radio-button label="desc">降序</el-radio-button>
<el-radio-button label="asc">升序</el-radio-button>
</el-radio-group>
</div>
</div>
<!-- 种子列表 -->
<div class="torrents-list">
<div class="list-header">
<span class="results-count">共找到 {{ totalCount }} 个种子</span>
</div>
<el-table
:data="torrents"
v-loading="loading"
@row-click="handleRowClick"
stripe
class="torrents-table"
>
<el-table-column label="分类" width="80">
<template #default="{ row }">
<el-tag :type="getCategoryType(row.category)" size="small">
{{ getCategoryName(row.category) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="种子信息" min-width="400">
<template #default="{ row }">
<div class="torrent-info">
<h4 class="torrent-title">{{ row.title }}</h4>
<div class="torrent-meta">
<span class="uploader">
<el-icon><User /></el-icon>
{{ row.uploader }}
</span>
<span class="upload-time">
<el-icon><Clock /></el-icon>
{{ formatTime(row.uploadTime) }}
</span>
<span class="file-size">
<el-icon><Document /></el-icon>
{{ row.size }}
</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="做种" width="80" align="center">
<template #default="{ row }">
<span class="seeders">{{ row.seeders }}</span>
</template>
</el-table-column>
<el-table-column label="下载" width="80" align="center">
<template #default="{ row }">
<span class="leechers">{{ row.leechers }}</span>
</template>
</el-table-column>
<el-table-column label="完成" width="80" align="center">
<template #default="{ row }">
<span>{{ row.downloads }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="120" align="center">
<template #default="{ row }">
<el-button
type="primary"
size="small"
:icon="Download"
@click.stop="handleDownload(row)"
>
下载
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-wrapper">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[20, 50, 100]"
:total="totalCount"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
</template>
<script>
import { ref, onMounted, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
import {
Search,
Upload,
Download,
User,
Clock,
Document
} from '@element-plus/icons-vue'
export default {
name: 'TorrentsView',
setup() {
const router = useRouter()
const route = useRoute()
const loading = ref(false)
const searchQuery = ref('')
const selectedCategory = ref('')
const sortBy = ref('upload_time')
const sortOrder = ref('desc')
const currentPage = ref(1)
const pageSize = ref(20)
const totalCount = ref(0)
const torrents = ref([
{
id: 1,
title: '[4K蓝光原盘] 阿凡达:水之道 Avatar: The Way of Water (2022)',
category: 'movie',
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: 'music',
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: 'software',
uploader: 'TechGuru',
uploadTime: '2025-06-03T08:45:00',
size: '12.8 GB',
seeders: 234,
leechers: 89,
downloads: 1205
}
])
onMounted(() => {
// 从URL参数初始化搜索条件
if (route.query.q) {
searchQuery.value = route.query.q
}
if (route.query.category) {
selectedCategory.value = route.query.category
}
fetchTorrents()
})
const fetchTorrents = async () => {
loading.value = true
try {
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 1000))
totalCount.value = 156
} catch (error) {
ElMessage.error('获取种子列表失败')
} finally {
loading.value = false
}
}
const handleSearch = () => {
currentPage.value = 1
updateURL()
fetchTorrents()
}
const handleFilter = () => {
currentPage.value = 1
updateURL()
fetchTorrents()
}
const updateURL = () => {
const query = {}
if (searchQuery.value) query.q = searchQuery.value
if (selectedCategory.value) query.category = selectedCategory.value
if (sortBy.value !== 'upload_time') query.sort = sortBy.value
if (sortOrder.value !== 'desc') query.order = sortOrder.value
if (currentPage.value > 1) query.page = currentPage.value
router.replace({ query })
}
const handleRowClick = (row) => {
router.push(`/torrent/${row.id}`)
}
const handleDownload = (row) => {
ElMessage.success(`开始下载: ${row.title}`)
// 这里实现下载逻辑
}
const handleSizeChange = (size) => {
pageSize.value = size
currentPage.value = 1
fetchTorrents()
}
const handleCurrentChange = (page) => {
currentPage.value = page
updateURL()
fetchTorrents()
}
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)
return `${days}天前`
}
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
}
return {
loading,
searchQuery,
selectedCategory,
sortBy,
sortOrder,
currentPage,
pageSize,
totalCount,
torrents,
handleSearch,
handleFilter,
handleRowClick,
handleDownload,
handleSizeChange,
handleCurrentChange,
formatTime,
getCategoryType,
getCategoryName,
Search,
Upload,
Download,
User,
Clock,
Document
}
}
}
</script>
<style lang="scss" scoped>
.torrents-page {
max-width: 1200px;
margin: 0 auto;
padding: 24px;
}
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
h1 {
font-size: 28px;
font-weight: 600;
color: #2c3e50;
margin: 0;
}
}
.search-section {
background: #fff;
border-radius: 12px;
padding: 24px;
margin-bottom: 24px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
.search-bar {
display: flex;
gap: 12px;
margin-bottom: 16px;
.el-input {
flex: 1;
}
}
.filters {
display: flex;
gap: 16px;
flex-wrap: wrap;
align-items: center;
.el-select {
width: 120px;
}
}
}
.torrents-list {
background: #fff;
border-radius: 12px;
padding: 24px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
.list-header {
margin-bottom: 16px;
.results-count {
font-size: 14px;
color: #909399;
}
}
.torrents-table {
.torrent-info {
.torrent-title {
font-size: 16px;
font-weight: 500;
color: #2c3e50;
margin: 0 0 8px 0;
line-height: 1.4;
cursor: pointer;
&:hover {
color: #409eff;
}
}
.torrent-meta {
display: flex;
gap: 16px;
font-size: 12px;
color: #909399;
span {
display: flex;
align-items: center;
gap: 4px;
}
}
}
.seeders {
color: #67c23a;
font-weight: 600;
}
.leechers {
color: #f56c6c;
font-weight: 600;
}
}
.pagination-wrapper {
margin-top: 24px;
text-align: center;
}
}
@media (max-width: 768px) {
.torrents-page {
padding: 16px;
}
.page-header {
flex-direction: column;
gap: 16px;
align-items: flex-start;
}
.filters {
flex-direction: column;
align-items: flex-start;
.el-select {
width: 100%;
}
}
.torrents-table {
:deep(.el-table__header),
:deep(.el-table__body) {
font-size: 12px;
}
}
}
</style>