mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-23 23:57:22 +08:00
✨ feat: 优化音频监听器初始化和设置保存逻辑
- 在 App.vue 中引入 initAudioListeners 函数,确保在播放音乐时初始化音频监听器。 - 在 MusicHook.ts 中重构音频监听器的初始化逻辑,增加音频加载的超时处理。 - 在设置页面中实现防抖保存功能,避免频繁更新设置,提高性能和用户体验。 这些更改旨在提升音频播放的稳定性和设置管理的效率。
This commit is contained in:
+22
-12
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { darkTheme, lightTheme } from 'naive-ui';
|
import { darkTheme, lightTheme } from 'naive-ui';
|
||||||
import { computed, onMounted, watch } from 'vue';
|
import { computed, nextTick, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import homeRouter from '@/router/home';
|
import homeRouter from '@/router/home';
|
||||||
@@ -21,6 +21,7 @@ import { usePlayerStore } from '@/store/modules/player';
|
|||||||
import { useSettingsStore } from '@/store/modules/settings';
|
import { useSettingsStore } from '@/store/modules/settings';
|
||||||
import { isElectron } from '@/utils';
|
import { isElectron } from '@/utils';
|
||||||
|
|
||||||
|
import { initAudioListeners } from './hooks/MusicHook';
|
||||||
import { isMobile } from './utils';
|
import { isMobile } from './utils';
|
||||||
|
|
||||||
const { locale } = useI18n();
|
const { locale } = useI18n();
|
||||||
@@ -61,18 +62,27 @@ const handleSetLanguage = (_: any, value: string) => {
|
|||||||
// settingsStore.setLanguage(value);
|
// settingsStore.setLanguage(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
settingsStore.initializeSettings();
|
||||||
settingsStore.initializeSettings();
|
handleSetLanguage(null, settingsStore.setData.language);
|
||||||
handleSetLanguage(null, settingsStore.setData.language);
|
settingsStore.initializeTheme();
|
||||||
settingsStore.initializeTheme();
|
settingsStore.initializeSystemFonts();
|
||||||
settingsStore.initializeSystemFonts();
|
if (isMobile.value) {
|
||||||
playerStore.initializePlayState();
|
menuStore.setMenus(homeRouter.filter((item) => item.meta.isMobile));
|
||||||
if (isMobile.value) {
|
}
|
||||||
menuStore.setMenus(homeRouter.filter((item) => item.meta.isMobile));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isElectron) {
|
if (isElectron) {
|
||||||
window.electron.ipcRenderer.on('language-changed', handleSetLanguage);
|
window.electron.ipcRenderer.on('language-changed', handleSetLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
// 先初始化播放状态
|
||||||
|
await playerStore.initializePlayState();
|
||||||
|
|
||||||
|
// 如果有正在播放的音乐,则初始化音频监听器
|
||||||
|
if (playerStore.playMusic && playerStore.playMusic.id) {
|
||||||
|
// 使用 nextTick 确保 DOM 更新后再初始化
|
||||||
|
await nextTick();
|
||||||
|
initAudioListeners();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createDiscreteApi } from 'naive-ui';
|
import { createDiscreteApi } from 'naive-ui';
|
||||||
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
import { computed, nextTick, onUnmounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
import i18n from '@/../i18n/renderer';
|
import i18n from '@/../i18n/renderer';
|
||||||
import useIndexedDB from '@/hooks/IndexDBHook';
|
import useIndexedDB from '@/hooks/IndexDBHook';
|
||||||
@@ -763,37 +763,74 @@ if (isElectron) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 在组件挂载时设置监听器
|
// 在组件挂载时设置监听器
|
||||||
onMounted(() => {
|
export const initAudioListeners = async () => {
|
||||||
// 初始化音频监听器
|
try {
|
||||||
setupAudioListeners();
|
// 确保有正在播放的音乐
|
||||||
|
if (!playerStore.playMusic || !playerStore.playMusic.id) {
|
||||||
// 监听歌词窗口关闭事件
|
console.log('没有正在播放的音乐,跳过音频监听器初始化');
|
||||||
if (isElectron) {
|
return;
|
||||||
window.api.onLyricWindowClosed(() => {
|
|
||||||
isLyricWindowOpen.value = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否需要初始化 sound 对象
|
|
||||||
if (!sound.value && audioService.getCurrentSound()) {
|
|
||||||
sound.value = audioService.getCurrentSound();
|
|
||||||
|
|
||||||
// 如果当前处于播放状态,启动进度更新
|
|
||||||
if (playerStore.play && sound.value) {
|
|
||||||
// 如果有保存的播放进度,应用它
|
|
||||||
if (playerStore.savedPlayProgress !== undefined && sound.value) {
|
|
||||||
try {
|
|
||||||
// 设置音频位置
|
|
||||||
sound.value.seek(playerStore.savedPlayProgress);
|
|
||||||
// 同时更新时间显示,这样进度条也会更新
|
|
||||||
nowTime.value = playerStore.savedPlayProgress;
|
|
||||||
console.log('恢复播放进度:', playerStore.savedPlayProgress);
|
|
||||||
} catch (e) {
|
|
||||||
console.error('恢复播放进度失败:', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
startProgressAnimation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确保有音频实例
|
||||||
|
const initialSound = audioService.getCurrentSound();
|
||||||
|
if (!initialSound) {
|
||||||
|
console.log('没有音频实例,等待音频加载...');
|
||||||
|
// 等待音频加载完成
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
const checkInterval = setInterval(() => {
|
||||||
|
const sound = audioService.getCurrentSound();
|
||||||
|
if (sound) {
|
||||||
|
clearInterval(checkInterval);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// 设置超时
|
||||||
|
setTimeout(() => {
|
||||||
|
clearInterval(checkInterval);
|
||||||
|
console.log('等待音频加载超时');
|
||||||
|
resolve();
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化音频监听器
|
||||||
|
setupAudioListeners();
|
||||||
|
|
||||||
|
// 监听歌词窗口关闭事件
|
||||||
|
if (isElectron) {
|
||||||
|
window.api.onLyricWindowClosed(() => {
|
||||||
|
isLyricWindowOpen.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取最新的音频实例
|
||||||
|
const finalSound = audioService.getCurrentSound();
|
||||||
|
if (finalSound) {
|
||||||
|
// 更新全局 sound 引用
|
||||||
|
sound.value = finalSound;
|
||||||
|
|
||||||
|
// 如果当前处于播放状态,启动进度更新
|
||||||
|
if (playerStore.play) {
|
||||||
|
// 如果有保存的播放进度,应用它
|
||||||
|
if (playerStore.savedPlayProgress !== undefined) {
|
||||||
|
try {
|
||||||
|
// 设置音频位置
|
||||||
|
finalSound.seek(playerStore.savedPlayProgress);
|
||||||
|
// 同时更新时间显示
|
||||||
|
nowTime.value = playerStore.savedPlayProgress;
|
||||||
|
console.log('恢复播放进度:', playerStore.savedPlayProgress);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('恢复播放进度失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startProgressAnimation();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn('无法获取音频实例,跳过进度更新初始化');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化音频监听器失败:', error);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ export const usePlayerStore = defineStore('player', () => {
|
|||||||
try {
|
try {
|
||||||
console.log('settingStore.setData', settingStore.setData);
|
console.log('settingStore.setData', settingStore.setData);
|
||||||
const isPlaying = settingStore.setData.autoPlay;
|
const isPlaying = settingStore.setData.autoPlay;
|
||||||
await handlePlayMusic(savedPlayMusic, isPlaying);
|
await handlePlayMusic({ ...savedPlayMusic, playMusicUrl: undefined }, isPlaying);
|
||||||
|
|
||||||
if (savedProgress) {
|
if (savedProgress) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
|||||||
|
|
||||||
if (isElectron) {
|
if (isElectron) {
|
||||||
window.electron.ipcRenderer.send('set-store-value', 'set', cloneDeep(mergedData));
|
window.electron.ipcRenderer.send('set-store-value', 'set', cloneDeep(mergedData));
|
||||||
|
console.log('mergedData', mergedData);
|
||||||
setData.value = cloneDeep(mergedData);
|
setData.value = cloneDeep(mergedData);
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem('appSettings', JSON.stringify(cloneDeep(mergedData)));
|
localStorage.setItem('appSettings', JSON.stringify(cloneDeep(mergedData)));
|
||||||
|
|||||||
@@ -461,9 +461,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useDebounceFn } from '@vueuse/core';
|
||||||
|
import { debounce } from 'lodash';
|
||||||
import type { FormRules } from 'naive-ui';
|
import type { FormRules } from 'naive-ui';
|
||||||
import { useMessage } from 'naive-ui';
|
import { useMessage } from 'naive-ui';
|
||||||
import { computed, h, nextTick, onMounted, ref, watch } from 'vue';
|
import { computed, h, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import localData from '@/../main/set.json';
|
import localData from '@/../main/set.json';
|
||||||
@@ -483,6 +485,15 @@ import config from '../../../../package.json';
|
|||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
// 创建一个本地缓存的setData,避免频繁更新
|
||||||
|
const localSetData = ref({ ...settingsStore.setData });
|
||||||
|
|
||||||
|
// 在组件卸载时保存设置
|
||||||
|
onUnmounted(() => {
|
||||||
|
// 确保最终设置被保存
|
||||||
|
settingsStore.setSetData(localSetData.value);
|
||||||
|
});
|
||||||
|
|
||||||
const checking = ref(false);
|
const checking = ref(false);
|
||||||
const updateInfo = ref<UpdateResult>({
|
const updateInfo = ref<UpdateResult>({
|
||||||
hasUpdate: false,
|
hasUpdate: false,
|
||||||
@@ -493,14 +504,44 @@ const updateInfo = ref<UpdateResult>({
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
// 创建一个防抖的保存函数
|
||||||
|
// const debouncedSaveSettings = debounce((newData) => {
|
||||||
|
// settingsStore.setSetData(newData);
|
||||||
|
// }, 500);
|
||||||
|
|
||||||
|
const saveSettings = useDebounceFn((data) => {
|
||||||
|
settingsStore.setSetData(data);
|
||||||
|
}, 500);
|
||||||
|
|
||||||
// 使用计算属性来管理设置数据
|
// 使用计算属性来管理设置数据
|
||||||
const setData = computed({
|
const setData = computed({
|
||||||
get: () => settingsStore.setData,
|
get: () => localSetData.value,
|
||||||
set: (newData) => {
|
set: (newData) => {
|
||||||
settingsStore.setSetData(newData);
|
localSetData.value = newData;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 监听localSetData变化,保存设置
|
||||||
|
watch(
|
||||||
|
() => localSetData.value,
|
||||||
|
(newValue) => {
|
||||||
|
saveSettings(newValue);
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 监听store中setData的变化,同步到本地
|
||||||
|
watch(
|
||||||
|
() => settingsStore.setData,
|
||||||
|
(newValue) => {
|
||||||
|
// 只在初始加载时更新本地数据,避免循环更新
|
||||||
|
if (JSON.stringify(localSetData.value) !== JSON.stringify(newValue)) {
|
||||||
|
localSetData.value = { ...newValue };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
const isDarkTheme = computed({
|
const isDarkTheme = computed({
|
||||||
get: () => settingsStore.theme === 'dark',
|
get: () => settingsStore.theme === 'dark',
|
||||||
set: () => settingsStore.toggleTheme()
|
set: () => settingsStore.toggleTheme()
|
||||||
|
|||||||
Reference in New Issue
Block a user