refactor(Player): 将播放器组件从App.vue中提取到独立的Player.vue组件

提取播放器逻辑到独立的Player.vue组件,以提高代码的可维护性和复用性。同时,更新了相关依赖和样式,确保功能不受影响。
This commit is contained in:
Astrian Zheng 2025-05-24 22:53:21 +10:00
parent 831ff82c8a
commit 6743b694c8
Signed by: Astrian
SSH Key Fingerprint: SHA256:rVnhx3DAKjujCwWE13aDl7uV6+9U1MvydLkNRXJrBiA
6 changed files with 80 additions and 37 deletions

View File

@ -5,12 +5,20 @@
"description": "A Vue-based browser extension.",
"content_scripts": [
{
"matches": ["https://monster-siren.hypergryph.com/"],
"js": ["content.js"],
"matches": [
"https://monster-siren.hypergryph.com/"
],
"js": [
"content.js"
],
"run_at": "document_end"
}
],
"host_permissions": ["https://monster-siren.hypergryph.com/*", "http://localhost:5173/*"],
"host_permissions": [
"https://monster-siren.hypergryph.com/*",
"http://localhost:5173/*",
"https://res01.hycdn.cn/*"
],
"icons": {
"16": "vite.svg",
"48": "vite.svg",
@ -19,9 +27,12 @@
"background": {
"service_worker": "background.js"
},
"permissions": ["tabs", "webRequest"],
"permissions": [
"tabs",
"webRequest"
],
"content_security_policy": {
"extension_pages": "default-src 'self'; script-src 'self' http://localhost:5173; style-src 'self' 'unsafe-inline'; connect-src 'self' ws://localhost:5173 https://monster-siren.hypergryph.com; img-src 'self' https://web.hycdn.cn;",
"extension_pages": "default-src 'self'; script-src 'self' http://localhost:5173; style-src 'self' 'unsafe-inline'; connect-src 'self' ws://localhost:5173 https://monster-siren.hypergryph.com; img-src 'self' https://web.hycdn.cn; media-src 'self' https://res01.hycdn.cn;",
"sandbox": "sandbox"
}
}

View File

@ -1,10 +1,9 @@
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { usePlayQueueStore } from './stores/usePlayQueueStore'
const playQueueStore = usePlayQueueStore()
import Player from './components/Player.vue'
const route = useRoute()
</script>
<template>
@ -54,22 +53,7 @@ const route = useRoute()
</div>
</button>
<div class="text-white w-48 h-9 bg-neutral-800/80 border border-[#ffffff39] rounded-full text-center backdrop-blur-3xl flex gap-2 overflow-hidden" v-if="playQueueStore.list.length !== 0">
<img :src="playQueueStore.list[playQueueStore.currentIndex].album?.coverUrl ?? ''" class="rounded-full" />
<div class="flex-1 flex items-center">
<span class="">{{ playQueueStore.list[playQueueStore.currentIndex].song.name }}</span>
</div>
<button class="h-9 w-9 flex justify-center items-center" @click="() => {
playQueueStore.isPlaying = !playQueueStore.isPlaying
}">
<div class="w-4 h-4" v-if="playQueueStore.isPlaying">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg>
</div>
<div class="w-4 h-4" v-else>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M19.376 12.4161L8.77735 19.4818C8.54759 19.635 8.23715 19.5729 8.08397 19.3432C8.02922 19.261 8 19.1645 8 19.0658V4.93433C8 4.65818 8.22386 4.43433 8.5 4.43433C8.59871 4.43433 8.69522 4.46355 8.77735 4.5183L19.376 11.584C19.6057 11.7372 19.6678 12.0477 19.5146 12.2774C19.478 12.3323 19.4309 12.3795 19.376 12.4161Z"></path></svg>
</div>
</button>
</div>
<Player />
</div>
</div>
</div>

View File

@ -16,8 +16,8 @@ export default {
const song: {
data: ApiResponse
} = await msrInstance.get(`song/${cid}`)
if (song.data.code!== 0) { return new Error(`Cannot get song: ${song.data.msg}`) }
return { song: song.data.data as Song }
if (song.data.code!== 0) { throw new Error(`Cannot get song: ${song.data.msg}`) }
return song.data.data as Song
},
async getAlbums() {
const albums: {
@ -36,7 +36,6 @@ export default {
} = await msrInstance.get(`album/${cid}/data`)
let data = album.data.data as Album
data.artistes = (albumMeta.data.data as Album).artistes
console.log(albumMeta)
return data
}
}

