improve add song function

This commit is contained in:
2024-11-25 09:57:12 +08:00
parent 7499298a8b
commit edf59e2082
3 changed files with 98 additions and 166 deletions

View File

@@ -4,6 +4,7 @@ import { QueryGetAPI } from '@/api/query'
import { SONG_API_URL } from '@/data/constants' import { SONG_API_URL } from '@/data/constants'
import { NEmpty } from 'naive-ui' import { NEmpty } from 'naive-ui'
import { computed, ref, watch } from 'vue' import { computed, ref, watch } from 'vue'
// @ts-ignore
import APlayer from 'vue3-aplayer' import APlayer from 'vue3-aplayer'
const props = defineProps<{ const props = defineProps<{

View File

@@ -18,6 +18,7 @@ import {
NButton, NButton,
NCheckbox, NCheckbox,
NDivider, NDivider,
NFlex,
NForm, NForm,
NFormItem, NFormItem,
NIcon, NIcon,
@@ -57,6 +58,8 @@ const neteaseIdInput = ref()
const fivesingSearchInput = ref() const fivesingSearchInput = ref()
const isModalLoading = ref(false) const isModalLoading = ref(false)
const onlyResetNameOnAdded = ref(true)
const neteaseSongListId = computed(() => { const neteaseSongListId = computed(() => {
try { try {
const url = new URL(neteaseIdInput.value) const url = new URL(neteaseIdInput.value)
@@ -72,10 +75,10 @@ const neteaseSongListId = computed(() => {
return Number(match[1]) return Number(match[1])
} }
} }
} catch (err) {} } catch (err) { }
try { try {
return Number(neteaseIdInput.value) return Number(neteaseIdInput.value)
} catch {} } catch { }
return null return null
}) })
@@ -89,6 +92,7 @@ const fivesingTotalPageCount = ref(1)
const fivesingCurrentPage = ref(1) const fivesingCurrentPage = ref(1)
const isGettingFivesingSongPlayUrl = ref(0) const isGettingFivesingSongPlayUrl = ref(0)
const showModalRenderKey = ref(0)
const authors = computed(() => { const authors = computed(() => {
return new List(songs.value) return new List(songs.value)
@@ -140,6 +144,10 @@ const songSelectOption = [
label: '英语', label: '英语',
value: '英语', value: '英语',
}, },
{
label: '韩语',
value: '韩语',
},
{ {
label: '法语', label: '法语',
value: '法语', value: '法语',
@@ -191,7 +199,7 @@ async function addCustomSong() {
if (data.data.length == 1) { if (data.data.length == 1) {
message.success('成功添加歌曲: ' + addSongModel.value.name) message.success('成功添加歌曲: ' + addSongModel.value.name)
songs.value.push(data.data[0]) songs.value.push(data.data[0])
addSongModel.value = {} as SongsInfo resetAddingSong(onlyResetNameOnAdded.value)
} else { } else {
message.error('未能添加歌曲, 已存在相同名称的曲目') message.error('未能添加歌曲, 已存在相同名称的曲目')
} }
@@ -302,6 +310,8 @@ async function addSongs(songsShoudAdd: SongsInfo[], from: SongFrom) {
Cover: s.cover, Cover: s.cover,
Tags: s.tags, Tags: s.tags,
Language: s.language, Language: s.language,
TranslateName: s.translateName,
Options: s.options,
})), })),
) )
} }
@@ -337,7 +347,7 @@ async function getFivesingSearchList(isRestart = false) {
isModalLoading.value = true isModalLoading.value = true
await fetch( await fetch(
FETCH_API + FETCH_API +
`http://search.5sing.kugou.com/home/json?keyword=${fivesingSearchInput.value}&sort=1&page=${fivesingCurrentPage.value}&filter=3`, `http://search.5sing.kugou.com/home/json?keyword=${fivesingSearchInput.value}&sort=1&page=${fivesingCurrentPage.value}&filter=3`,
) )
.then(async (data) => { .then(async (data) => {
const json = await data.json() const json = await data.json()
@@ -564,6 +574,15 @@ async function setFunctionEnable(enable: boolean) {
message.error('无法' + (enable ? '启用' : '禁用')) message.error('无法' + (enable ? '启用' : '禁用'))
} }
} }
function resetAddingSong(onlyName = false) {
if (onlyName) {
addSongModel.value.name = ''
addSongModel.value.description = ''
}
addSongModel.value = {} as SongsInfo
showModalRenderKey.value++
message.success('已重置')
}
onMounted(async () => { onMounted(async () => {
await getSongs() await getSongs()
@@ -572,16 +591,12 @@ onMounted(async () => {
<template> <template>
<NSpace align="center"> <NSpace align="center">
<NAlert <NAlert :type="accountInfo.settings.enableFunctions.includes(FunctionTypes.SongList) ? 'success' : 'warning'"
:type="accountInfo.settings.enableFunctions.includes(FunctionTypes.SongList) ? 'success' : 'warning'" style="max-width: 200px">
style="max-width: 200px"
>
启用歌单 启用歌单
<NDivider vertical /> <NDivider vertical />
<NSwitch <NSwitch :value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.SongList)"
:value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.SongList)" @update:value="setFunctionEnable" />
@update:value="setFunctionEnable"
/>
</NAlert> </NAlert>
<NButton @click="showModal = true" type="primary"> 添加歌曲 </NButton> <NButton @click="showModal = true" type="primary"> 添加歌曲 </NButton>
<NButton @click="exportData" type="primary" secondary> 导出为 CSV </NButton> <NButton @click="exportData" type="primary" secondary> 导出为 CSV </NButton>
@@ -589,23 +604,20 @@ onMounted(async () => {
<NButton @click="$router.push({ name: 'user-songList', params: { id: accountInfo?.name } })" secondary> <NButton @click="$router.push({ name: 'user-songList', params: { id: accountInfo?.name } })" secondary>
前往展示页 前往展示页
</NButton> </NButton>
<NButton <NButton :loading="isLoading" @click="() => {
:loading="isLoading" getSongs()
@click=" message.success('完成')
() => { }
getSongs() ">
message.success('完成')
}
"
>
刷新 刷新
</NButton> </NButton>
<NButton @click="$router.push({ name: 'manage-index', query: { tab: 'setting', setting: 'template', template: 'songlist' } })"> <NButton
@click="$router.push({ name: 'manage-index', query: { tab: 'setting', setting: 'template', template: 'songlist' } })">
修改模板 修改模板
</NButton> </NButton>
</NSpace> </NSpace>
<NDivider style="margin: 16px 0 16px 0" /> <NDivider style="margin: 16px 0 16px 0" />
<NModal v-model:show="showModal" style="max-width: 1000px" preset="card"> <NModal v-model:show="showModal" style="max-width: 1000px" preset="card" :key="showModalRenderKey">
<template #header> 添加歌曲 </template> <template #header> 添加歌曲 </template>
<NScrollbar style="max-height: 80vh"> <NScrollbar style="max-height: 80vh">
<NSpin :show="isModalLoading"> <NSpin :show="isModalLoading">
@@ -613,62 +625,27 @@ onMounted(async () => {
<NTabPane name="custom" tab="手动录入"> <NTabPane name="custom" tab="手动录入">
<NForm ref="formRef" :rules="addSongRules" :model="addSongModel"> <NForm ref="formRef" :rules="addSongRules" :model="addSongModel">
<NFormItem path="name" label="名称"> <NFormItem path="name" label="名称">
<NInput <NInput v-model:value="addSongModel.name" autosize style="min-width: 200px" placeholder="就是歌曲名称"
v-model:value="addSongModel.name" :status="songs.findIndex((s) => s.name == addSongModel.name) > -1 ? 'error' : 'success'" />
autosize
style="min-width: 200px"
placeholder="就是歌曲名称"
:status="songs.findIndex((s) => s.name == addSongModel.name) > -1 ? 'error' : 'success'"
/>
</NFormItem> </NFormItem>
<NFormItem path="author" label="作者"> <NFormItem path="author" label="作者 (可多选)">
<NSelect <NSelect v-model:value="addSongModel.author" :options="authors" filterable multiple tag
v-model:value="addSongModel.author" placeholder="输入后按回车新增" />
:options="authors"
filterable
multiple
tag
placeholder="输入后按回车新增"
/>
</NFormItem> </NFormItem>
<NFormItem path="description" label="备注"> <NFormItem path="description" label="备注">
<NInput <NInput v-model:value="addSongModel.description" placeholder="可选" :maxlength="250" show-count autosize
v-model:value="addSongModel.description" style="min-width: 300px" clearable />
placeholder="可选"
:maxlength="250"
show-count
autosize
style="min-width: 300px"
clearable
/>
</NFormItem> </NFormItem>
<NFormItem path="language" label="语言"> <NFormItem path="language" label="语言 (可多选)">
<NSelect <NSelect v-model:value="addSongModel.language" filterable multiple clearable tag
v-model:value="addSongModel.language" placeholder="可选,输入后按回车新增" :options="songSelectOption" />
filterable
multiple
clearable
tag
placeholder="可选,输入后按回车新增"
:options="songSelectOption"
/>
</NFormItem> </NFormItem>
<NFormItem path="tags" label="标签"> <NFormItem path="tags" label="标签 (可多选)">
<NSelect <NSelect v-model:value="addSongModel.tags" filterable multiple clearable tag placeholder="可选,输入后按回车新增"
v-model:value="addSongModel.tags" :options="tags" />
filterable
multiple
clearable
tag
placeholder="可选,输入后按回车新增"
:options="tags"
/>
</NFormItem> </NFormItem>
<NFormItem path="url" label="链接"> <NFormItem path="url" label="链接">
<NInput <NInput v-model:value="addSongModel.url" placeholder="可选, 后缀为mp3、wav、ogg时将会尝试播放, 否则会在新页面打开" />
v-model:value="addSongModel.url"
placeholder="可选, 后缀为mp3、wav、ogg时将会尝试播放, 否则会在新页面打开"
/>
</NFormItem> </NFormItem>
<NFormItem path="options"> <NFormItem path="options">
<template #label> <template #label>
@@ -681,20 +658,16 @@ onMounted(async () => {
</NTooltip> </NTooltip>
</template> </template>
<NSpace vertical> <NSpace vertical>
<NCheckbox <NCheckbox :checked="addSongModel.options != undefined" @update:checked="(checked: boolean) => {
:checked="addSongModel.options != undefined" addSongModel.options = checked
@update:checked=" ? ({
(checked: boolean) => { needJianzhang: false,
addSongModel.options = checked needTidu: false,
? ({ needZongdu: false,
needJianzhang: false, } as SongRequestOption)
needTidu: false, : undefined
needZongdu: false, }
} as SongRequestOption) ">
: undefined
}
"
>
是否启用 是否启用
</NCheckbox> </NCheckbox>
<template v-if="addSongModel.options != undefined"> <template v-if="addSongModel.options != undefined">
@@ -704,14 +677,10 @@ onMounted(async () => {
<NCheckbox v-model:checked="addSongModel.options.needZongdu"> 需要总督 </NCheckbox> <NCheckbox v-model:checked="addSongModel.options.needZongdu"> 需要总督 </NCheckbox>
</NSpace> </NSpace>
<NSpace align="center"> <NSpace align="center">
<NCheckbox <NCheckbox :checked="addSongModel.options.scMinPrice != undefined" @update:checked="(checked: boolean) => {
:checked="addSongModel.options.scMinPrice != undefined" if (addSongModel.options) addSongModel.options.scMinPrice = checked ? 30 : undefined
@update:checked=" }
(checked: boolean) => { ">
if (addSongModel.options) addSongModel.options.scMinPrice = checked ? 30 : undefined
}
"
>
需要SC 需要SC
</NCheckbox> </NCheckbox>
<NInputGroup v-if="addSongModel.options?.scMinPrice" style="width: 200px"> <NInputGroup v-if="addSongModel.options?.scMinPrice" style="width: 200px">
@@ -720,14 +689,10 @@ onMounted(async () => {
</NInputGroup> </NInputGroup>
</NSpace> </NSpace>
<NSpace align="center"> <NSpace align="center">
<NCheckbox <NCheckbox :checked="addSongModel.options.fanMedalMinLevel != undefined" @update:checked="(checked: boolean) => {
:checked="addSongModel.options.fanMedalMinLevel != undefined" if (addSongModel.options) addSongModel.options.fanMedalMinLevel = checked ? 5 : undefined
@update:checked=" }
(checked: boolean) => { ">
if (addSongModel.options) addSongModel.options.fanMedalMinLevel = checked ? 5 : undefined
}
"
>
需要粉丝牌 需要粉丝牌
<NTooltip> <NTooltip>
<template #trigger> <template #trigger>
@@ -745,17 +710,16 @@ onMounted(async () => {
</NSpace> </NSpace>
</NFormItem> </NFormItem>
</NForm> </NForm>
<NButton type="primary" @click="addCustomSong"> 添加 </NButton> <NFlex align="center">
<NButton type="primary" @click="addCustomSong"> 添加 </NButton>
<NButton type="warning" @click="resetAddingSong()"> 还原 </NButton>
<NButton type="warning" @click="resetAddingSong(true)"> 还原(仅歌名和备注) </NButton>
<NCheckbox v-model:checked="onlyResetNameOnAdded"> 添加完成时仅重置歌名和备注 </NCheckbox>
</NFlex>
</NTabPane> </NTabPane>
<NTabPane name="netease" tab="从网易云歌单导入"> <NTabPane name="netease" tab="从网易云歌单导入">
<NInput <NInput clearable style="width: 100%" autosize :status="neteaseSongListId ? 'success' : 'error'"
clearable v-model:value="neteaseIdInput" placeholder="直接输入歌单Id或者网页链接">
style="width: 100%"
autosize
:status="neteaseSongListId ? 'success' : 'error'"
v-model:value="neteaseIdInput"
placeholder="直接输入歌单Id或者网页链接"
>
<template #suffix> <template #suffix>
<NTag v-if="neteaseSongListId" type="success" size="small"> 歌单Id: {{ neteaseSongListId }} </NTag> <NTag v-if="neteaseSongListId" type="success" size="small"> 歌单Id: {{ neteaseSongListId }} </NTag>
</template> </template>
@@ -764,13 +728,8 @@ onMounted(async () => {
<NButton type="primary" @click="getNeteaseSongList" :disabled="!neteaseSongListId"> 获取 </NButton> <NButton type="primary" @click="getNeteaseSongList" :disabled="!neteaseSongListId"> 获取 </NButton>
<template v-if="neteaseSongsOptions.length > 0"> <template v-if="neteaseSongsOptions.length > 0">
<NDivider style="margin: 10px" /> <NDivider style="margin: 10px" />
<NTransfer <NTransfer style="height: 500px" ref="transfer" v-model:value="selectedNeteaseSongs"
style="height: 500px" :options="neteaseSongsOptions" source-filterable />
ref="transfer"
v-model:value="selectedNeteaseSongs"
:options="neteaseSongsOptions"
source-filterable
/>
<NDivider style="margin: 10px" /> <NDivider style="margin: 10px" />
<NButton type="primary" @click="addNeteaseSongs"> <NButton type="primary" @click="addNeteaseSongs">
添加到歌单 | {{ selectedNeteaseSongs.length }} 添加到歌单 | {{ selectedNeteaseSongs.length }}
@@ -778,14 +737,8 @@ onMounted(async () => {
</template> </template>
</NTabPane> </NTabPane>
<NTabPane name="5sing" tab="从5sing搜索"> <NTabPane name="5sing" tab="从5sing搜索">
<NInput <NInput clearable style="width: 100%" autosize v-model:value="fivesingSearchInput" placeholder="输入要搜索的歌名"
clearable maxlength="15" />
style="width: 100%"
autosize
v-model:value="fivesingSearchInput"
placeholder="输入要搜索的歌名"
maxlength="15"
/>
<NDivider style="margin: 10px" /> <NDivider style="margin: 10px" />
<NButton type="primary" @click="getFivesingSearchList(true)" :disabled="!fivesingSearchInput"> <NButton type="primary" @click="getFivesingSearchList(true)" :disabled="!fivesingSearchInput">
搜索 搜索
@@ -814,12 +767,8 @@ onMounted(async () => {
</td> </td>
<td style="display: flex; justify-content: flex-end"> <td style="display: flex; justify-content: flex-end">
<!-- 在这里播放song.url链接中的音频 --> <!-- 在这里播放song.url链接中的音频 -->
<NButton <NButton size="small" v-if="!song.url" @click="playFivesingSong(song)"
size="small" :loading="isGettingFivesingSongPlayUrl == song.id">
v-if="!song.url"
@click="playFivesingSong(song)"
:loading="isGettingFivesingSongPlayUrl == song.id"
>
试听 试听
</NButton> </NButton>
<audio v-else controls style="max-height: 30px"> <audio v-else controls style="max-height: 30px">
@@ -827,12 +776,8 @@ onMounted(async () => {
</audio> </audio>
</td> </td>
<td> <td>
<NButton <NButton size="small" color="green" @click="addFingsingSongs(song)"
size="small" :disabled="songs.findIndex((s) => s.from == SongFrom.FiveSing && s.id == song.id) > -1">
color="green"
@click="addFingsingSongs(song)"
:disabled="songs.findIndex((s) => s.from == SongFrom.FiveSing && s.id == song.id) > -1"
>
添加 添加
</NButton> </NButton>
</td> </td>
@@ -841,34 +786,20 @@ onMounted(async () => {
</NTable> </NTable>
</div> </div>
<br /> <br />
<NPagination <NPagination v-model:page="fivesingCurrentPage" :page-count="fivesingTotalPageCount" simple
v-model:page="fivesingCurrentPage" @update-page="getFivesingSearchList(false)" />
:page-count="fivesingTotalPageCount"
simple
@update-page="getFivesingSearchList(false)"
/>
</template> </template>
</NTabPane> </NTabPane>
<NTabPane name="file" tab="从文件导入"> <NTabPane name="file" tab="从文件导入">
<NAlert type="info"> <NAlert type="info">
Excel 文件格式详见: Excel 文件格式详见:
<NButton <NButton type="info" tag="a" href="https://www.yuque.com/megghy/dez70g/ngrqwkiegrh593w5" target="_blank"
type="info" size="tiny">
tag="a"
href="https://www.yuque.com/megghy/dez70g/ngrqwkiegrh593w5"
target="_blank"
size="tiny"
>
此页面 此页面
</NButton> </NButton>
</NAlert> </NAlert>
<NUpload <NUpload v-model:file-list="uploadFiles" :default-upload="false" :max="1" directory-dnd
v-model:file-list="uploadFiles" @before-upload="beforeUpload">
:default-upload="false"
:max="1"
directory-dnd
@before-upload="beforeUpload"
>
<NUploadDragger> <NUploadDragger>
<div style="margin-bottom: 12px"> <div style="margin-bottom: 12px">
<NIcon size="48" :depth="3"> <NIcon size="48" :depth="3">
@@ -886,12 +817,8 @@ onMounted(async () => {
添加到歌单 | {{ selecteduploadSongs.length }} 添加到歌单 | {{ selecteduploadSongs.length }}
</NButton> </NButton>
<NDivider style="margin: 10px" /> <NDivider style="margin: 10px" />
<NTransfer <NTransfer style="height: 400px" v-model:value="selecteduploadSongs" :options="uploadSongsOptions"
style="height: 400px" source-filterable />
v-model:value="selecteduploadSongs"
:options="uploadSongsOptions"
source-filterable
/>
</template> </template>
</NTabPane> </NTabPane>
<NTabPane name="directory" tab="从文件夹读取"> 开发中... </NTabPane> <NTabPane name="directory" tab="从文件夹读取"> 开发中... </NTabPane>

View File

@@ -256,7 +256,11 @@ async function addSong(danmaku: EventModel) {
`[OPEN-LIVE-LIVE-REQUEST] 收到 [${danmaku.name}] 的点播${danmaku.type == EventDataTypes.SC ? 'SC' : '弹幕'}: ${danmaku.msg}`, `[OPEN-LIVE-LIVE-REQUEST] 收到 [${danmaku.name}] 的点播${danmaku.type == EventDataTypes.SC ? 'SC' : '弹幕'}: ${danmaku.msg}`,
) )
if (settings.value.enableOnStreaming && accountInfo.value?.streamerInfo?.isStreaming != true) { if (settings.value.enableOnStreaming && accountInfo.value?.streamerInfo?.isStreaming != true) {
message.info('当前未在直播中, 无法添加点播请求. 或者关闭设置中的仅允许直播时加入') notice.info({
title: `${danmaku.name} 点播失败`,
description: '当前未在直播中, 无法添加点播请求. 或者关闭设置中的仅允许直播时加入',
meta: () => h(NTime, { type: 'relative', time: Date.now(), key: updateKey.value }),
})
return return
} }
if (accountInfo.value) { if (accountInfo.value) {
@@ -940,7 +944,7 @@ onUnmounted(() => {
</NTooltip> </NTooltip>
</NSpace> </NSpace>
<NSpace justify="end" align="center"> <NSpace justify="end" align="center">
<NTooltip v-if="song.song"> <NTooltip v-if="song.song?.url">
<template #trigger> <template #trigger>
<NButton circle type="success" style="height: 30px; width: 30px" <NButton circle type="success" style="height: 30px; width: 30px"
:loading="isLrcLoading == song?.song?.key" @click="selectedSong = song.song"> :loading="isLrcLoading == song?.song?.key" @click="selectedSong = song.song">