Merge pull request 'fix(downloadAll): 一点点修改' (#92) from awalol/um-react:fix-downloadall into main

Reviewed-on: https://git.unlock-music.dev/um/um-react/pulls/92
This commit is contained in:
鲁树人
2025-07-16 10:05:52 +00:00
6 changed files with 49 additions and 35 deletions

View File

@@ -69,7 +69,7 @@
- WSA 可以参考 [MagiskOnWSALocal](https://github.com/LSPosed/MagiskOnWSALocal) 的说明操作。 - WSA 可以参考 [MagiskOnWSALocal](https://github.com/LSPosed/MagiskOnWSALocal) 的说明操作。
- 雷电模拟器可以在「模拟器设置」 → 「其他设置」中启用 root 特权。 - 雷电模拟器可以在「模拟器设置」 → 「其他设置」中启用 root 特权。
![雷电模拟器 其他设置](../src/faq/assets/ld_settings_misc.webp) ![雷电模拟器 其他设置](../src/faq/assets/ld_settings_misc@2x.webp)
### Via 等浏览器无法正常解密/下载 ### Via 等浏览器无法正常解密/下载
@@ -87,10 +87,6 @@
- 无法下载解密后内容 - 无法下载解密后内容
- 下载的文件名错误 - 下载的文件名错误
### 新版解锁网站没有批量下载
目前没有做。抱歉。
## 仍有问题? ## 仍有问题?
欢迎进入[Telegram 交流群](https://t.me/unlock_music_chat),一起探讨。 欢迎进入[Telegram 交流群](https://t.me/unlock_music_chat),一起探讨。

View File

@@ -65,3 +65,12 @@ h6 {
opacity: 0.75; opacity: 0.75;
} }
} }
#downloadAll {
position: absolute;
right: 0.5em;
bottom: 72px;
width: 48px;
height: 48px;
margin: 10px;
}

View File

