625 lines
24 KiB
JavaScript
625 lines
24 KiB
JavaScript
/**
|
||
* 龙蛟IBP系统主页面对象模型
|
||
*/
|
||
const BasePage = require('../utils/BasePage');
|
||
const FileUtils = require('../utils/FileUtils');
|
||
|
||
class LongiMainPage extends BasePage {
|
||
/**
|
||
* 创建主页面对象
|
||
* @param {import('@playwright/test').Page} page Playwright页面对象
|
||
*/
|
||
constructor(page) {
|
||
super(page);
|
||
|
||
// 页面元素选择器
|
||
this.selectors = {
|
||
// 侧边导航菜单 - 使用更精确的选择器
|
||
sideNav: '.ly-side-nav, .el-menu', // 主菜单
|
||
menuToggle: '.hamburger-container, .fold-btn, button.hamburger, .vab-content .toggle-icon', // 菜单展开/收起按钮,提供多个可能的选择器
|
||
menuContainer: '.el-scrollbar__view > .el-menu', // 菜单容器
|
||
menuItems: '.el-sub-menu__title, .el-menu-item', // 菜单项
|
||
menuItemText: '.titleSpan', // 菜单项文本
|
||
firstLevelIndicator: '.menuIcon', // 一级菜单指示器
|
||
thirdLevelMenu: '.el-popper.is-light.el-popover .menuTitle.canClick', // 三级菜单项
|
||
thirdLevelIndicator: '.el-icon-arrow-right', // 三级菜单指示器(箭头图标)
|
||
subMenuIndicator: '.el-sub-menu__icon-arrow' // 子菜单指示器
|
||
};
|
||
|
||
// 设置超时时间
|
||
this.timeout = 10000;
|
||
}
|
||
|
||
/**
|
||
* 检查菜单是否已展开
|
||
* @returns {Promise<boolean>} 菜单是否已展开
|
||
*/
|
||
async isMenuExpanded() {
|
||
// 获取菜单元素
|
||
const sideNav = this.page.locator(this.selectors.sideNav).first();
|
||
|
||
// 检查菜单的位置
|
||
const leftValue = await sideNav.evaluate(el => {
|
||
const style = window.getComputedStyle(el);
|
||
console.log(`菜单现在的偏移量是:${style.left}`);
|
||
return style.left;
|
||
});
|
||
|
||
// 如果left是0px,说明菜单已展开
|
||
return leftValue === '0px';
|
||
}
|
||
|
||
/**
|
||
* 点击展开菜单
|
||
* @returns {Promise<void>}
|
||
*/
|
||
async clickExpandMenu() {
|
||
try {
|
||
// 尝试查找菜单切换按钮
|
||
const toggleButton = this.page.locator(this.selectors.menuToggle).first();
|
||
|
||
// 检查按钮是否可见
|
||
const isVisible = await toggleButton.isVisible().catch(() => false);
|
||
if (!isVisible) {
|
||
console.log('菜单切换按钮不可见,尝试其他方法');
|
||
// 如果按钮不可见,可以尝试其他方法,比如键盘快捷键或直接修改DOM
|
||
return;
|
||
}
|
||
|
||
// 点击菜单切换按钮
|
||
await toggleButton.click();
|
||
console.log('已点击展开菜单');
|
||
} catch (error) {
|
||
console.error('点击展开菜单时出错:', error);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查并展开侧边菜单
|
||
* 如果菜单已收起,则点击展开
|
||
* @returns {Promise<boolean>} 是否执行了展开操作
|
||
*/
|
||
async expandSideMenu() {
|
||
try {
|
||
// 检查菜单是否已展开
|
||
const isExpanded = await this.isMenuExpanded();
|
||
|
||
if (!isExpanded) {
|
||
console.log('菜单未展开,点击展开');
|
||
await this.clickExpandMenu();
|
||
return true;
|
||
} else {
|
||
console.log('菜单已经处于展开状态');
|
||
return false;
|
||
}
|
||
} catch (error) {
|
||
console.error('展开菜单时出错:', error);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查菜单数据文件是否存在并加载数据
|
||
*/
|
||
async checkAndLoadMenuItems() {
|
||
try {
|
||
// 加载JSON文件
|
||
const menuItems = FileUtils.loadFromJsonFile(process.env.MENU_DATA_FILE_PATH);
|
||
|
||
// 检查是否成功加载数据
|
||
if (menuItems && Array.isArray(menuItems) && menuItems.length > 0) {
|
||
console.log(`从文件 ${process.env.BASE_URL} 成功加载了 ${menuItems.length} 个菜单项`);
|
||
return menuItems;
|
||
} else {
|
||
await this.expandSideMenu();
|
||
return await this.findAndSaveMenuItems();
|
||
}
|
||
} catch (error) {
|
||
console.error(`检查并加载菜单项时出错: ${error}`);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 查找菜单项并保存到文件
|
||
*/
|
||
async findAndSaveMenuItems() {
|
||
try {
|
||
// 查找菜单项
|
||
const menuItems = await this.findMenuItems();
|
||
|
||
// 如果没有找到菜单项,则返回空数组
|
||
if (!menuItems || menuItems.length === 0) {
|
||
console.warn('未找到任何菜单项,无法保存到文件');
|
||
return [];
|
||
}
|
||
|
||
// 过滤掉不能序列化的element属性
|
||
const menuItemsForSave = menuItems.map(({element, ...rest}) => rest);
|
||
|
||
// 保存到文件
|
||
FileUtils.saveToJsonFile(menuItemsForSave, process.env.MENU_DATA_FILE_PATH);
|
||
|
||
console.log(`已找到并保存 ${menuItems.length} 个菜单项到文件: ${process.env.MENU_DATA_FILE_PATH}`);
|
||
|
||
return menuItems;
|
||
} catch (error) {
|
||
console.error('查找并保存菜单项时出错:', error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 查找所有菜单项
|
||
* @returns {Promise<Array>} 菜单项数组
|
||
*/
|
||
async findMenuItems() {
|
||
try {
|
||
console.log('开始查找菜单项...');
|
||
|
||
// 等待菜单加载完成
|
||
await this.page.waitForSelector(this.selectors.sideNav, {
|
||
timeout: parseInt(process.env.MENU_TIME_OUT || '30000', 10)
|
||
});
|
||
|
||
// 获取所有菜单项
|
||
const items = await this.page.locator(this.selectors.menuItems).all();
|
||
console.log(`找到 ${items.length} 个菜单项元素`);
|
||
const menuItems = [];
|
||
// 处理每个菜单项
|
||
for (let i = 0; i < items.length; i++) {
|
||
const item = items[i];
|
||
//过滤一级菜单
|
||
let isTopMenu = (await item.locator(this.selectors.firstLevelIndicator).count()) > 0;
|
||
if (isTopMenu) {
|
||
continue;
|
||
}
|
||
// 获取菜单项文本
|
||
const text = await item.textContent();
|
||
|
||
// 检查是否是可见的菜单项
|
||
const isVisible = await item.isVisible();
|
||
|
||
if (isVisible && text.trim()) {
|
||
// 检查是否有子菜单指示器
|
||
const hasSubMenuIndicator = await item.evaluate(el => {
|
||
return el.querySelector('.el-submenu__icon-arrow') !== null ||
|
||
el.querySelector('.el-icon-arrow-down') !== null;
|
||
});
|
||
|
||
// 检查是否有三级菜单指示器
|
||
const hasThirdLevelIndicator = await item.evaluate(el => {
|
||
// 检查是否有特定的三级菜单指示器
|
||
return el.classList.contains('is-opened') ||
|
||
el.querySelector('.third-level-menu') !== null ||
|
||
el.querySelector('.el-menu--inline') !== null;
|
||
});
|
||
|
||
// 检查是否是子菜单标题
|
||
const isSubMenuTitle = await item.evaluate(el => el.classList.contains('el-sub-menu__title'));
|
||
|
||
// 综合判断是否有三级菜单
|
||
const hasThirdMenu = isSubMenuTitle || hasSubMenuIndicator || hasThirdLevelIndicator;
|
||
|
||
console.log(`菜单项 "${text.trim()}" ${hasThirdMenu ? '有' : '没有'}三级菜单 (通过DOM结构判断)`);
|
||
|
||
// 生成唯一标识符,结合索引和文本
|
||
const uniqueId = `menu_${i}_${text.trim().replace(/\s+/g, '_')}`;
|
||
|
||
// 获取菜单路径
|
||
const menuPath = await this.getMenuPath(item);
|
||
|
||
menuItems.push({
|
||
index: i,
|
||
text: text.trim(),
|
||
element: item,
|
||
hasThirdMenu: hasThirdMenu,
|
||
uniqueId: uniqueId,
|
||
// 添加路径信息,帮助识别菜单层级
|
||
path: menuPath
|
||
});
|
||
}
|
||
}
|
||
|
||
console.log(`🔍 找到 ${menuItems.length} 个可测试的菜单项`);
|
||
return menuItems;
|
||
} catch (error) {
|
||
console.error('查找菜单项时出错:', error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取菜单项的路径信息
|
||
* @param {Object} menuItem 菜单项元素
|
||
* @returns {Promise<string>} 菜单路径
|
||
*/
|
||
async getMenuPath(menuItem) {
|
||
try {
|
||
// 尝试获取父级菜单的文本
|
||
const parentText = await menuItem.evaluate(el => {
|
||
// 查找最近的父级菜单项
|
||
const parent = el.closest('.el-submenu');
|
||
if (parent) {
|
||
const parentTitle = parent.querySelector('.el-submenu__title');
|
||
if (parentTitle) {
|
||
const titleSpan = parentTitle.querySelector('.titleSpan');
|
||
return titleSpan ? titleSpan.textContent.trim() : parentTitle.textContent.trim();
|
||
}
|
||
}
|
||
return '';
|
||
});
|
||
|
||
const itemText = await menuItem.textContent();
|
||
|
||
if (parentText) {
|
||
return `${parentText} > ${itemText}`;
|
||
}
|
||
|
||
return itemText;
|
||
} catch (error) {
|
||
console.error('获取菜单路径时出错:', error);
|
||
return '';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 通过索引查找菜单项
|
||
* @param {number} index 菜单项索引
|
||
* @param {Array} menuItems 菜单项数组,如果未提供则会调用findMenuItems获取
|
||
* @returns {Promise<Object|null>} 找到的菜单项或null
|
||
*/
|
||
async findMenuItemByIndex(index, menuItems = null) {
|
||
try {
|
||
// 如果未提供菜单项数组,则获取
|
||
if (!menuItems) {
|
||
menuItems = await this.findMenuItems();
|
||
}
|
||
|
||
// 查找指定索引的菜单项
|
||
const menuItem = menuItems.find(item => item.index === index);
|
||
|
||
if (menuItem) {
|
||
console.log(`通过索引 ${index} 找到菜单项: "${menuItem.text}"`);
|
||
return menuItem;
|
||
} else {
|
||
console.log(`未找到索引为 ${index} 的菜单项`);
|
||
return null;
|
||
}
|
||
} catch (error) {
|
||
console.error(`通过索引查找菜单项时出错: ${error}`);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 通过文本和可选的索引查找菜单项
|
||
* 当有多个同名菜单项时,可以通过指定occurrence来选择第几个匹配项
|
||
* @param {string} text 菜单项文本
|
||
* @param {number} occurrence 第几个匹配项,从0开始计数,默认为0(第一个)
|
||
* @param {Array} menuItems 菜单项数组,如果未提供则会调用findMenuItems获取
|
||
* @returns {Promise<Object|null>} 找到的菜单项或null
|
||
*/
|
||
async findMenuItemByText(text, occurrence = 0, menuItems = null) {
|
||
try {
|
||
// 如果未提供菜单项数组,则获取
|
||
if (!menuItems) {
|
||
menuItems = await this.findMenuItems();
|
||
}
|
||
|
||
// 查找所有匹配文本的菜单项
|
||
const matchingItems = menuItems.filter(item => item.text === text);
|
||
|
||
if (matchingItems.length > 0) {
|
||
if (occurrence < matchingItems.length) {
|
||
const menuItem = matchingItems[occurrence];
|
||
console.log(`通过文本 "${text}" 找到第 ${occurrence + 1} 个菜单项,索引为 ${menuItem.index}`);
|
||
return menuItem;
|
||
} else {
|
||
console.log(`未找到第 ${occurrence + 1} 个文本为 "${text}" 的菜单项,只有 ${matchingItems.length} 个匹配项`);
|
||
return null;
|
||
}
|
||
} else {
|
||
console.log(`未找到文本为 "${text}" 的菜单项`);
|
||
return null;
|
||
}
|
||
} catch (error) {
|
||
console.error(`通过文本查找菜单项时出错: ${error}`);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 通过唯一ID查找菜单项
|
||
* @param {string} uniqueId 菜单项的唯一ID
|
||
* @param {Array} menuItems 菜单项数组,如果未提供则会调用findMenuItems获取
|
||
* @returns {Promise<Object|null>} 找到的菜单项或null
|
||
*/
|
||
async findMenuItemByUniqueId(uniqueId, menuItems = null) {
|
||
try {
|
||
// 如果未提供菜单项数组,则获取
|
||
if (!menuItems) {
|
||
menuItems = await this.findMenuItems();
|
||
}
|
||
|
||
// 查找指定唯一ID的菜单项
|
||
const menuItem = menuItems.find(item => item.uniqueId === uniqueId);
|
||
|
||
if (menuItem) {
|
||
console.log(`通过唯一ID ${uniqueId} 找到菜单项: "${menuItem.text}"`);
|
||
return menuItem;
|
||
} else {
|
||
console.log(`未找到唯一ID为 ${uniqueId} 的菜单项`);
|
||
return null;
|
||
}
|
||
} catch (error) {
|
||
console.error(`通过唯一ID查找菜单项时出错: ${error}`);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查是否存在三级菜单并进行相应处理
|
||
* @param {Object} menuItem 菜单项对象,包含索引、文本和元素
|
||
* @param {number} timeout 超时时间(毫秒),默认30秒
|
||
* @returns {Promise<{hasThirdMenu: boolean, thirdMenuItems: Array}>} 是否有三级菜单及三级菜单项数组
|
||
*/
|
||
async checkForThirdLevelMenu(menuItem, timeout = 30000) {
|
||
try {
|
||
console.log(`点击菜单项 "${menuItem.text}" 检查三级菜单...`);
|
||
|
||
// 点击菜单项,触发三级菜单弹出
|
||
await menuItem.element.click();
|
||
|
||
// 等待弹出动画完成,增加等待时间
|
||
await this.page.waitForTimeout(2000);
|
||
|
||
// 检查三级菜单
|
||
const thirdMenuSelector = this.selectors.thirdLevelMenu;
|
||
|
||
// 尝试等待三级菜单出现,但不抛出错误
|
||
const hasThirdMenu = await this.page.locator(thirdMenuSelector).count().then(count => count > 0).catch(() => false);
|
||
|
||
// 如果没有立即找到,再等待一段时间再次检查
|
||
let thirdMenuCount = 0;
|
||
if (hasThirdMenu) {
|
||
thirdMenuCount = await this.page.locator(thirdMenuSelector).count();
|
||
} else {
|
||
// 再等待一段时间,有些菜单可能加载较慢
|
||
await this.page.waitForTimeout(1000);
|
||
thirdMenuCount = await this.page.locator(thirdMenuSelector).count();
|
||
}
|
||
|
||
console.log(`菜单项 "${menuItem.text}" ${thirdMenuCount > 0 ? '有' : '没有'}三级菜单,找到 ${thirdMenuCount} 个三级菜单项`);
|
||
|
||
// 如果没有三级菜单,直接返回
|
||
if (thirdMenuCount === 0) {
|
||
return {hasThirdMenu: false, thirdMenuItems: []};
|
||
}
|
||
|
||
// 收集三级菜单项
|
||
const thirdMenuItems = [];
|
||
for (let i = 0; i < thirdMenuCount; i++) {
|
||
const item = this.page.locator(thirdMenuSelector).nth(i);
|
||
const text = await item.textContent();
|
||
|
||
thirdMenuItems.push({
|
||
index: i,
|
||
text: text.trim(),
|
||
element: item
|
||
});
|
||
}
|
||
|
||
// 输出三级菜单项文本
|
||
const menuTexts = thirdMenuItems.map(item => item.text).join(', ');
|
||
console.log(`三级菜单项: ${menuTexts}`);
|
||
|
||
return {hasThirdMenu: true, thirdMenuItems};
|
||
} catch (error) {
|
||
console.error(`检查三级菜单时出错: ${error}`);
|
||
return {hasThirdMenu: false, thirdMenuItems: []};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理菜单项,包括检查和处理可能的三级菜单
|
||
* @param {Object} menuItem 菜单项对象,包含索引、文本和元素以及hasThirdMenu标志
|
||
* @param {Function} processWithThirdMenu 处理有三级菜单情况的回调函数
|
||
* @param {Function} processWithoutThirdMenu 处理没有三级菜单情况的回调函数
|
||
* @returns {Promise<{hasThirdMenu: boolean, thirdMenuItems: Array}>} 处理结果
|
||
*/
|
||
async processMenuItem(menuItem, processWithThirdMenu = null, processWithoutThirdMenu = null) {
|
||
try {
|
||
console.log(`处理菜单项: "${menuItem.text}"`);
|
||
|
||
// 使用菜单项中的hasThirdMenu字段
|
||
const hasThirdMenu = menuItem.hasThirdMenu;
|
||
|
||
// 点击菜单项
|
||
await menuItem.element.click();
|
||
await this.page.waitForTimeout(1000); // 等待可能的动画完成
|
||
|
||
let thirdMenuItems = [];
|
||
|
||
// 如果有三级菜单,获取三级菜单项
|
||
if (hasThirdMenu) {
|
||
const thirdMenuSelector = this.selectors.thirdLevelMenu;
|
||
const thirdMenuCount = await this.page.locator(thirdMenuSelector).count();
|
||
|
||
console.log(`菜单项 "${menuItem.text}" 有三级菜单,找到 ${thirdMenuCount} 个三级菜单项`);
|
||
|
||
// 收集三级菜单项
|
||
for (let i = 0; i < thirdMenuCount; i++) {
|
||
const item = this.page.locator(thirdMenuSelector).nth(i);
|
||
const text = await item.textContent();
|
||
|
||
thirdMenuItems.push({
|
||
index: i,
|
||
text: text.trim(),
|
||
element: item
|
||
});
|
||
}
|
||
|
||
// 输出三级菜单项文本
|
||
const menuTexts = thirdMenuItems.map(item => item.text).join(', ');
|
||
console.log(`三级菜单项: ${menuTexts}`);
|
||
} else {
|
||
console.log(`菜单项 "${menuItem.text}" 没有三级菜单`);
|
||
}
|
||
|
||
// 根据是否有三级菜单调用相应的处理函数
|
||
if (hasThirdMenu && processWithThirdMenu) {
|
||
await processWithThirdMenu(menuItem, thirdMenuItems);
|
||
} else if (!hasThirdMenu && processWithoutThirdMenu) {
|
||
await processWithoutThirdMenu(menuItem);
|
||
}
|
||
|
||
return {hasThirdMenu, thirdMenuItems};
|
||
} catch (error) {
|
||
console.error(`处理菜单项时出错: ${error}`);
|
||
return {hasThirdMenu: false, thirdMenuItems: []};
|
||
}
|
||
}
|
||
|
||
async handleAllMenus(menuItems) {
|
||
for (let i = 0; i < menuItems.length; i++) {
|
||
await this.handleSingleMenu(menuItems[i]);
|
||
}
|
||
}
|
||
|
||
async handleSingleMenu(menu) {
|
||
await this.expandSideMenu();
|
||
if (menu.hasThirdMenu) {
|
||
await this.handleThreeLevelMenu(menu);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 等待页面加载完成,包括检查加载遮罩和错误提示
|
||
* @param {Object} menu 菜单对象,包含text等信息
|
||
* @param {string} [subMenuText] 子菜单文本,可选
|
||
* @returns {Promise<{success: boolean, error: string|null}>}
|
||
*/
|
||
async waitForPageLoadWithRetry(menu, subMenuText = '') {
|
||
const pageName = subMenuText ? `${menu.text} > ${subMenuText}` : menu.text;
|
||
console.log(`等待页面 ${pageName} 数据加载...`);
|
||
|
||
let retryCount = 0;
|
||
const maxRetries = 30;
|
||
const retryInterval = 500;
|
||
|
||
while (retryCount < maxRetries) {
|
||
try {
|
||
// 检查是否存在加载遮罩
|
||
const hasLoadingMask = await this.page.locator('.el-loading-mask').count() > 0;
|
||
|
||
// 检查是否存在错误提示
|
||
const hasErrorBox = await this.page.locator('.el-message-box__message').count() > 0;
|
||
const hasErrorMessage = await this.page.locator('.el-message--error').count() > 0;
|
||
|
||
// 如果存在错误提示,立即返回错误状态
|
||
if (hasErrorBox || hasErrorMessage) {
|
||
console.log('页面加载出现错误');
|
||
let errorMessage = '';
|
||
if (hasErrorBox) {
|
||
errorMessage = await this.page.locator('.el-message-box__message').textContent();
|
||
} else if (hasErrorMessage) {
|
||
errorMessage = await this.page.locator('.el-message--error').textContent();
|
||
}
|
||
return {
|
||
success: false,
|
||
error: `页面 ${pageName} 加载出现错误: ${errorMessage}`
|
||
};
|
||
}
|
||
|
||
// 如果还有加载遮罩,继续等待
|
||
if (hasLoadingMask) {
|
||
retryCount++;
|
||
console.log(`等待加载中... (${retryCount}/${maxRetries})`);
|
||
await this.page.waitForTimeout(retryInterval);
|
||
continue;
|
||
}
|
||
|
||
// 如果没有加载遮罩也没有错误,说明加载完成
|
||
console.log('页面数据加载完成');
|
||
await this.page.waitForTimeout(1000); // 额外等待一秒确保页面稳定
|
||
return {
|
||
success: true,
|
||
error: null
|
||
};
|
||
|
||
} catch (error) {
|
||
console.error(`检查页面加载状态时出错: ${error}`);
|
||
retryCount++;
|
||
await this.page.waitForTimeout(retryInterval);
|
||
}
|
||
}
|
||
|
||
// 超过最大重试次数
|
||
console.log('页面加载超时,继续执行...');
|
||
return {
|
||
success: false,
|
||
error: `页面 ${pageName} 加载超时 (${maxRetries} 次重试)`
|
||
};
|
||
}
|
||
|
||
async handleThreeLevelMenu(menu) {
|
||
try {
|
||
// 使用下标定位菜单元素
|
||
const menuElement = await this.page.locator(this.selectors.menuItems).nth(menu.index);
|
||
|
||
// 首次点击菜单项显示三级菜单
|
||
await menuElement.click();
|
||
await this.page.waitForTimeout(1000);
|
||
|
||
// 获取所有三级菜单项的文本和数量信息
|
||
const thirdMenuItems = await this.page.locator(this.selectors.thirdLevelMenu).all();
|
||
const totalItems = thirdMenuItems.length;
|
||
console.log(`✓ ${menu.text} 包含 ${totalItems} 个三级菜单`);
|
||
|
||
// 存储所有三级菜单的文本,因为后续重新获取元素时会需要
|
||
const thirdMenuTexts = [];
|
||
for (const item of thirdMenuItems) {
|
||
thirdMenuTexts.push(await item.textContent());
|
||
}
|
||
|
||
// 处理每个三级菜单项
|
||
for (let i = 0; i < totalItems; i++) {
|
||
const progress = (((i + 1) / totalItems) * 100).toFixed(1);
|
||
const currentMenuText = thirdMenuTexts[i];
|
||
|
||
console.log(`\n🔸 处理三级菜单 [${i + 1}/${totalItems}] (${progress}%): ${menu.text} > ${currentMenuText}`);
|
||
|
||
// 只有在处理第二个及以后的菜单项时,才需要重新点击二级菜单
|
||
if (i > 0) {
|
||
await menuElement.click();
|
||
await this.page.waitForTimeout(1000);
|
||
}
|
||
|
||
// 重新获取当前要点击的三级菜单项
|
||
const currentThirdMenuItem = await this.page.locator(this.selectors.thirdLevelMenu)
|
||
.filter({ hasText: currentMenuText })
|
||
.first();
|
||
|
||
// 点击当前三级菜单项
|
||
await currentThirdMenuItem.click();
|
||
|
||
// 使用新的等待页面加载方法,传入menu对象和当前三级菜单文本
|
||
const loadResult = await this.waitForPageLoadWithRetry(menu, currentMenuText);
|
||
if (!loadResult.success) {
|
||
console.warn(loadResult.error);
|
||
}
|
||
|
||
// 等待一段时间后继续处理下一个三级菜单
|
||
await this.page.waitForTimeout(1000);
|
||
}
|
||
|
||
console.log(`✅ 完成菜单 "${menu.text}" 的所有三级菜单处理 (100%)`);
|
||
|
||
} catch (error) {
|
||
console.error(`处理三级菜单时出错: ${error}`);
|
||
}
|
||
}
|
||
}
|
||
|
||
module.exports = LongiMainPage;
|