mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-06 18:36:55 +08:00
nothing
This commit is contained in:
18
src/App.vue
18
src/App.vue
@@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<NMessageProvider>
|
||||
<NConfigProvider :theme-overrides="themeOverrides" style="height: 100vh">
|
||||
<ViewerLayout v-if="layout == 'viewer'" />
|
||||
<ManageLayout v-else-if="layout == 'manage'" />
|
||||
<template v-else>
|
||||
<RouterView />
|
||||
</template>
|
||||
</NConfigProvider>
|
||||
<NNotificationProvider>
|
||||
<NConfigProvider :theme-overrides="themeOverrides" :locale="zhCN" style="height: 100vh">
|
||||
<ViewerLayout v-if="layout == 'viewer'" />
|
||||
<ManageLayout v-else-if="layout == 'manage'" />
|
||||
<template v-else>
|
||||
<RouterView />
|
||||
</template>
|
||||
</NConfigProvider>
|
||||
</NNotificationProvider>
|
||||
</NMessageProvider>
|
||||
</template>
|
||||
|
||||
@@ -14,7 +16,7 @@
|
||||
import ViewerLayout from '@/views/ViewerLayout.vue'
|
||||
import ManageLayout from '@/views/ManageLayout.vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { NConfigProvider, NMessageProvider } from 'naive-ui'
|
||||
import { NConfigProvider, NMessageProvider, NNotificationProvider, zhCN } from 'naive-ui'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
@@ -24,14 +24,31 @@ export interface AccountInfo extends UserInfo {
|
||||
biliVerifyCode?: string
|
||||
emailVerifyUrl?: string
|
||||
}
|
||||
export interface SongsInfo {
|
||||
id: string
|
||||
export interface SongAuthorInfo {
|
||||
name: string
|
||||
author: string
|
||||
url: string
|
||||
cover: string
|
||||
from: string
|
||||
language: string
|
||||
desc: string
|
||||
tags: string[]
|
||||
id: number
|
||||
}
|
||||
export enum SongFrom {
|
||||
Custom,
|
||||
Netease,
|
||||
FiveSing,
|
||||
}
|
||||
export interface SongsInfo {
|
||||
id: number
|
||||
key: string
|
||||
name: string
|
||||
author: string[]
|
||||
url: string
|
||||
from: SongFrom
|
||||
language: SongLanguage[]
|
||||
description?: string
|
||||
tags?: string[]
|
||||
}
|
||||
export enum SongLanguage {
|
||||
Chinese, // 中文
|
||||
English, // 英文
|
||||
Japanese, // 日文
|
||||
Spanish, // 西班牙文
|
||||
French, // 法文
|
||||
Other, //其他
|
||||
}
|
||||
|
||||
@@ -1,14 +1,58 @@
|
||||
<script setup lang="ts">
|
||||
import { SongsInfo } from '@/api/api-models'
|
||||
import { DataTableColumns, NAvatar, NButton, NCollapseTransition, NDataTable, NInput, NList, NListItem, NSpace } from 'naive-ui'
|
||||
import { onMounted, h, ref } from 'vue'
|
||||
import { SongAuthorInfo, SongFrom, SongLanguage, SongsInfo } from '@/api/api-models'
|
||||
import { QueryPostAPI } from '@/api/query'
|
||||
import { SONG_API_URL } from '@/data/constants'
|
||||
import {
|
||||
DataTableColumns,
|
||||
FormInst,
|
||||
FormRules,
|
||||
NAvatar,
|
||||
NButton,
|
||||
NCollapseTransition,
|
||||
NDataTable,
|
||||
NDivider,
|
||||
NEllipsis,
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NList,
|
||||
NListItem,
|
||||
NModal,
|
||||
NSelect,
|
||||
NSpace,
|
||||
NTag,
|
||||
NText,
|
||||
useMessage,
|
||||
} from 'naive-ui'
|
||||
import { onMounted, h, ref, watch } from 'vue'
|
||||
import APlayer from 'vue3-aplayer'
|
||||
|
||||
const props = defineProps<{
|
||||
songs: SongsInfo[]
|
||||
canEdit?: boolean
|
||||
}>()
|
||||
const songsInternal = ref<{ [id: string]: SongsInfo }>({})
|
||||
watch(
|
||||
() => props.songs,
|
||||
(newV) => {
|
||||
let map = new Map()
|
||||
newV.forEach((s) => {
|
||||
s.tags?.forEach((t) => map.set(t, t))
|
||||
})
|
||||
map.forEach((tag) => {
|
||||
tagsSelectOption.value.push({
|
||||
label: tag,
|
||||
value: tag,
|
||||
})
|
||||
})
|
||||
songsInternal.value = newV
|
||||
}
|
||||
)
|
||||
const songsInternal = ref(props.songs)
|
||||
const message = useMessage()
|
||||
|
||||
const showModal = ref(false)
|
||||
const updateSongModel = ref<SongsInfo>({} as SongsInfo)
|
||||
|
||||
const columns = ref<DataTableColumns<SongsInfo>>()
|
||||
const aplayerMusic = ref<{
|
||||
title: string
|
||||
@@ -17,91 +61,115 @@ const aplayerMusic = ref<{
|
||||
pic: string
|
||||
}>()
|
||||
|
||||
const createColumns = (): DataTableColumns<SongsInfo> => [
|
||||
{
|
||||
title: '',
|
||||
key: 'cover',
|
||||
resizable: false,
|
||||
width: 50,
|
||||
render(data) {
|
||||
return h(NAvatar, {
|
||||
src: data.cover,
|
||||
imgProps: {},
|
||||
})
|
||||
const formRef = ref<FormInst | null>(null)
|
||||
const updateSongRules: FormRules = {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入歌曲名称',
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码',
|
||||
},
|
||||
],
|
||||
}
|
||||
const songSelectOption = [
|
||||
{
|
||||
label: '中文',
|
||||
value: SongLanguage.Chinese,
|
||||
},
|
||||
{
|
||||
label: '日语',
|
||||
value: SongLanguage.Japanese,
|
||||
},
|
||||
{
|
||||
label: '英语',
|
||||
value: SongLanguage.English,
|
||||
},
|
||||
{
|
||||
label: '法语',
|
||||
value: SongLanguage.French,
|
||||
},
|
||||
{
|
||||
label: '西语',
|
||||
value: SongLanguage.Spanish,
|
||||
},
|
||||
{
|
||||
label: '其他',
|
||||
value: SongLanguage.Other,
|
||||
},
|
||||
]
|
||||
const tagsSelectOption = ref<{ label: string; value: string }[]>([])
|
||||
|
||||
const createColumns = (): DataTableColumns<SongsInfo> => [
|
||||
{
|
||||
title: '名称',
|
||||
key: 'name',
|
||||
resizable: true,
|
||||
minWidth: 100,
|
||||
sorter: 'default',
|
||||
render(data) {
|
||||
return props.canEdit
|
||||
? h(NInput, {
|
||||
value: data.name,
|
||||
onUpdateValue(v) {
|
||||
songsInternal.value[data.id].name = v
|
||||
},
|
||||
})
|
||||
: h('span', data.name)
|
||||
return h('span', data.name)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '作者',
|
||||
key: 'author',
|
||||
key: 'artist',
|
||||
resizable: true,
|
||||
render(data) {
|
||||
return props.canEdit
|
||||
? h(NInput, {
|
||||
value: data.author,
|
||||
onUpdateValue(v) {
|
||||
songsInternal.value[data.id].author = v
|
||||
},
|
||||
})
|
||||
: h('span', data.author)
|
||||
return h(NSpace, { size: 5 }, () => data.author.map((a) => h(NTag, { bordered: false, size: 'small', type: 'info' }, () => a)))
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
key: 'description',
|
||||
resizable: true,
|
||||
minWidth: 75,
|
||||
render(data) {
|
||||
return props.canEdit
|
||||
? h(NInput, {
|
||||
value: data.desc,
|
||||
onUpdateValue(v) {
|
||||
songsInternal.value[data.id].desc = v
|
||||
},
|
||||
})
|
||||
: h('span', data.desc)
|
||||
return h(NEllipsis, () => data.description)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '标签',
|
||||
key: 'tags',
|
||||
resizable: true,
|
||||
render(data) {
|
||||
return (data.tags?.length ?? 0) > 0 ? h(NSpace, { size: 5 }, () => data.tags?.map((a) => h(NTag, { bordered: false, size: 'small' }, () => a))) : null
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'manage',
|
||||
minWidth: 75,
|
||||
disabled: () => !props.canEdit,
|
||||
width: 200,
|
||||
render(data) {
|
||||
return h(NSpace, [
|
||||
return h(NSpace, () => [
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
onClick: () => console.log(1),
|
||||
size:'small',
|
||||
onClick: () => {
|
||||
updateSongModel.value = JSON.parse(JSON.stringify(data))
|
||||
showModal.value = true
|
||||
},
|
||||
},
|
||||
{
|
||||
default: () => '保存',
|
||||
default: () => '修改',
|
||||
}
|
||||
),
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
type: 'primary',
|
||||
size:'small',
|
||||
onClick: () => {
|
||||
aplayerMusic.value = {
|
||||
title: data.name,
|
||||
artist: data.author,
|
||||
artist: data.author.join('/') ?? '',
|
||||
src: data.url,
|
||||
pic: data.cover,
|
||||
pic: '',
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -109,22 +177,85 @@ const createColumns = (): DataTableColumns<SongsInfo> => [
|
||||
default: () => '播放',
|
||||
}
|
||||
),
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
type: 'error',
|
||||
size:'small',
|
||||
onClick: () => {
|
||||
aplayerMusic.value = {
|
||||
title: data.name,
|
||||
artist: data.author.join('/') ?? '',
|
||||
src: data.url,
|
||||
pic: '',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
default: () => '删除',
|
||||
}
|
||||
),
|
||||
])
|
||||
},
|
||||
},
|
||||
]
|
||||
onMounted(() => {
|
||||
props.songs.forEach((song) => {
|
||||
songsInternal.value[song.id] = song
|
||||
function renderCell(value: string | number) {
|
||||
if (!value) {
|
||||
return h(NText, { depth: 3 }, { default: () => '未填写' })
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
async function updateSong() {
|
||||
await QueryPostAPI<SongsInfo>(SONG_API_URL + 'update', {
|
||||
key: updateSongModel.value.key,
|
||||
song: updateSongModel.value,
|
||||
}).then((data) => {
|
||||
if (data.code == 200) {
|
||||
const index = songsInternal.value.findIndex((s) => s.key == data.data.key)
|
||||
songsInternal.value.splice(index, 1, data.data)
|
||||
message.success('已更新歌曲信息')
|
||||
} else {
|
||||
message.error('未能更新歌曲信息: ' + data.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
songsInternal.value = props.songs
|
||||
columns.value = createColumns()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
歌单 {{ songs.length }}
|
||||
歌单 {{ songsInternal.length }}
|
||||
<Transition>
|
||||
<APlayer v-if="aplayerMusic" :music="aplayerMusic" />
|
||||
</Transition>
|
||||
<NDataTable :columns="columns" :data="songs"> </NDataTable>
|
||||
<NDataTable :columns="columns" :data="songsInternal"> </NDataTable>
|
||||
<NModal v-model:show="showModal" style="max-width: 600px" preset="card">
|
||||
<template #header> 修改信息 </template>
|
||||
<NForm ref="formRef" :rules="updateSongRules" :model="updateSongModel" :render-cell="renderCell">
|
||||
<NFormItem path="name" label="名称">
|
||||
<NInput v-model:value="updateSongModel.name" autosize style="min-width: 200px" placeholder="就是歌曲名称" />
|
||||
</NFormItem>
|
||||
<NFormItem path="author" label="作者">
|
||||
<NSelect v-model:value="updateSongModel.author" filterable multiple tag placeholder="输入,按回车确认" :show-arrow="false" :show="false" />
|
||||
</NFormItem>
|
||||
<NFormItem path="description" label="备注">
|
||||
<NInput v-model:value="updateSongModel.description" placeholder="可选" :maxlength="250" show-count autosize style="min-width: 300px" clearable />
|
||||
</NFormItem>
|
||||
<NFormItem path="language" label="语言">
|
||||
<NSelect v-model:value="updateSongModel.language" multiple :options="songSelectOption" placeholder="可选" />
|
||||
</NFormItem>
|
||||
<NFormItem path="tags" label="标签">
|
||||
<NSelect v-model:value="updateSongModel.tags" filterable multiple tag placeholder="可选,按回车确认" :show-arrow="false" :show="false" :options="tagsSelectOption" />
|
||||
</NFormItem>
|
||||
<NFormItem path="url" label="链接">
|
||||
<NInput v-model:value="updateSongModel.url" placeholder="可选, 后缀为mp3、wav、ogg时将会尝试播放, 否则会在新页面打开" :disabled="updateSongModel.from != SongFrom.Custom" />
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<NDivider style="margin: 10px" />
|
||||
<NButton @click="updateSong"> 更新 </NButton>
|
||||
</NModal>
|
||||
</template>
|
||||
|
||||
@@ -8,3 +8,4 @@ export const TURNSTILE_KEY = '0x4AAAAAAAETUSAKbds019h0'
|
||||
export const USER_API_URL = `${BASE_API}user/`
|
||||
export const ACCOUNT_API_URL = `${BASE_API}account/`
|
||||
export const BILI_API_URL = `${BASE_API}bili/`
|
||||
export const SONG_API_URL = `${BASE_API}song-list/`
|
||||
|
||||
@@ -1,11 +1,241 @@
|
||||
<script setup lang="ts">
|
||||
import { SongsInfo } from '@/api/api-models'
|
||||
import { useAccount } from '@/api/account'
|
||||
import { SongFrom, SongLanguage, SongsInfo } from '@/api/api-models'
|
||||
import { QueryGetAPI, QueryPostAPI } from '@/api/query'
|
||||
import SongList from '@/components/SongList.vue'
|
||||
import { ref } from 'vue'
|
||||
import { SONG_API_URL } from '@/data/constants'
|
||||
import { ca } from 'date-fns/locale'
|
||||
import { FormInst, FormRules, NButton, NDivider, NForm, NFormItem, NInput, NInputGroup, NInputGroupLabel, NModal, NSelect, NSpace, NSpin, NTabPane, NTabs, NTag, NTransfer, useMessage } from 'naive-ui'
|
||||
import { Option } from 'naive-ui/es/transfer/src/interface'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
|
||||
const message = useMessage()
|
||||
const accountInfo = useAccount()
|
||||
|
||||
const showModal = ref(false)
|
||||
const neteaseIdInput = ref()
|
||||
const isModalLoading = ref(false)
|
||||
|
||||
const neteaseSongListId = computed(() => {
|
||||
try {
|
||||
const url = new URL(neteaseIdInput.value)
|
||||
console.log(url)
|
||||
if (url.host == 'music.163.com') {
|
||||
let regex = /id=(\d+)/
|
||||
|
||||
// 使用exec方法在链接中查找匹配项
|
||||
let match = regex.exec(neteaseIdInput.value)
|
||||
|
||||
// 如果找到了匹配项,那么match[1]就是分组1的值,也就是id的值
|
||||
if (match) {
|
||||
return Number(match[1])
|
||||
}
|
||||
}
|
||||
} catch (err) {}
|
||||
try {
|
||||
return Number(neteaseIdInput.value)
|
||||
} catch {}
|
||||
return null
|
||||
})
|
||||
|
||||
const songs = ref<SongsInfo[]>([])
|
||||
const neteaseSongs = ref<SongsInfo[]>([])
|
||||
const neteaseSongsOptions = ref<Option[]>([])
|
||||
const selectedNeteaseSongs = ref<string[]>([])
|
||||
|
||||
const formRef = ref<FormInst | null>(null)
|
||||
const addSongModel = ref<SongsInfo>({} as SongsInfo)
|
||||
const addSongRules: FormRules = {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入歌曲名称',
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码',
|
||||
},
|
||||
],
|
||||
}
|
||||
const songSelectOption = [
|
||||
{
|
||||
label: '中文',
|
||||
value: SongLanguage.Chinese,
|
||||
},
|
||||
{
|
||||
label: '日语',
|
||||
value: SongLanguage.Japanese,
|
||||
},
|
||||
{
|
||||
label: '英语',
|
||||
value: SongLanguage.English,
|
||||
},
|
||||
{
|
||||
label: '法语',
|
||||
value: SongLanguage.French,
|
||||
},
|
||||
{
|
||||
label: '西语',
|
||||
value: SongLanguage.Spanish,
|
||||
},
|
||||
{
|
||||
label: '其他',
|
||||
value: SongLanguage.Other,
|
||||
},
|
||||
]
|
||||
|
||||
async function addCustomSong() {
|
||||
isModalLoading.value = true
|
||||
formRef.value
|
||||
?.validate()
|
||||
.then(async () => {
|
||||
await addSongs([addSongModel.value], SongFrom.Custom)
|
||||
.then((data) => {
|
||||
if (data.code == 200) {
|
||||
if (data.data.length == 1) {
|
||||
message.success('成功添加歌曲: ' + addSongModel.value.name)
|
||||
songs.value.push(data.data[0])
|
||||
addSongModel.value = {} as SongsInfo
|
||||
} else {
|
||||
message.error('未能添加歌曲, 已存在相同名称的曲目')
|
||||
}
|
||||
} else {
|
||||
message.error('添加失败: ' + data.message)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
message.error('添加失败')
|
||||
console.error(err)
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
isModalLoading.value = false
|
||||
})
|
||||
}
|
||||
async function addNeteaseSongs() {
|
||||
isModalLoading.value = true
|
||||
const selected = neteaseSongs.value.filter((s) => selectedNeteaseSongs.value.find((select) => s.key == select))
|
||||
await addSongs(selected, SongFrom.Netease)
|
||||
.then((data) => {
|
||||
if (data.code == 200) {
|
||||
message.success(`已添加 ${data.data.length} 首歌曲`)
|
||||
songs.value.push(...data.data)
|
||||
neteaseSongsOptions.value = neteaseSongs.value.map((s) => ({
|
||||
label: `${s.name} - ${s.author.join('/')}`,
|
||||
value: s.key,
|
||||
disabled: songs.value.findIndex((exist) => exist.id == s.id) > -1 || data.data.findIndex((add) => add.id == s.id) > -1,
|
||||
}))
|
||||
} else {
|
||||
message.error('添加失败: ' + data.message)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
message.error('添加失败')
|
||||
console.error(err)
|
||||
})
|
||||
.finally(() => {
|
||||
isModalLoading.value = false
|
||||
})
|
||||
}
|
||||
async function addSongs(songsShoudAdd: SongsInfo[], from: SongFrom) {
|
||||
return QueryPostAPI<SongsInfo[]>(
|
||||
SONG_API_URL + 'add',
|
||||
songsShoudAdd.map((s) => ({
|
||||
Name: s.name,
|
||||
Id: from == SongFrom.Custom ? -1 : s.id,
|
||||
From: from,
|
||||
Author: s.author,
|
||||
Url: s.url,
|
||||
Description: s.description,
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
async function getNeteaseSongList() {
|
||||
isModalLoading.value = true
|
||||
await QueryGetAPI<SongsInfo[]>(SONG_API_URL + 'get-netease-list', {
|
||||
id: neteaseSongListId.value,
|
||||
})
|
||||
.then((data) => {
|
||||
if (data.code == 200) {
|
||||
neteaseSongs.value = data.data
|
||||
neteaseSongsOptions.value = data.data.map((s) => ({
|
||||
label: `${s.name} - ${s.author.join('/')}`,
|
||||
value: s.key,
|
||||
disabled: songs.value.findIndex((exist) => exist.id == s.id) > -1,
|
||||
}))
|
||||
message.success(`成功获取歌曲信息, 共 ${data.data.length} 条, 歌单中已存在 ${neteaseSongsOptions.value.filter((s) => s.disabled).length} 首`)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
message.error(err)
|
||||
})
|
||||
.finally(() => {
|
||||
isModalLoading.value = false
|
||||
})
|
||||
}
|
||||
async function getSongs() {
|
||||
await QueryGetAPI<any>(SONG_API_URL + 'get', {
|
||||
uId: accountInfo.value?.biliId,
|
||||
}).then((data) => {
|
||||
if (data.code == 200) {
|
||||
songs.value = data.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await getSongs()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NButton @click="showModal = true"> 添加歌曲 </NButton>
|
||||
<NModal v-model:show="showModal" style="max-width: 600px" preset="card">
|
||||
<template #header> 添加歌曲 </template>
|
||||
<NSpin :show="isModalLoading">
|
||||
<NTabs default-value="custom" animated>
|
||||
<NTabPane name="custom" tab="手动录入">
|
||||
<NForm ref="formRef" :rules="addSongRules" :model="addSongModel">
|
||||
<NFormItem path="name" label="名称">
|
||||
<NInput v-model:value="addSongModel.name" autosize style="min-width: 200px" placeholder="就是歌曲名称" />
|
||||
</NFormItem>
|
||||
<NFormItem path="author" label="作者">
|
||||
<NSelect v-model:value="addSongModel.author" filterable multiple tag placeholder="输入,按回车确认" :show-arrow="false" :show="false" />
|
||||
</NFormItem>
|
||||
<NFormItem path="description" label="备注">
|
||||
<NInput v-model:value="addSongModel.description" placeholder="可选" :maxlength="250" show-count autosize style="min-width: 300px" clearable />
|
||||
</NFormItem>
|
||||
<NFormItem path="language" label="语言">
|
||||
<NSelect v-model:value="addSongModel.language" multiple :options="songSelectOption" placeholder="可选" />
|
||||
</NFormItem>
|
||||
<NFormItem path="url" label="链接">
|
||||
<NInput v-model:value="addSongModel.url" placeholder="可选, 后缀为mp3、wav、ogg时将会尝试播放, 否则会在新页面打开" />
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<NButton type="primary" @click="addCustomSong"> 添加 </NButton>
|
||||
</NTabPane>
|
||||
<NTabPane name="netease" tab="从网易云歌单导入">
|
||||
<NInput clearable style="width: 100%" autosize :status="neteaseSongListId ? 'success' : 'error'" v-model:value="neteaseIdInput" placeholder="直接输入歌单Id或者网页链接">
|
||||
<template #suffix>
|
||||
<NTag v-if="neteaseSongListId" type="success" size="small"> 歌单Id: {{ neteaseSongListId }} </NTag>
|
||||
</template>
|
||||
</NInput>
|
||||
<NDivider style="margin: 10px" />
|
||||
<NButton type="primary" @click="getNeteaseSongList"> 获取 </NButton>
|
||||
<template v-if="neteaseSongsOptions.length > 0">
|
||||
<NDivider style="margin: 10px" />
|
||||
<NTransfer style="height: 500px" ref="transfer" v-model:value="selectedNeteaseSongs" :options="neteaseSongsOptions" source-filterable />
|
||||
<NDivider style="margin: 10px" />
|
||||
<NButton type="primary" @click="addNeteaseSongs"> 添加到歌单 | {{ selectedNeteaseSongs.length }} 首 </NButton>
|
||||
</template>
|
||||
</NTabPane>
|
||||
<NTabPane name="5sing" tab="从5sing搜索"> </NTabPane>
|
||||
</NTabs>
|
||||
</NSpin>
|
||||
</NModal>
|
||||
<SongList :songs="songs" />
|
||||
</template>
|
||||
|
||||
@@ -1,55 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { SongsInfo } from '@/api/api-models'
|
||||
import { QueryGetPaginationAPI } from '@/api/query'
|
||||
import { QueryGetAPI, QueryGetPaginationAPI } from '@/api/query'
|
||||
import SongList from '@/components/SongList.vue'
|
||||
import { USER_API_URL } from '@/data/constants'
|
||||
import { SONG_API_URL, USER_API_URL } from '@/data/constants'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRouteParams } from '@vueuse/router'
|
||||
import { useAccount } from '@/api/account'
|
||||
|
||||
const accountInfo = useAccount()
|
||||
const songs = ref<SongsInfo[]>()
|
||||
const uId = useRouteParams('id', '-1', { transform: Number })
|
||||
|
||||
async function RequestData() {
|
||||
songs.value = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'test',
|
||||
author: '雪路',
|
||||
url: 'https://music.163.com/song/media/outer/url?id=1995844771.mp3',
|
||||
cover: 'https://ukamnads.icu/file/components.png',
|
||||
from: '网易云',
|
||||
language: '中文',
|
||||
desc: 'xuelu',
|
||||
tags: ['hao'],
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'test2',
|
||||
author: '雪路2',
|
||||
url: 'https://music.163.com/song/media/outer/url?id=1995844771.mp3',
|
||||
cover: 'https://ukamnads.icu/file/components.png',
|
||||
from: '网易云2',
|
||||
language: '中文2',
|
||||
desc: 'xuelu',
|
||||
tags: ['hao'],
|
||||
},
|
||||
]
|
||||
await QueryGetPaginationAPI<SongsInfo[]>(`${USER_API_URL}info`, {
|
||||
async function getSongs() {
|
||||
await QueryGetAPI<SongsInfo[]>(SONG_API_URL + 'get', {
|
||||
uId: uId.value,
|
||||
}).then((data) => {
|
||||
if (data.code == 200) {
|
||||
songs.value = data.data
|
||||
}
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.code == 200) {
|
||||
songs.value = result.data.datas
|
||||
} else {
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await RequestData()
|
||||
await getSongs()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user