连接了种子搜索
Change-Id: Idc439815f713ac4de7916529fc41fc185fb513fa
diff --git a/src/api/torrent.js b/src/api/torrent.js
index bccf99c..cd66464 100644
--- a/src/api/torrent.js
+++ b/src/api/torrent.js
@@ -17,6 +17,35 @@
}
/**
+ * 搜索种子
+ * @param {Object} searchParams - 搜索参数
+ * @param {string} searchParams.keyword - 搜索关键词
+ * @param {string} searchParams.category - 分类
+ * @param {string} searchParams.sortBy - 排序字段
+ * @param {string} searchParams.sortOrder - 排序方向
+ * @param {number} searchParams.page - 页码
+ * @param {number} searchParams.entriesPerPage - 每页条数
+ * @returns {Promise}
+ */
+export function searchTorrents(searchParams) {
+ return request({
+ url: '/torrent/search',
+ method: 'post',
+ data: searchParams
+ }).catch(error => {
+ console.error('🚨 API请求失败:', {
+ url: '/torrent/search',
+ requestedURL: error.config?.url,
+ baseURL: error.config?.baseURL,
+ fullURL: error.config?.baseURL ? error.config.baseURL + error.config.url : error.config?.url,
+ status: error.response?.status,
+ statusText: error.response?.statusText
+ })
+ throw error
+ })
+}
+
+/**
* 获取分类列表
* @returns {Promise}
*/
@@ -34,7 +63,7 @@
*/
export function getTags() {
console.log('调用获取标签列表API...')
- // 由于后端没有标签的Controller,返回模拟数据
+ // 后端没有标签的Controller,返回模拟数据
return new Promise((resolve) => {
setTimeout(() => {
resolve({
@@ -58,17 +87,4 @@
url: `/torrent/${infoHash}`,
method: 'get'
})
-}
-
-/**
- * 获取种子列表
- * @param {Object} params - 查询参数
- * @returns {Promise}
- */
-export function getTorrents(params) {
- return request({
- url: '/torrents',
- method: 'get',
- params
- })
}
\ No newline at end of file
diff --git a/src/views/torrent/TorrentsView.vue b/src/views/torrent/TorrentsView.vue
index 1ae9f4b..e02971e 100644
--- a/src/views/torrent/TorrentsView.vue
+++ b/src/views/torrent/TorrentsView.vue
@@ -1,479 +1,500 @@
-<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;
- }
- }
-}
+<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>
+
+
+ </div>
+ </div>
+
+ <!-- 种子列表 -->
+ <div class="torrents-list">
+ <div class="list-header">
+ <span class="results-count">共找到 {{ totalCount }} 个种子</span>
+ </div>
+
+ <!-- <div style="background: yellow; padding: 10px; margin: 10px 0;">
+ <p>调试信息:</p>
+ <p>torrents长度: {{ torrents.length }}</p>
+ <p>totalCount: {{ totalCount }}</p>
+ <p>loading: {{ loading }}</p>
+ <pre>{{ JSON.stringify(torrents[0], null, 2) }}</pre>
+ </div> -->
+
+ <el-table
+ :data="torrents"
+ v-loading="loading"
+ @row-click="handleRowClick"
+ stripe
+ class="torrents-table"
+ >
+ <el-table-column label="分类" width="100">
+ <template #default="{ row }">
+ <el-tag
+ :type="getCategoryType(row.category)"
+ size="small"
+ >
+ {{ row.category?.name || '未分类' }}
+ </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-subtitle" v-if="row.subTitle">
+ {{ row.subTitle }}
+ </div>
+ <div class="torrent-meta">
+ <span class="uploader">
+ <el-icon><User /></el-icon>
+ {{ row.anonymous ? '匿名用户' : row.user?.username }}
+ </span>
+ <span class="upload-time">
+ <el-icon><Clock /></el-icon>
+ {{ formatTime(row.createdAt) }}
+ </span>
+ <span class="file-size">
+ <el-icon><Document /></el-icon>
+ {{ formatSize(row.size) }}
+ </span>
+ </div>
+ <div class="torrent-tags" v-if="row.tag && row.tag.length > 0">
+ <el-tag
+ v-for="tag in row.tag"
+ :key="tag"
+ size="small"
+ type="info"
+ class="tag-item"
+ >
+ {{ tag }}
+ </el-tag>
+ </div>
+ </div>
+ </template>
+ </el-table-column>
+
+ <el-table-column label="做种" width="80" align="center">
+ <template #default="{ row }">
+ <span class="seeders">{{ row.seeders || 0 }}</span>
+ </template>
+ </el-table-column>
+
+ <el-table-column label="下载" width="80" align="center">
+ <template #default="{ row }">
+ <span class="leechers">{{ row.leechers || 0 }}</span>
+ </template>
+ </el-table-column>
+
+ <el-table-column label="完成" width="80" align="center">
+ <template #default="{ row }">
+ <span>{{ row.downloads || 0 }}</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="[10,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'
+import { searchTorrents } from '@/api/torrent'
+
+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 totalPages = ref(0)
+
+ const torrents = ref([])
+
+ onMounted(() => {
+ // 从URL参数初始化搜索条件
+ if (route.query.q) {
+ searchQuery.value = route.query.q
+ }
+ if (route.query.category) {
+ selectedCategory.value = route.query.category
+ }
+ if (route.query.page) {
+ currentPage.value = parseInt(route.query.page)
+ }
+
+ fetchTorrents()
+ })
+
+ const fetchTorrents = async () => {
+ loading.value = true
+ try {
+ const searchParams = {
+ keyword: searchQuery.value || '', // 搜索关键词
+ page: currentPage.value - 1, // 后端页码从0开始
+ entriesPerPage: pageSize.value // 每页显示数量
+ }
+
+ console.log('🔍 发送搜索请求,参数:', searchParams)
+
+ const response = await searchTorrents(searchParams)
+
+ console.log('✅ 接收到响应:', response)
+
+ if (response) { // response直接就是数据
+ torrents.value = response.torrents || []
+ totalCount.value = response.totalElements || 0
+ totalPages.value = response.totalPages || 1
+
+ console.log('📊 处理后的数据:', {
+ torrentsCount: torrents.value.length,
+ totalCount: totalCount.value,
+ firstTorrent: torrents.value[0]
+ })
+ }
+ } catch (error) {
+ console.error('获取种子列表失败:', error)
+ console.error('📝 错误详情:', {
+ message: error.message,
+ status: error.response?.status,
+ data: error.response?.data
+ })
+ ElMessage.error(`获取种子列表失败: ${error.response?.data?.message || error.message}`)
+ // 如果请求失败,清空数据
+ torrents.value = []
+ totalCount.value = 0
+ } 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 (currentPage.value > 1) query.page = currentPage.value
+
+ router.replace({ query })
+ }
+
+ const handleRowClick = (row) => {
+ router.push(`/torrent/${row.id || row.infoHash}`)
+ }
+
+ const handleDownload = (row) => {
+ ElMessage.success(`开始下载: ${row.title || row.name}`)
+ // 这里实现下载逻辑
+ }
+
+ const handleSizeChange = (size) => {
+ pageSize.value = size
+ currentPage.value = 1
+ fetchTorrents()
+ }
+
+ const handleCurrentChange = (page) => {
+ currentPage.value = page
+ updateURL()
+ fetchTorrents()
+ }
+
+ const formatTime = (timeString) => {
+ if (!timeString) return '-'
+
+ 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 < 30) return `${days}天前`
+
+ return date.toLocaleDateString('zh-CN')
+ }
+
+ const formatSize = (sizeInBytes) => {
+ if (!sizeInBytes) return '-'
+
+ const units = ['B', 'KB', 'MB', 'GB', 'TB']
+ let size = sizeInBytes
+ let unitIndex = 0
+
+ while (size >= 1024 && unitIndex < units.length - 1) {
+ size /= 1024
+ unitIndex++
+ }
+
+ return `${size.toFixed(1)} ${units[unitIndex]}`
+ }
+
+ const getCategoryType = (category) => {
+ if (!category) return 'default'
+ const types = {
+ 'os': 'primary',
+ 'movie': 'success',
+ 'tv': 'info',
+ 'music': 'warning',
+ 'software': 'danger'
+ }
+ return types[category.slug] || 'default'
+ }
+
+ return {
+ loading,
+ searchQuery,
+ selectedCategory,
+ sortBy,
+ sortOrder,
+ currentPage,
+ pageSize,
+ totalCount,
+ torrents,
+ handleSearch,
+ handleFilter,
+ handleRowClick,
+ handleDownload,
+ handleSizeChange,
+ handleCurrentChange,
+ formatTime,
+ formatSize,
+ getCategoryType,
+ 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>
\ No newline at end of file