🐞 fix: 修复歌词管理引用错误

This commit is contained in:
imsyy
2025-11-17 18:15:28 +08:00
parent 392c64f06b
commit c9f3553806
2 changed files with 68 additions and 25 deletions

View File

@@ -13,10 +13,6 @@ import { isEmpty } from "lodash-es";
// 然后根据配置的歌词排除内容来处理 // 然后根据配置的歌词排除内容来处理
// 然后写入 store // 然后写入 store
class LyricManager { class LyricManager {
// Store
private musicStore = useMusicStore();
private statusStore = useStatusStore();
private settingStore = useSettingStore();
/** /**
* 在线歌词请求序列 * 在线歌词请求序列
* 每次发起新请求递增 * 每次发起新请求递增
@@ -32,11 +28,13 @@ class LyricManager {
* 包括清空歌词数据、重置歌词索引、关闭 TTMLL 歌词等 * 包括清空歌词数据、重置歌词索引、关闭 TTMLL 歌词等
*/ */
private resetSongLyric() { private resetSongLyric() {
const musicStore = useMusicStore();
const statusStore = useStatusStore();
// 重置歌词数据 // 重置歌词数据
this.musicStore.setSongLyric({}, true); musicStore.setSongLyric({}, true);
this.statusStore.usingTTMLLyric = false; statusStore.usingTTMLLyric = false;
// 重置歌词索引 // 重置歌词索引
this.statusStore.lyricIndex = -1; statusStore.lyricIndex = -1;
} }
/** /**
* 歌词内容对齐 * 歌词内容对齐
@@ -101,13 +99,16 @@ class LyricManager {
* @returns 歌词数据 * @returns 歌词数据
*/ */
private async handleOnlineLyric(id: number): Promise<SongLyric> { private async handleOnlineLyric(id: number): Promise<SongLyric> {
const musicStore = useMusicStore();
const statusStore = useStatusStore();
const settingStore = useSettingStore();
// 请求序列
const req = this.activeLyricReq; const req = this.activeLyricReq;
const settingStore = this.settingStore;
// 请求是否成功 // 请求是否成功
let adopted = false; let adopted = false;
let result: SongLyric = { lrcData: [], yrcData: [] }; let result: SongLyric = { lrcData: [], yrcData: [] };
// 过期判断 // 过期判断
const isStale = () => this.activeLyricReq !== req || this.musicStore.playSong?.id !== id; const isStale = () => this.activeLyricReq !== req || musicStore.playSong?.id !== id;
// 处理 TTML 歌词 // 处理 TTML 歌词
const adoptTTML = async () => { const adoptTTML = async () => {
try { try {
@@ -161,7 +162,7 @@ class LyricManager {
}; };
// 统一判断与设置 TTML // 统一判断与设置 TTML
await Promise.allSettled([adoptTTML(), adoptLRC()]); await Promise.allSettled([adoptTTML(), adoptLRC()]);
this.statusStore.usingTTMLLyric = Boolean( statusStore.usingTTMLLyric = Boolean(
settingStore.enableTTMLLyric && result.yrcData?.length && !result.lrcData?.length, settingStore.enableTTMLLyric && result.yrcData?.length && !result.lrcData?.length,
); );
return result; return result;
@@ -173,6 +174,7 @@ class LyricManager {
*/ */
private async handleLocalLyric(path: string): Promise<SongLyric> { private async handleLocalLyric(path: string): Promise<SongLyric> {
try { try {
const statusStore = useStatusStore();
const { lyric, format }: { lyric?: string; format?: "lrc" | "ttml" } = const { lyric, format }: { lyric?: string; format?: "lrc" | "ttml" } =
await window.electron.ipcRenderer.invoke("get-music-lyric", path); await window.electron.ipcRenderer.invoke("get-music-lyric", path);
if (!lyric) return { lrcData: [], yrcData: [] }; if (!lyric) return { lrcData: [], yrcData: [] };
@@ -180,13 +182,13 @@ class LyricManager {
if (format === "ttml") { if (format === "ttml") {
const ttml = parseTTML(lyric); const ttml = parseTTML(lyric);
const lines = ttml?.lines || []; const lines = ttml?.lines || [];
this.statusStore.usingTTMLLyric = true; statusStore.usingTTMLLyric = true;
return { lrcData: [], yrcData: lines }; return { lrcData: [], yrcData: lines };
} }
// 解析本地歌词并对其 // 解析本地歌词并对其
const lrcLines = parseLrc(lyric); const lrcLines = parseLrc(lyric);
const aligned = this.alignLocalLyrics({ lrcData: lrcLines, yrcData: [] }); const aligned = this.alignLocalLyrics({ lrcData: lrcLines, yrcData: [] });
this.statusStore.usingTTMLLyric = false; statusStore.usingTTMLLyric = false;
return aligned; return aligned;
} catch { } catch {
return { lrcData: [], yrcData: [] }; return { lrcData: [], yrcData: [] };
@@ -199,16 +201,49 @@ class LyricManager {
*/ */
private async checkLocalLyricOverride(id: number): Promise<SongLyric> { private async checkLocalLyricOverride(id: number): Promise<SongLyric> {
console.log("检测本地歌词覆盖", id); console.log("检测本地歌词覆盖", id);
const { localLyricPath } = this.settingStore; const statusStore = useStatusStore();
const settingStore = useSettingStore();
const { localLyricPath } = settingStore;
if (!isElectron || !localLyricPath.length) return { lrcData: [], yrcData: [] }; if (!isElectron || !localLyricPath.length) return { lrcData: [], yrcData: [] };
// 从本地遍历 // 从本地遍历
try {
const lyricDirs = Array.isArray(localLyricPath) ? localLyricPath.map((p) => String(p)) : [];
// 读取本地歌词
const { lrc, ttml } = await window.electron.ipcRenderer.invoke( const { lrc, ttml } = await window.electron.ipcRenderer.invoke(
"read-local-lyric", "read-local-lyric",
localLyricPath, lyricDirs,
id, id,
); );
this.statusStore.usingTTMLLyric = Boolean(ttml); statusStore.usingTTMLLyric = Boolean(ttml);
return { lrcData: parseLrc(lrc || ""), yrcData: parseTTML(ttml || "").lines || [] }; let lrcLines: LyricLine[] = [];
let ttmlLines: LyricLine[] = [];
// 安全解析 LRC
try {
const lrcContent = typeof lrc === "string" ? lrc : "";
if (lrcContent) {
lrcLines = parseLrc(lrcContent);
}
} catch (err) {
console.error("parseLrc 本地解析失败:", err);
lrcLines = [];
}
// 安全解析 TTML
try {
const ttmlContent = typeof ttml === "string" ? ttml : "";
if (ttmlContent) {
ttmlLines = parseTTML(ttmlContent).lines || [];
}
} catch (err) {
console.error("parseTTML 本地解析失败:", err);
statusStore.usingTTMLLyric = false;
ttmlLines = [];
}
return { lrcData: lrcLines, yrcData: ttmlLines };
} catch (error) {
console.error("读取本地歌词失败:", error);
statusStore.usingTTMLLyric = false;
return { lrcData: [], yrcData: [] };
}
} }
/** /**
* 处理歌词排除 * 处理歌词排除
@@ -216,7 +251,8 @@ class LyricManager {
* @returns 处理后的歌词数据 * @returns 处理后的歌词数据
*/ */
private handleLyricExclude(lyricData: SongLyric): SongLyric { private handleLyricExclude(lyricData: SongLyric): SongLyric {
const { enableExcludeLyrics, excludeKeywords, excludeRegexes } = this.settingStore; const settingStore = useSettingStore();
const { enableExcludeLyrics, excludeKeywords, excludeRegexes } = settingStore;
// 未开启排除 // 未开启排除
if (!enableExcludeLyrics) return lyricData; if (!enableExcludeLyrics) return lyricData;
// 处理正则表达式 // 处理正则表达式
@@ -254,17 +290,21 @@ class LyricManager {
* @param path 本地歌词路径(可选) * @param path 本地歌词路径(可选)
*/ */
public async handleLyric(id: number, path?: string) { public async handleLyric(id: number, path?: string) {
const musicStore = useMusicStore();
const statusStore = useStatusStore();
try { try {
// 歌词加载状态 // 歌词加载状态
this.statusStore.lyricLoading = true; statusStore.lyricLoading = true;
// 重置歌词 // 重置歌词
this.resetSongLyric(); this.resetSongLyric();
// 标记当前歌词请求(避免旧请求覆盖新请求) // 标记当前歌词请求(避免旧请求覆盖新请求)
this.activeLyricReq = ++this.lyricReqSeq; this.activeLyricReq = ++this.lyricReqSeq;
// 检查歌词覆盖 // 检查歌词覆盖
let lyricData = await this.checkLocalLyricOverride(id); let lyricData = await this.checkLocalLyricOverride(id);
console.log("本地歌词覆盖", lyricData);
// 开始获取歌词 // 开始获取歌词
if (isEmpty(lyricData.lrcData) || isEmpty(lyricData.yrcData)) { if (!isEmpty(lyricData.lrcData) || !isEmpty(lyricData.yrcData)) {
// 进行本地歌词对齐 // 进行本地歌词对齐
lyricData = this.alignLocalLyrics(lyricData); lyricData = this.alignLocalLyrics(lyricData);
} else if (path) { } else if (path) {
@@ -278,8 +318,8 @@ class LyricManager {
} catch (error) { } catch (error) {
} finally { } finally {
// 歌词加载状态 // 歌词加载状态
if (this.musicStore.playSong?.id === undefined || this.activeLyricReq === this.lyricReqSeq) { if (musicStore.playSong?.id === undefined || this.activeLyricReq === this.lyricReqSeq) {
this.statusStore.lyricLoading = false; statusStore.lyricLoading = false;
} }
} }
} }

View File

@@ -21,6 +21,7 @@ import {
import { isDev, isElectron } from "./env"; import { isDev, isElectron } from "./env";
import { getLyricData } from "./player-utils/lyric"; import { getLyricData } from "./player-utils/lyric";
import audioContextManager from "@/utils/player-utils/context"; import audioContextManager from "@/utils/player-utils/context";
import lyricManager from "./lyricManager";
import blob from "./blob"; import blob from "./blob";
// 播放器核心 // 播放器核心
@@ -248,6 +249,8 @@ class Player {
// 获取歌曲附加信息 - 非电台和本地 // 获取歌曲附加信息 - 非电台和本地
if (type !== "radio" && !path) getLyricData(id); if (type !== "radio" && !path) getLyricData(id);
else resetSongLyric(); else resetSongLyric();
// 获取歌词数据
lyricManager.handleLyric(id, path);
// 定时获取状态 // 定时获取状态
if (!this.playerInterval) this.handlePlayStatus(); if (!this.playerInterval) this.handlePlayStatus();
// 新增播放历史 // 新增播放历史