[+] 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: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'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 = {
|
export const API = {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import Button from "../../../components/Button.svelte"
|
import Button from "../../../components/Button.svelte"
|
||||||
import type { NeteaseSongBrief } from "../../../shared/types"
|
import type { NeteaseSongBrief } from "../../../shared/types"
|
||||||
import { API } from "../../../lib/client"
|
import { API } from "../../../lib/client"
|
||||||
|
import ErrorDialog from "../../../components/status/ErrorDialog.svelte";
|
||||||
|
|
||||||
let link = $state('')
|
let link = $state('')
|
||||||
|
|
||||||
@@ -18,6 +19,8 @@
|
|||||||
total: songs.length,
|
total: songs.length,
|
||||||
done: songs.filter(song => song.status !== 'importing').length
|
done: songs.filter(song => song.status !== 'importing').length
|
||||||
})
|
})
|
||||||
|
let error = $state('')
|
||||||
|
let id = $state('')
|
||||||
|
|
||||||
function statusToIcon(stat: string): string {
|
function statusToIcon(stat: string): string {
|
||||||
switch (stat) {
|
switch (stat) {
|
||||||
@@ -34,52 +37,34 @@
|
|||||||
status = 'importing'
|
status = 'importing'
|
||||||
songs = []
|
songs = []
|
||||||
|
|
||||||
try {
|
API.netease.startImport(link)
|
||||||
const data = await API.netease.startImport(link)
|
.catch(e => error = e.message)
|
||||||
|
.then(data => {
|
||||||
if (data.error) {
|
id = data.playlistId
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
songs = data.songs
|
songs = data.songs
|
||||||
|
|
||||||
if (data.done) {
|
const interval = setInterval(() => {
|
||||||
clearInterval(interval)
|
API.netease.checkProgress(data.id)
|
||||||
status = 'success'
|
.catch(e => {
|
||||||
}
|
error = e.message
|
||||||
} catch (e) {
|
clearInterval(interval)
|
||||||
console.error(e)
|
})
|
||||||
clearInterval(interval)
|
.then(data => {
|
||||||
}
|
songs = data.songs
|
||||||
}, 1000)
|
if (data.done) {
|
||||||
|
clearInterval(interval)
|
||||||
|
status = 'success'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<AppBar title="从网易云导入"/>
|
<AppBar title="从网易云导入"/>
|
||||||
|
|
||||||
|
<ErrorDialog error={error} />
|
||||||
|
|
||||||
<div class="vbox gap-16px flex-1 min-h-0">
|
<div class="vbox gap-16px flex-1 min-h-0">
|
||||||
<div class="m3-font-body-medium mfg-on-surface-variant py-12px p-content">
|
<div class="m3-font-body-medium mfg-on-surface-variant py-12px p-content">
|
||||||
去网易云 APP 找一个你喜欢的日本语歌单,点击分享,再点击复制链接,然后把链接粘贴到这里就可以开始导入了!
|
去网易云 APP 找一个你喜欢的日本语歌单,点击分享,再点击复制链接,然后把链接粘贴到这里就可以开始导入了!
|
||||||
@@ -113,6 +98,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="py-16px p-content">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
Reference in New Issue
Block a user