diff --git a/tests/pages/LongiMainPage.js b/tests/pages/LongiMainPage.js index c53658f..d00b851 100644 --- a/tests/pages/LongiMainPage.js +++ b/tests/pages/LongiMainPage.js @@ -503,86 +503,166 @@ class LongiMainPage extends BasePage { 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(); - } + const config = { + maxRetries: 30, + retryInterval: 500 + }; + + // 检查页面状态的内部方法 + const checkPageStatus = async () => { + const selectors = { + loadingMask: '.el-loading-mask', + errorBox: '.el-message-box__message', + errorMessage: '.el-message--error' + }; + + // 检查错误状态 + for (const [key, selector] of Object.entries(selectors)) { + const count = await this.page.locator(selector).count(); + if (count > 0 && key !== 'loadingMask') { + const errorText = await this.page.locator(selector).textContent(); return { success: false, - error: `页面 ${pageName} 加载出现错误: ${errorMessage}` + error: `页面 ${pageName} 加载出现错误: ${errorText}` }; } + } - // 如果还有加载遮罩,继续等待 - if (hasLoadingMask) { - retryCount++; - console.log(`等待加载中... (${retryCount}/${maxRetries})`); - await this.page.waitForTimeout(retryInterval); - continue; - } - - // 如果没有加载遮罩也没有错误,说明加载完成 - console.log('页面数据加载完成'); + // 检查加载状态 + const isLoading = await this.page.locator(selectors.loadingMask).count() > 0; + if (!isLoading) { await this.page.waitForTimeout(1000); // 额外等待一秒确保页面稳定 - return { - success: true, - error: null - }; + return {success: true, error: null}; + } + return null; // 继续等待 + }; + + // 重试逻辑 + for (let retryCount = 0; retryCount < config.maxRetries; retryCount++) { + try { + const status = await checkPageStatus(); + if (status) return status; + + console.log(`等待加载中... (${retryCount + 1}/${config.maxRetries})`); + await this.page.waitForTimeout(config.retryInterval); } catch (error) { console.error(`检查页面加载状态时出错: ${error}`); - retryCount++; - await this.page.waitForTimeout(retryInterval); } } - // 超过最大重试次数 - console.log('页面加载超时,继续执行...'); return { success: false, - error: `页面 ${pageName} 加载超时 (${maxRetries} 次重试)` + error: `页面 ${pageName} 加载超时 (${config.maxRetries} 次重试)` }; } + /** + * 获取二级菜单元素 + * @private + */ + async getSecondLevelMenu(menu) { + const menuElement = await this.page.locator(this.selectors.menuItems).nth(menu.index); + await menuElement.click(); + await this.page.waitForTimeout(500); // 减少等待时间 + return menuElement; + } + + /** + * 获取三级菜单项 + * @private + */ + async getThirdLevelMenuItems(menuElement) { + const thirdMenuItems = await this.page.locator(this.selectors.thirdLevelMenu).all(); + const thirdMenuTexts = await Promise.all( + thirdMenuItems.map(item => item.textContent()) + ); + return { + thirdMenuTexts: thirdMenuTexts.map(text => text.trim()), + totalItems: thirdMenuItems.length + }; + } + + /** + * 关闭当前活动的标签页 + * @param {string} pageName 页面名称,用于日志显示 + * @returns {Promise} 是否成功关闭标签页 + */ + async closeActiveTab(pageName) { + try { + console.log(`🗑️ 正在关闭页面 "${pageName}" 的tab...`); + + // 检查是否存在活动的tab和关闭按钮 + const activeTab = this.page.locator('.vab-tabs .el-tabs--card .el-tabs__item.is-active'); + const closeButton = activeTab.locator('.el-icon.is-icon-close'); + + const hasActiveTab = await activeTab.count() > 0; + const hasCloseButton = await closeButton.count() > 0; + + if (hasActiveTab && hasCloseButton) { + // 确保关闭按钮可见并点击 + await closeButton.waitFor({ state: 'visible', timeout: 5000 }); + await closeButton.click(); + + // 等待关闭动画完成 + await this.page.waitForTimeout(500); + return true; + } else { + console.log(`⚠️ [${pageName}] 没有找到可关闭的tab,继续执行...`); + return false; + } + } catch (error) { + console.error(`关闭标签页时出错 [${pageName}]:`, error.message); + return false; + } + } + + /** + * 点击并等待三级菜单项 + * @private + */ + async clickAndWaitThirdMenuItem(menu, currentMenuText) { + try { + const currentThirdMenuItem = await this.page.locator(this.selectors.thirdLevelMenu) + .filter({hasText: currentMenuText}) + .first(); + + await currentThirdMenuItem.click(); + const loadResult = await this.waitForPageLoadWithRetry(menu, currentMenuText); + + if (!loadResult.success) { + console.warn(loadResult.error); + } + + // 在页面加载完成后关闭标签页 + await this.closeActiveTab(`${menu.text} > ${currentMenuText}`); + } catch (error) { + console.error(`点击三级菜单项失败 [${currentMenuText}]:`, error.message); + } + } + + /** + * 处理三级菜单 + * @param {Object} menu 菜单对象 + */ 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()); + // 获取并点击二级菜单 + const menuElement = await this.getSecondLevelMenu(menu); + if (!menuElement) { + throw new Error(`未找到二级菜单: ${menu.text}`); } + // 获取三级菜单项 + const {thirdMenuTexts, totalItems} = await this.getThirdLevelMenuItems(menuElement); + if (totalItems === 0) { + console.log(`⚠️ ${menu.text} 没有找到三级菜单项`); + return; + } + + console.log(`✓ ${menu.text} 包含 ${totalItems} 个三级菜单`); + // 处理每个三级菜单项 for (let i = 0; i < totalItems; i++) { const progress = (((i + 1) / totalItems) * 100).toFixed(1); @@ -590,34 +670,19 @@ class LongiMainPage extends BasePage { console.log(`\n🔸 处理三级菜单 [${i + 1}/${totalItems}] (${progress}%): ${menu.text} > ${currentMenuText}`); - // 只有在处理第二个及以后的菜单项时,才需要重新点击二级菜单 + // 重新点击二级菜单(仅从第二个开始) if (i > 0) { await menuElement.click(); - await this.page.waitForTimeout(1000); + await this.page.waitForTimeout(500); } - // 重新获取当前要点击的三级菜单项 - 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); + await this.clickAndWaitThirdMenuItem(menu, currentMenuText); } - console.log(`✅ 完成菜单 "${menu.text}" 的所有三级菜单处理 (100%)`); + console.log(`✅ 完成菜单 "${menu.text}" 的所有三级菜单处理`); } catch (error) { - console.error(`处理三级菜单时出错: ${error}`); + console.error(`处理三级菜单时出错 [${menu.text}]:`, error.message); } } }