|
@@ -1,6 +1,5 @@
|
|
|
const { app, BrowserWindow ,ipcMain} = require('electron')
|
|
const { app, BrowserWindow ,ipcMain} = require('electron')
|
|
|
const path = require('path')
|
|
const path = require('path')
|
|
|
-const http = require('http')
|
|
|
|
|
const os = require('os')
|
|
const os = require('os')
|
|
|
const fs = require('fs')
|
|
const fs = require('fs')
|
|
|
const config = require('../configs/config.js')
|
|
const config = require('../configs/config.js')
|
|
@@ -43,72 +42,10 @@ if (process.platform === 'win32') {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/**
|
|
|
|
|
- * 检测 Vite 开发服务器实际使用的端口
|
|
|
|
|
- * 如果配置的端口被占用,Vite 会自动尝试下一个端口
|
|
|
|
|
- * 需要确认是 Vite 服务器,而不仅仅是端口响应
|
|
|
|
|
- */
|
|
|
|
|
-async function findVitePort(startPort, maxAttempts = 10) {
|
|
|
|
|
- const viteHost = config.vite?.host || 'localhost'
|
|
|
|
|
-
|
|
|
|
|
- for (let offset = 0; offset < maxAttempts; offset++) {
|
|
|
|
|
- const port = startPort + offset
|
|
|
|
|
- const isViteServer = await new Promise((resolve) => {
|
|
|
|
|
- const req = http.get(`http://${viteHost}:${port}`, (res) => {
|
|
|
|
|
- // 检查状态码
|
|
|
|
|
- if (res.statusCode !== 200) {
|
|
|
|
|
- resolve(false)
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 读取响应数据确认是否是 Vite 服务器
|
|
|
|
|
- let data = ''
|
|
|
|
|
- let resolved = false
|
|
|
|
|
-
|
|
|
|
|
- res.on('data', (chunk) => {
|
|
|
|
|
- if (resolved) return
|
|
|
|
|
- data += chunk.toString()
|
|
|
|
|
- // 如果响应包含 Vite 特征,立即确认
|
|
|
|
|
- if (data.length > 100 && (data.includes('/vite') || data.includes('Vite') || data.includes('vite/client'))) {
|
|
|
|
|
- resolved = true
|
|
|
|
|
- resolve(true)
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- res.on('end', () => {
|
|
|
|
|
- if (resolved) return
|
|
|
|
|
- // 检查响应内容是否包含 Vite 特征
|
|
|
|
|
- if (data.includes('/vite') || data.includes('Vite') || data.includes('vite/client')) {
|
|
|
|
|
- resolve(true)
|
|
|
|
|
- } else {
|
|
|
|
|
- resolve(false)
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- req.on('error', () => {
|
|
|
|
|
- resolve(false)
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- req.setTimeout(2000, () => {
|
|
|
|
|
- req.destroy()
|
|
|
|
|
- resolve(false)
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- if (isViteServer) {
|
|
|
|
|
- return port
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 如果找不到,返回配置的端口
|
|
|
|
|
- return startPort
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
// 保存主窗口引用,用于推送消息
|
|
// 保存主窗口引用,用于推送消息
|
|
|
let mainWindowInstance = null
|
|
let mainWindowInstance = null
|
|
|
|
|
|
|
|
-async function createWindow() {
|
|
|
|
|
|
|
+function createWindow() {
|
|
|
const mainWindow = new BrowserWindow({
|
|
const mainWindow = new BrowserWindow({
|
|
|
width: config.window.width,
|
|
width: config.window.width,
|
|
|
height: config.window.height,
|
|
height: config.window.height,
|
|
@@ -124,12 +61,8 @@ async function createWindow() {
|
|
|
mainWindowInstance = mainWindow
|
|
mainWindowInstance = mainWindow
|
|
|
|
|
|
|
|
if (isDev) {
|
|
if (isDev) {
|
|
|
- // 从配置文件读取 Vite 开发服务器端口
|
|
|
|
|
- const configPort = config.vite?.port || 5173
|
|
|
|
|
- // 检测实际使用的端口(如果配置端口被占用,Vite 会自动尝试下一个)
|
|
|
|
|
- const vitePort = await findVitePort(configPort)
|
|
|
|
|
|
|
+ const vitePort = config.vite?.port || 5173
|
|
|
const viteHost = config.vite?.host || 'localhost'
|
|
const viteHost = config.vite?.host || 'localhost'
|
|
|
-
|
|
|
|
|
console.log(`Loading Vite dev server at http://${viteHost}:${vitePort}`)
|
|
console.log(`Loading Vite dev server at http://${viteHost}:${vitePort}`)
|
|
|
mainWindow.loadURL(`http://${viteHost}:${vitePort}`)
|
|
mainWindow.loadURL(`http://${viteHost}:${vitePort}`)
|
|
|
|
|
|
|
@@ -167,69 +100,66 @@ ipcMain.handle('run-nodejs-script', async (event, scriptName, ...parameters) =>
|
|
|
let stderr = ''
|
|
let stderr = ''
|
|
|
let resolved = false
|
|
let resolved = false
|
|
|
|
|
|
|
|
|
|
+ const finish = (result) => {
|
|
|
|
|
+ if (resolved) return
|
|
|
|
|
+ resolved = true
|
|
|
|
|
+ resolve(result)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
nodeProcess.stdout.on('data', (data) => {
|
|
nodeProcess.stdout.on('data', (data) => {
|
|
|
const dataStr = data.toString()
|
|
const dataStr = data.toString()
|
|
|
stdout += dataStr
|
|
stdout += dataStr
|
|
|
-
|
|
|
|
|
- // 检查是否是 JSON 格式的成功消息(用于持续运行的脚本)
|
|
|
|
|
|
|
+ const isLongRunning = scriptName.includes('screenshot') || scriptName.includes('adb/')
|
|
|
try {
|
|
try {
|
|
|
const lines = dataStr.trim().split('\n')
|
|
const lines = dataStr.trim().split('\n')
|
|
|
for (const line of lines) {
|
|
for (const line of lines) {
|
|
|
if (line.trim().startsWith('{')) {
|
|
if (line.trim().startsWith('{')) {
|
|
|
const json = JSON.parse(line.trim())
|
|
const json = JSON.parse(line.trim())
|
|
|
- if (json.success && !resolved) {
|
|
|
|
|
- resolved = true
|
|
|
|
|
- // 对于持续运行的脚本,收到成功消息后立即返回,不等待进程结束
|
|
|
|
|
- resolve({
|
|
|
|
|
- success: true,
|
|
|
|
|
- stdout: line.trim(),
|
|
|
|
|
- stderr: stderr.trim(),
|
|
|
|
|
- exitCode: null
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ if (json.success && isLongRunning) {
|
|
|
|
|
+ finish({ success: true, stdout: line.trim(), stderr: stderr.trim(), exitCode: null })
|
|
|
|
|
+ return
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- } catch (e) {
|
|
|
|
|
- // 不是 JSON,继续收集输出
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ } catch (e) {}
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
nodeProcess.stderr.on('data', (data) => {
|
|
nodeProcess.stderr.on('data', (data) => {
|
|
|
stderr += data.toString()
|
|
stderr += data.toString()
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- nodeProcess.on('close', (code) => {
|
|
|
|
|
- runningProcesses.delete(processKey)
|
|
|
|
|
|
|
+ const timeoutId = setTimeout(() => {
|
|
|
if (!resolved) {
|
|
if (!resolved) {
|
|
|
- resolve({
|
|
|
|
|
- success: code === 0,
|
|
|
|
|
|
|
+ finish({
|
|
|
|
|
+ success: false,
|
|
|
stdout: stdout.trim(),
|
|
stdout: stdout.trim(),
|
|
|
stderr: stderr.trim(),
|
|
stderr: stderr.trim(),
|
|
|
- exitCode: code
|
|
|
|
|
|
|
+ exitCode: 1,
|
|
|
|
|
+ message: 'Script is running in background'
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
+ }, 5000)
|
|
|
|
|
+
|
|
|
|
|
+ nodeProcess.on('close', (code) => {
|
|
|
|
|
+ clearTimeout(timeoutId)
|
|
|
|
|
+ runningProcesses.delete(processKey)
|
|
|
|
|
+ const exitCode = (code !== null && code !== undefined) ? code : 1
|
|
|
|
|
+ finish({
|
|
|
|
|
+ success: exitCode === 0,
|
|
|
|
|
+ stdout: stdout.trim(),
|
|
|
|
|
+ stderr: stderr.trim(),
|
|
|
|
|
+ exitCode
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
nodeProcess.on('error', (error) => {
|
|
nodeProcess.on('error', (error) => {
|
|
|
|
|
+ clearTimeout(timeoutId)
|
|
|
runningProcesses.delete(processKey)
|
|
runningProcesses.delete(processKey)
|
|
|
if (!resolved) {
|
|
if (!resolved) {
|
|
|
|
|
+ resolved = true
|
|
|
reject(error)
|
|
reject(error)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
-
|
|
|
|
|
- // 对于持续运行的脚本,设置超时,如果 5 秒内没有收到成功消息,也返回
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- if (!resolved) {
|
|
|
|
|
- resolved = true
|
|
|
|
|
- resolve({
|
|
|
|
|
- success: true,
|
|
|
|
|
- stdout: stdout.trim(),
|
|
|
|
|
- stderr: stderr.trim(),
|
|
|
|
|
- exitCode: null,
|
|
|
|
|
- message: 'Script is running in background'
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- }, 5000)
|
|
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|