From 482a79f1c7425bb9289f8b42fd0cf99e4e30d3bf Mon Sep 17 00:00:00 2001 From: gmh01 Date: Thu, 23 Jul 2026 20:53:11 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=9B=BF=E6=8D=A2=20execSync=20?= =?UTF-8?q?=E4=B8=BA=E5=BC=82=E6=AD=A5=20runAsync=20=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E6=89=93=E5=8C=85=E6=97=B6=E4=B8=BB=E8=BF=9B=E7=A8=8B=E9=98=BB?= =?UTF-8?q?=E5=A1=9E=E7=99=BD=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/builder.js | 55 ++++++++++++++++++++++++--------- src/components/PackProgress.vue | 2 +- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/electron/builder.js b/electron/builder.js index 5b092e3..6e544fa 100644 --- a/electron/builder.js +++ b/electron/builder.js @@ -1,16 +1,37 @@ const fs = require('fs') const path = require('path') -const { execSync, spawn } = require('child_process') +const { exec, spawn } = require('child_process') const { getConfigPath, getSrcDir } = require('./project') let isCancelled = false +let buildingProcess = null function cancelPack() { isCancelled = true + if (buildingProcess) { + try { buildingProcess.kill() } catch (e) {} + buildingProcess = null + } +} + +function runAsync(cmd, args, options) { + return new Promise((resolve, reject) => { + const child = spawn(cmd, args, { ...options, shell: true, stdio: ['pipe', 'pipe', 'pipe'] }) + let stdout = '' + let stderr = '' + child.stdout.on('data', (d) => { stdout += d.toString() }) + child.stderr.on('data', (d) => { stderr += d.toString() }) + child.on('error', reject) + child.on('close', (code) => { + if (code === 0) resolve(stdout) + else reject(new Error(stderr || stdout || `进程退出码 ${code}`)) + }) + }) } async function startPack(projectPath, outputPath, onProgress) { isCancelled = false + buildingProcess = null const config = JSON.parse(fs.readFileSync(getConfigPath(projectPath), 'utf-8')) const srcDir = getSrcDir(projectPath) const tempDir = path.join(projectPath, '.web2app', 'temp-build') @@ -91,17 +112,14 @@ async function startPack(projectPath, outputPath, onProgress) { fs.writeFileSync(templatePackagePath, JSON.stringify(templatePackage, null, 2)) if (isCancelled) return { success: false, cancelled: true } - onProgress({ stage: 'install', message: '安装依赖 (首次较慢)...', percent: 50 }) + onProgress({ stage: 'install', message: '正在安装依赖...', percent: 45 }) try { const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm' - execSync(`${npmCmd} install --production`, { - cwd: tempDir, - stdio: 'pipe', - timeout: 300000 - }) + onProgress({ stage: 'install', message: '正在安装依赖 (首次可能需要几分钟)...', percent: 50 }) + await runAsync(npmCmd, ['install', '--production'], { cwd: tempDir, timeout: 300000 }) } catch (err) { - onProgress({ stage: 'install', message: `依赖安装失败: ${err.message}`, percent: 50 }) + onProgress({ stage: 'error', message: `依赖安装失败: ${err.message}`, percent: 0 }) return { success: false, error: err.message } } @@ -112,7 +130,7 @@ async function startPack(projectPath, outputPath, onProgress) { const builderPath = path.join(tempDir, 'node_modules', '.bin', 'electron-builder') const builderCmd = process.platform === 'win32' ? `${builderPath}.cmd` : builderPath - const builderProcess = spawn(builderCmd, ['--config', templatePackagePath], { + buildingProcess = spawn(builderCmd, ['--config', templatePackagePath], { cwd: tempDir, shell: true, stdio: ['pipe', 'pipe', 'pipe'] @@ -120,7 +138,7 @@ async function startPack(projectPath, outputPath, onProgress) { let buildOutput = '' - builderProcess.stdout.on('data', (data) => { + buildingProcess.stdout.on('data', (data) => { buildOutput += data.toString() const msg = data.toString() @@ -128,16 +146,24 @@ async function startPack(projectPath, outputPath, onProgress) { onProgress({ stage: 'build', message: '正在打包...', percent: 75 }) } else if (msg.includes('signing')) { onProgress({ stage: 'sign', message: '正在签名...', percent: 85 }) + } else if (msg.includes('downloading')) { + onProgress({ stage: 'download', message: msg.trim(), percent: 55 }) + } else if (msg.includes('building')) { + onProgress({ stage: 'build', message: msg.trim(), percent: 70 }) } else { - onProgress({ stage: 'build', message: msg.trim(), percent: 75 }) + const line = msg.trim() + if (line) { + onProgress({ stage: 'build', message: line, percent: 65 }) + } } }) - builderProcess.stderr.on('data', (data) => { + buildingProcess.stderr.on('data', (data) => { buildOutput += data.toString() }) - builderProcess.on('close', (code) => { + buildingProcess.on('close', (code) => { + buildingProcess = null if (isCancelled) { resolve({ success: false, cancelled: true }) return @@ -173,7 +199,8 @@ async function startPack(projectPath, outputPath, onProgress) { resolve({ success: true, outputPath: installerPath }) }) - builderProcess.on('error', (err) => { + buildingProcess.on('error', (err) => { + buildingProcess = null resolve({ success: false, error: err.message }) }) }) diff --git a/src/components/PackProgress.vue b/src/components/PackProgress.vue index 53203a1..a5c0d74 100644 --- a/src/components/PackProgress.vue +++ b/src/components/PackProgress.vue @@ -6,7 +6,7 @@
-
+
{{ stageLabel }} {{ Math.round(progress.percent) }}%