mirror of
https://github.com/imsyy/SPlayer.git
synced 2025-11-25 03:14:57 +08:00
🐞 fix: 修复歌词加载过慢仍旧展示上一首 #532
This commit is contained in:
3
components.d.ts
vendored
3
components.d.ts
vendored
@@ -97,18 +97,15 @@ declare module 'vue' {
|
||||
NP: typeof import('naive-ui')['NP']
|
||||
NPopconfirm: typeof import('naive-ui')['NPopconfirm']
|
||||
NPopover: typeof import('naive-ui')['NPopover']
|
||||
NProgress: typeof import('naive-ui')['NProgress']
|
||||
NQrCode: typeof import('naive-ui')['NQrCode']
|
||||
NRadio: typeof import('naive-ui')['NRadio']
|
||||
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
|
||||
NResult: typeof import('naive-ui')['NResult']
|
||||
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||
NSelect: typeof import('naive-ui')['NSelect']
|
||||
NSkeleton: typeof import('naive-ui')['NSkeleton']
|
||||
NSlider: typeof import('naive-ui')['NSlider']
|
||||
NSpin: typeof import('naive-ui')['NSpin']
|
||||
NSwitch: typeof import('naive-ui')['NSwitch']
|
||||
NTab: typeof import('naive-ui')['NTab']
|
||||
NTabPane: typeof import('naive-ui')['NTabPane']
|
||||
NTabs: typeof import('naive-ui')['NTabs']
|
||||
NTag: typeof import('naive-ui')['NTag']
|
||||
|
||||
@@ -6,7 +6,7 @@ import vue from "@vitejs/plugin-vue";
|
||||
import AutoImport from "unplugin-auto-import/vite";
|
||||
import Components from "unplugin-vue-components/vite";
|
||||
import viteCompression from "vite-plugin-compression";
|
||||
import VueDevTools from "vite-plugin-vue-devtools";
|
||||
// import VueDevTools from "vite-plugin-vue-devtools";
|
||||
import wasm from "vite-plugin-wasm";
|
||||
|
||||
export default defineConfig(({ command, mode }) => {
|
||||
@@ -49,7 +49,7 @@ export default defineConfig(({ command, mode }) => {
|
||||
root: ".",
|
||||
plugins: [
|
||||
vue(),
|
||||
mode === "development" && VueDevTools(),
|
||||
// mode === "development" && VueDevTools(),
|
||||
AutoImport({
|
||||
imports: [
|
||||
"vue",
|
||||
|
||||
@@ -16,11 +16,16 @@ const initLyricIpc = (): void => {
|
||||
// 切换桌面歌词
|
||||
ipcMain.on("toggle-desktop-lyric", (_event, val: boolean) => {
|
||||
if (val) {
|
||||
if (!lyricWin) {
|
||||
lyricWin = lyricWindow.create();
|
||||
} else {
|
||||
lyricWin?.show();
|
||||
}
|
||||
lyricWin?.setAlwaysOnTop(true, "screen-saver");
|
||||
} else {
|
||||
lyricWin?.destroy();
|
||||
lyricWin = null;
|
||||
// 关闭:不销毁窗口,直接隐藏,保留位置与状态
|
||||
if (!lyricWin) return;
|
||||
lyricWin.hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ export const songLyric = (id: number) => {
|
||||
*/
|
||||
export const songLyricTTML = async (id: number) => {
|
||||
if (isElectron) {
|
||||
return request({ url: "/lyric/ttml", params: { id } });
|
||||
return request({ url: "/lyric/ttml", params: { id, noCookie: true } });
|
||||
} else {
|
||||
const url = `https://amll-ttml-db.stevexmh.net/ncm/${id}`;
|
||||
try {
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<!-- 评论 -->
|
||||
<PlayerComment v-if="isShowComment && !statusStore.pureLyricMode" />
|
||||
<!-- 歌词 -->
|
||||
<div v-else-if="musicStore.isHasLrc" class="content-right">
|
||||
<div class="content-right">
|
||||
<!-- 数据 -->
|
||||
<PlayerData
|
||||
v-if="statusStore.pureLyricMode && musicStore.isHasLrc"
|
||||
@@ -218,6 +218,7 @@ onBeforeUnmount(() => {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
will-change: width, opacity, transform;
|
||||
transition:
|
||||
width 0.3s,
|
||||
opacity 0.5s cubic-bezier(0.34, 1.56, 0.64, 1),
|
||||
@@ -232,6 +233,7 @@ onBeforeUnmount(() => {
|
||||
max-width: 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: opacity 0.3s;
|
||||
.player-data {
|
||||
margin-top: 0;
|
||||
margin-bottom: 26px;
|
||||
@@ -272,6 +274,9 @@ onBeforeUnmount(() => {
|
||||
.content-left {
|
||||
width: 100%;
|
||||
}
|
||||
.content-right {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
:key="amLyricsData?.[0]?.words?.length"
|
||||
:class="['lyric-am', { pure: statusStore.pureLyricMode }]"
|
||||
>
|
||||
<div v-if="statusStore.lyricLoading" class="lyric-loading">歌词正在加载中...</div>
|
||||
<LyricPlayer
|
||||
v-else
|
||||
ref="lyricPlayerRef"
|
||||
:lyricLines="amLyricsData"
|
||||
:currentTime="playSeek"
|
||||
@@ -37,7 +39,6 @@ import { useMusicStore, useSettingStore, useStatusStore } from "@/stores";
|
||||
import { msToS } from "@/utils/time";
|
||||
import { getLyricLanguage } from "@/utils/lyric";
|
||||
import player from "@/utils/player";
|
||||
import { watch } from "vue";
|
||||
import LyricMenu from "./LyricMenu.vue";
|
||||
|
||||
const musicStore = useMusicStore();
|
||||
@@ -47,11 +48,15 @@ const settingStore = useSettingStore();
|
||||
const lyricPlayerRef = ref<any | null>(null);
|
||||
|
||||
// 实时播放进度
|
||||
const playSeek = ref<number>(player.getSeek());
|
||||
const playSeek = ref<number>(
|
||||
Math.floor((player.getSeek() + statusStore.getSongOffset(musicStore.playSong?.id)) * 1000),
|
||||
);
|
||||
|
||||
// 实时更新播放进度
|
||||
const { pause: pauseSeek, resume: resumeSeek } = useRafFn(() => {
|
||||
const seekInSeconds = player.getSeek();
|
||||
const songId = musicStore.playSong?.id;
|
||||
const offsetSeconds = statusStore.getSongOffset(songId);
|
||||
const seekInSeconds = player.getSeek() + offsetSeconds;
|
||||
playSeek.value = Math.floor(seekInSeconds * 1000);
|
||||
});
|
||||
|
||||
@@ -164,4 +169,14 @@ onBeforeUnmount(() => {
|
||||
font-family: var(--ja-font-family);
|
||||
}
|
||||
}
|
||||
|
||||
.lyric-loading {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--amll-lyric-view-color, #efefef);
|
||||
font-size: 22px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
@after-enter="lyricsScroll(statusStore.lyricIndex)"
|
||||
@after-leave="lyricsScroll(statusStore.lyricIndex)"
|
||||
>
|
||||
<n-scrollbar ref="lyricScroll" class="lyric-scroll" tabindex="-1">
|
||||
<div v-if="statusStore.lyricLoading" class="lyric-loading">歌词正在加载中...</div>
|
||||
<n-scrollbar v-else ref="lyricScroll" class="lyric-scroll" tabindex="-1">
|
||||
<!-- 逐字歌词 -->
|
||||
<template v-if="settingStore.showYrc && musicStore.isHasYrc">
|
||||
<div id="lrc-placeholder" class="placeholder">
|
||||
@@ -597,3 +598,14 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.lyric-loading {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 22px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -52,6 +52,8 @@ interface StatusState {
|
||||
playIndex: number;
|
||||
/** 歌词播放索引 */
|
||||
lyricIndex: number;
|
||||
/** 歌词加载状态 */
|
||||
lyricLoading: boolean;
|
||||
/** 当前播放时间 */
|
||||
currentTime: number;
|
||||
/** 歌曲总时长 */
|
||||
@@ -116,6 +118,7 @@ export const useStatusStore = defineStore("status", {
|
||||
spectrumsData: [],
|
||||
playIndex: -1,
|
||||
lyricIndex: -1,
|
||||
lyricLoading: false,
|
||||
playRate: 1,
|
||||
playVolume: 0.7,
|
||||
playVolumeMute: 0,
|
||||
|
||||
@@ -44,6 +44,8 @@ export const resetSongLyric = () => {
|
||||
// 重置歌词数据
|
||||
musicStore.setSongLyric({}, true);
|
||||
statusStore.usingTTMLLyric = false;
|
||||
// 标记为加载中(切歌时防止显示上一首歌词)
|
||||
statusStore.lyricLoading = true;
|
||||
// 重置歌词索引
|
||||
statusStore.lyricIndex = -1;
|
||||
};
|
||||
@@ -109,6 +111,8 @@ export const parsedLyricsData = (lyricData: any, skipExclude: boolean = false):
|
||||
);
|
||||
// 重置歌词索引
|
||||
statusStore.lyricIndex = -1;
|
||||
// 歌词已加载完成
|
||||
statusStore.lyricLoading = false;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,23 +13,37 @@ export const getLyricData = async (id: number) => {
|
||||
const musicStore = useMusicStore();
|
||||
const settingStore = useSettingStore();
|
||||
const statusStore = useStatusStore();
|
||||
// 切歌或重新获取时,先标记为加载中
|
||||
statusStore.lyricLoading = true;
|
||||
|
||||
if (!id) {
|
||||
statusStore.usingTTMLLyric = false;
|
||||
resetSongLyric();
|
||||
statusStore.lyricLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 检测本地歌词覆盖
|
||||
const getLyric = getLyricFun(settingStore.localLyricPath, id);
|
||||
const [{ lyric: lyricRes, isLocal: lyricLocal }, { lyric: ttmlContent, isLocal: ttmlLocal }] =
|
||||
await Promise.all([
|
||||
getLyric("lrc", songLyric),
|
||||
settingStore.enableTTMLLyric ? getLyric("ttml", songLyricTTML) : getLyric("ttml"),
|
||||
]);
|
||||
// 先加载 LRC,不阻塞到 TTML 完成
|
||||
const lrcPromise = getLyric("lrc", songLyric);
|
||||
const ttmlPromise = settingStore.enableTTMLLyric ? getLyric("ttml", songLyricTTML) : null;
|
||||
|
||||
const { lyric: lyricRes, isLocal: lyricLocal } = await lrcPromise;
|
||||
parsedLyricsData(lyricRes, lyricLocal && !settingStore.enableExcludeLocalLyrics);
|
||||
if (ttmlContent) {
|
||||
// LRC 到达后即可认为加载完成
|
||||
statusStore.lyricLoading = false;
|
||||
|
||||
// TTML 并行加载,完成后增量更新,不阻塞整体流程
|
||||
if (ttmlPromise) {
|
||||
statusStore.usingTTMLLyric = false;
|
||||
void ttmlPromise
|
||||
.then(({ lyric: ttmlContent, isLocal: ttmlLocal }) => {
|
||||
if (!ttmlContent) {
|
||||
statusStore.usingTTMLLyric = false;
|
||||
return;
|
||||
}
|
||||
const parsedResult = parseTTML(ttmlContent);
|
||||
if (!parsedResult?.lines?.length) {
|
||||
statusStore.usingTTMLLyric = false;
|
||||
@@ -57,6 +71,11 @@ export const getLyricData = async (id: number) => {
|
||||
} else {
|
||||
statusStore.usingTTMLLyric = false;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("❌ Error loading TTML lyrics:", err);
|
||||
statusStore.usingTTMLLyric = false;
|
||||
});
|
||||
} else {
|
||||
statusStore.usingTTMLLyric = false;
|
||||
}
|
||||
@@ -66,6 +85,7 @@ export const getLyricData = async (id: number) => {
|
||||
console.error("❌ Error loading lyrics:", error);
|
||||
statusStore.usingTTMLLyric = false;
|
||||
resetSongLyric();
|
||||
statusStore.lyricLoading = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -647,7 +647,10 @@ class Player {
|
||||
window.$message.warning("当前列表歌曲无法播放,请更换歌曲");
|
||||
} else {
|
||||
window.$message.error("该歌曲暂无音源,跳至下一首");
|
||||
this.nextOrPrev("next");
|
||||
// 防止切歌保护状态阻塞跳转
|
||||
this.switching = false;
|
||||
await this.nextOrPrev("next");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -658,7 +661,10 @@ class Player {
|
||||
window.$message.warning("当前列表歌曲无法播放,请更换歌曲");
|
||||
} else {
|
||||
window.$message.error("该歌曲暂无音源,跳至下一首");
|
||||
this.nextOrPrev("next");
|
||||
// 防止切歌保护状态阻塞跳转
|
||||
this.switching = false;
|
||||
await this.nextOrPrev("next");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -668,7 +674,9 @@ class Player {
|
||||
return;
|
||||
} else {
|
||||
window.$message.error("该歌曲无法播放,跳至下一首");
|
||||
this.nextOrPrev();
|
||||
// 防止切歌保护状态阻塞跳转
|
||||
this.switching = false;
|
||||
await this.nextOrPrev();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user