🐞 fix: 修复窗口 IPC 报错 & 歌单去重

This commit is contained in:
imsyy
2025-11-10 23:43:13 +08:00
parent 58e3c6e21c
commit 3b3f321a3d
12 changed files with 91 additions and 40 deletions

2
components.d.ts vendored
View File

@@ -97,7 +97,6 @@ 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']
@@ -107,7 +106,6 @@ declare module 'vue' {
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']

View File

@@ -8,7 +8,6 @@ import mainWindow from "../windows/main-window";
*/
const initLyricIpc = (): void => {
const store = useStore();
const mainWin = mainWindow.getWin();
// 歌词窗口
let lyricWin: BrowserWindow | null = null;
@@ -58,6 +57,7 @@ const initLyricIpc = (): void => {
// 更新歌词窗口配置
ipcMain.on("update-desktop-lyric-option", (_, option, callback: boolean = false) => {
const mainWin = mainWindow.getWin();
if (!option || !isWinAlive(lyricWin)) return;
// 增量更新
const prevOption = store.get("lyric.config");
@@ -69,7 +69,9 @@ const initLyricIpc = (): void => {
if (callback && isWinAlive(lyricWin)) {
lyricWin.webContents.send("update-desktop-lyric-option", option);
}
mainWin?.webContents.send("update-desktop-lyric-option", option);
if (isWinAlive(mainWin)) {
mainWin?.webContents.send("update-desktop-lyric-option", option);
}
});
// 播放状态更改
@@ -155,7 +157,8 @@ const initLyricIpc = (): void => {
// 请求歌词数据
ipcMain.on("request-desktop-lyric-data", () => {
if (!isWinAlive(lyricWin)) return;
const mainWin = mainWindow.getWin();
if (!isWinAlive(lyricWin) || !isWinAlive(mainWin)) return;
// 触发窗口更新
mainWin?.webContents.send("request-desktop-lyric-data");
});
@@ -171,14 +174,16 @@ const initLyricIpc = (): void => {
// 关闭桌面歌词
ipcMain.on("closeDesktopLyric", () => {
if (!isWinAlive(lyricWin)) return;
const mainWin = mainWindow.getWin();
if (!isWinAlive(lyricWin) || !isWinAlive(mainWin)) return;
lyricWin.hide();
mainWin?.webContents.send("closeDesktopLyric");
});
// 锁定/解锁桌面歌词
ipcMain.on("toogleDesktopLyricLock", (_, isLock: boolean, isTemp: boolean = false) => {
if (!isWinAlive(lyricWin)) return;
const mainWin = mainWindow.getWin();
if (!isWinAlive(lyricWin) || !isWinAlive(mainWin)) return;
// 是否穿透
if (isLock) {
lyricWin.setIgnoreMouseEvents(true, { forward: true });

View File

@@ -7,13 +7,12 @@ import mainWindow from "../windows/main-window";
* @returns void
*/
const initShortcutIpc = (): void => {
const mainWin = mainWindow.getWin();
// 快捷键是否被注册
ipcMain.handle("is-shortcut-registered", (_, shortcut: string) => isShortcutRegistered(shortcut));
// 注册快捷键
ipcMain.handle("register-all-shortcut", (_, allShortcuts: any): string[] | false => {
const mainWin = mainWindow.getWin();
if (!mainWin || !allShortcuts) return false;
// 卸载所有快捷键
unregisterShortcuts();

View File

@@ -1,4 +1,4 @@
import { ipcMain, net, powerSaveBlocker, session } from "electron";
import { app, ipcMain, net, powerSaveBlocker, session } from "electron";
import { ipcLog } from "../logger";
import { getFonts } from "font-list";
import { useStore } from "../store";
@@ -10,7 +10,6 @@ import mainWindow from "../windows/main-window";
*/
const initSystemIpc = (): void => {
const store = useStore();
const mainWin = mainWindow.getWin();
/** 阻止系统息屏 ID */
let preventId: number | null = null;
@@ -28,6 +27,11 @@ const initSystemIpc = (): void => {
}
});
// 退出应用
ipcMain.on("quit-app", () => {
app.exit();
});
// 获取系统全部字体
ipcMain.handle("get-all-fonts", async () => {
try {
@@ -41,13 +45,18 @@ const initSystemIpc = (): void => {
// 取消代理
ipcMain.on("remove-proxy", () => {
const mainWin = mainWindow.getWin();
store.set("proxy", "");
mainWin?.webContents.session.setProxy({ proxyRules: "" });
if (mainWin) {
mainWin?.webContents.session.setProxy({ proxyRules: "" });
}
ipcLog.info("✅ Remove proxy successfully");
});
// 配置网络代理
ipcMain.on("set-proxy", (_, config) => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
const proxyRules = `${config.protocol}://${config.server}:${config.port}`;
store.set("proxy", proxyRules);
mainWin?.webContents.session.setProxy({ proxyRules });

View File

@@ -7,12 +7,13 @@ import lyricWindow from "../windows/lyric-window";
*/
const initTrayIpc = (): void => {
const tray = getMainTray();
const lyricWin = lyricWindow.getWin();
// 音乐播放状态更改
ipcMain.on("play-status-change", (_, playStatus: boolean) => {
const lyricWin = lyricWindow.getWin();
tray?.setPlayState(playStatus ? "play" : "pause");
lyricWin?.webContents.send("play-status-change", playStatus);
if (!lyricWin) return;
lyricWin.webContents.send("play-status-change", playStatus);
});
// 音乐名称更改

View File

@@ -3,10 +3,12 @@ import { checkUpdate, startDownloadUpdate } from "../update";
import mainWindow from "../windows/main-window";
const initUpdateIpc = () => {
const mainWin = mainWindow.getWin();
// 检查更新
ipcMain.on("check-update", (_event, showTip) => checkUpdate(mainWin!, showTip));
ipcMain.on("check-update", (_event, showTip) => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
checkUpdate(mainWin, showTip);
});
// 开始下载更新
ipcMain.on("start-download-update", () => startDownloadUpdate());

View File

@@ -11,22 +11,24 @@ import loginWindow from "../windows/login-window";
* @returns void
*/
const initWindowsIpc = (): void => {
// 相关窗口
const mainWin = mainWindow.getWin();
const loadWin = loadWindow.getWin();
// store
const store = useStore();
// 当前窗口状态
ipcMain.on("win-state", (event) => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
event.returnValue = mainWin?.isMaximized();
});
// 加载完成
ipcMain.on("win-loaded", () => {
const loadWin = loadWindow.getWin();
const mainWin = mainWindow.getWin();
if (loadWin && !loadWin.isDestroyed()) loadWin.destroy();
const isMaximized = store.get("window")?.maximized;
if (isMaximized) mainWin?.maximize();
if (!mainWin) return;
mainWin?.show();
mainWin?.focus();
// 解决窗口不立即显示
@@ -45,34 +47,37 @@ const initWindowsIpc = (): void => {
// 最小化
ipcMain.on("win-min", (event) => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
event.preventDefault();
mainWin?.minimize();
});
// 最大化
ipcMain.on("win-max", () => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
mainWin?.maximize();
});
// 还原
ipcMain.on("win-restore", () => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
mainWin?.restore();
});
// 关闭
ipcMain.on("win-close", (event) => {
event.preventDefault();
mainWin?.close();
app.quit();
});
// 隐藏
ipcMain.on("win-hide", () => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
mainWin?.hide();
});
// 显示
ipcMain.on("win-show", () => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
mainWin?.show();
mainWin?.focus();
});
@@ -85,11 +90,15 @@ const initWindowsIpc = (): void => {
// 向主窗口发送事件
ipcMain.on("send-to-mainWin", (_, eventName, ...args) => {
mainWin?.webContents.send(eventName, ...args);
const mainWin = mainWindow.getWin();
if (!mainWin || mainWin.isDestroyed() || mainWin.webContents.isDestroyed()) return;
mainWin.webContents.send(eventName, ...args);
});
// 显示进度
ipcMain.on("set-bar", (_event, val: number | "none" | "indeterminate" | "error" | "paused") => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
switch (val) {
case "none":
mainWin?.setProgressBar(-1);
@@ -115,6 +124,8 @@ const initWindowsIpc = (): void => {
// 开启控制台
ipcMain.on("open-dev-tools", () => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
mainWin?.webContents.openDevTools({
title: "SPlayer DevTools",
mode: isDev ? "right" : "detach",
@@ -122,10 +133,16 @@ const initWindowsIpc = (): void => {
});
// 开启登录窗口
ipcMain.on("open-login-web", () => loginWindow.create(mainWin!));
ipcMain.on("open-login-web", () => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
loginWindow.create(mainWin);
});
// 开启设置
ipcMain.on("open-setting", (_, type) => {
const mainWin = mainWindow.getWin();
if (!mainWin) return;
mainWin?.show();
mainWin?.focus();
mainWin?.webContents.send("openSetting", type);

View File

@@ -28,9 +28,11 @@ class LyricWindow {
});
// 歌词窗口关闭
this.win?.on("close", () => {
this.win = null;
const mainWin = mainWindow?.getWin();
if (!mainWin || mainWin.isDestroyed() || mainWin.webContents.isDestroyed()) return;
mainWin?.webContents.send("closeDesktopLyric");
if (mainWin) {
mainWin?.webContents.send("closeDesktopLyric");
}
});
}
/**
@@ -79,7 +81,8 @@ class LyricWindow {
* @returns BrowserWindow | null
*/
getWin(): BrowserWindow | null {
return this.win;
if (this.win && !this.win?.isDestroyed()) return this.win;
return null;
}
}

View File

@@ -81,6 +81,13 @@ class MainWindow {
this.saveBounds();
});
}
// 窗口关闭
this.win?.on("close", (event) => {
event.preventDefault();
this.win?.show();
this.win?.focus();
this.win?.webContents.send("win-will-close");
});
}
/**
* 创建窗口
@@ -110,7 +117,10 @@ class MainWindow {
* @returns BrowserWindow | null
*/
getWin(): BrowserWindow | null {
return this.win;
if (this.win && !this.win.isDestroyed()) {
return this.win;
}
return null;
}
/**
* 显示主窗口

View File

@@ -124,7 +124,7 @@ const hideOrClose = (action: "hide" | "exit") => {
settingStore.closeAppMethod = action;
}
showCloseModal.value = false;
window.electron.ipcRenderer.send(action === "hide" ? "win-hide" : "win-close");
window.electron.ipcRenderer.send(action === "hide" ? "win-hide" : "quit-app");
};
// 尝试关闭软件
@@ -203,6 +203,9 @@ onMounted(() => {
window.electron.ipcRenderer.on("win-state-change", (_event, value: boolean) => {
isMax.value = value;
});
window.electron.ipcRenderer.on("win-will-close", () => {
tryClose();
});
}
});
</script>

View File

@@ -130,7 +130,7 @@ const isReadOver = useElementVisibility(readOverRef);
// 关闭软件
const closeApp = () => {
window.electron.ipcRenderer.send("win-close");
window.electron.ipcRenderer.send("quit-app");
};
</script>

View File

@@ -175,7 +175,7 @@ import { playlistDetail, playlistAllSongs } from "@/api/playlist";
import { formatCoverList, formatSongsList } from "@/utils/format";
import { coverLoaded, formatNumber, fuzzySearch, renderIcon } from "@/utils/helper";
import { renderToolbar } from "@/utils/meta";
import { debounce, isObject } from "lodash-es";
import { debounce, isObject, uniqBy } from "lodash-es";
import { useDataStore, useStatusStore } from "@/stores";
import { openBatchList, openUpdatePlaylist } from "@/utils/modal";
import { formatTimestamp } from "@/utils/time";
@@ -302,7 +302,8 @@ const getPlaylistData = async (id: number, getList: boolean, refresh: boolean) =
if (isLogin() === 1 && (playlistDetailData.value?.count as number) < 800) {
const ids: number[] = detail.privileges.map((song: any) => song.id as number);
const result = await songDetail(ids);
playlistData.value = formatSongsList(result.songs);
// 直接批量详情返回时也进行一次按 id 去重
playlistData.value = uniqBy(formatSongsList(result.songs), "id");
} else {
await getPlaylistAllSongs(id, playlistDetailData.value.count || 0, refresh);
}
@@ -317,7 +318,8 @@ const loadLikedCache = () => {
playlistDetailData.value = dataStore.likeSongsList.detail;
}
if (dataStore.likeSongsList.data.length) {
playlistData.value = dataStore.likeSongsList.data;
// 去重缓存中的歌曲,避免重复展示与后续重复拼接
playlistData.value = uniqBy(dataStore.likeSongsList.data, "id");
}
};
@@ -339,11 +341,13 @@ const getPlaylistAllSongs = async (
const result = await playlistAllSongs(id, limit, offset);
const songData = formatSongsList(result.songs);
listData.push(...songData);
if (!refresh) playlistData.value = playlistData.value.concat(songData);
// 非刷新模式下,增量拼接时进行去重,避免与缓存或上一页数据重复
if (!refresh) playlistData.value = uniqBy([...playlistData.value, ...songData], "id");
// 更新数据
offset += limit;
} while (offset < count && isLikedPage.value);
if (refresh) playlistData.value = listData;
// 刷新模式下,统一以最终聚合数据为准,并进行去重
if (refresh) playlistData.value = uniqBy(listData, "id");
// 关闭加载
loadingMsgShow(false);
};