mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-24 08:07:23 +08:00
✨ feat: 优化音乐列表加载和播放逻辑,增强性能和用户体验
This commit is contained in:
@@ -88,11 +88,15 @@ onMounted(() => {
|
|||||||
homeRouter.filter((item) => item.meta.isMobile)
|
homeRouter.filter((item) => item.meta.isMobile)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
window.electron.ipcRenderer.on('set-language', handleSetLanguage);
|
if (isElectron) {
|
||||||
|
window.electron.ipcRenderer.on('set-language', handleSetLanguage);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.electron.ipcRenderer.removeListener('set-language', handleSetLanguage);
|
if (isElectron) {
|
||||||
|
window.electron.ipcRenderer.removeListener('set-language', handleSetLanguage);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -119,10 +119,11 @@ const props = withDefaults(
|
|||||||
const emit = defineEmits(['update:show', 'update:loading', 'remove-song']);
|
const emit = defineEmits(['update:show', 'update:loading', 'remove-song']);
|
||||||
|
|
||||||
const page = ref(0);
|
const page = ref(0);
|
||||||
const pageSize = 20;
|
const pageSize = 40;
|
||||||
const isLoadingMore = ref(false);
|
const isLoadingMore = ref(false);
|
||||||
const displayedSongs = ref<any[]>([]);
|
const displayedSongs = ref<any[]>([]);
|
||||||
const loadingList = ref(false);
|
const loadingList = ref(false);
|
||||||
|
const loadedIds = ref(new Set<number>()); // 用于追踪已加载的歌曲ID
|
||||||
|
|
||||||
// 计算总数
|
// 计算总数
|
||||||
const total = computed(() => {
|
const total = computed(() => {
|
||||||
@@ -144,11 +145,31 @@ const formatDetail = computed(() => (detail: any) => {
|
|||||||
return detail;
|
return detail;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const loadAllSongs = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const loadNext = () => {
|
||||||
|
if (displayedSongs.value.length >= total.value) {
|
||||||
|
resolve(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadMoreSongs()
|
||||||
|
.then(() => {
|
||||||
|
// 使用 setTimeout 避免阻塞主线程
|
||||||
|
setTimeout(loadNext, 100);
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
};
|
||||||
|
|
||||||
|
loadNext();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handlePlay = () => {
|
const handlePlay = () => {
|
||||||
const tracks = props.songList || [];
|
// 立即使用当前已加载的歌曲开始播放
|
||||||
store.commit(
|
store.commit(
|
||||||
'setPlayList',
|
'setPlayList',
|
||||||
tracks.map((item) => ({
|
displayedSongs.value.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
picUrl: item.al.picUrl,
|
picUrl: item.al.picUrl,
|
||||||
song: {
|
song: {
|
||||||
@@ -156,6 +177,30 @@ const handlePlay = () => {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 如果还有未加载的歌曲,在后台异步加载
|
||||||
|
if (displayedSongs.value.length < total.value) {
|
||||||
|
setTimeout(() => {
|
||||||
|
loadAllSongs()
|
||||||
|
.then(() => {
|
||||||
|
// 加载完成后更新完整播放列表
|
||||||
|
store.commit(
|
||||||
|
'setPlayList',
|
||||||
|
displayedSongs.value.map((item) => ({
|
||||||
|
...item,
|
||||||
|
picUrl: item.al.picUrl,
|
||||||
|
song: {
|
||||||
|
artists: item.ar
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('加载完整播放列表失败:', error);
|
||||||
|
window.$message.warning(t('common.partialLoadFailed'));
|
||||||
|
});
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const close = () => {
|
const close = () => {
|
||||||
@@ -172,23 +217,32 @@ const loadMoreSongs = async () => {
|
|||||||
// 如果有 trackIds,需要分批请求歌曲详情
|
// 如果有 trackIds,需要分批请求歌曲详情
|
||||||
const start = page.value * pageSize;
|
const start = page.value * pageSize;
|
||||||
const end = Math.min((page.value + 1) * pageSize, total.value);
|
const end = Math.min((page.value + 1) * pageSize, total.value);
|
||||||
const trackIds = props.listInfo.trackIds.slice(start, end).map((item) => item.id);
|
|
||||||
|
|
||||||
if (trackIds.length > 0) {
|
// 从 trackIds 中获取需要加载的 ID
|
||||||
const { data } = await getMusicDetail(trackIds);
|
const trackIdsToLoad = props.listInfo.trackIds
|
||||||
|
.slice(start, end)
|
||||||
|
.map((item) => item.id)
|
||||||
|
.filter((id) => !loadedIds.value.has(id));
|
||||||
|
|
||||||
|
if (trackIdsToLoad.length > 0) {
|
||||||
|
const { data } = await getMusicDetail(trackIdsToLoad);
|
||||||
|
// 更新已加载ID集合
|
||||||
|
data.songs.forEach((song) => loadedIds.value.add(song.id));
|
||||||
displayedSongs.value = [...displayedSongs.value, ...data.songs];
|
displayedSongs.value = [...displayedSongs.value, ...data.songs];
|
||||||
page.value++;
|
|
||||||
}
|
}
|
||||||
|
page.value++;
|
||||||
} else {
|
} else {
|
||||||
// 如果没有 trackIds,直接使用 songList 分页
|
// 如果没有 trackIds,直接使用 songList 分页
|
||||||
const start = page.value * pageSize;
|
const start = page.value * pageSize;
|
||||||
const end = Math.min((page.value + 1) * pageSize, props.songList.length);
|
const end = Math.min((page.value + 1) * pageSize, props.songList.length);
|
||||||
const newSongs = props.songList.slice(start, end);
|
const newSongs = props.songList.slice(start, end);
|
||||||
|
newSongs.forEach((song) => loadedIds.value.add(song.id));
|
||||||
displayedSongs.value = [...displayedSongs.value, ...newSongs];
|
displayedSongs.value = [...displayedSongs.value, ...newSongs];
|
||||||
page.value++;
|
page.value++;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载歌曲失败:', error);
|
console.error('加载歌曲失败:', error);
|
||||||
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
isLoadingMore.value = false;
|
isLoadingMore.value = false;
|
||||||
loadingList.value = false;
|
loadingList.value = false;
|
||||||
@@ -226,10 +280,23 @@ watch(
|
|||||||
() => props.songList,
|
() => props.songList,
|
||||||
(newSongs) => {
|
(newSongs) => {
|
||||||
page.value = 0;
|
page.value = 0;
|
||||||
displayedSongs.value = newSongs.slice(0, pageSize);
|
loadedIds.value.clear();
|
||||||
if (newSongs.length > pageSize) {
|
displayedSongs.value = [];
|
||||||
page.value = 1;
|
|
||||||
|
// 优先加载 songList 的数据
|
||||||
|
if (newSongs.length > 0) {
|
||||||
|
displayedSongs.value = newSongs;
|
||||||
|
// 记录已加载的歌曲ID
|
||||||
|
newSongs.forEach((song) => loadedIds.value.add(song.id));
|
||||||
|
// 计算起始页码
|
||||||
|
page.value = Math.ceil(newSongs.length / pageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果还有更多歌曲需要加载(通过 trackIds),则继续加载
|
||||||
|
if (props.listInfo?.trackIds && total.value > newSongs.length) {
|
||||||
|
loadMoreSongs();
|
||||||
|
}
|
||||||
|
|
||||||
loadingList.value = false;
|
loadingList.value = false;
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
|
|||||||
@@ -329,6 +329,7 @@ const actions = {
|
|||||||
commit('setCurrentArtistId', id);
|
commit('setCurrentArtistId', id);
|
||||||
},
|
},
|
||||||
async initializeSystemFonts({ commit, state }) {
|
async initializeSystemFonts({ commit, state }) {
|
||||||
|
if (!isElectron) return;
|
||||||
// 如果已经有字体列表(不只是默认字体),则不重复获取
|
// 如果已经有字体列表(不只是默认字体),则不重复获取
|
||||||
if (state.systemFonts.length > 1) return;
|
if (state.systemFonts.length > 1) return;
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,13 @@ export const formatNumber = (num: string | number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getImgUrl = (url: string | undefined, size: string = '') => {
|
export const getImgUrl = (url: string | undefined, size: string = '') => {
|
||||||
|
if (!url) return '';
|
||||||
|
|
||||||
|
if (url.includes('thumbnail')) {
|
||||||
|
// 只替换最后一个 thumbnail 参数的尺寸
|
||||||
|
return url.replace(/thumbnail=\d+y\d+(?!.*thumbnail)/, `thumbnail=${size}`);
|
||||||
|
}
|
||||||
|
|
||||||
const imgUrl = `${url}?param=${size}`;
|
const imgUrl = `${url}?param=${size}`;
|
||||||
return imgUrl;
|
return imgUrl;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
<div class="recommend-item-img">
|
<div class="recommend-item-img">
|
||||||
<n-image
|
<n-image
|
||||||
class="recommend-item-img-img"
|
class="recommend-item-img-img"
|
||||||
:src="getImgUrl(item.picUrl || item.coverImgUrl, '200y200')"
|
:src="getImgUrl(item.picUrl || item.coverImgUrl, '300y300')"
|
||||||
width="200"
|
width="200"
|
||||||
height="200"
|
height="200"
|
||||||
lazy
|
lazy
|
||||||
|
|||||||
Reference in New Issue
Block a user