diff --git a/electron/main/backend/install-manager.ts b/electron/main/backend/install-manager.ts index 66312021..05f4c328 100644 --- a/electron/main/backend/install-manager.ts +++ b/electron/main/backend/install-manager.ts @@ -947,6 +947,54 @@ ipcMain.handle("check-apm-available", async () => { return await checkApmAvailable(); }); +// 显示 APM 安装对话框(在点击安装按钮时提前检查) +ipcMain.handle("show-apm-install-dialog", async (event) => { + const webContents = event.sender; + const win = BrowserWindow.fromWebContents(webContents); + const superUserCmd = await checkSuperUserCommand(); + + const { response } = await dialog.showMessageBox(win ?? undefined, { + type: "question", + title: "需要安装 APM", + message: "此应用需要使用 APM 安装。", + detail: + "APM 是星火应用商店的软件包兼容工具,此应用使用星火 APM 提供支持,安装APM后方可安装此应用,是否确认安装?", + buttons: ["确认", "取消"], + defaultId: 0, + cancelId: 1, + }); + + if (response !== 0) { + return { success: false, cancelled: true }; + } + + const installApmOk = await runInstallApm(superUserCmd); + if (!installApmOk) { + await dialog.showMessageBox(win ?? undefined, { + type: "error", + title: "安装失败", + message: "安装 APM 失败", + detail: "请检查网络或权限后重试", + buttons: ["确定"], + defaultId: 0, + }); + return { success: false, cancelled: false }; + } + + // 安装APM成功,提示用户已安装成功,需要重启后方可展示应用 + await dialog.showMessageBox(win ?? undefined, { + type: "info", + title: "APM 安装成功", + message: "恭喜您,APM 已成功安装", + detail: + "恭喜您,APM 已成功安装!\n首次安装APM后,需要重启电脑后方可在启动器展示应用。您可在应用安装完毕后择机重启电脑\n若您需要立即使用应用,可在应用安装后先在应用商店中打开您的应用。", + buttons: ["确定"], + defaultId: 0, + }); + + return { success: true, cancelled: false }; +}); + // eslint-disable-next-line @typescript-eslint/no-explicit-any ipcMain.handle("uninstall-installed", async (_event, payload: any) => { const pkgname = typeof payload === "string" ? payload : payload.pkgname; diff --git a/src/App.vue b/src/App.vue index ded589d8..95d938fa 100644 --- a/src/App.vue +++ b/src/App.vue @@ -834,11 +834,11 @@ const toggleAllUpgrades = () => { })); }; -const upgradeSingleApp = (app: UpdateAppItem) => { +const upgradeSingleApp = async (app: UpdateAppItem) => { if (!app?.pkgname) return; const target = apps.value.find((a) => a.pkgname === app.pkgname); if (target) { - handleUpgrade(target); + await handleUpgrade(target); } else { // If we can't find it in the list (e.g. category not loaded?), use the info we have // But handleUpgrade expects App. Let's try to construct minimal App @@ -861,15 +861,15 @@ const upgradeSingleApp = (app: UpdateAppItem) => { origin: "apm", // Default to APM if unknown, or try to guess currentStatus: "installed", }; - handleUpgrade(minimalApp); + await handleUpgrade(minimalApp); } }; -const upgradeSelectedApps = () => { +const upgradeSelectedApps = async () => { const selectedApps = upgradableApps.value.filter((app) => app.selected); - selectedApps.forEach((app) => { - upgradeSingleApp(app); - }); + for (const app of selectedApps) { + await upgradeSingleApp(app); + } }; const openInstalledModal = () => { @@ -945,8 +945,8 @@ const onDetailRemove = (app: App) => { requestUninstall(app); }; -const onDetailInstall = (app: App) => { - handleInstall(app); +const onDetailInstall = async (app: App) => { + await handleInstall(app); }; const closeUninstallModal = () => { diff --git a/src/modules/processInstall.ts b/src/modules/processInstall.ts index 4bfc0cae..d67a43d2 100644 --- a/src/modules/processInstall.ts +++ b/src/modules/processInstall.ts @@ -21,10 +21,25 @@ import axios from "axios"; let downloadIdCounter = 0; const logger = pino({ name: "processInstall.ts" }); -export const handleInstall = (appObj?: App) => { +export const handleInstall = async (appObj?: App) => { const targetApp = appObj || currentApp.value; if (!targetApp?.pkgname) return; + // APM 应用:在创建下载任务前检查 APM 是否可用 + if (targetApp.origin === "apm") { + const hasApm = await window.ipcRenderer.invoke("check-apm-available"); + if (!hasApm) { + // 发送事件到主进程显示 APM 安装对话框 + const { success, cancelled } = await window.ipcRenderer.invoke( + "show-apm-install-dialog", + ); + if (!success || cancelled) { + // 用户取消或未安装成功,不继续安装应用 + return; + } + } + } + if ( downloads.value.find( (d) => d.pkgname === targetApp.pkgname && d.origin === targetApp.origin, @@ -98,9 +113,24 @@ export const handleRetry = (download_: DownloadItem) => { window.ipcRenderer.send("queue-install", JSON.stringify(download_)); }; -export const handleUpgrade = (app: App) => { +export const handleUpgrade = async (app: App) => { if (!app.pkgname) return; + // APM 应用:在创建下载任务前检查 APM 是否可用 + if (app.origin === "apm") { + const hasApm = await window.ipcRenderer.invoke("check-apm-available"); + if (!hasApm) { + // 发送事件到主进程显示 APM 安装对话框 + const { success, cancelled } = await window.ipcRenderer.invoke( + "show-apm-install-dialog", + ); + if (!success || cancelled) { + // 用户取消或未安装成功,不继续更新应用 + return; + } + } + } + if ( downloads.value.find( (d) => d.pkgname === app.pkgname && d.origin === app.origin,