music(player): 侧边栏 ★ 标记 + sort-bar '仅看收藏' 切换
deploy music / build-and-deploy (push) Successful in 1m59s

This commit is contained in:
Fam Zheng
2026-05-26 10:24:00 +01:00
parent 83418c198f
commit 089de84396
+44 -2
View File
@@ -54,6 +54,12 @@
<button :class="{ active: sortMode === 'least' }" @click="setSort('least')">最少播放</button> <button :class="{ active: sortMode === 'least' }" @click="setSort('least')">最少播放</button>
<button :class="{ active: sortMode === 'recent' }" @click="setSort('recent')">最近</button> <button :class="{ active: sortMode === 'recent' }" @click="setSort('recent')">最近</button>
<button :class="{ active: sortMode === 'random' }" @click="setSort('random')">随机</button> <button :class="{ active: sortMode === 'random' }" @click="setSort('random')">随机</button>
<button
class="fav-toggle"
:class="{ active: favOnly }"
:title="favOnly ? '显示全部' : '仅看收藏'"
@click="toggleFavOnly"
>{{ favOnly ? '★' : '☆' }}</button>
</div> </div>
<div class="playlist"> <div class="playlist">
@@ -72,7 +78,10 @@
title="单击切换 / 双击切换并播放" title="单击切换 / 双击切换并播放"
> >
<div class="row-main"> <div class="row-main">
<div class="row-title">{{ p.title }}</div> <div class="row-title">
<span v-if="p.favorite" class="row-fav" title="已收藏"></span>
{{ p.title }}
</div>
<div class="row-meta"> <div class="row-meta">
<span v-if="p.artist">{{ p.artist }}</span> <span v-if="p.artist">{{ p.artist }}</span>
<span v-if="p.category" class="cat">{{ p.category }}</span> <span v-if="p.category" class="cat">{{ p.category }}</span>
@@ -416,6 +425,7 @@ const activeTagName = ref(null)
const search = ref('') const search = ref('')
const sortMode = ref(localStorage.getItem('music.sort') || 'name') const sortMode = ref(localStorage.getItem('music.sort') || 'name')
const favOnly = ref(localStorage.getItem('music.favOnly') === 'true')
const repeatOne = ref(false) const repeatOne = ref(false)
const volume = ref(parseFloat(localStorage.getItem('music.vol') || '1')) const volume = ref(parseFloat(localStorage.getItem('music.vol') || '1'))
const muted = ref(localStorage.getItem('music.muted') === '1') const muted = ref(localStorage.getItem('music.muted') === '1')
@@ -648,6 +658,9 @@ const tabs = computed(() => {
const filtered = computed(() => { const filtered = computed(() => {
const q = search.value.trim().toLowerCase() const q = search.value.trim().toLowerCase()
let arr = pieces.value let arr = pieces.value
if (favOnly.value) {
arr = arr.filter(p => p.favorite)
}
if (q) { if (q) {
arr = arr.filter(p => { arr = arr.filter(p => {
const hay = `${p.title} ${p.artist || ''} ${p.category || ''} ${(p.tags || []).join(' ')}`.toLowerCase() const hay = `${p.title} ${p.artist || ''} ${p.category || ''} ${(p.tags || []).join(' ')}`.toLowerCase()
@@ -655,6 +668,7 @@ const filtered = computed(() => {
}) })
} }
arr = [...arr] arr = [...arr]
// 名称排序时,收藏的自然置顶;其它模式按用户选的指标排,不强行打断
switch (sortMode.value) { switch (sortMode.value) {
case 'hot': case 'hot':
arr.sort((a, b) => b.play_count - a.play_count || a.title.localeCompare(b.title, 'zh')) arr.sort((a, b) => b.play_count - a.play_count || a.title.localeCompare(b.title, 'zh'))
@@ -676,11 +690,21 @@ const filtered = computed(() => {
break break
} }
default: default:
arr.sort((a, b) => a.title.localeCompare(b.title, 'zh')) arr.sort((a, b) => {
const fa = a.favorite ? 1 : 0
const fb = b.favorite ? 1 : 0
if (fa !== fb) return fb - fa
return a.title.localeCompare(b.title, 'zh')
})
} }
return arr return arr
}) })
function toggleFavOnly() {
favOnly.value = !favOnly.value
localStorage.setItem('music.favOnly', favOnly.value ? 'true' : 'false')
}
function hash(id, seed) { function hash(id, seed) {
let x = (id ^ Math.floor(seed * 1e9)) >>> 0 let x = (id ^ Math.floor(seed * 1e9)) >>> 0
x = (x ^ (x << 13)) >>> 0 x = (x ^ (x << 13)) >>> 0
@@ -1378,6 +1402,24 @@ onBeforeUnmount(() => {
border-color: var(--accent-strong); border-color: var(--accent-strong);
color: var(--accent); color: var(--accent);
} }
.sort-bar .fav-toggle {
margin-left: auto;
border-radius: 4px !important;
border-right-width: 1px !important;
font-size: 14px;
padding: 4px 8px;
}
.sort-bar .fav-toggle.active {
color: #f5b800;
border-color: #f5b800;
background: rgba(245, 184, 0, 0.12);
}
.row-fav {
color: #f5b800;
margin-right: 4px;
font-size: 12px;
}
.playlist { flex: 1; overflow-y: auto; } .playlist { flex: 1; overflow-y: auto; }
.hint { padding: 40px 20px; text-align: center; color: var(--text-mute); font-size: 14px; } .hint { padding: 40px 20px; text-align: center; color: var(--text-mute); font-size: 14px; }