fix: 修复打包编译自动化异常问题

This commit is contained in:
DEV_DSW
2026-03-19 16:55:31 +08:00
parent 37be5e8ba7
commit 0dc7f39db2
8 changed files with 90 additions and 56 deletions

View File

@@ -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 实例。

View File

@@ -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);

46
package-lock.json generated
View File

@@ -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",

View File

@@ -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",

View File

@@ -11,7 +11,7 @@ const openedTabIndexByChannelName = new Map<string, number>()
function getScriptsDir() {
return app.isPackaged
? path.join(process.resourcesPath, 'scripts')
? path.join(__dirname, 'scripts')
: path.join(process.cwd(), 'src/main/scripts')
}

View File

@@ -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) => {
if (child.stdout) {
child.stdout.on('data', (data: Buffer) => {
const text = data.toString();
stdoutTail = appendTail(stdoutTail, text);
log.info(`stdout: ${text}`);
});
}
child.stderr?.on('data', (data: Buffer) => {
if (child.stderr) {
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',
});
});
child.on('close', (code: number | null) => {
// 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,

View File

@@ -43,7 +43,9 @@ export async function launchLocalChrome() {
chromeProcess.on('error', reject);
// 等浏览器起来
// 延迟几秒等浏览器起来
setTimeout(() => {
resolve(0);
}, 3000); // 延迟3秒
});
}

View File

@@ -48,7 +48,6 @@
"**/*.ts",
"**/*.js",
"src/renderer/permission.ts",
"src/main/scripts/*.js",
"src/main/scripts/*.mjs"
"src/main/scripts/*.js"
]
}