diff --git a/index.html b/index.html index f6e5246..6d2c046 100644 --- a/index.html +++ b/index.html @@ -6,13 +6,14 @@ vtsuru.live - + + diff --git a/src/Utils.ts b/src/Utils.ts index 0049d5e..1b5c4c0 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -33,3 +33,19 @@ export function objectsToCSV(arr: any[]) { }) .join('\n') } +export function GetGuardColor(level: number | null | undefined): string { + if (level) { + switch (level) { + case 1: { + return 'rgb(122, 4, 35)' + } + case 2: { + return 'rgb(157, 155, 255)' + } + case 3: { + return 'rgb(104, 136, 241)' + } + } + } + return '' +} \ No newline at end of file diff --git a/src/components/SongList.vue b/src/components/SongList.vue index 504f250..b17a6af 100644 --- a/src/components/SongList.vue +++ b/src/components/SongList.vue @@ -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({} as SongsInfo) const searchMusicKeyword = ref() const debouncedInput = refDebounced(searchMusicKeyword, 500) -const aplayerMusic = ref<{ - title: string - artist: string - src: string - lrc: string -}>() +const playingSong = ref() +const isLrcLoading = ref() const formRef = ref(null) const updateSongRules: FormRules = { @@ -255,7 +252,9 @@ function createColumns(): DataTableColumns { 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 { }, ] } -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(() => { 共 {{ songsComputed.length }} 首 -
- +
+
diff --git a/src/components/SongPlayer.vue b/src/components/SongPlayer.vue new file mode 100644 index 0000000..e9758a2 --- /dev/null +++ b/src/components/SongPlayer.vue @@ -0,0 +1,127 @@ + + + diff --git a/src/data/constants.ts b/src/data/constants.ts index cd1da22..18f5b52 100644 --- a/src/data/constants.ts +++ b/src/data/constants.ts @@ -33,6 +33,7 @@ export const ScheduleTemplateMap = { } as { [key: string]: { name: string; compoent: any } } export const SongListTemplateMap = { '': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/songListTemplate/DefaultSongListTemplate.vue')) }, + simple: { name: '简单', compoent: defineAsyncComponent(() => import('@/views/view/songListTemplate/SimpleSongListTemplate.vue')) }, } as { [key: string]: { name: string; compoent: any } } export const IndexTemplateMap = { '': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/indexTemplate/DefaultIndexTemplate.vue')) }, diff --git a/src/views/ViewerLayout.vue b/src/views/ViewerLayout.vue index 79984a8..721186f 100644 --- a/src/views/ViewerLayout.vue +++ b/src/views/ViewerLayout.vue @@ -148,7 +148,7 @@ onMounted(async () => { - + diff --git a/src/views/open_live/MusicRequest.vue b/src/views/open_live/MusicRequest.vue index d4137c4..952e7c2 100644 --- a/src/views/open_live/MusicRequest.vue +++ b/src/views/open_live/MusicRequest.vue @@ -62,6 +62,7 @@ import { computed, h, onActivated, onDeactivated, onMounted, onUnmounted, ref } import { useRoute } from 'vue-router' import SongRequestOBS from '../obs/SongRequestOBS.vue' import APlayer from 'vue3-aplayer' +import SongPlayer from '@/components/SongPlayer.vue' const defaultSettings = { orderPrefix: '点歌', @@ -115,13 +116,7 @@ const settings = computed({ } }, }) -const aplayerMusic = ref<{ - title: string - artist: string - src: string - lrc: string - autoplay: boolean -}>() +const selectedSong = ref() const props = defineProps<{ client: DanmakuClient @@ -693,96 +688,7 @@ async function updateActive() { console.error(err) } } -function playMusic(song: SongRequestInfo) { - aplayerMusic.value = undefined - if (song.song?.from == SongFrom.Netease) GetLyric(song.song) - else { - aplayerMusic.value = { - title: song.song?.name ?? '未知', - artist: song.song?.author?.join('/') ?? '', - src: song.song?.url ?? '', - lrc: '', - autoplay: true, - } - } -} 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, - - autoplay: true, - } - //aplayerMusic.value.lrc = data.data.lyric - } - }) - .catch((err) => { - console.error(err) - aplayerMusic.value = { - title: song.name, - artist: song.author.join('/') ?? '', - src: song.url, - lrc: '', - autoplay: true, - } - }) - .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() -} let timer: any let updateActiveTimer: any @@ -849,16 +755,7 @@ onUnmounted(() => {
- + @@ -888,8 +785,8 @@ onUnmounted(() => { 共 {{ activeSongs.length }} 首 -
- +
+
@@ -945,7 +842,7 @@ onUnmounted(() => {