下载数
Change-Id: Id3c07b7d57de7f92e2f550306cf339a0c892fc6d
diff --git a/src/api/torrent.js b/src/api/torrent.js
index e49887e..586e22c 100644
--- a/src/api/torrent.js
+++ b/src/api/torrent.js
@@ -140,4 +140,16 @@
url: `/torrent/download/${infoHash}`,
method: 'get'
})
+}
+
+/**
+ * 获取种子下载数
+ * @param {string} infoHash - 种子的info hash
+ * @returns {Promise}
+ */
+export function downloadTorrentNum(infoHash) {
+ return request({
+ url: `/torrent/${infoHash}/downloads`,
+ method: 'get'
+ })
}
\ No newline at end of file
diff --git a/src/views/forum/TopicView.vue b/src/views/forum/TopicView.vue
index c79bfa8..0374dac 100644
--- a/src/views/forum/TopicView.vue
+++ b/src/views/forum/TopicView.vue
@@ -1,4 +1,5 @@
<template>
+ <Navbar />
<div class="topic-page">
<Navbar />
<div class="page-container">
diff --git a/src/views/torrent/TorrentDetailView.vue b/src/views/torrent/TorrentDetailView.vue
index 28af1f6..8b1c8fd 100644
--- a/src/views/torrent/TorrentDetailView.vue
+++ b/src/views/torrent/TorrentDetailView.vue
@@ -95,17 +95,17 @@
</div>
<div class="torrent-stats">
- <div class="stat-item seeders">
+ <!-- <div class="stat-item seeders">
<span class="stat-number">{{ peerStats.seeders }}</span>
<span class="stat-label">做种</span>
- </div>
- <div class="stat-item leechers">
+ </div> -->
+ <!-- <div class="stat-item leechers">
<span class="stat-number">{{ peerStats.leechers }}</span>
<span class="stat-label">下载</span>
- </div>
+ </div> -->
<div class="stat-item downloads">
- <span class="stat-number">{{ torrentInfo.finishes }}</span>
- <span class="stat-label">完成</span>
+ <span class="stat-number">{{ peerStats.downloads }}</span>
+ <span class="stat-label">总下载</span>
</div>
</div>
@@ -344,7 +344,8 @@
const torrentFiles = ref([])
const peerStats = ref({
seeders: 0,
- leechers: 0
+ leechers: 0,
+ downloads: 0
})
const seedersList = ref([])
@@ -399,6 +400,9 @@
// 获取用户活动数据(如果有相关API)
await fetchPeerStats(infoHash)
+ // 获取下载数
+ await fetchDownloadCount(infoHash)
+
// 获取评论(如果有相关API)
await fetchComments(infoHash)
} else {
@@ -464,6 +468,18 @@
}
}
+ const fetchDownloadCount = async (infoHash) => {
+ try {
+ const response = await axios.get(`/api/torrent/${infoHash}/downloads`)
+ if (response.status === 200) {
+ peerStats.value.downloads = response.data
+ }
+ } catch (error) {
+ console.error('获取下载数失败:', error)
+ peerStats.value.downloads = 0
+ }
+ }
+
const fetchComments = async (infoHash) => {
try {
// 这里应该调用获取评论的API
@@ -533,6 +549,15 @@
}
)
+ // 检查响应类型是否为JSON(表示发生了错误)
+ const contentType = response.headers['content-type'];
+ if (contentType && contentType.includes('application/json')) {
+ // 将blob转换为json以读取错误信息
+ const errorText = await response.data.text();
+ const errorData = JSON.parse(errorText);
+ throw new Error(errorData.message || '下载失败');
+ }
+
// 从响应头中获取文件名,如果没有则使用默认格式
let fileName = response.headers?.['content-disposition']?.split('filename=')[1]
if (!fileName) {
@@ -556,7 +581,41 @@
ElMessage.success('种子文件下载完成')
} catch (error) {
console.error('下载失败:', error)
- ElMessage.error(error.response?.data?.message || '下载失败,请稍后重试')
+ // 根据错误类型显示不同的错误信息
+ let errorMessage = '下载失败,请稍后重试';
+
+ if (error.response) {
+ const status = error.response.status;
+ const data = error.response.data;
+
+ switch(status) {
+ case 401:
+ errorMessage = '认证失败,请检查登录状态或passkey是否正确';
+ break;
+ case 403:
+ if (data.message?.includes('share ratio')) {
+ errorMessage = '分享率不足,无法下载';
+ } else if (data.message?.includes('torrent:download_review')) {
+ errorMessage = '该种子正在审核中,您没有权限下载';
+ } else {
+ errorMessage = '您没有权限下载此种子';
+ }
+ break;
+ case 404:
+ if (data.message?.includes('torrent not registered')) {
+ errorMessage = '该种子未在服务器注册';
+ } else if (data.message?.includes('file are missing')) {
+ errorMessage = '种子文件丢失,请联系管理员';
+ } else {
+ errorMessage = '种子不存在';
+ }
+ break;
+ default:
+ errorMessage = data.message || '下载失败,请稍后重试';
+ }
+ }
+
+ ElMessage.error(errorMessage)
} finally {
downloading.value = false
}
diff --git a/src/views/torrent/TorrentsView.vue b/src/views/torrent/TorrentsView.vue
index 596ca22..20d5dd0 100644
--- a/src/views/torrent/TorrentsView.vue
+++ b/src/views/torrent/TorrentsView.vue
@@ -106,23 +106,23 @@
</template>
</el-table-column>
- <el-table-column label="做种" width="80" align="center">
+ <!-- <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> -->
<el-table-column label="下载" width="80" align="center">
<template #default="{ row }">
- <span class="leechers">{{ row.leechers || 0 }}</span>
+ <span class="downloads">{{ row.downloadCount || 0 }}</span>
</template>
</el-table-column>
- <el-table-column label="完成" width="80" align="center">
+ <!-- <el-table-column label="完成" width="80" align="center">
<template #default="{ row }">
<span>{{ row.downloads || 0 }}</span>
</template>
- </el-table-column>
+ </el-table-column> -->
<el-table-column label="操作" width="120" align="center">
<template #default="{ row }">
@@ -168,6 +168,7 @@
} from '@element-plus/icons-vue'
import { searchTorrents, getCategories } from '@/api/torrent'
import Navbar from '@/components/Navbar.vue'
+import axios from 'axios'
export default {
name: 'TorrentsView',
@@ -207,20 +208,30 @@
fetchTorrents()
})
+ const fetchDownloadCount = async (torrent) => {
+ try {
+ const response = await axios.get(`/api/torrent/${torrent.infoHash}/downloads`)
+ if (response.status === 200) {
+ torrent.downloadCount = response.data
+ }
+ } catch (error) {
+ console.error('获取下载数失败:', error)
+ torrent.downloadCount = 0
+ }
+ }
+
const fetchTorrents = async () => {
loading.value = true
try {
if (selectedCategory.value) {
- // 使用 GET 请求
const response = await fetch(`/api/torrent/search?category=${selectedCategory.value}`)
- .then(res => res.json())
+ .then(res => res.json())
torrents.value = response.torrents || []
totalCount.value = response.totalElements || 0
totalPages.value = response.totalPages || 1
} else {
- // 使用 POST 请求(搜索)
const searchParams = {
keyword: searchQuery.value || '',
page: currentPage.value - 1,
@@ -234,6 +245,11 @@
totalPages.value = response.totalPages || 1
}
+ // 为每个种子获取下载数
+ for (const torrent of torrents.value) {
+ await fetchDownloadCount(torrent)
+ }
+
} catch (error) {
console.error('获取种子列表失败:', error)
ElMessage.error('获取种子列表失败')
@@ -287,9 +303,87 @@
router.push(`/torrent/${row.infoHash}`)
}
- const handleDownload = (row) => {
- ElMessage.success(`开始下载: ${row.title || row.name}`)
- // 这里实现下载逻辑
+ const handleDownload = async (row) => {
+ try {
+ const response = await axios.get(
+ `/api/torrent/download/${row.infoHash}`,
+ {
+ responseType: 'blob',
+ // 如果需要传递passkey,可以在这里添加params
+ params: {
+ // passkey: userStore.passkey // 如果你有用户store存储passkey
+ }
+ }
+ )
+
+ // 检查响应类型是否为JSON(表示发生了错误)
+ const contentType = response.headers['content-type'];
+ if (contentType && contentType.includes('application/json')) {
+ // 将blob转换为json以读取错误信息
+ const errorText = await response.data.text();
+ const errorData = JSON.parse(errorText);
+ throw new Error(errorData.message || '下载失败');
+ }
+
+ // 从响应头中获取文件名,如果没有则使用默认格式
+ let fileName = response.headers?.['content-disposition']?.split('filename=')[1]
+ if (!fileName) {
+ // 使用默认的文件名格式
+ fileName = `${row.title}.torrent`
+ } else {
+ // 解码文件名
+ fileName = decodeURIComponent(fileName)
+ }
+
+ // 创建下载链接
+ const url = window.URL.createObjectURL(new Blob([response.data], { type: 'application/x-bittorrent' }))
+ const link = document.createElement('a')
+ link.href = url
+ link.download = fileName
+ document.body.appendChild(link)
+ link.click()
+ document.body.removeChild(link)
+ window.URL.revokeObjectURL(url)
+
+ ElMessage.success('种子文件下载完成')
+ } catch (error) {
+ console.error('下载失败:', error)
+ // 根据错误类型显示不同的错误信息
+ let errorMessage = '下载失败,请稍后重试';
+
+ if (error.response) {
+ const status = error.response.status;
+ const data = error.response.data;
+
+ switch(status) {
+ case 401:
+ errorMessage = '认证失败,请检查登录状态或passkey是否正确';
+ break;
+ case 403:
+ if (data.message?.includes('share ratio')) {
+ errorMessage = '分享率不足,无法下载';
+ } else if (data.message?.includes('torrent:download_review')) {
+ errorMessage = '该种子正在审核中,您没有权限下载';
+ } else {
+ errorMessage = '您没有权限下载此种子';
+ }
+ break;
+ case 404:
+ if (data.message?.includes('torrent not registered')) {
+ errorMessage = '该种子未在服务器注册';
+ } else if (data.message?.includes('file are missing')) {
+ errorMessage = '种子文件丢失,请联系管理员';
+ } else {
+ errorMessage = '种子不存在';
+ }
+ break;
+ default:
+ errorMessage = data.message || '下载失败,请稍后重试';
+ }
+ }
+
+ ElMessage.error(errorMessage)
+ }
}
const handleSizeChange = (size) => {