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

View File

@@ -395,15 +395,11 @@ const setMusicFull = () => {
}
.progress-bar {
height: 2px !important;
height: 3px !important;
transform: scaleY(0.67);
&:hover {
height: 3px !important;
.progress-track,
.progress-fill {
height: 3px !important;
}
transform: scaleY(1);
}
}
}
@@ -496,21 +492,19 @@ const setMusicFull = () => {
.progress-bar {
@apply relative w-full cursor-pointer;
height: 2px;
height: 4px;
transform: scaleY(0.5);
transform-origin: bottom center;
transition: transform 0.2s ease;
&:hover {
height: 4px;
.progress-track,
.progress-fill {
height: 4px;
}
transform: scaleY(1);
}
}
.progress-track {
@apply absolute inset-x-0 bottom-0 transition-all duration-200;
height: 2px;
@apply absolute inset-x-0 bottom-0 transition-colors duration-200;
height: 4px;
background: rgba(0, 0, 0, 0.1);
.dark & {
@@ -519,9 +513,10 @@ const setMusicFull = () => {
}
.progress-fill {
@apply absolute bottom-0 left-0 transition-all duration-200;
height: 2px;
@apply absolute bottom-0 left-0;
height: 4px;
background: var(--primary-color, #18a058);
transition: background-color 0.2s ease;
}
.like-active {

View File

@@ -175,8 +175,6 @@ const toggleMenu = () => {
position: relative;
bottom: 0;
left: 0;
z-index: 99;
@apply bg-light dark:bg-black border-t border-gray-200 dark:border-gray-700;
z-index: 99999;
@apply bg-light dark:bg-black border-none border-gray-200 dark:border-gray-700;

View File

@@ -43,6 +43,8 @@ export const usePlayerCoreStore = defineStore(
const availableAudioDevices = ref<AudioOutputDevice[]>([]);
let checkPlayTime: NodeJS.Timeout | null = null;
let checkPlaybackRetryCount = 0;
const MAX_CHECKPLAYBACK_RETRIES = 3;
// ==================== Computed ====================
const currentSong = computed(() => playMusic.value);
@@ -124,6 +126,7 @@ export const usePlayerCoreStore = defineStore(
console.log(`[${actualRequestId}] 播放事件触发,歌曲成功开始播放`);
audioService.off('play', onPlayHandler);
audioService.off('playerror', onPlayErrorHandler);
checkPlaybackRetryCount = 0; // 播放成功,重置重试计数
if (checkPlayTime) {
clearTimeout(checkPlayTime);
checkPlayTime = null;
@@ -141,8 +144,19 @@ export const usePlayerCoreStore = defineStore(
return;
}
// 检查重试次数限制
if (checkPlaybackRetryCount >= MAX_CHECKPLAYBACK_RETRIES) {
console.warn(`播放重试已达上限 (${MAX_CHECKPLAYBACK_RETRIES} 次),停止重试`);
checkPlaybackRetryCount = 0;
setPlayMusic(false);
return;
}
if (userPlayIntent.value && play.value) {
console.log('播放失败尝试刷新URL并重新播放');
checkPlaybackRetryCount++;
console.log(
`播放失败尝试刷新URL并重新播放 (重试 ${checkPlaybackRetryCount}/${MAX_CHECKPLAYBACK_RETRIES})`
);
// 本地音乐不需要刷新 URL
if (!playMusic.value.playMusicUrl?.startsWith('local://')) {
playMusic.value.playMusicUrl = undefined;
@@ -189,10 +203,22 @@ export const usePlayerCoreStore = defineStore(
}
if (!audioService.isActuallyPlaying() && userPlayIntent.value && play.value) {
console.log(`${timeout}ms后歌曲未真正播放且用户仍希望播放尝试重新获取URL`);
audioService.off('play', onPlayHandler);
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
if (!playMusic.value.playMusicUrl?.startsWith('local://')) {
playMusic.value.playMusicUrl = undefined;
@@ -211,10 +237,11 @@ export const usePlayerCoreStore = defineStore(
/**
* 核心播放处理函数
*/
const handlePlayMusic = async (music: SongResult, isPlay: boolean = true) => {
// 如果是新歌曲,重置已尝试的音源(使用 SongSourceConfigManager 按歌曲隔离)
const handlePlayMusic = async (music: SongResult, shouldPlay: boolean = true) => {
// 如果是新歌曲,重置已尝试的音源和重试计数
if (music.id !== playMusic.value.id) {
SongSourceConfigManager.clearTriedSources(music.id);
checkPlaybackRetryCount = 0;
}
// 创建新的播放请求并取消之前的所有请求
@@ -273,9 +300,11 @@ export const usePlayerCoreStore = defineStore(
music.primaryColor = primaryColor;
music.playLoading = true;
// 更新 playMusic
// 更新 playMusic 和播放状态
playMusic.value = music;
play.value = isPlay;
play.value = shouldPlay;
isPlay.value = shouldPlay;
userPlayIntent.value = shouldPlay;
// 更新标题
let title = music.name;
@@ -339,6 +368,8 @@ export const usePlayerCoreStore = defineStore(
const result = await playAudio(requestId);
if (result) {
// 播放成功,清除 isFirstPlay 标记,避免暂停时被误判为新歌
playMusic.value.isFirstPlay = false;
playbackRequestManager.completeRequest(requestId);
return true;
} else {