Spaces:
Paused
Paused
| import { chromium } from 'playwright'; | |
| import config from '../config.js'; | |
| import { loadCookies, saveScreenshot, getHumanReadableTimestamp } from './common-utils.js'; | |
| import { info, error } from './logger.js'; | |
| /** | |
| * 创建浏览器实例和上下文 | |
| * @param {string} cookieFile - Cookie 文件路径 | |
| * @param {string} cookiesFromEnv - 环境变量中的cookies | |
| * @returns {Object} { browser, context, page } | |
| */ | |
| export async function createBrowserSession(cookieFile, cookiesFromEnv) { | |
| info('启动浏览器...'); | |
| const browser = await chromium.launch(config.browserOptions); | |
| const context = await browser.newContext(); | |
| // 读取并设置cookies(优先使用环境变量) | |
| const cookies = loadCookies(cookieFile, cookiesFromEnv); | |
| await context.addCookies(cookies); | |
| const page = await context.newPage(); | |
| return { browser, context, page }; | |
| } | |
| /** | |
| * 导航到 WebIDE 页面并验证登录状态 | |
| * @param {Object} page - Playwright 页面对象 | |
| */ | |
| export async function navigateToWebIDE(page) { | |
| info('导航到WebIDE页面...'); | |
| await page.goto(config.webideUrl); | |
| // 等待页面加载 | |
| await page.waitForTimeout(config.waitTimes.pageLoad); | |
| info('当前页面URL:', page.url()); | |
| info('页面标题:', await page.title()); | |
| // 检查并处理"立即重试"按钮 这个是企业版的才会有的 | |
| await handleRetryButton(page); | |
| // 检查是否成功登录 | |
| try { | |
| await page.waitForSelector(config.selectors.editor, { | |
| timeout: 60000 | |
| }); | |
| info('成功进入WebIDE界面'); | |
| return true; | |
| } catch (err) { | |
| info('警告: 未检测到编辑器界面,可能需要重新登录'); | |
| return false; | |
| } | |
| } | |
| /** | |
| * 检查并点击"立即重试"按钮 | |
| * @param {Object} page - Playwright 页面对象 | |
| * @returns {boolean} 是否找到并点击了重试按钮 | |
| */ | |
| export async function handleRetryButton(page) { | |
| try { | |
| const retryButton = await page.waitForSelector('button.btn__21_ID', { timeout: 5000 }); | |
| if (retryButton && await retryButton.isVisible()) { | |
| info('发现"立即重试"按钮,点击处理...'); | |
| await retryButton.click(); | |
| return true; | |
| } | |
| } catch (err) { | |
| // 没有找到重试按钮,继续执行 | |
| info('未发现"立即重试"按钮,继续执行...'); | |
| } | |
| return false; | |
| } | |
| /** | |
| * 处理模态对话框 | |
| * @param {Object} page - Playwright 页面对象 | |
| */ | |
| export async function handleModalDialog(page) { | |
| try { | |
| const dialogButton = await page.waitForSelector(config.selectors.dialogButton, { timeout: 30000 }); | |
| if (dialogButton && await dialogButton.isVisible()) { | |
| info('发现模态对话框按钮,点击处理...'); | |
| await dialogButton.click(); | |
| await page.waitForTimeout(500); | |
| return true; | |
| } | |
| } catch (err) { | |
| // 没有找到对话框按钮,继续执行 | |
| info('未发现模态对话框,继续执行...'); | |
| } | |
| return false; | |
| } | |
| /** | |
| * 打开终端 | |
| * @param {Object} page - Playwright 页面对象 | |
| * @returns {Object|null} 终端元素或 null | |
| */ | |
| export async function openTerminal(page) { | |
| info('尝试打开终端 (Ctrl+~)...'); | |
| // 确保页面获得焦点 | |
| await page.click('body'); | |
| await page.waitForTimeout(500); | |
| // 按下 Ctrl+~ 打开终端 | |
| await page.keyboard.press('Control+`'); | |
| // 等待终端打开 | |
| await page.waitForTimeout(config.waitTimes.terminalOpen); | |
| // 尝试多种方式查找终端 | |
| const terminalSelectors = config.selectors.terminals; | |
| let terminalFound = false; | |
| let terminalElement = null; | |
| for (const selector of terminalSelectors) { | |
| try { | |
| terminalElement = await page.waitForSelector(selector, { timeout: 2000 }); | |
| if (terminalElement) { | |
| info(`找到终端元素: ${selector}`); | |
| terminalFound = true; | |
| break; | |
| } | |
| } catch (err) { | |
| // 继续尝试下一个选择器 | |
| } | |
| } | |
| if (!terminalFound) { | |
| info('未找到终端元素,尝试直接输入命令...'); | |
| return null; | |
| } else { | |
| // 点击终端区域确保焦点 | |
| await terminalElement.click(); | |
| await page.waitForTimeout(500); | |
| return terminalElement; | |
| } | |
| } | |
| /** | |
| * 在终端中执行命令 | |
| * @param {Object} page - Playwright 页面对象 | |
| * @param {string} command - 要执行的命令 | |
| */ | |
| export async function executeTerminalCommand(page, command) { | |
| info(`执行命令: ${command}`); | |
| // 输入命令 | |
| await page.keyboard.type(command); | |
| await page.waitForTimeout(500); | |
| // 按回车执行命令 | |
| await page.keyboard.press('Enter'); | |
| // 等待命令执行 | |
| await page.waitForTimeout(config.waitTimes.commandExecution); | |
| info('命令已执行'); | |
| } | |
| /** | |
| * 完整的命令执行流程 | |
| * @param {Object} page - Playwright 页面对象 | |
| * @param {string} screenshotPrefix - 截图文件名前缀 | |
| * @returns {boolean} 执行是否成功 | |
| */ | |
| export async function executeCommandFlow(page, screenshotPrefix = 'screenshot') { | |
| try { | |
| // 处理模态对话框 | |
| await handleModalDialog(page); | |
| // 打开终端 | |
| await openTerminal(page); | |
| // 执行命令 | |
| await executeTerminalCommand(page, config.command); | |
| // 截图保存执行结果 | |
| const screenshotDir = config.screenshotDir || './screenshots'; | |
| const screenshotPath = await saveScreenshot(page, screenshotDir, screenshotPrefix); | |
| return true; | |
| } catch (err) { | |
| error(`[${getHumanReadableTimestamp()}] 执行命令时发生错误:`, err); | |
| return false; | |
| } | |
| } | |