- 弹窗使用 Tabs 切换两种下载方式 - 浏览器下载保留逐条触发逻辑 - 下载工具页提供 aria2 / wget 命令示例与复制全部链接
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
|||||||
Image,
|
Image,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
Typography,
|
Typography,
|
||||||
|
Tabs,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { DownloadOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons';
|
import { DownloadOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
@@ -128,20 +129,20 @@ export default function VideosPage() {
|
|||||||
const [downloadResults, setDownloadResults] = useState<DownloadResult[]>([]);
|
const [downloadResults, setDownloadResults] = useState<DownloadResult[]>([]);
|
||||||
const [downloadModalOpen, setDownloadModalOpen] = useState(false);
|
const [downloadModalOpen, setDownloadModalOpen] = useState(false);
|
||||||
|
|
||||||
const handleBatchDownload = async () => {
|
const allDownloadUrls = downloadResults.flatMap((item) =>
|
||||||
const ids = selectedRows.map((v) => v.videoId);
|
item.urls.map((u) => u.url)
|
||||||
try {
|
);
|
||||||
const results = await batchDownload(ids);
|
|
||||||
const valid = results.filter((r) => r.urls.length > 0);
|
const wgetCommand = allDownloadUrls.map((url) => `wget "${url}"`).join('\n');
|
||||||
setDownloadResults(valid);
|
const aria2Command = allDownloadUrls.map((url) => `aria2c "${url}"`).join('\n');
|
||||||
setDownloadModalOpen(true);
|
|
||||||
setSelectedRows([]);
|
const copyAllUrls = () => {
|
||||||
} catch (error) {
|
navigator.clipboard.writeText(allDownloadUrls.join('\n')).then(() => {
|
||||||
message.error('获取下载地址失败');
|
message.success('已复制全部链接');
|
||||||
}
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const startDownloads = () => {
|
const startBrowserDownloads = () => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
downloadResults.forEach((item) => {
|
downloadResults.forEach((item) => {
|
||||||
item.urls.forEach((urlInfo) => {
|
item.urls.forEach((urlInfo) => {
|
||||||
@@ -161,6 +162,19 @@ export default function VideosPage() {
|
|||||||
message.success(`已尝试触发 ${count} 个下载任务`);
|
message.success(`已尝试触发 ${count} 个下载任务`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleBatchDownload = async () => {
|
||||||
|
const ids = selectedRows.map((v) => v.videoId);
|
||||||
|
try {
|
||||||
|
const results = await batchDownload(ids);
|
||||||
|
const valid = results.filter((r) => r.urls.length > 0);
|
||||||
|
setDownloadResults(valid);
|
||||||
|
setDownloadModalOpen(true);
|
||||||
|
setSelectedRows([]);
|
||||||
|
} catch (error) {
|
||||||
|
message.error('获取下载地址失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleRowClick = (record: VideoItem) => {
|
const handleRowClick = (record: VideoItem) => {
|
||||||
setDetail(record);
|
setDetail(record);
|
||||||
setDrawerOpen(true);
|
setDrawerOpen(true);
|
||||||
@@ -295,20 +309,30 @@ export default function VideosPage() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
title="批量下载地址"
|
title="批量下载"
|
||||||
open={downloadModalOpen}
|
open={downloadModalOpen}
|
||||||
width={800}
|
width={820}
|
||||||
onCancel={() => setDownloadModalOpen(false)}
|
onCancel={() => setDownloadModalOpen(false)}
|
||||||
footer={[
|
footer={[
|
||||||
<Button key="download" type="primary" onClick={startDownloads}>
|
|
||||||
开始下载
|
|
||||||
</Button>,
|
|
||||||
<Button key="close" onClick={() => setDownloadModalOpen(false)}>
|
<Button key="close" onClick={() => setDownloadModalOpen(false)}>
|
||||||
关闭
|
关闭
|
||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<div style={{ maxHeight: 400, overflow: 'auto' }}>
|
<Tabs
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: 'browser',
|
||||||
|
label: '浏览器下载',
|
||||||
|
children: (
|
||||||
|
<Space direction="vertical" style={{ width: '100%' }}>
|
||||||
|
<Button type="primary" onClick={startBrowserDownloads}>
|
||||||
|
开始浏览器下载
|
||||||
|
</Button>
|
||||||
|
<Text type="secondary">
|
||||||
|
将逐个创建下载任务,间隔 300ms,降低被浏览器拦截的概率。若被拦截,请使用「下载工具」方式。
|
||||||
|
</Text>
|
||||||
|
<div style={{ maxHeight: 320, overflow: 'auto' }}>
|
||||||
{downloadResults.map((item) => (
|
{downloadResults.map((item) => (
|
||||||
<div key={item.videoId} style={{ marginBottom: 12 }}>
|
<div key={item.videoId} style={{ marginBottom: 12 }}>
|
||||||
<Text strong>{item.title || item.videoId}</Text>
|
<Text strong>{item.title || item.videoId}</Text>
|
||||||
@@ -323,6 +347,60 @@ export default function VideosPage() {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'tools',
|
||||||
|
label: '下载工具',
|
||||||
|
children: (
|
||||||
|
<Space direction="vertical" style={{ width: '100%' }}>
|
||||||
|
<Button onClick={copyAllUrls}>复制全部链接</Button>
|
||||||
|
<div style={{ background: '#f6f8fa', padding: 16, borderRadius: 8 }}>
|
||||||
|
<Text strong>推荐方式</Text>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<Text>
|
||||||
|
复制全部链接后,使用 <Text code>aria2</Text> 或{' '}
|
||||||
|
<Text code>wget</Text> 等工具批量下载。
|
||||||
|
</Text>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Text>aria2 支持断点续传、多线程,适合下载大文件。</Text>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<Text strong>aria2 示例</Text>
|
||||||
|
<pre
|
||||||
|
style={{
|
||||||
|
background: '#1e1e1e',
|
||||||
|
color: '#d4d4d4',
|
||||||
|
padding: 12,
|
||||||
|
borderRadius: 4,
|
||||||
|
overflow: 'auto',
|
||||||
|
fontSize: 12,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{aria2Command || '# 暂无下载链接'}
|
||||||
|
</pre>
|
||||||
|
<Text strong>wget 示例</Text>
|
||||||
|
<pre
|
||||||
|
style={{
|
||||||
|
background: '#1e1e1e',
|
||||||
|
color: '#d4d4d4',
|
||||||
|
padding: 12,
|
||||||
|
borderRadius: 4,
|
||||||
|
overflow: 'auto',
|
||||||
|
fontSize: 12,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{wgetCommand || '# 暂无下载链接'}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Drawer
|
<Drawer
|
||||||
|
|||||||
Reference in New Issue
Block a user