This commit is contained in:
Megghy
2023-06-12 14:49:05 +08:00
parent 1b6bb7c248
commit 64a6bece5c
6 changed files with 463 additions and 109 deletions

View File

@@ -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>