Files
netdisk-fast-download/web-front/src/components/DownloadDialog.vue

267 lines
8.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<el-dialog
title="文件下载"
v-model="dialogVisible"
width="600px"
:close-on-click-modal="false"
@close="$emit('update:visible', false)"
>
<div v-if="info" class="download-info-content">
<div class="download-file-header">
<i class="fas fa-file" style="margin-right: 8px; color: #409eff;"></i>
<strong>{{ info.fileName || '未命名文件' }}</strong>
</div>
<el-alert
title="该文件需要特殊请求头才能下载,无法直接通过浏览器下载。请使用以下方式之一:"
type="warning"
:closable="false"
show-icon
style="margin-bottom: 16px;"
/>
<el-tabs v-model="activeTab">
<el-tab-pane label="发送到下载器" name="downloader">
<div class="downloader-section">
<template v-if="isThunder">
<p v-if="thunderNeedsCookie" style="color: #f56c6c; margin-bottom: 12px;">
<i class="fas fa-exclamation-circle"></i>
该文件需要 Cookie 认证迅雷不支持自定义 Cookie请切换到 Aria2/Motrix/Gopeed
</p>
<p v-else-if="thunderNeedsUa" style="color: #e6a23c; margin-bottom: 12px;">
<i class="fas fa-exclamation-triangle"></i>
该文件需要特殊 User-Agent 才能下载迅雷客户端可能不支持自定义 UA下载可能失败建议切换到 Aria2/Motrix/Gopeed
</p>
<p v-else style="color: #909399; margin-bottom: 12px;">
<i class="fas fa-bolt"></i>
迅雷将通过浏览器唤起本地客户端下载
</p>
</template>
<template v-else>
<p v-if="!connected" style="color: #e6a23c; margin-bottom: 12px;">
<i class="fas fa-exclamation-triangle"></i>
未检测到下载器连接请先在首页配置下载器Aria2/Motrix/Gopeed/迅雷
</p>
<p v-else style="color: #67c23a; margin-bottom: 12px;">
<i class="fas fa-check-circle"></i>
下载器已连接 ({{ downloaderVersion }})
</p>
</template>
<el-button
type="success"
@click="sendToDownloader"
:disabled="(isThunder && thunderNeedsCookie) || (!isThunder && !connected)"
:loading="sending"
>
<i class="fas fa-paper-plane"></i> 发送到下载器
</el-button>
<el-button
v-if="!isThunder"
size="small"
@click="doTestConnection"
style="margin-left: 8px;"
>
测试连接
</el-button>
</div>
</el-tab-pane>
<el-tab-pane label="Aria2 命令" name="aria2">
<el-input
type="textarea"
:model-value="info.aria2Command"
:rows="4"
readonly
resize="none"
class="download-command-textarea"
/>
<div class="download-actions">
<el-button type="primary" size="small" @click="copyText(info.aria2Command)">
<i class="fas fa-copy"></i> 复制 Aria2 命令
</el-button>
</div>
</el-tab-pane>
<el-tab-pane label="Curl 命令" name="curl">
<el-input
type="textarea"
:model-value="info.curlCommand"
:rows="4"
readonly
resize="none"
class="download-command-textarea"
/>
<div class="download-actions">
<el-button type="primary" size="small" @click="copyText(info.curlCommand)">
<i class="fas fa-copy"></i> 复制 Curl 命令
</el-button>
</div>
</el-tab-pane>
</el-tabs>
<div style="margin-top: 16px; text-align: right;">
<el-button size="small" type="warning" @click="doDirectDownload">
直接打开链接可能失败
</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
import { testConnection, addDownload, getConfig, hasCookieHeader, hasCustomUaHeader } from '@/utils/downloaderService'
export default {
name: 'DownloadDialog',
props: {
/** v-model:visible 控制弹窗显示 */
visible: {
type: Boolean,
default: false
},
/**
* 下载信息对象
* { downloadUrl, fileName, downloadHeaders, aria2Command, curlCommand, aria2JsonRpc, needDownloader }
*/
downloadInfo: {
type: Object,
default: null
}
},
emits: ['update:visible', 'close'],
data() {
return {
activeTab: 'downloader',
connected: false,
downloaderVersion: '',
sending: false
}
},
computed: {
dialogVisible: {
get() { return this.visible },
set(val) { this.$emit('update:visible', val) }
},
info() { return this.downloadInfo },
isThunder() { return getConfig().downloaderType === 'thunder' },
thunderNeedsCookie() { return this.isThunder && this.info && hasCookieHeader(this.info.downloadHeaders) },
thunderNeedsUa() { return this.isThunder && this.info && hasCustomUaHeader(this.info.downloadHeaders) }
},
watch: {
visible(val) {
if (val) {
this.activeTab = 'downloader'
this.checkConnection()
}
}
},
methods: {
/** 检测下载器连接状态 */
async checkConnection() {
const result = await testConnection()
this.connected = result.connected
this.downloaderVersion = result.version
},
/** 手动测试连接 */
async doTestConnection() {
const result = await testConnection()
this.connected = result.connected
this.downloaderVersion = result.version
if (result.connected) {
this.$message.success(`下载器连接正常 (${result.version})`)
} else {
this.$message.error('无法连接到下载器,请检查配置')
}
},
/** 发送到 Aria2/Motrix/Gopeed */
async sendToDownloader() {
if (!this.info) return
this.sending = true
try {
const gid = await addDownload(
this.info.downloadUrl,
this.info.downloadHeaders,
this.info.fileName
)
this.$message.success('已发送到下载器任务ID: ' + gid)
this.dialogVisible = false
} catch (error) {
console.error('发送到下载器失败:', error)
this.$message.error('发送到下载器失败: ' + (error.message || '未知错误'))
} finally {
this.sending = false
}
},
/** 直接打开下载链接(可能因缺请求头而失败) */
doDirectDownload() {
if (this.info && this.info.downloadUrl) {
const a = document.createElement('a')
a.href = this.info.downloadUrl
a.target = '_blank'
a.rel = 'noopener noreferrer'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
this.dialogVisible = false
}
},
/** 复制文本到剪贴板 */
async copyText(text) {
if (!text) return
try {
await navigator.clipboard.writeText(text)
this.$message.success('已复制到剪贴板')
} catch {
const textarea = document.createElement('textarea')
textarea.value = text
textarea.style.position = 'fixed'
textarea.style.opacity = '0'
document.body.appendChild(textarea)
textarea.select()
document.execCommand('copy')
document.body.removeChild(textarea)
this.$message.success('已复制到剪贴板')
}
}
}
}
</script>
<style scoped>
.download-info-content {
padding: 0 4px;
}
.download-file-header {
font-size: 16px;
margin-bottom: 12px;
padding: 10px 14px;
background: #f0f7ff;
border-radius: 8px;
display: flex;
align-items: center;
word-break: break-all;
}
:deep(.dark) .download-file-header,
.dark-theme .download-file-header {
background: #1a3350;
}
.download-command-textarea :deep(.el-textarea__inner) {
font-family: 'Courier New', Courier, monospace;
font-size: 12px;
background: #f5f5f5;
color: #333;
}
:deep(.dark) .download-command-textarea :deep(.el-textarea__inner),
.dark-theme .download-command-textarea :deep(.el-textarea__inner) {
background: #1e1e1e;
color: #d4d4d4;
}
.download-actions {
margin-top: 10px;
display: flex;
gap: 8px;
}
.downloader-section {
padding: 16px 0;
}
</style>