music(player): 加音量条 + 静音按钮(localStorage 持久化)
deploy music / build-and-deploy (push) Successful in 1m48s
deploy music / build-and-deploy (push) Successful in 1m48s
This commit is contained in:
@@ -230,6 +230,20 @@
|
|||||||
<div class="fill" :style="{ width: progressPct + '%' }"></div>
|
<div class="fill" :style="{ width: progressPct + '%' }"></div>
|
||||||
</div>
|
</div>
|
||||||
<span class="time">{{ fmtTime(duration) }}</span>
|
<span class="time">{{ fmtTime(duration) }}</span>
|
||||||
|
<button
|
||||||
|
class="btn-icon vol-icon"
|
||||||
|
:title="muted ? '取消静音' : '静音'"
|
||||||
|
@click="toggleMute"
|
||||||
|
>{{ volIcon }}</button>
|
||||||
|
<input
|
||||||
|
class="vol-slider"
|
||||||
|
type="range"
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
:value="muted ? 0 : Math.round(volume * 100)"
|
||||||
|
@input="onVolumeInput"
|
||||||
|
title="音量"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
@@ -336,6 +350,37 @@ 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 repeatOne = ref(false)
|
const repeatOne = ref(false)
|
||||||
|
const volume = ref(parseFloat(localStorage.getItem('music.vol') || '1'))
|
||||||
|
const muted = ref(localStorage.getItem('music.muted') === '1')
|
||||||
|
|
||||||
|
const volIcon = computed(() => {
|
||||||
|
if (muted.value || volume.value === 0) return '🔇'
|
||||||
|
if (volume.value < 0.34) return '🔈'
|
||||||
|
if (volume.value < 0.67) return '🔉'
|
||||||
|
return '🔊'
|
||||||
|
})
|
||||||
|
|
||||||
|
function applyVolume() {
|
||||||
|
if (audioEl.value) {
|
||||||
|
audioEl.value.volume = volume.value
|
||||||
|
audioEl.value.muted = muted.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onVolumeInput(e) {
|
||||||
|
const v = parseInt(e.target.value, 10) / 100
|
||||||
|
volume.value = isNaN(v) ? 0 : Math.max(0, Math.min(1, v))
|
||||||
|
if (volume.value > 0 && muted.value) muted.value = false
|
||||||
|
localStorage.setItem('music.vol', String(volume.value))
|
||||||
|
localStorage.setItem('music.muted', muted.value ? '1' : '0')
|
||||||
|
applyVolume()
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleMute() {
|
||||||
|
muted.value = !muted.value
|
||||||
|
localStorage.setItem('music.muted', muted.value ? '1' : '0')
|
||||||
|
applyVolume()
|
||||||
|
}
|
||||||
|
|
||||||
const audioEl = ref(null)
|
const audioEl = ref(null)
|
||||||
const lyricsBoxEl = ref(null)
|
const lyricsBoxEl = ref(null)
|
||||||
@@ -650,6 +695,7 @@ function onTimeUpdate(e) {
|
|||||||
|
|
||||||
function onLoaded(e) {
|
function onLoaded(e) {
|
||||||
duration.value = e.target.duration || 0
|
duration.value = e.target.duration || 0
|
||||||
|
applyVolume()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onEnded() {
|
function onEnded() {
|
||||||
@@ -1364,6 +1410,38 @@ onBeforeUnmount(() => {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vol-icon { font-size: 16px; width: 32px; height: 32px; }
|
||||||
|
.vol-slider {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 90px;
|
||||||
|
height: 4px;
|
||||||
|
background: var(--border);
|
||||||
|
border-radius: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.vol-slider:focus { outline: none; }
|
||||||
|
.vol-slider::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
background: var(--accent-strong);
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.vol-slider::-moz-range-thumb {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
background: var(--accent-strong);
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.vol-slider { width: 60px; }
|
||||||
|
}
|
||||||
|
|
||||||
/* Chat sidebar */
|
/* Chat sidebar */
|
||||||
.chat {
|
.chat {
|
||||||
width: 320px;
|
width: 320px;
|
||||||
|
|||||||
Reference in New Issue
Block a user