@@ -15,7 +15,6 @@ import { Bounce, ToastContainer } from 'react-toastify';
import { SettingsHome } from '~/features/settings/SettingsHome'; import { SettingsHome } from '~/features/settings/SettingsHome';
import { FAQ_PAGES } from '~/faq/FAQPages'; import { FAQ_PAGES } from '~/faq/FAQPages';
import { FaqHome } from '~/faq/FaqHome'; import { FaqHome } from '~/faq/FaqHome';
import { DownloadAll } from '~/components/DownloadAll.tsx';
// Private to this file only. // Private to this file only.
const store = setupStore(); const store = setupStore();
@@ -72,7 +71,6 @@ export function AppRoot() {
transition={Bounce} transition={Bounce}
/> />
<DownloadAll />
<Footer /> <Footer />
</Provider> </Provider>
</BrowserRouter> </BrowserRouter>

View File

@@ -1,49 +1,68 @@
import { DecryptedAudioFile, selectFiles } from '~/features/file-listing/fileListingSlice'; import { DecryptedAudioFile, ProcessState, selectFiles } from '~/features/file-listing/fileListingSlice';
import { FaDownload } from 'react-icons/fa'; import { FaDownload } from 'react-icons/fa';
import { useAppSelector } from '~/hooks'; import { useAppSelector } from '~/hooks';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
export function DownloadAll() { export function DownloadAll() {
const files = useAppSelector(selectFiles); const files = useAppSelector(selectFiles);
const filesLength = Object.keys(files).length;
const onClickDownloadAll = async () => { const onClickDownloadAll = async () => {
console.time('DownloadAll'); //开始计时
const fileCount = Object.keys(files).length;
if (fileCount === 0) {
toast.warning('未添加文件');
return;
}
//判断所有文件是否处理完成
const allComplete = Object.values(files).every((file) => file.state !== ProcessState.PROCESSING);
if (!allComplete) {
toast.warning('请等待所有文件解密完成');
return;
}
//过滤处理失败的文件
const completeFiles = Object.values(files).filter((file) => file.state === ProcessState.COMPLETE);
//开始下载
let dir: FileSystemDirectoryHandle | undefined; let dir: FileSystemDirectoryHandle | undefined;
let success = 0;
try { try {
dir = await window.showDirectoryPicker(); dir = await window.showDirectoryPicker({ mode: 'readwrite' });
} catch (e) { } catch (e) {
console.error(e); console.error(e);
if (e instanceof Error && e.name === 'AbortError') { if (e instanceof Error && e.name === 'AbortError') {
return; return;
} }
} }
for (const [_, file] of Object.entries(files)) { toast.warning('开始下载,请稍候');
const promises = Object.values(completeFiles).map(async (file) => {
console.log(`开始下载: ${file.fileName}`);
try { try {
if (dir) { if (dir) {
await DownloadNew(dir, file); await DownloadNew(dir, file);
} else { } else {
await DownloadOld(file); await DownloadOld(file);
} }
success++; console.log(`成功下载: ${file.fileName}`);
} catch (e) { } catch (e) {
console.error(`下载失败: ${file.fileName}`, e); console.error(`下载失败: ${file.fileName}`, e);
toast.error(`出现错误: ${e}`); toast.error(`出现错误: ${e}`);
throw e;
} }
} });
if (success === filesLength) { await Promise.allSettled(promises).then((f) => {
toast.success(`成功下载: ${success}/${filesLength}`); const success = f.filter((result) => result.status === 'fulfilled').length;
if (success === fileCount) {
toast.success(`成功下载: ${success}/${fileCount}`);
} else { } else {
toast.error(`成功下载: ${success}/${filesLength}`); toast.warning(`成功下载: ${success}/${fileCount}`);
} }
});
console.timeEnd('DownloadAll'); //停止计时
}; };
return ( return (
<button <button className="btn btn-primary" id="downloadAll" onClick={onClickDownloadAll} title="下载全部">
style={{ width: '48px', height: '48px', paddingInline: '0px', margin: '10px', marginLeft: 'auto' }}
className="btn btn-primary"
onClick={onClickDownloadAll}
title="下载全部"
>
<FaDownload /> <FaDownload />
</button> </button>
); );

View File

@@ -1,6 +1,5 @@
import { ExtLink } from '~/components/ExtLink'; import { ExtLink } from '~/components/ExtLink';
import { Header2, Header3, Header4 } from '~/components/HelpText/Headers'; import { Header2, Header3, Header4 } from '~/components/HelpText/Headers';
import { ProjectIssue } from '~/components/ProjectIssue';
import { NavLink } from 'react-router'; import { NavLink } from 'react-router';
@@ -12,15 +11,6 @@ export function OtherFAQ() {
<p></p> <p></p>
<p>使</p> <p>使</p>
<Header3 id="batch-dl"></Header3>
<p>
{'暂时没有实现,不过你可以在 '}
<ProjectIssue id={34} title="[UI] 全部下载功能" />
{' 以及 '}
<ProjectIssue id={43} title="批量下载" />
{' 追踪该问题。'}
</p>
<Header3 id="android-browsers">安卓: 浏览器支持说明</Header3> <Header3 id="android-browsers">安卓: 浏览器支持说明</Header3>
<p> 使 Chrome Firefox </p> <p> 使 Chrome Firefox </p>
<div className="flex flex-col md:flex-row gap-2 md:gap-8"> <div className="flex flex-col md:flex-row gap-2 md:gap-8">

View File

@@ -1,5 +1,6 @@
import { RiErrorWarningLine } from 'react-icons/ri'; import { RiErrorWarningLine } from 'react-icons/ri';
import { SelectFile } from '../components/SelectFile'; import { SelectFile } from '../components/SelectFile';
import { DownloadAll } from '~/components/DownloadAll.tsx';
import { FileListing } from '~/features/file-listing/FileListing'; import { FileListing } from '~/features/file-listing/FileListing';
import { useAppDispatch, useAppSelector } from '~/hooks.ts'; import { useAppDispatch, useAppSelector } from '~/hooks.ts';
@@ -39,6 +40,7 @@ export function MainTab() {
<div className="w-full mt-4"> <div className="w-full mt-4">
<FileListing /> <FileListing />
</div> </div>
<DownloadAll />
</div> </div>
</div> </div>
); );