fix: 修复自动播放循环与暂停失效问题 (H-UI-05/H-UI-07)

- fix(player): 修复 checkPlaybackState 无限重试循环,添加最大重试次数限制 (3次)
- fix(player): 修复 handlePlayMusic 参数 isPlay 遮蔽同名 ref 导致 play/isPlay/userPlayIntent 状态不同步
- fix(player): 播放成功后清除 isFirstPlay 标记,避免暂停时被 setPlay 误判为新歌从头播放
- fix(ui): 移除 AppMenu z-index 重复声明 (H-UI-05)
- perf(ui): MiniPlayBar 进度条 hover 改用 transform: scaleY() 替代 height 变化 (H-UI-07)
This commit is contained in:
alger
2026-03-15 15:49:59 +08:00
parent 2182c295c1
commit 239229a60c
3 changed files with 50 additions and 26 deletions
+13 -18
View File
@@ -395,15 +395,11 @@ const setMusicFull = () => {
} }
.progress-bar { .progress-bar {
height: 2px !important; height: 3px !important;
transform: scaleY(0.67);
&:hover { &:hover {
height: 3px !important; transform: scaleY(1);
.progress-track,
.progress-fill {
height: 3px !important;
}
} }
} }
} }
@@ -496,21 +492,19 @@ const setMusicFull = () => {
.progress-bar { .progress-bar {
@apply relative w-full cursor-pointer; @apply relative w-full cursor-pointer;
height: 2px; height: 4px;
transform: scaleY(0.5);
transform-origin: bottom center;
transition: transform 0.2s ease;
&:hover { &:hover {
height: 4px; transform: scaleY(1);
.progress-track,
.progress-fill {
height: 4px;
}
} }
} }
.progress-track { .progress-track {
@apply absolute inset-x-0 bottom-0 transition-all duration-200; @apply absolute inset-x-0 bottom-0 transition-colors duration-200;
height: 2px; height: 4px;
background: rgba(0, 0, 0, 0.1); background: rgba(0, 0, 0, 0.1);
.dark & { .dark & {
@@ -519,9 +513,10 @@ const setMusicFull = () => {
} }
.progress-fill { .progress-fill {
@apply absolute bottom-0 left-0 transition-all duration-200; @apply absolute bottom-0 left-0;
height: 2px; height: 4px;
background: var(--primary-color, #18a058); background: var(--primary-color, #18a058);
transition: background-color 0.2s ease;
} }
.like-active { .like-active {
@@ -175,8 +175,6 @@ const toggleMenu = () => {
position: relative; position: relative;
bottom: 0; bottom: 0;
left: 0; left: 0;
z-index: 99;
@apply bg-light dark:bg-black border-t border-gray-200 dark:border-gray-700;
z-index: 99999; z-index: 99999;
@apply bg-light dark:bg-black border-none border-gray-200 dark:border-gray-700; @apply bg-light dark:bg-black border-none border-gray-200 dark:border-gray-700;
+37 -6
View File
@@ -43,6 +43,8 @@ export const usePlayerCoreStore = defineStore(
const availableAudioDevices = ref<AudioOutputDevice[]>([]); const availableAudioDevices = ref<AudioOutputDevice[]>([]);
let checkPlayTime: NodeJS.Timeout | null = null; let checkPlayTime: NodeJS.Timeout | null = null;
let checkPlaybackRetryCount = 0;
const MAX_CHECKPLAYBACK_RETRIES = 3;
// ==================== Computed ==================== // ==================== Computed ====================
const currentSong = computed(() => playMusic.value); const currentSong = computed(() => playMusic.value);
@@ -124,6 +126,7 @@ export const usePlayerCoreStore = defineStore(
console.log(`[${actualRequestId}] 播放事件触发,歌曲成功开始播放`); console.log(`[${actualRequestId}] 播放事件触发,歌曲成功开始播放`);
audioService.off('play', onPlayHandler); audioService.off('play', onPlayHandler);
audioService.off('playerror', onPlayErrorHandler); audioService.off('playerror', onPlayErrorHandler);
checkPlaybackRetryCount = 0; // 播放成功,重置重试计数
if (checkPlayTime) { if (checkPlayTime) {
clearTimeout(checkPlayTime); clearTimeout(checkPlayTime);
checkPlayTime = null; checkPlayTime = null;
@@ -141,8 +144,19 @@ export const usePlayerCoreStore = defineStore(
return; return;
} }
// 检查重试次数限制
if (checkPlaybackRetryCount >= MAX_CHECKPLAYBACK_RETRIES) {
console.warn(`播放重试已达上限 (${MAX_CHECKPLAYBACK_RETRIES} 次),停止重试`);
checkPlaybackRetryCount = 0;
setPlayMusic(false);
return;
}
if (userPlayIntent.value && play.value) { if (userPlayIntent.value && play.value) {
console.log('播放失败,尝试刷新URL并重新播放'); checkPlaybackRetryCount++;
console.log(
`播放失败,尝试刷新URL并重新播放 (重试 ${checkPlaybackRetryCount}/${MAX_CHECKPLAYBACK_RETRIES})`
);
// 本地音乐不需要刷新 URL // 本地音乐不需要刷新 URL
if (!playMusic.value.playMusicUrl?.startsWith('local://')) { if (!playMusic.value.playMusicUrl?.startsWith('local://')) {
playMusic.value.playMusicUrl = undefined; playMusic.value.playMusicUrl = undefined;
@@ -189,10 +203,22 @@ export const usePlayerCoreStore = defineStore(
} }
if (!audioService.isActuallyPlaying() && userPlayIntent.value && play.value) { if (!audioService.isActuallyPlaying() && userPlayIntent.value && play.value) {
console.log(`${timeout}ms后歌曲未真正播放且用户仍希望播放,尝试重新获取URL`);
audioService.off('play', onPlayHandler); audioService.off('play', onPlayHandler);
audioService.off('playerror', onPlayErrorHandler); audioService.off('playerror', onPlayErrorHandler);
// 检查重试次数限制
if (checkPlaybackRetryCount >= MAX_CHECKPLAYBACK_RETRIES) {
console.warn(`超时重试已达上限 (${MAX_CHECKPLAYBACK_RETRIES} 次),停止重试`);
checkPlaybackRetryCount = 0;
setPlayMusic(false);
return;
}
checkPlaybackRetryCount++;
console.log(
`${timeout}ms后歌曲未真正播放,尝试重新获取URL (重试 ${checkPlaybackRetryCount}/${MAX_CHECKPLAYBACK_RETRIES})`
);
// 本地音乐不需要刷新 URL // 本地音乐不需要刷新 URL
if (!playMusic.value.playMusicUrl?.startsWith('local://')) { if (!playMusic.value.playMusicUrl?.startsWith('local://')) {
playMusic.value.playMusicUrl = undefined; playMusic.value.playMusicUrl = undefined;
@@ -211,10 +237,11 @@ export const usePlayerCoreStore = defineStore(
/** /**
* 核心播放处理函数 * 核心播放处理函数
*/ */
const handlePlayMusic = async (music: SongResult, isPlay: boolean = true) => { const handlePlayMusic = async (music: SongResult, shouldPlay: boolean = true) => {
// 如果是新歌曲,重置已尝试的音源(使用 SongSourceConfigManager 按歌曲隔离) // 如果是新歌曲,重置已尝试的音源和重试计数
if (music.id !== playMusic.value.id) { if (music.id !== playMusic.value.id) {
SongSourceConfigManager.clearTriedSources(music.id); SongSourceConfigManager.clearTriedSources(music.id);
checkPlaybackRetryCount = 0;
} }
// 创建新的播放请求并取消之前的所有请求 // 创建新的播放请求并取消之前的所有请求
@@ -273,9 +300,11 @@ export const usePlayerCoreStore = defineStore(
music.primaryColor = primaryColor; music.primaryColor = primaryColor;
music.playLoading = true; music.playLoading = true;
// 更新 playMusic // 更新 playMusic 和播放状态
playMusic.value = music; playMusic.value = music;
play.value = isPlay; play.value = shouldPlay;
isPlay.value = shouldPlay;
userPlayIntent.value = shouldPlay;
// 更新标题 // 更新标题
let title = music.name; let title = music.name;
@@ -339,6 +368,8 @@ export const usePlayerCoreStore = defineStore(
const result = await playAudio(requestId); const result = await playAudio(requestId);
if (result) { if (result) {
// 播放成功,清除 isFirstPlay 标记,避免暂停时被误判为新歌
playMusic.value.isFirstPlay = false;
playbackRequestManager.completeRequest(requestId); playbackRequestManager.completeRequest(requestId);
return true; return true;
} else { } else {