44
src/components/Player.vue Normal file
View File

@ -0,0 +1,44 @@
<script setup lang="ts">
import { usePlayQueueStore } from '../stores/usePlayQueueStore'
import { useTemplateRef, watch } from 'vue'
const playQueueStore = usePlayQueueStore()
const player = useTemplateRef('playerRef')
watch(() => playQueueStore.isPlaying, (newValue) => {
if (newValue) { player.value?.play() }
else { player.value?.pause() }
})
</script>
<template>
<div>
<audio :src="playQueueStore.list[playQueueStore.currentIndex] ? playQueueStore.list[playQueueStore.currentIndex].song.sourceUrl : ''" ref="playerRef" autoplay v-if="playQueueStore.list.length !== 0"></audio>
<div
class="text-white w-48 h-9 bg-neutral-800/80 border border-[#ffffff39] rounded-full text-center backdrop-blur-3xl flex gap-2 overflow-hidden"
v-if="playQueueStore.list.length !== 0">
<img :src="playQueueStore.list[playQueueStore.currentIndex].album?.coverUrl ?? ''" class="rounded-full" />
<div class="flex-1 flex items-center">
<span class="">{{ playQueueStore.list[playQueueStore.currentIndex].song.name }}</span>
</div>
<button class="h-9 w-9 flex justify-center items-center" @click="() => {
playQueueStore.isPlaying = !playQueueStore.isPlaying
}">
<div class="w-4 h-4" v-if="playQueueStore.isPlaying">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path>
</svg>
</div>
<div class="w-4 h-4" v-else>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path
d="M19.376 12.4161L8.77735 19.4818C8.54759 19.635 8.23715 19.5729 8.08397 19.3432C8.02922 19.261 8 19.1645 8 19.0658V4.93433C8 4.65818 8.22386 4.43433 8.5 4.43433C8.59871 4.43433 8.69522 4.46355 8.77735 4.5183L19.376 11.584C19.6057 11.7372 19.6678 12.0477 19.5146 12.2774C19.478 12.3323 19.4309 12.3795 19.376 12.4161Z">
</path>
</svg>
</div>
</button>
</div>
</div>
</template>

View File

@ -13,8 +13,12 @@ const playQueue = usePlayQueueStore()
onMounted(async () => {
try {
const res = await apis.getAlbum(albumId as string)
let res = await apis.getAlbum(albumId as string)
for (const track in res.songs) {
res.songs[parseInt(track)] = await apis.getSong(res.songs[parseInt(track)].cid)
}
album.value = res
console.log(res)
} catch (error) {
console.log(error)
}
@ -35,6 +39,7 @@ function playTheAlbum() {
let newPlayQueue = []
for (const track of album.value?.songs ?? []) {
console.log(track)
newPlayQueue.push({
song: track,
album: album.value
@ -67,8 +72,7 @@ function playTheAlbum() {
<div class="flex gap-2">
<button
class="bg-sky-500/20 hover:bg-sky-500/30 active:bg-sky-600/30 active:shadow-inner border border-[#ffffff39] rounded-full w-56 h-10 text-base text-white flex justify-center items-center gap-2"
@click="playTheAlbum"
>
@click="playTheAlbum">
<div class="w-4 h-4">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path
@ -115,8 +119,8 @@ function playTheAlbum() {
<div class="flex flex-col justify-center">
<div class="text-white text-base">{{ track.name }}</div>
<div class="text-white/50 text-sm"
v-if="artistsOrganize(track.artistes) !== artistsOrganize(album?.artistes ?? [])">
{{ artistsOrganize(track.artistes) }}
v-if="artistsOrganize(track.artists ?? []) !== artistsOrganize(album?.artistes ?? [])">
{{ artistsOrganize(track.artists ?? []) }}
</div>
</div>
</button>

3
src/vite-env.d.ts vendored
View File

@ -12,7 +12,8 @@ type Song = {
lyricUrl?: string | null
mvUrl?: string | null
mvCoverUrl?: string | null
artistes: string[]
artistes?: string[]
artists?: string[]
}
type Album = {