Skip to content

Commit 5e777d6

Browse files
🎈 perf: 优化下载逻辑
1 parent 6dbbb3f commit 5e777d6

2 files changed

Lines changed: 53 additions & 11 deletions

File tree

src/components/Setting/LocalSetting.vue

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,14 @@
144144
</n-card>
145145
<n-card class="set-item">
146146
<div class="label">
147-
<n-text class="name">模拟播放下载</n-text>
147+
<n-text class="name">模拟播放下载<n-tag type="warning" size="small" round>Beta</n-tag></n-text>
148148
<n-text class="tip" :depth="3">使用播放接口进行下载,可能解决部分下载失败问题</n-text>
149149
</div>
150150
<n-switch
151-
v-model:value="settingStore.usePlaybackForDownload"
151+
:value="settingStore.usePlaybackForDownload"
152152
:round="false"
153153
class="set"
154+
@update:value="handlePlaybackDownloadChange"
154155
/>
155156
</n-card>
156157
<n-card class="set-item">
@@ -180,6 +181,23 @@ const choosePath = async () => {
180181
const path = await window.electron.ipcRenderer.invoke("choose-path");
181182
if (path) settingStore.downloadPath = path;
182183
};
184+
185+
// 模拟播放下载开关
186+
const handlePlaybackDownloadChange = (value: boolean) => {
187+
if (value) {
188+
window.$dialog.warning({
189+
title: "开启提示",
190+
content: "模拟播放下载可能导致部分音质歌词嵌入异常且未经完整测试可能有不稳定情况,确认要打开吗?",
191+
positiveText: "确认打开",
192+
negativeText: "取消",
193+
onPositiveClick: () => {
194+
settingStore.usePlaybackForDownload = true;
195+
},
196+
});
197+
} else {
198+
settingStore.usePlaybackForDownload = false;
199+
}
200+
};
183201
</script>
184202

185203
<style lang="scss" scoped>

src/utils/download.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,54 @@ interface DownloadOptions {
1212
quality: SongLevelType;
1313
downloadPath?: string;
1414
skipIfExist?: boolean;
15+
mode?: "standard" | "playback";
1516
}
1617

1718
export const downloadSong = async ({
1819
song,
1920
quality,
2021
downloadPath,
2122
skipIfExist,
23+
mode,
2224
}: DownloadOptions): Promise<{ success: boolean; skipped?: boolean; message?: string }> => {
2325
try {
2426
const settingStore = useSettingStore();
2527
let url = "";
2628
let type = "mp3";
2729

30+
const usePlayback = mode ? mode === "playback" : settingStore.usePlaybackForDownload;
31+
2832
// 获取下载链接
29-
if (settingStore.usePlaybackForDownload) {
30-
const levelName = songLevelData[quality].level;
31-
// @ts-ignore
32-
const result = await songUrl(song.id, levelName);
33-
if (result.code !== 200 || !result?.data?.[0]?.url) {
34-
return { success: false, message: result.message || "获取播放链接失败" };
33+
const levelName = songLevelData[quality].level;
34+
// songUrl 仅支持以下音质
35+
const allowedLevels = [
36+
"standard",
37+
"higher",
38+
"exhigh",
39+
"lossless",
40+
"hires",
41+
"jyeffect",
42+
"sky",
43+
"jymaster",
44+
];
45+
46+
// 如果开启了“使用播放链接下载”且音质支持,则尝试获取播放链接
47+
if (usePlayback && allowedLevels.includes(levelName)) {
48+
try {
49+
// @ts-ignore: levelName is checked against allowedLevels at runtime
50+
const result = await songUrl(song.id, levelName);
51+
if (result.code === 200 && result?.data?.[0]?.url) {
52+
url = result.data[0].url;
53+
type = (result.data[0].type || result.data[0].encodeType || "mp3").toLowerCase();
54+
}
55+
} catch (e) {
56+
console.error("Error fetching playback url for download:", e);
3557
}
36-
url = result.data[0].url;
37-
type = (result.data[0].type || result.data[0].encodeType || "mp3").toLowerCase();
38-
} else {
58+
}
59+
60+
// 如果没有获取到 URL (可能是因为没开启设置,或者音质不支持,或者获取失败),则使用标准下载接口
61+
if (!url) {
62+
3963
const result = await songDownloadUrl(song.id, quality);
4064
if (result.code !== 200 || !result?.data?.url) {
4165
return { success: false, message: result.message || "获取下载链接失败" };

0 commit comments

Comments
 (0)