feat(update): 重构自动更新系统,使用 electron-updater 替代手动下载

- CI 构建 macOS 拆分为 x64/arm64 分别构建,合并 latest-mac.yml
- 主进程使用 electron-updater 管理检查、下载、安装全流程
- 渲染进程 UpdateModal 改为响应式同步主进程更新状态
- IPC 通道统一为 app-update:* 系列
- 窗口拦截外部链接在系统浏览器打开
- 新增 5 语言更新相关国际化文案
This commit is contained in:
alger
2026-03-11 22:01:00 +08:00
parent a62e6d256e
commit bf341fa7c8
22 changed files with 958 additions and 466 deletions
+9 -4
View File
@@ -1,5 +1,7 @@
import { ElectronAPI } from '@electron-toolkit/preload';
import type { AppUpdateState } from '../shared/appUpdate';
interface API {
minimize: () => void;
maximize: () => void;
@@ -17,11 +19,14 @@ interface API {
sendSong: (data: any) => void;
unblockMusic: (id: number, data: any, enabledSources?: string[]) => Promise<any>;
onLyricWindowClosed: (callback: () => void) => void;
startDownload: (url: string) => void;
onDownloadProgress: (callback: (progress: number, status: string) => void) => void;
onDownloadComplete: (callback: (success: boolean, filePath: string) => void) => void;
getAppUpdateState: () => Promise<AppUpdateState>;
checkAppUpdate: (manual?: boolean) => Promise<AppUpdateState>;
downloadAppUpdate: () => Promise<AppUpdateState>;
installAppUpdate: () => Promise<boolean>;
openAppUpdatePage: () => Promise<boolean>;
onAppUpdateState: (callback: (state: AppUpdateState) => void) => void;
removeAppUpdateListeners: () => void;
onLanguageChanged: (callback: (locale: string) => void) => void;
removeDownloadListeners: () => void;
importCustomApiPlugin: () => Promise<{ name: string; content: string } | null>;
importLxMusicScript: () => Promise<{ name: string; content: string } | null>;
invoke: (channel: string, ...args: any[]) => Promise<any>;
+12 -10
View File
@@ -2,6 +2,8 @@ import { electronAPI } from '@electron-toolkit/preload';
import type { IpcRendererEvent } from 'electron';
import { contextBridge, ipcRenderer } from 'electron';
import type { AppUpdateState } from '../shared/appUpdate';
// Custom APIs for renderer
const api = {
minimize: () => ipcRenderer.send('minimize-window'),
@@ -26,13 +28,17 @@ const api = {
onLyricWindowClosed: (callback: () => void) => {
ipcRenderer.on('lyric-window-closed', () => callback());
},
// 更新相关
startDownload: (url: string) => ipcRenderer.send('start-download', url),
onDownloadProgress: (callback: (progress: number, status: string) => void) => {
ipcRenderer.on('download-progress', (_event, progress, status) => callback(progress, status));
getAppUpdateState: () => ipcRenderer.invoke('app-update:get-state') as Promise<AppUpdateState>,
checkAppUpdate: (manual = false) =>
ipcRenderer.invoke('app-update:check', { manual }) as Promise<AppUpdateState>,
downloadAppUpdate: () => ipcRenderer.invoke('app-update:download') as Promise<AppUpdateState>,
installAppUpdate: () => ipcRenderer.invoke('app-update:quit-and-install') as Promise<boolean>,
openAppUpdatePage: () => ipcRenderer.invoke('app-update:open-release-page') as Promise<boolean>,
onAppUpdateState: (callback: (state: AppUpdateState) => void) => {
ipcRenderer.on('app-update:state', (_event, state: AppUpdateState) => callback(state));
},
onDownloadComplete: (callback: (success: boolean, filePath: string) => void) => {
ipcRenderer.on('download-complete', (_event, success, filePath) => callback(success, filePath));
removeAppUpdateListeners: () => {
ipcRenderer.removeAllListeners('app-update:state');
},
// 语言相关
onLanguageChanged: (callback: (locale: string) => void) => {
@@ -40,10 +46,6 @@ const api = {
callback(locale);
});
},
removeDownloadListeners: () => {
ipcRenderer.removeAllListeners('download-progress');
ipcRenderer.removeAllListeners('download-complete');
},
// 歌词缓存相关
invoke: (channel: string, ...args: any[]) => {
const validChannels = [