feat: add vue-toast-notification for user feedback and implement queue management in TrackItem component

This commit is contained in:
Astrian Zheng 2025-05-27 17:03:55 +10:00
parent 7f86c8bfa9
commit c6868ed2a2
Signed by: Astrian
SSH Key Fingerprint: SHA256:rVnhx3DAKjujCwWE13aDl7uV6+9U1MvydLkNRXJrBiA
8 changed files with 71 additions and 12 deletions

13
package-lock.json generated
View File

@ -15,6 +15,7 @@
"tailwindcss": "^4.1.7",
"vue": "^3.5.13",
"vue-router": "^4.5.1",
"vue-toast-notification": "^3.1.3",
"webextension-polyfill": "^0.12.0"
},
"devDependencies": {
@ -2675,6 +2676,18 @@
"vue": "^3.2.0"
}
},
"node_modules/vue-toast-notification": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/vue-toast-notification/-/vue-toast-notification-3.1.3.tgz",
"integrity": "sha512-XNyWqwLIGBFfX5G9sK+clq3N3IPlhDjzNdbZaXkEElcotPlWs0wWZailk1vqhdtLYT/93Y4FHAVuzyatLmPZRA==",
"license": "MIT",
"engines": {
"node": ">=12.15.0"
},
"peerDependencies": {
"vue": "^3.0"
}
},
"node_modules/vue-tsc": {
"version": "2.2.10",
"resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.10.tgz",

View File

@ -20,6 +20,7 @@
"tailwindcss": "^4.1.7",
"vue": "^3.5.13",
"vue-router": "^4.5.1",
"vue-toast-notification": "^3.1.3",
"webextension-polyfill": "^0.12.0"
},
"devDependencies": {

View File

@ -0,0 +1,11 @@
<script setup lang="ts">
defineProps<{
size: number
}>()
</script>
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" :class="`w-${size} h-${size}`">
<path d="M2 18H12V20H2V18ZM2 11H22V13H2V11ZM2 4H22V6H2V4ZM18 18V15H20V18H23V20H20V23H18V20H15V18H18Z"></path>
</svg>
</template>

View File

@ -131,6 +131,7 @@ function playTheAlbum(from: number = 0) {
playQueue.isPlaying = true
playQueue.isBuffering = true
}
</script>
<template>

View File

@ -180,7 +180,6 @@ function updateCurrentTime() {
const remainingTimeThreshold = config.remainingTimeThreshold || 30
if ((progress > preloadTrigger || remainingTime < remainingTimeThreshold) && !playQueueStore.isPreloading) {
console.log(`[Player] 触发预加载 - 进度: ${Math.round(progress * 100)}%, 剩余: ${Math.round(remainingTime)}s`)
try {
if (typeof playQueueStore.preloadNext === 'function') {

View File

@ -1,18 +1,44 @@
<script setup lang="ts">
import { artistsOrganize } from '../utils'
import { ref } from 'vue'
import { usePlayQueueStore } from '../stores/usePlayQueueStore'
import { useToast } from 'vue-toast-notification'
defineProps<{
import QueueAddIcon from '../assets/icons/queueadd.vue'
import StarEmptyIcon from '../assets/icons/starempty.vue'
const props = defineProps<{
album?: Album,
track: Song,
index: number,
playfrom: (index: number) => void,
}>()
const hover = ref(false)
const playQueueStore = usePlayQueueStore()
const toast = useToast()
function appendToQueue() {
console.log('aaa')
let queue = playQueueStore.list
queue.push({
song: props.track,
album: props.album,
} as QueueItem)
playQueueStore.list = queue
playQueueStore.queueReplaceLock = true
toast.success('已添加到队列末尾', {
position: 'top-right',
duration: 500,
})
}
</script>
<template>
<button
class="flex align-center gap-4 text-left px-2 h-[2.75rem] hover:bg-neutral-600/40 odd:bg-netural-600/20 align-center relative overflow-hidden bg-neutral-800/20 odd:bg-neutral-800/40 transition-all"
@click="playfrom(index)">
class="flex justify-between align-center gap-4 text-left px-2 h-[2.75rem] hover:bg-neutral-600/40 odd:bg-netural-600/20 relative overflow-hidden bg-neutral-800/20 odd:bg-neutral-800/40 transition-all"
@click="playfrom(index)" @mouseenter="() => { hover = true; console.log('aaa') }" @mouseleave="hover = false">
<span class="text-[3.7rem] text-white/10 absolute left-0 top-[-1.4rem] track_num">{{ index + 1 }}</span>
@ -24,6 +50,16 @@ defineProps<{
</div>
</div>
<div class="flex items-center justify-center gap-2" v-if="hover">
<button @click.stop="appendToQueue"
class="hover:scale-110 transition-all text-white/50 hover:text-white active:text-white/40 active:scale-95">
<QueueAddIcon :size="4" />
</button>
<button @click.stop=""
class="hover:scale-110 transition-all text-white/50 hover:text-white active:text-white/40 active:scale-95">
<StarEmptyIcon :size="4" />
</button>
</div>
</button>
</template>

View File

@ -2,6 +2,8 @@ import { createApp } from 'vue'
import { createWebHashHistory, createRouter } from 'vue-router'
import './style.css'
import { createPinia } from 'pinia'
import ToastPlugin from 'vue-toast-notification'
import 'vue-toast-notification/dist/theme-default.css'
import App from './App.vue'
import HomePage from './pages/Home.vue'
@ -21,5 +23,5 @@ const router = createRouter({
const pinia = createPinia()
createApp(App).use(router).use(pinia).mount('#app')
createApp(App).use(router).use(pinia).use(ToastPlugin).mount('#app')

View File

@ -55,11 +55,9 @@ export const usePlayQueueStore = defineStore('queue', () => {
// 预加载下一首歌
const preloadNext = async () => {
console.log('[Store] preloadNext 被调用')
const nextIndex = getNextIndex.value
if (nextIndex === -1) {
console.log('[Store] 没有下一首歌,跳过预加载')
return
}
@ -72,7 +70,6 @@ export const usePlayQueueStore = defineStore('queue', () => {
}
if (!nextSong || !nextSong.song) {
console.log('[Store] 下一首歌曲不存在,跳过预加载')
return
}
@ -80,7 +77,6 @@ export const usePlayQueueStore = defineStore('queue', () => {
// 如果已经预加载过,跳过
if (preloadedAudio.value.has(songId)) {
console.log(`[Store] 歌曲 ${songId} 已预加载`)
return
}
@ -156,8 +152,8 @@ export const usePlayQueueStore = defineStore('queue', () => {
const limitPreloadCache = () => {
while (preloadedAudio.value.size > 3) {
const oldestKey = preloadedAudio.value.keys().next().value
if (oldestKey) {
clearPreloadedAudio(oldestKey)
if (oldestKey) {
clearPreloadedAudio(oldestKey)
} else {
break
}