[+] Fully implement netease import

This commit is contained in:
2025-11-19 23:07:36 +08:00
parent dbaca29397
commit 69c9e42a3c
3 changed files with 56 additions and 41 deletions
+18
View File
@@ -0,0 +1,18 @@
<script lang="ts">
import Dialog from "./Dialog.svelte";
let p: {
error?: string
} = $props()
let open = $derived(!!p.error)
</script>
<Dialog title="错误" bind:open buttons={[{
text: "刷新重试",
onclick: () => location.reload()
}]}>
<div class="text-red-500">
{p.error}
</div>
</Dialog>
+7 -1
View File
@@ -8,7 +8,13 @@ export async function post(endpoint: string, data: any) {
headers: {
'Content-Type': 'application/json'
}
}).then(res => res.json())
}).then(async res => {
if (res.status >= 400) throw new Error(`错误 ${res.status}${await res.text()}`)
return res.json()
}).catch(e => {
console.error(e)
throw e
})
}
export const API = {
+31 -40
View File
@@ -4,6 +4,7 @@
import Button from "../../../components/Button.svelte"
import type { NeteaseSongBrief } from "../../../shared/types"
import { API } from "../../../lib/client"
import ErrorDialog from "../../../components/status/ErrorDialog.svelte";
let link = $state('')
@@ -18,6 +19,8 @@
total: songs.length,
done: songs.filter(song => song.status !== 'importing').length
})
let error = $state('')
let id = $state('')
function statusToIcon(stat: string): string {
switch (stat) {
@@ -34,52 +37,34 @@
status = 'importing'
songs = []
try {
const data = await API.netease.startImport(link)
if (data.error) {
alert(data.error)
status = 'error'
return
}
const importId = data.id
songs = data.songs
pollProgress(importId)
} catch (e) {
console.error(e)
status = 'error'
alert('Failed to start import')
}
}
async function pollProgress(id: string) {
const interval = setInterval(async () => {
try {
const data = await API.netease.checkProgress(id)
if (data.error) {
clearInterval(interval)
return
}
API.netease.startImport(link)
.catch(e => error = e.message)
.then(data => {
id = data.playlistId
songs = data.songs
if (data.done) {
clearInterval(interval)
status = 'success'
}
} catch (e) {
console.error(e)
clearInterval(interval)
}
}, 1000)
const interval = setInterval(() => {
API.netease.checkProgress(data.id)
.catch(e => {
error = e.message
clearInterval(interval)
})
.then(data => {
songs = data.songs
if (data.done) {
clearInterval(interval)
status = 'success'
}
})
}, 1000)
})
}
</script>
<AppBar title="从网易云导入"/>
<ErrorDialog error={error} />
<div class="vbox gap-16px flex-1 min-h-0">
<div class="m3-font-body-medium mfg-on-surface-variant py-12px p-content">
去网易云 APP 找一个你喜欢的日本语歌单,点击分享,再点击复制链接,然后把链接粘贴到这里就可以开始导入了!
@@ -113,6 +98,12 @@
</div>
<div class="py-16px p-content">
<Button big icon="i-material-symbols:download" onclick={startImport} disabled={status === 'importing'}>开始导入</Button>
{#if status === 'idle'}
<Button big icon="i-material-symbols:download" onclick={startImport}>开始导入</Button>
{:else if status === 'success'}
<a href="/playlist/{id}">
<Button big icon="i-material-symbols:right-arrow">查看歌单</Button>
</a>
{/if}
</div>
</div>