add simplesonglist

This commit is contained in:
2023-11-29 21:50:56 +08:00
parent cfe883e902
commit 776e5ffc1e
10 changed files with 398 additions and 256 deletions

View File

@@ -40,6 +40,7 @@ import APlayer from 'vue3-aplayer'
import { NotepadEdit20Filled, Delete24Filled, Play24Filled, SquareArrowForward24Filled, Info24Filled } from '@vicons/fluent'
import NeteaseIcon from '@/svgs/netease.svg'
import FiveSingIcon from '@/svgs/fivesing.svg'
import SongPlayer from './SongPlayer.vue'
const props = defineProps<{
songs: SongsInfo[]
@@ -72,12 +73,8 @@ const updateSongModel = ref<SongsInfo>({} as SongsInfo)
const searchMusicKeyword = ref()
const debouncedInput = refDebounced(searchMusicKeyword, 500)
const aplayerMusic = ref<{
title: string
artist: string
src: string
lrc: string
}>()
const playingSong = ref<SongsInfo>()
const isLrcLoading = ref<string>()
const formRef = ref<FormInst | null>(null)
const updateSongRules: FormRules = {
@@ -255,7 +252,9 @@ function createColumns(): DataTableColumns<SongsInfo> {
size: 'small',
circle: true,
loading: isLrcLoading.value == data.key,
onClick: () => OnPlayMusic(data),
onClick: () => {
playingSong.value = data
},
},
{
icon: () => h(NIcon, { component: Play24Filled }),
@@ -319,92 +318,7 @@ function createColumns(): DataTableColumns<SongsInfo> {
},
]
}
function OnPlayMusic(song: SongsInfo) {
aplayerMusic.value = undefined
if (song.from == SongFrom.Netease) GetLyric(song)
else {
aplayerMusic.value = {
title: song.name,
artist: song.author.join('/') ?? '',
src: song.url,
lrc: '',
}
}
}
const isLrcLoading = ref('')
async function GetLyric(song: SongsInfo) {
isLrcLoading.value = song.key
QueryGetAPI<{ lyric: string; tlyric: string }>(SONG_API_URL + 'get-netease-lyric', { id: song.id })
.then((data) => {
console.log(mergeLyrics(data.data.lyric, data.data.tlyric))
if (data.code == 200) {
aplayerMusic.value = {
title: song.name,
artist: song.author.join('/') ?? '',
src: song.url,
lrc: data.data.tlyric ? mergeLyrics(data.data.lyric, data.data.tlyric) : data.data.lyric,
}
//aplayerMusic.value.lrc = data.data.lyric
}
})
.catch((err) => {
console.error(err)
aplayerMusic.value = {
title: song.name,
artist: song.author.join('/') ?? '',
src: song.url,
lrc: '',
}
})
.finally(() => {
isLrcLoading.value = ''
})
}
function mergeLyrics(originalLyrics: string, translatedLyrics: string): string {
const originalLines = originalLyrics.split('\n')
const translatedLines = translatedLyrics.split('\n')
let mergedLyrics = ''
for (let i = 0; i < originalLines.length; i++) {
const originalLine = originalLines[i]?.trim()
const originalTimeMatch = originalLine?.match(/\[(\d{2}:\d{2}\.\d{2,3})\]/) // 匹配原歌词的时间字符串
let mergedLine = originalLine
if (originalTimeMatch) {
const originalTime = originalTimeMatch[1]
const translatedLineIndex = translatedLines.findIndex((line) => line.includes(originalTime))
if (translatedLineIndex !== -1) {
const translatedLine = translatedLines[translatedLineIndex]
const translatedTimeMatch = translatedLine.match(/\[(\d{2}:\d{2}\.\d{2,3})\]/) // 匹配翻译歌词的时间字符串
if (translatedTimeMatch && translatedTimeMatch[1] === originalTime) {
const translatedText = translatedLine.slice(translatedTimeMatch[0].length).trim()
if (translatedText) {
mergedLine += ` (${translatedText})`
}
translatedLines.splice(translatedLineIndex, 1) // 从翻译歌词数组中移除已匹配的行
}
}
}
if (!mergedLine.match(/^\[(\d{2}:\d{2}\.\d{2,3})\]$/)) {
//不是空行
mergedLyrics += `${mergedLine}\n`
}
}
// 将剩余的非空翻译歌词单独放在一行
for (const translatedLine of translatedLines) {
const translatedText = translatedLine.trim()
if (translatedText) {
mergedLyrics += `${translatedText}\n`
}
}
return mergedLyrics.trim()
}
function GetPlayButton(song: SongsInfo) {
switch (song.from) {
case SongFrom.FiveSing: {
@@ -550,8 +464,8 @@ onMounted(() => {
</NCard>
<NDivider style="margin: 5px 0 5px 0"> {{ songsComputed.length }} </NDivider>
<Transition>
<div v-if="aplayerMusic" class="song-list">
<APlayer :music="aplayerMusic" autoplay :showLrc="aplayerMusic.lrc != null && aplayerMusic.lrc.length > 0" />
<div v-if="playingSong" class="song-list">
<SongPlayer :song="playingSong" v-model:is-lrc-loading="isLrcLoading" />
<NDivider style="margin: 15px 0 15px 0" />
</div>
</Transition>

View File

@@ -0,0 +1,127 @@
<script setup lang="ts">
import { SongsInfo, SongFrom } from '@/api/api-models'
import { QueryGetAPI } from '@/api/query'
import { SONG_API_URL } from '@/data/constants'
import { NEmpty } from 'naive-ui'
import { computed, ref, toRef, toRefs, watch } from 'vue'
import APlayer from 'vue3-aplayer'
const props = defineProps<{
song: SongsInfo | undefined
isLrcLoading?: string
}>()
const currentSong = toRef(props, 'song')
const emits = defineEmits(['update:isLrcLoading'])
const aplayerMusic = ref({
title: '',
artist: '',
src: '',
pic: '',
lrc: '',
})
const temp = computed(() => {
if (props.song) OnPlayMusic(props.song)
return props.song
})
watch(temp, (newV) => {
if (newV) console.log('开始播放: ' + newV.name)
})
function OnPlayMusic(song: SongsInfo) {
if (song.from == SongFrom.Netease) GetLyric(song)
else {
aplayerMusic.value = {
title: song.name,
artist: song.author?.join('/') ?? '',
src: song.url,
pic: '',
lrc: '',
}
}
}
async function GetLyric(song: SongsInfo) {
emits('update:isLrcLoading', song.key)
QueryGetAPI<{ lyric: string; tlyric: string }>(SONG_API_URL + 'get-netease-lyric', { id: song.id })
.then((data) => {
console.log(mergeLyrics(data.data.lyric, data.data.tlyric))
if (data.code == 200) {
//props.song.value.lrc = data.data.tlyric ? mergeLyrics(data.data.lyric, data.data.tlyric) : data.data.lyric
aplayerMusic.value = {
title: song.name,
artist: song.author?.join('/') ?? '',
src: song.url,
pic: '',
lrc: data.data.tlyric ? mergeLyrics(data.data.lyric, data.data.tlyric) : data.data.lyric,
}
//aplayerMusic.value.lrc = data.data.lyric
} else {
aplayerMusic.value = {
title: song.name,
artist: song.author?.join('/') ?? '',
src: song.url,
pic: '',
lrc: '',
}
}
})
.catch((err) => {
console.error(err)
})
.finally(() => {
emits('update:isLrcLoading', undefined)
})
}
function mergeLyrics(originalLyrics: string, translatedLyrics: string): string {
const originalLines = originalLyrics.split('\n')
const translatedLines = translatedLyrics.split('\n')
let mergedLyrics = ''
for (let i = 0; i < originalLines.length; i++) {
const originalLine = originalLines[i]?.trim()
const originalTimeMatch = originalLine?.match(/\[(\d{2}:\d{2}\.\d{2,3})\]/) // 匹配原歌词的时间字符串
let mergedLine = originalLine
if (originalTimeMatch) {
const originalTime = originalTimeMatch[1]
const translatedLineIndex = translatedLines.findIndex((line) => line.includes(originalTime))
if (translatedLineIndex !== -1) {
const translatedLine = translatedLines[translatedLineIndex]
const translatedTimeMatch = translatedLine.match(/\[(\d{2}:\d{2}\.\d{2,3})\]/) // 匹配翻译歌词的时间字符串
if (translatedTimeMatch && translatedTimeMatch[1] === originalTime) {
const translatedText = translatedLine.slice(translatedTimeMatch[0].length).trim()
if (translatedText) {
mergedLine += ` (${translatedText})`
}
translatedLines.splice(translatedLineIndex, 1) // 从翻译歌词数组中移除已匹配的行
}
}
}
if (!mergedLine.match(/^\[(\d{2}:\d{2}\.\d{2,3})\]$/)) {
//不是空行
mergedLyrics += `${mergedLine}\n`
}
}
// 将剩余的非空翻译歌词单独放在一行
for (const translatedLine of translatedLines) {
const translatedText = translatedLine.trim()
if (translatedText) {
mergedLyrics += `${translatedText}\n`
}
}
return mergedLyrics.trim()
}
</script>
<template>
<NEmpty v-if="!aplayerMusic.src" :description="props.isLrcLoading ? '歌词加载中...' : '暂无歌曲'" />
<APlayer v-else :music="aplayerMusic" autoplay :showLrc="aplayerMusic?.lrc && aplayerMusic.lrc.length > 0" />
</template>