[+] Fully implement netease import
This commit is contained in:
@@ -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
@@ -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 = {
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user