From 74c4eb4fbc7dd0d91bbbfac2b91bbb2bf1fa0b68 Mon Sep 17 00:00:00 2001 From: Elysia Date: Sat, 14 Feb 2026 00:16:18 +0800 Subject: [PATCH] feat(install): add metalink download support and progress tracking close #12 --- AGENTS.md | 3 +- electron/main/backend/install-manager.ts | 263 +++++++++++++++++------ src/App.vue | 9 +- src/components/AppDetailModal.vue | 18 +- src/components/DownloadDetail.vue | 28 ++- src/components/DownloadQueue.vue | 4 +- src/global/typedefinition.ts | 16 +- src/modules/processInstall.ts | 13 ++ 8 files changed, 276 insertions(+), 78 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index eef13af6..dd5c0a1c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -725,6 +725,7 @@ export const watchDownloadsChange = (callback: () => void) => { ### Code Style - **Use TypeScript strict mode** - no `any` types without `eslint-disable` +- **Avoid used of eslint-disable directly** - use `undefined` instead if you really do not know its type. - **Prefer Composition API** - ` diff --git a/src/components/DownloadQueue.vue b/src/components/DownloadQueue.vue index f7a4f7a8..41ef9c00 100644 --- a/src/components/DownloadQueue.vue +++ b/src/components/DownloadQueue.vue @@ -86,7 +86,7 @@

下载中 {{ download.progress }}%下载中 {{ Math.floor(download.progress * 100) }}% 安装中...

diff --git a/src/global/typedefinition.ts b/src/global/typedefinition.ts index 9290488e..92ed5ea6 100644 --- a/src/global/typedefinition.ts +++ b/src/global/typedefinition.ts @@ -1,16 +1,20 @@ -export interface InstallLog { +export interface InstallStatus { id: number; - success: boolean; time: number; - exitCode: number | null; message: string; } -export interface DownloadResult extends InstallLog { +export interface InstallLog extends InstallStatus { success: boolean; exitCode: number | null; } +export interface DownloadResult extends InstallStatus { + success: boolean; + exitCode: number | null; + status: DownloadItemStatus | null; +} + export type DownloadItemStatus = | "downloading" | "installing" @@ -26,7 +30,7 @@ export interface DownloadItem { version: string; icon: string; status: DownloadItemStatus; - progress: number; // 0 ~ 100 的百分比,或 0 ~ 1 的小数(建议统一) + progress: number; // 0 ~ 1 的小数 downloadedSize: number; // 已下载字节数 totalSize: number; // 总字节数(可能为 0 初始时) speed: number; // 当前下载速度,单位如 B/s @@ -41,6 +45,8 @@ export interface DownloadItem { retry: boolean; // 当前是否为重试下载 upgradeOnly?: boolean; // 是否为仅升级任务 error?: string; + metalinkUrl?: string; // Metalink 下载链接 + filename?: string; // 文件名 } /* diff --git a/src/modules/processInstall.ts b/src/modules/processInstall.ts index 4bf66e3c..5eb3411d 100644 --- a/src/modules/processInstall.ts +++ b/src/modules/processInstall.ts @@ -44,6 +44,8 @@ export const handleInstall = () => { logs: [{ time: Date.now(), message: "开始下载..." }], source: "APM Store", retry: false, + filename: currentApp.value.filename, + metalinkUrl: `${window.apm_store.arch}/${currentApp.value.category}/${currentApp.value.pkgname}/${currentApp.value.filename}.metalink`, }; downloads.value.push(download); @@ -114,6 +116,17 @@ window.ipcRenderer.on("install-status", (_event, log: InstallLog) => { const downloadObj = downloads.value.find((d) => d.id === log.id); if (downloadObj) downloadObj.status = log.message as DownloadItemStatus; }); + +window.ipcRenderer.on( + "install-progress", + (_event, payload: { id: number; progress: number }) => { + const downloadObj = downloads.value.find((d) => d.id === payload.id); + if (downloadObj) { + downloadObj.progress = payload.progress; + } + }, +); + window.ipcRenderer.on("install-log", (_event, log: InstallLog) => { const downloadObj = downloads.value.find((d) => d.id === log.id); if (downloadObj)