|
|
<template> |
|
|
<button |
|
|
class="play-mode-toggle" |
|
|
:class="{ 'active': isActive }" |
|
|
@click="toggleMode" |
|
|
:title="modeText" |
|
|
> |
|
|
<i :class="modeIcon" class="mode-icon"></i> |
|
|
<span class="mode-text" v-if="showText">{{ modeText }}</span> |
|
|
</button> |
|
|
</template> |
|
|
|
|
|
<script setup> |
|
|
import { computed } from 'vue' |
|
|
import { usePlayerStore } from '@/stores/player' |
|
|
|
|
|
const props = defineProps({ |
|
|
|
|
|
showText: { |
|
|
type: Boolean, |
|
|
default: false |
|
|
}, |
|
|
|
|
|
|
|
|
isActive: { |
|
|
type: Boolean, |
|
|
default: false |
|
|
}, |
|
|
|
|
|
|
|
|
size: { |
|
|
type: String, |
|
|
default: 'medium', |
|
|
validator: (value) => ['small', 'medium', 'large'].includes(value) |
|
|
} |
|
|
}) |
|
|
|
|
|
const emit = defineEmits(['change']) |
|
|
|
|
|
const playerStore = usePlayerStore() |
|
|
|
|
|
|
|
|
const modeIcon = computed(() => { |
|
|
const iconMap = { |
|
|
'list': 'fas fa-list-ul', |
|
|
'loop': 'fas fa-redo-alt', |
|
|
'random': 'fas fa-random' |
|
|
} |
|
|
return iconMap[playerStore.playMode] || iconMap.list |
|
|
}) |
|
|
|
|
|
|
|
|
const modeText = computed(() => { |
|
|
const textMap = { |
|
|
'list': '列表循环', |
|
|
'loop': '单曲循环', |
|
|
'random': '随机播放' |
|
|
} |
|
|
return textMap[playerStore.playMode] || textMap.list |
|
|
}) |
|
|
|
|
|
|
|
|
const toggleMode = () => { |
|
|
const modes = ['list', 'loop', 'random'] |
|
|
const currentIndex = modes.indexOf(playerStore.playMode) |
|
|
const nextIndex = (currentIndex + 1) % modes.length |
|
|
const nextMode = modes[nextIndex] |
|
|
|
|
|
playerStore.setPlayMode(nextMode) |
|
|
emit('change', nextMode) |
|
|
} |
|
|
</script> |
|
|
|
|
|
<style scoped> |
|
|
.play-mode-toggle { |
|
|
display: inline-flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
gap: 6px; |
|
|
border: none; |
|
|
background: transparent; |
|
|
color: var(--text-secondary); |
|
|
cursor: pointer; |
|
|
transition: var(--transition-fast); |
|
|
border-radius: 50%; |
|
|
padding: 8px; |
|
|
min-width: 44px; |
|
|
min-height: 44px; |
|
|
} |
|
|
|
|
|
.play-mode-toggle:hover { |
|
|
color: var(--text-primary); |
|
|
background: rgba(255, 255, 255, 0.1); |
|
|
} |
|
|
|
|
|
.play-mode-toggle.active { |
|
|
color: var(--accent-red); |
|
|
} |
|
|
|
|
|
.play-mode-toggle.active:hover { |
|
|
color: var(--accent-red-hover); |
|
|
} |
|
|
|
|
|
.mode-icon { |
|
|
font-size: 16px; |
|
|
transition: var(--transition-fast); |
|
|
} |
|
|
|
|
|
.mode-text { |
|
|
font-size: 12px; |
|
|
font-weight: 500; |
|
|
white-space: nowrap; |
|
|
} |
|
|
|
|
|
|
|
|
.play-mode-toggle[data-size="small"] { |
|
|
min-width: 36px; |
|
|
min-height: 36px; |
|
|
padding: 6px; |
|
|
} |
|
|
|
|
|
.play-mode-toggle[data-size="small"] .mode-icon { |
|
|
font-size: 14px; |
|
|
} |
|
|
|
|
|
.play-mode-toggle[data-size="small"] .mode-text { |
|
|
font-size: 11px; |
|
|
} |
|
|
|
|
|
.play-mode-toggle[data-size="large"] { |
|
|
min-width: 52px; |
|
|
min-height: 52px; |
|
|
padding: 10px; |
|
|
} |
|
|
|
|
|
.play-mode-toggle[data-size="large"] .mode-icon { |
|
|
font-size: 18px; |
|
|
} |
|
|
|
|
|
.play-mode-toggle[data-size="large"] .mode-text { |
|
|
font-size: 13px; |
|
|
} |
|
|
|
|
|
|
|
|
@media (max-width: 375px) { |
|
|
.play-mode-toggle { |
|
|
min-width: 40px; |
|
|
min-height: 40px; |
|
|
padding: 6px; |
|
|
} |
|
|
|
|
|
.mode-icon { |
|
|
font-size: 14px; |
|
|
} |
|
|
|
|
|
.mode-text { |
|
|
font-size: 11px; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.play-mode-toggle:active { |
|
|
transform: scale(0.95); |
|
|
} |
|
|
|
|
|
|
|
|
.play-mode-toggle .fa-random { |
|
|
animation: random-pulse 2s ease-in-out infinite; |
|
|
} |
|
|
|
|
|
@keyframes random-pulse { |
|
|
0%, 100% { |
|
|
opacity: 1; |
|
|
} |
|
|
50% { |
|
|
opacity: 0.6; |
|
|
} |
|
|
} |
|
|
|
|
|
.play-mode-toggle .fa-redo-alt { |
|
|
animation: loop-spin 3s linear infinite; |
|
|
} |
|
|
|
|
|
@keyframes loop-spin { |
|
|
from { |
|
|
transform: rotate(0deg); |
|
|
} |
|
|
to { |
|
|
transform: rotate(360deg); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.play-mode-toggle.active .fa-random, |
|
|
.play-mode-toggle.active .fa-redo-alt { |
|
|
animation-play-state: paused; |
|
|
} |
|
|
</style> |