From 0dc7f39db221c640cb1f9bff23c82ace9c9fe6b0 Mon Sep 17 00:00:00 2001 From: DEV_DSW <562304744@qq.com> Date: Thu, 19 Mar 2026 16:55:31 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=89=93=E5=8C=85?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E8=87=AA=E5=8A=A8=E5=8C=96=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PROJECT_OVERVIEW.md | 10 ++-- forge.config.ts | 34 +++++++++++--- package-lock.json | 46 ++++++++++++------- package.json | 1 + src/main/process/runTaskOperationService.ts | 2 +- .../service/execute-script-service/index.ts | 44 ++++++++---------- src/main/utils/chrome/launchLocalChrome.ts | 6 ++- tsconfig.app.json | 3 +- 8 files changed, 90 insertions(+), 56 deletions(-) diff --git a/PROJECT_OVERVIEW.md b/PROJECT_OVERVIEW.md index 28c56b7..925c825 100644 --- a/PROJECT_OVERVIEW.md +++ b/PROJECT_OVERVIEW.md @@ -28,11 +28,11 @@ * **`providers/`**: AI 模型提供商。 * `OpenAIProvider.ts`: 支持流式传输的 OpenAI 对话补全实现。 * **`scripts/`**: 由主进程执行的自动化脚本。 - * `fg_trace.mjs`: 飞猪自动化脚本。 - * `mt_trace.mjs`: 美团自动化脚本。 - * `dy_hotel_trace.mjs` / `dy_hot_spring_trace.mjs`: 抖音自动化脚本。 - * `xc_trace.mjs`: 携程/去哪儿自动化脚本。 - * `open_all_channel.mjs`: 在浏览器中打开所有已配置渠道的脚本。 + * `fg_trace.js`: 飞猪自动化脚本。 + * `mt_trace.js`: 美团自动化脚本。 + * `dy_hotel_trace.js` / `dy_hot_spring_trace.js`: 抖音自动化脚本。 + * `xc_trace.js`: 携程/去哪儿自动化脚本。 + * `open_all_channel.js`: 在浏览器中打开所有已配置渠道的脚本。 * `common/tabs.js`: 用于连接 Chrome 并智能管理/复用标签页的工具。 * **`utils/chrome/`**: Chrome 管理助手。 * `launchLocalChrome.ts`: 启动带有 `--remote-debugging-port=9222` 参数的本地 Chrome 实例。 diff --git a/forge.config.ts b/forge.config.ts index 602a9c0..8298599 100644 --- a/forge.config.ts +++ b/forge.config.ts @@ -61,31 +61,53 @@ const config: ForgeConfig = { hooks: { async packageAfterCopy(forgeConfig, buildPath, electronVersion, platform, arch) { const src = path.join(__dirname, 'src/main/scripts'); - const dest = path.join(buildPath, 'resources', 'scripts'); + const dest = path.join(buildPath, '.vite', 'build', 'scripts'); await fs.ensureDir(dest); // Bundle mjs scripts using esbuild const files = await fs.readdir(src); for (const file of files) { - if (file.endsWith('.mjs')) { + if (file.endsWith('.js')) { await esbuild.build({ entryPoints: [path.join(src, file)], outfile: path.join(dest, file), bundle: true, platform: 'node', - target: 'node16', // Adjust based on Electron version - external: ['electron', 'chromium-bidi/lib/cjs/bidiMapper/BidiMapper', 'chromium-bidi/lib/cjs/cdp/CdpConnection'], // Exclude electron if imported - format: 'esm', + target: 'node24', // Adjust based on Electron version + external: [ 'electron' ], // Exclude electron and playwright dependencies from bundling + format: 'cjs', }); } else { - // Copy other files (e.g., .md, .png) directly await fs.copy(path.join(src, file), path.join(dest, file)); } } + // Force playwright into the packaged node_modules since Forge Vite plugin ignores it + const playwrightSrc = path.join(__dirname, 'node_modules', 'playwright'); + const playwrightDest = path.join(buildPath, 'node_modules', 'playwright'); + if (await fs.pathExists(playwrightSrc)) { + await fs.ensureDir(path.join(buildPath, 'node_modules')); + await fs.copy(playwrightSrc, playwrightDest); + } + + const playwrightCoreSrc = path.join(__dirname, 'node_modules', 'playwright-core'); + const playwrightCoreDest = path.join(buildPath, 'node_modules', 'playwright-core'); + if (await fs.pathExists(playwrightCoreSrc)) { + await fs.ensureDir(path.join(buildPath, 'node_modules')); + await fs.copy(playwrightCoreSrc, playwrightCoreDest); + } + + const chromiumBidiSrc = path.join(__dirname, 'node_modules', 'chromium-bidi'); + const chromiumBidiDest = path.join(buildPath, 'node_modules', 'chromium-bidi'); + if (await fs.pathExists(chromiumBidiSrc)) { + await fs.ensureDir(path.join(buildPath, 'node_modules')); + await fs.copy(chromiumBidiSrc, chromiumBidiDest); + } + // Force bytenode into the packaged node_modules since Forge Vite plugin ignores it const bytenodeSrc = path.join(__dirname, 'node_modules', 'bytenode'); const bytenodeDest = path.join(buildPath, 'node_modules', 'bytenode'); + if (await fs.pathExists(bytenodeSrc)) { await fs.ensureDir(path.join(buildPath, 'node_modules')); await fs.copy(bytenodeSrc, bytenodeDest); diff --git a/package-lock.json b/package-lock.json index 9e7a142..091c12b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "axios": "^1.13.2", "browser-use-sdk": "^2.0.12", "bytenode": "^1.5.7", + "chromium-bidi": "^15.0.0", "crypto": "^1.0.1", "crypto-js": "^4.2.0", "dexie": "^4.2.1", @@ -4408,6 +4409,28 @@ "node": ">=6.0" } }, + "node_modules/chromium-bidi": { + "version": "15.0.0", + "resolved": "https://registry.npmmirror.com/chromium-bidi/-/chromium-bidi-15.0.0.tgz", + "integrity": "sha512-ESWZM1u85CoeSozBXXG9M73S5tH0EjkqnFJoQ6F3MHs2YGe0CLVMaRvhGxetLP6w4GVR59+/cpWvDLUpLvJXLQ==", + "license": "Apache-2.0", + "dependencies": { + "mitt": "^3.0.1", + "zod": "^3.24.1" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/chromium-bidi/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmmirror.com/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-2.2.0.tgz", @@ -4941,6 +4964,13 @@ "license": "MIT", "optional": true }, + "node_modules/devtools-protocol": { + "version": "0.0.1601756", + "resolved": "https://registry.npmmirror.com/devtools-protocol/-/devtools-protocol-0.0.1601756.tgz", + "integrity": "sha512-ZEzotAqFOtCVHwxZ1fch2rEvnTOV9I2GtrmD2wZKRbGgadmp7R3D0suDXokzKZmguw0sLoD3cNYAHCjy6CMLeg==", + "license": "BSD-3-Clause", + "peer": true + }, "node_modules/dexie": { "version": "4.3.0", "resolved": "https://registry.npmmirror.com/dexie/-/dexie-4.3.0.tgz", @@ -12372,22 +12402,6 @@ "dev": true, "license": "ISC" }, - "node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", - "extraneous": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index ab41e3e..3c1957f 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "axios": "^1.13.2", "browser-use-sdk": "^2.0.12", "bytenode": "^1.5.7", + "chromium-bidi": "^15.0.0", "crypto": "^1.0.1", "crypto-js": "^4.2.0", "dexie": "^4.2.1", diff --git a/src/main/process/runTaskOperationService.ts b/src/main/process/runTaskOperationService.ts index c67b999..9e2dfc5 100644 --- a/src/main/process/runTaskOperationService.ts +++ b/src/main/process/runTaskOperationService.ts @@ -11,7 +11,7 @@ const openedTabIndexByChannelName = new Map() function getScriptsDir() { return app.isPackaged - ? path.join(process.resourcesPath, 'scripts') + ? path.join(__dirname, 'scripts') : path.join(process.cwd(), 'src/main/scripts') } diff --git a/src/main/service/execute-script-service/index.ts b/src/main/service/execute-script-service/index.ts index 76c4b32..553ed77 100644 --- a/src/main/service/execute-script-service/index.ts +++ b/src/main/service/execute-script-service/index.ts @@ -1,5 +1,5 @@ import { EventEmitter } from 'events'; -import { spawn } from 'child_process'; +import { utilityProcess } from 'electron'; import log from 'electron-log'; @@ -26,7 +26,7 @@ export class executeScriptService extends EventEmitter { const channels = options?.channels ?? ''; const startTabIndex = options?.startTabIndex ?? ''; - const child = spawn(process.execPath, [scriptPath], { + const child = utilityProcess.fork(scriptPath, [], { env: { ...process.env, ROOM_TYPE: String(roomType), @@ -37,35 +37,31 @@ export class executeScriptService extends EventEmitter { CHANNELS: typeof channels === 'string' ? channels : JSON.stringify(channels), START_TAB_INDEX: String(startTabIndex), }, - stdio: 'inherit' + stdio: 'pipe' }); let stdoutTail = ''; let stderrTail = ''; - child.stdout?.on('data', (data: Buffer) => { - const text = data.toString(); - stdoutTail = appendTail(stdoutTail, text); - log.info(`stdout: ${text}`); - }); - - child.stderr?.on('data', (data: Buffer) => { - const text = data.toString(); - stderrTail = appendTail(stderrTail, text); - log.info(`stderr: ${text}`); - }); - - child.on('error', (err: any) => { - resolve({ - success: false, - exitCode: null, - stdoutTail, - stderrTail, - error: err?.message || 'Failed to start script process', + if (child.stdout) { + child.stdout.on('data', (data: Buffer) => { + const text = data.toString(); + stdoutTail = appendTail(stdoutTail, text); + log.info(`stdout: ${text}`); }); - }); + } - child.on('close', (code: number | null) => { + if (child.stderr) { + child.stderr.on('data', (data: Buffer) => { + const text = data.toString(); + stderrTail = appendTail(stderrTail, text); + log.info(`stderr: ${text}`); + }); + } + + // utilityProcess doesn't throw 'error' directly like child_process, but we can catch spawn errors or just resolve on exit + // Electron's utilityProcess emits 'exit' instead of 'close' for completion + child.on('exit', (code: number) => { log.info(`子进程退出,退出码 ${code}`); resolve({ success: code === 0, diff --git a/src/main/utils/chrome/launchLocalChrome.ts b/src/main/utils/chrome/launchLocalChrome.ts index d4193b1..71578a5 100644 --- a/src/main/utils/chrome/launchLocalChrome.ts +++ b/src/main/utils/chrome/launchLocalChrome.ts @@ -43,7 +43,9 @@ export async function launchLocalChrome() { chromeProcess.on('error', reject); - // 等浏览器起来 - resolve(0); + // 延迟几秒等浏览器起来 + setTimeout(() => { + resolve(0); + }, 3000); // 延迟3秒 }); } diff --git a/tsconfig.app.json b/tsconfig.app.json index 38bce8d..b141062 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -48,7 +48,6 @@ "**/*.ts", "**/*.js", "src/renderer/permission.ts", - "src/main/scripts/*.js", - "src/main/scripts/*.mjs" + "src/main/scripts/*.js" ] }