From fb0831f2eb18315494f6c0908791d76a024a40b3 Mon Sep 17 00:00:00 2001 From: alger Date: Fri, 17 Jan 2025 00:02:57 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=BA=94=E7=94=A8=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=9C=A8=E5=86=85=E9=83=A8=E6=9B=B4=E6=96=B0=20?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=89=93=E5=BC=80=E5=AE=89=E8=A3=85=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/index.ts | 4 + src/main/modules/update.ts | 90 +++++++++++++ src/preload/index.d.ts | 4 + src/preload/index.ts | 12 ++ .../components/common/UpdateModal.vue | 119 ++++++++++++++---- 5 files changed, 206 insertions(+), 23 deletions(-) create mode 100644 src/main/modules/update.ts diff --git a/src/main/index.ts b/src/main/index.ts index 9ef9c61..6cc5fd8 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -7,6 +7,7 @@ import { initializeConfig } from './modules/config'; import { initializeFileManager } from './modules/fileManager'; import { initializeShortcuts, registerShortcuts } from './modules/shortcuts'; import { initializeTray } from './modules/tray'; +import { setupUpdateHandlers } from './modules/update'; import { createMainWindow, initializeWindowManager } from './modules/window'; import { startMusicApi } from './server'; @@ -45,6 +46,9 @@ function initialize() { // 初始化快捷键 initializeShortcuts(mainWindow); + + // 初始化更新处理程序 + setupUpdateHandlers(mainWindow); } // 应用程序准备就绪时的处理 diff --git a/src/main/modules/update.ts b/src/main/modules/update.ts new file mode 100644 index 0000000..7dfdefe --- /dev/null +++ b/src/main/modules/update.ts @@ -0,0 +1,90 @@ +import axios from 'axios'; +import { exec } from 'child_process'; +import { app, BrowserWindow, ipcMain } from 'electron'; +import * as fs from 'fs'; +import * as path from 'path'; + +export function setupUpdateHandlers(_mainWindow: BrowserWindow) { + ipcMain.on('start-download', async (event, url: string) => { + try { + const response = await axios({ + url, + method: 'GET', + responseType: 'stream', + onDownloadProgress: (progressEvent: { loaded: number; total?: number }) => { + if (!progressEvent.total) return; + const percent = Math.round((progressEvent.loaded / progressEvent.total) * 100); + const downloaded = (progressEvent.loaded / 1024 / 1024).toFixed(2); + const total = (progressEvent.total / 1024 / 1024).toFixed(2); + event.sender.send('download-progress', percent, `已下载 ${downloaded}MB / ${total}MB`); + } + }); + + const fileName = url.split('/').pop() || 'update.exe'; + const downloadPath = path.join(app.getPath('downloads'), fileName); + + // 创建写入流 + const writer = fs.createWriteStream(downloadPath); + + // 将响应流写入文件 + response.data.pipe(writer); + + // 处理写入完成 + writer.on('finish', () => { + event.sender.send('download-complete', true, downloadPath); + }); + + // 处理写入错误 + writer.on('error', (error) => { + console.error('Write file error:', error); + event.sender.send('download-complete', false, ''); + }); + } catch (error) { + console.error('Download failed:', error); + event.sender.send('download-complete', false, ''); + } + }); + + ipcMain.on('install-update', (_event, filePath: string) => { + if (!fs.existsSync(filePath)) { + console.error('Installation file not found:', filePath); + return; + } + + const { platform } = process; + + // 关闭当前应用 + app.quit(); + + // 根据不同平台执行安装 + if (platform === 'win32') { + exec(`"${filePath}"`, (error) => { + if (error) { + console.error('Error starting installer:', error); + } + }); + } else if (platform === 'darwin') { + // 挂载 DMG 文件 + exec(`open "${filePath}"`, (error) => { + if (error) { + console.error('Error opening DMG:', error); + } + }); + } else if (platform === 'linux') { + const ext = path.extname(filePath); + if (ext === '.AppImage') { + exec(`chmod +x "${filePath}" && "${filePath}"`, (error) => { + if (error) { + console.error('Error running AppImage:', error); + } + }); + } else if (ext === '.deb') { + exec(`pkexec dpkg -i "${filePath}"`, (error) => { + if (error) { + console.error('Error installing deb package:', error); + } + }); + } + } + }); +} diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts index a52e117..fdebf6e 100644 --- a/src/preload/index.d.ts +++ b/src/preload/index.d.ts @@ -13,6 +13,10 @@ declare global { miniTray: () => void; restart: () => void; unblockMusic: (id: number, data: any) => Promise; + startDownload: (url: string) => void; + onDownloadProgress: (callback: (progress: number, status: string) => void) => void; + onDownloadComplete: (callback: (success: boolean, filePath: string) => void) => void; + removeDownloadListeners: () => void; invoke: (channel: string, ...args: any[]) => Promise; }; $message: any; diff --git a/src/preload/index.ts b/src/preload/index.ts index 20809d2..c38cd57 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -12,6 +12,18 @@ const api = { openLyric: () => ipcRenderer.send('open-lyric'), sendLyric: (data) => ipcRenderer.send('send-lyric', data), unblockMusic: (id) => ipcRenderer.invoke('unblock-music', id), + // 更新相关 + 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)); + }, + onDownloadComplete: (callback: (success: boolean, filePath: string) => void) => { + ipcRenderer.on('download-complete', (_event, success, filePath) => callback(success, filePath)); + }, + removeDownloadListeners: () => { + ipcRenderer.removeAllListeners('download-progress'); + ipcRenderer.removeAllListeners('download-complete'); + }, // 歌词缓存相关 invoke: (channel: string, ...args: any[]) => { const validChannels = ['get-cached-lyric', 'cache-lyric', 'clear-lyric-cache']; diff --git a/src/renderer/components/common/UpdateModal.vue b/src/renderer/components/common/UpdateModal.vue index 17d7dff..8163d4b 100644 --- a/src/renderer/components/common/UpdateModal.vue +++ b/src/renderer/components/common/UpdateModal.vue @@ -3,7 +3,8 @@ v-model:show="showModal" preset="dialog" :show-icon="false" - :mask-closable="true" + :mask-closable="!downloading" + :closable="!downloading" class="update-app-modal" style="width: 800px; max-width: 90vw" > @@ -15,7 +16,6 @@

发现新版本 {{ updateInfo.latestVersion }}

当前版本 {{ updateInfo.currentVersion }}

- 不再提示
@@ -23,11 +23,35 @@
-