第一次

This commit is contained in:
dengqichen 2025-03-06 09:35:07 +08:00
parent 08910deeed
commit 5e1d37134e

View File

@ -80,7 +80,6 @@ class LongiMainPage extends BasePage {
* @returns {Promise<boolean>} 是否执行了展开操作 * @returns {Promise<boolean>} 是否执行了展开操作
*/ */
async expandSideMenu() { async expandSideMenu() {
try {
// 检查菜单是否已展开 // 检查菜单是否已展开
const isExpanded = await this.isMenuExpanded(); const isExpanded = await this.isMenuExpanded();
@ -88,15 +87,10 @@ class LongiMainPage extends BasePage {
console.log('菜单未展开,点击展开'); console.log('菜单未展开,点击展开');
await this.clickExpandMenu(); await this.clickExpandMenu();
return true; return true;
} else {
// console.log('菜单已经处于展开状态');
return false;
} }
} catch (error) {
console.error('展开菜单时出错:', error);
return false; return false;
} }
}
/** /**
* 检查菜单数据文件是否存在并加载数据 * 检查菜单数据文件是否存在并加载数据
@ -115,6 +109,7 @@ class LongiMainPage extends BasePage {
return await this.findAndSaveMenuItems(); return await this.findAndSaveMenuItems();
} }
} catch (error) { } catch (error) {
// 文件操作错误需要被捕获并处理
console.error(`检查并加载菜单项时出错: ${error}`); console.error(`检查并加载菜单项时出错: ${error}`);
return null; return null;
} }
@ -124,7 +119,6 @@ class LongiMainPage extends BasePage {
* 查找菜单项并保存到文件 * 查找菜单项并保存到文件
*/ */
async findAndSaveMenuItems() { async findAndSaveMenuItems() {
try {
// 查找菜单项 // 查找菜单项
const menuItems = await this.findMenuItems(); const menuItems = await this.findMenuItems();
@ -134,6 +128,7 @@ class LongiMainPage extends BasePage {
return []; return [];
} }
try {
// 过滤掉不能序列化的element属性 // 过滤掉不能序列化的element属性
const menuItemsForSave = menuItems.map(({element, ...rest}) => rest); const menuItemsForSave = menuItems.map(({element, ...rest}) => rest);
@ -144,8 +139,9 @@ class LongiMainPage extends BasePage {
return menuItems; return menuItems;
} catch (error) { } catch (error) {
console.error('查找并保存菜单项时出错:', error); // 文件操作错误需要被捕获
return []; console.error('保存菜单项到文件时出错:', error);
return menuItems; // 即使保存失败也返回找到的菜单项
} }
} }
@ -154,7 +150,6 @@ class LongiMainPage extends BasePage {
* @returns {Promise<Array>} 菜单项数组 * @returns {Promise<Array>} 菜单项数组
*/ */
async findMenuItems() { async findMenuItems() {
try {
console.log('开始查找菜单项...'); console.log('开始查找菜单项...');
// 等待菜单加载完成 // 等待菜单加载完成
@ -166,6 +161,7 @@ class LongiMainPage extends BasePage {
const items = await this.page.locator(this.selectors.menuItems).all(); const items = await this.page.locator(this.selectors.menuItems).all();
console.log(`找到 ${items.length} 个菜单项元素`); console.log(`找到 ${items.length} 个菜单项元素`);
const menuItems = []; const menuItems = [];
// 处理每个菜单项 // 处理每个菜单项
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
const item = items[i]; const item = items[i];
@ -215,7 +211,6 @@ class LongiMainPage extends BasePage {
element: item, element: item,
hasThirdMenu: hasThirdMenu, hasThirdMenu: hasThirdMenu,
uniqueId: uniqueId, uniqueId: uniqueId,
// 添加路径信息,帮助识别菜单层级
path: menuPath path: menuPath
}); });
} }
@ -223,10 +218,6 @@ class LongiMainPage extends BasePage {
console.log(`🔍 找到 ${menuItems.length} 个可测试的菜单项`); console.log(`🔍 找到 ${menuItems.length} 个可测试的菜单项`);
return menuItems; return menuItems;
} catch (error) {
console.error('查找菜单项时出错:', error);
return [];
}
} }
/** /**
@ -235,7 +226,6 @@ class LongiMainPage extends BasePage {
* @returns {Promise<string>} 菜单路径 * @returns {Promise<string>} 菜单路径
*/ */
async getMenuPath(menuItem) { async getMenuPath(menuItem) {
try {
// 尝试获取父级菜单的文本 // 尝试获取父级菜单的文本
const parentText = await menuItem.evaluate(el => { const parentText = await menuItem.evaluate(el => {
// 查找最近的父级菜单项 // 查找最近的父级菜单项
@ -251,22 +241,47 @@ class LongiMainPage extends BasePage {
}); });
const itemText = await menuItem.textContent(); const itemText = await menuItem.textContent();
return parentText ? `${parentText} > ${itemText}` : itemText;
if (parentText) {
return `${parentText} > ${itemText}`;
}
return itemText;
} catch (error) {
console.error('获取菜单路径时出错:', error);
return '';
}
} }
/**
* 处理所有菜单点击
* @param {Array} menuItems 菜单项数组
*/
async handleAllMenuClicks(menuItems) { async handleAllMenuClicks(menuItems) {
try {
for (let i = 0; i < menuItems.length; i++) { for (let i = 0; i < menuItems.length; i++) {
await this.handleSingleMenuClick(menuItems[i]); await this.handleSingleMenuClick(menuItems[i]);
} }
} catch (error) {
console.error('处理菜单点击时出错:', error);
throw error; // 向上传播错误
}
}
/**
* 处理单个菜单点击
* @param {Object} menu 菜单对象
*/
async handleSingleMenuClick(menu) {
await this.expandSideMenu();
// 在处理菜单前重新获取最新的element
menu = await this.restoreMenuElement(menu);
if (!menu.element) {
console.error(`无法找到菜单项 "${menu.text}" 的element跳过处理`);
return;
}
if (menu.hasThirdMenu) {
await this.handleThreeLevelMenu(menu);
} else {
// 处理二级菜单点击
await this.handleMenuClick(menu);
}
// 执行内存回收
await this.cleanupMemory(menu.text);
} }
/** /**
@ -276,7 +291,6 @@ class LongiMainPage extends BasePage {
* @private * @private
*/ */
async restoreMenuElement(menuItem) { async restoreMenuElement(menuItem) {
try {
// 获取当前页面上的所有菜单元素 // 获取当前页面上的所有菜单元素
const currentMenuElements = await this.page.locator(this.selectors.menuItems).all(); const currentMenuElements = await this.page.locator(this.selectors.menuItems).all();
let foundElement = null; let foundElement = null;
@ -323,10 +337,6 @@ class LongiMainPage extends BasePage {
} }
return menuItem; return menuItem;
} catch (error) {
console.error(`恢复菜单项element时出错 [${menuItem.text}]:`, error.message);
return menuItem;
}
} }
/** /**
@ -356,30 +366,155 @@ class LongiMainPage extends BasePage {
} }
} }
async handleSingleMenuClick(menu) { /**
try { * 获取三级菜单列表
await this.expandSideMenu(); * @param {Object} parentMenu 父级菜单对象
// 在处理菜单前重新获取最新的element * @returns {Promise<Array>} 三级菜单项数组
menu = await this.restoreMenuElement(menu); * @private
*/
async getThirdLevelMenus(parentMenu) {
// 检查三级菜单是否存在
const elements = await this.page.locator('.el-popper.is-light.el-popover .menuTitle.canClick').all();
if (elements.length === 0) {
return [];
}
if (!menu.element) { // 收集所有三级菜单项
console.error(`无法找到菜单项 "${menu.text}" 的element跳过处理`); const thirdMenus = [];
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const text = await element.textContent();
thirdMenus.push({
index: i,
text: text.trim(),
element: element,
hasThirdMenu: false, // 三级菜单项不会有下一级
uniqueId: `menu_${parentMenu.uniqueId}_${i}_${text.trim().replace(/\s+/g, '_')}`,
path: `${parentMenu.text} > ${text.trim()}`
});
}
return thirdMenus;
}
/**
* 处理三级菜单
* @param {Object} menu 菜单对象
*/
async handleThreeLevelMenu(menu) {
console.log(`处理三级菜单: ${menu.text}`);
// 1. 点击展开三级菜单
await menu.element.click();
await this.page.waitForTimeout(500);
// 2. 获取三级菜单列表
const thirdMenus = await this.getThirdLevelMenus(menu);
if (thirdMenus.length === 0) {
console.log(`未找到三级菜单项`);
return; return;
} }
if (menu.hasThirdMenu) { // 3. 处理每个三级菜单项
await this.handleThreeLevelMenu(menu); for (let i = 0; i < thirdMenus.length; i++) {
} else { const thirdMenu = thirdMenus[i];
// 处理二级菜单点击 console.log(`处理第 ${i + 1}/${thirdMenus.length} 个三级菜单项: ${thirdMenu.text}`);
await this.handleMenuClick(menu);
await this.handleMenuClick(thirdMenu, menu);
// 如果还有下一个菜单项,重新展开三级菜单
if (i < thirdMenus.length - 1) {
await menu.element.click();
await this.page.waitForTimeout(500);
}
}
} }
// 执行内存回收 /**
await this.cleanupMemory(menu.text); * 处理菜单点击和页面加载
* @param {Object} menuInfo 菜单信息对象
* @param {Object} parentMenu 父级菜单可选
*/
async handleMenuClick(menuInfo, parentMenu = null) {
const menuPath = parentMenu ? `${parentMenu.text} > ${menuInfo.text}` : menuInfo.text;
console.log(`点击菜单: ${menuPath}`);
// 1. 点击菜单并等待页面加载
await menuInfo.element.click();
const loadResult = await this.waitForPageLoadWithRetry(menuInfo);
if (!loadResult) {
console.warn(`页面加载失败: ${menuPath}`);
return;
}
// 2. 处理页面中的标签页
await this.handleAllTabs(menuInfo);
// 3. 关闭当前标签页
await this.closeActiveTab(menuPath);
}
/**
* 处理单个TAB页
* @param {Object} tabInfo TAB页信息对象包含textisActive和element属性
* @param {Object} parentMenu 父级菜单对象
* @private
*/
async handleSingleTab(tabInfo, parentMenu) {
try {
const menuPath = parentMenu.path || parentMenu.text;
console.log(`🔹 处理TAB页: ${menuPath} > ${tabInfo.text}`);
// 直接使用传入的element点击
await tabInfo.element.click();
await this.waitForPageLoadWithRetry(parentMenu, tabInfo.text)
} catch (error) {
console.error(`处理TAB页失败 [${parentMenu.text} > ${tabInfo.text}]:`, error.message);
}
}
/**
* 处理所有TAB页
* @param {Object} menu 菜单对象
* @private
*/
async handleAllTabs(menu) {
try {
// 等待TAB容器加载
await this.page.waitForTimeout(1000);
// 使用更精确的选择器获取工作区的TAB页
const tabs = await this.page.locator('.workSpaceBaseTab .el-tabs__item').all();
if (tabs.length === 0) {
console.log(`📝 ${menu.text} 没有TAB页`);
return;
}
console.log(`📑 ${menu.text} 找到 ${tabs.length} 个TAB页`);
// 获取所有TAB页的完整信息文本、激活状态和元素引用
const tabInfos = await Promise.all(
tabs.map(async element => ({
text: (await element.textContent()).trim(),
isActive: await element.evaluate(el => el.classList.contains('is-active')),
element: element // 保存元素引用
}))
);
// 处理每个非激活的TAB页
for (const tabInfo of tabInfos) {
// 跳过当前激活的TAB页因为它已经是默认加载的
if (!tabInfo.isActive) {
await this.handleSingleTab(tabInfo, menu);
} else {
console.log(`⏭️ 跳过当前激活的TAB页: ${menu.text} > ${tabInfo.text}`);
}
}
} catch (error) { } catch (error) {
console.error(`处理菜单失败 [${menu.text}]:`, error.message); console.error(`处理TAB页失败 [${menu.text}]:`, error.message);
throw error;
} }
} }
@ -477,171 +612,6 @@ class LongiMainPage extends BasePage {
return false; return false;
} }
} }
/**
* 获取三级菜单列表
* @param {Object} parentMenu 父级菜单对象
* @returns {Promise<Array>} 三级菜单项数组
* @private
*/
async getThirdLevelMenus(parentMenu) {
try {
// 检查三级菜单是否存在
const elements = await this.page.locator('.el-popper.is-light.el-popover .menuTitle.canClick').all();
if (elements.length === 0) {
return [];
}
// 收集所有三级菜单项
const thirdMenus = [];
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const text = await element.textContent();
thirdMenus.push({
index: i,
text: text.trim(),
element: element,
hasThirdMenu: false, // 三级菜单项不会有下一级
uniqueId: `menu_${parentMenu.uniqueId}_${i}_${text.trim().replace(/\s+/g, '_')}`,
path: `${parentMenu.text} > ${text.trim()}`
});
}
return thirdMenus;
} catch (error) {
console.error(`获取三级菜单失败: ${error.message}`);
return [];
}
}
/**
* 处理三级菜单
* @param {Object} menu 菜单对象
*/
async handleThreeLevelMenu(menu) {
console.log(`处理三级菜单: ${menu.text}`);
// 1. 点击展开三级菜单
await menu.element.click();
await this.page.waitForTimeout(500);
// 2. 获取三级菜单列表
const thirdMenus = await this.getThirdLevelMenus(menu);
if (thirdMenus.length === 0) {
console.log(`未找到三级菜单项`);
return;
}
// 3. 处理每个三级菜单项
for (let i = 0; i < thirdMenus.length; i++) {
const thirdMenu = thirdMenus[i];
console.log(`处理第 ${i + 1}/${thirdMenus.length} 个三级菜单项: ${thirdMenu.text}`);
await this.handleMenuClick(thirdMenu, menu);
// 如果还有下一个菜单项,重新展开三级菜单
if (i < thirdMenus.length - 1) {
await menu.element.click();
await this.page.waitForTimeout(500);
}
}
}
/**
* 处理菜单点击和页面加载
* @param {Object} menuInfo 菜单信息对象
* @param {Object} parentMenu 父级菜单可选
*/
async handleMenuClick(menuInfo, parentMenu = null) {
const menuPath = parentMenu ? `${parentMenu.text} > ${menuInfo.text}` : menuInfo.text;
console.log(`点击菜单: ${menuPath}`);
// 1. 点击菜单并等待页面加载
await menuInfo.element.click();
const loadResult = await this.waitForPageLoadWithRetry(menuInfo);
if (!loadResult) {
console.warn(`页面加载失败: ${menuPath}`);
return false;
}
// 2. 处理页面中的标签页
await this.handleAllTabs(menuInfo);
// 3. 关闭当前标签页
await this.closeActiveTab(menuPath);
return true;
}
/**
* 处理单个TAB页
* @param {Object} tabInfo TAB页信息对象包含textisActive和element属性
* @param {Object} parentMenu 父级菜单对象
* @returns {Promise<boolean>} 处理是否成功
* @private
*/
async handleSingleTab(tabInfo, parentMenu) {
try {
const menuPath = parentMenu.path || parentMenu.text;
console.log(`🔹 处理TAB页: ${menuPath} > ${tabInfo.text}`);
// 直接使用传入的element点击
await tabInfo.element.click();
return !await this.waitForPageLoadWithRetry(parentMenu, tabInfo.text);
} catch (error) {
console.error(`处理TAB页失败 [${parentMenu.text} > ${tabInfo.text}]:`, error.message);
return false;
}
}
/**
* 处理所有TAB页
* @param {Object} menu 菜单对象
* @returns {Promise<boolean>} 处理是否成功
* @private
*/
async handleAllTabs(menu) {
try {
// 等待TAB容器加载
await this.page.waitForTimeout(1000);
// 使用更精确的选择器获取工作区的TAB页
const tabs = await this.page.locator('.workSpaceBaseTab .el-tabs__item').all();
if (tabs.length === 0) {
console.log(`📝 ${menu.text} 没有TAB页`);
return true;
}
console.log(`📑 ${menu.text} 找到 ${tabs.length} 个TAB页`);
// 获取所有TAB页的完整信息文本、激活状态和元素引用
const tabInfos = await Promise.all(
tabs.map(async element => ({
text: (await element.textContent()).trim(),
isActive: await element.evaluate(el => el.classList.contains('is-active')),
element: element // 保存元素引用
}))
);
// 处理每个非激活的TAB页
for (const tabInfo of tabInfos) {
// 跳过当前激活的TAB页因为它已经是默认加载的
if (!tabInfo.isActive) {
await this.handleSingleTab(tabInfo, menu);
} else {
console.log(`⏭️ 跳过当前激活的TAB页: ${menu.text} > ${tabInfo.text}`);
}
}
return true;
} catch (error) {
console.error(`处理TAB页失败 [${menu.text}]:`, error.message);
return false;
}
}
} }
module.exports = LongiMainPage; module.exports = LongiMainPage;