musiclist的绘制ui与其功能为强耦合导致无法复用,只能我自己写点函数凑合用
parent
5ded7c7e19
commit
0affe04683
|
@ -1,48 +1,81 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="playlist-window">
|
<div class="playlist-window">
|
||||||
<button class="close-button" @click="emitClose">✖</button>
|
<button class="close-button" @click="emitClose">✖</button>
|
||||||
<h2 class="title">播放列表</h2>
|
<h2 class="title">播放列表</h2>
|
||||||
<div class="song-list">
|
<div class="song-list">
|
||||||
<div v-for="(song, index) in songs" :key="index" class="song-item">
|
<div
|
||||||
<div class="song-index">{{ index + 1 }}</div>
|
v-for="(song, index) in songs"
|
||||||
<div class="song-info">
|
:key="index"
|
||||||
<div class="song-title">{{ song.title }}</div>
|
class="song-item"
|
||||||
<div class="song-meta">{{ song.artist }} · {{ song.album }}</div>
|
:class="[
|
||||||
</div>
|
{ active: currentPlayIndexValue === index },
|
||||||
|
{ selected: selectedIndex === index || rightClickSelectedIndex === index }
|
||||||
|
]"
|
||||||
|
@click="handleListItemClick(index)"
|
||||||
|
@contextmenu.prevent="handleListItemRightClick(index, $event)"
|
||||||
|
>
|
||||||
|
<div class="song-index">{{ index + 1 }}</div>
|
||||||
|
<div class="song-info">
|
||||||
|
<div class="song-title">{{ song.title }}</div>
|
||||||
|
<div class="song-meta">{{ song.artist }} · {{ song.album }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed, toRef } from 'vue'
|
||||||
import { tempPlayList, currentPlaybackOrder } from '@renderer/store/player/state'
|
import { tempPlayList, currentPlaybackOrder, currentPlayIndex } from '@renderer/store/player/state'
|
||||||
|
|
||||||
|
// 为了模板里更方便使用 .value,这里取一个普通变量
|
||||||
|
const currentPlayIndexValue = toRef(currentPlayIndex, 'value')
|
||||||
|
|
||||||
const emit = defineEmits(['close'])
|
const emit = defineEmits(['close'])
|
||||||
// todo 点击item切换歌曲
|
|
||||||
// todo 当前播放歌曲的item高亮
|
// 把 ref 数组转成本地 reactive 引用
|
||||||
const playlist = ref(tempPlayList)
|
const playlist = ref(tempPlayList)
|
||||||
|
|
||||||
|
// 计算渲染顺序后的歌曲信息列表
|
||||||
const songs = computed(() => {
|
const songs = computed(() => {
|
||||||
let showlist = []
|
const showlist = []
|
||||||
for (const index of currentPlaybackOrder.value) {
|
for (const idx of currentPlaybackOrder.value) {
|
||||||
const playMusicInfo = playlist.value[index]
|
const info = playlist.value[idx]
|
||||||
showlist.push({
|
if (info && info.musicInfo) {
|
||||||
title: playMusicInfo.musicInfo.name,
|
showlist.push({
|
||||||
artist: playMusicInfo.musicInfo.singer,
|
title: info.musicInfo.name,
|
||||||
album: playMusicInfo.musicInfo.meta.albumName,
|
artist: info.musicInfo.singer,
|
||||||
})
|
album: info.musicInfo.meta.albumName,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return showlist
|
return showlist
|
||||||
},
|
})
|
||||||
)
|
|
||||||
const emitClose = () => {
|
// 本地控制的“选中”索引
|
||||||
|
const selectedIndex = ref(null)
|
||||||
|
const rightClickSelectedIndex = ref(null)
|
||||||
|
|
||||||
|
// 点击选中
|
||||||
|
function handleListItemClick(index) {
|
||||||
|
selectedIndex.value = index
|
||||||
|
// 也可以在这里改变 currentPlayIndex
|
||||||
|
currentPlayIndex.value = index
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右键选中
|
||||||
|
function handleListItemRightClick(index, event) {
|
||||||
|
rightClickSelectedIndex.value = index
|
||||||
|
// 这里你可以记录 event.clientX/Y 来显示菜单
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭按钮
|
||||||
|
function emitClose() {
|
||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.playlist-window {
|
.playlist-window {
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
color: white;
|
color: white;
|
||||||
|
@ -51,18 +84,11 @@ const emitClose = () => {
|
||||||
width: 320px;
|
width: 320px;
|
||||||
max-height: 80%;
|
max-height: 80%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
position: relative;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
/* 关闭按钮 */
|
||||||
margin-bottom: 15px;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
|
||||||
}p
|
|
||||||
|
|
||||||
.close-button {
|
.close-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
|
@ -74,48 +100,88 @@ const emitClose = () => {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 标题 */
|
||||||
|
.title {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 歌曲列表容器 */
|
||||||
.song-list {
|
.song-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 交替背景:奇数白色,偶数浅灰 */
|
||||||
|
.song-item:nth-child(2n-1) {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.song-item:nth-child(2n) {
|
||||||
|
background-color: #f5f5f5; /* 很浅的灰 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 通用样式 */
|
||||||
.song-item {
|
.song-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background-color: #2c2c2c;
|
|
||||||
transition: background-color 0.2s;
|
transition: background-color 0.2s;
|
||||||
|
cursor: pointer;
|
||||||
|
color: black; /* 字体统一黑色 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* hover 状态稍微加深一下 */
|
||||||
.song-item:hover {
|
.song-item:hover {
|
||||||
background-color: #3a3a3a;
|
background-color: #eaeaea;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 当前播放项高亮(深灰) */
|
||||||
|
.active {
|
||||||
|
background-color: #555555 !important;
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选中(左键或右键)状态,更深的灰 */
|
||||||
|
.selected {
|
||||||
|
background-color: #333333 !important;
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 序号 */
|
||||||
.song-index {
|
.song-index {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
color: #aaa;
|
color: #666666;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 歌曲信息 */
|
||||||
.song-info {
|
.song-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 标题 */
|
||||||
.song-title {
|
.song-title {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 元信息(歌手 · 专辑) */
|
||||||
.song-meta {
|
.song-meta {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #888;
|
color: #444444;
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -69,7 +69,7 @@ export const playInfo = shallowReactive<LX.Player.PlayInfo>({
|
||||||
|
|
||||||
export const playedList = window.lxData.playedList = shallowReactive<LX.Player.PlayMusicInfo[]>([])
|
export const playedList = window.lxData.playedList = shallowReactive<LX.Player.PlayMusicInfo[]>([])
|
||||||
|
|
||||||
export const tempPlayList = shallowReactive<LX.Player.PlayMusicInfo[]>([])//todo
|
export const tempPlayList = shallowReactive<LX.Player.PlayMusicInfo[]>([])
|
||||||
|
|
||||||
export const currentPlayIndex = ref<number>(0)
|
export const currentPlayIndex = ref<number>(0)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue