File size: 5,427 Bytes
86b6928
 
 
dd27eb1
86b6928
 
 
 
f9e1174
86b6928
 
f9e1174
dd27eb1
86b6928
 
 
f9e1174
 
86b6928
 
 
 
 
 
 
 
 
 
 
 
dd27eb1
86b6928
 
 
 
 
dd27eb1
 
86b6928
6c80fe2
 
 
 
86b6928
 
 
 
 
dd27eb1
86b6928
dd27eb1
 
86b6928
 
 
 
6c80fe2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86b6928
 
 
 
 
 
 
 
dd27eb1
86b6928
 
 
 
dd27eb1
86b6928
dd27eb1
86b6928
 
 
 
 
 
 
 
 
 
dd27eb1
86b6928
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd27eb1
86b6928
 
 
dd27eb1
86b6928
 
 
 
 
dd27eb1
86b6928
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd27eb1
86b6928
 
 
 
 
 
 
 
 
 
 
dd27eb1
86b6928
 
 
 
 
 
 
 
 
 
6c80fe2
86b6928
 
 
 
 
 
 
 
 
 
dd27eb1
 
86b6928
 
dd27eb1
 
86b6928
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
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;
  }
}