优化文件路径
This commit is contained in:
parent
b7f00b5a9f
commit
39983043e1
@ -156,6 +156,7 @@ class BasePage {
|
||||
|
||||
/**
|
||||
* 等待页面加载完成
|
||||
* @deprecated 请使用 waitForPageLoadWithRetry 方法替代
|
||||
*/
|
||||
async waitForPageLoad() {
|
||||
await this.page.waitForLoadState('networkidle', {
|
||||
@ -163,6 +164,83 @@ class BasePage {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 等待页面加载完成,带重试机制
|
||||
* @param {Object} context 上下文信息对象
|
||||
* @param {string} [context.text] 页面名称或描述
|
||||
* @param {string} [context.path] 页面路径
|
||||
* @param {string} [subContext] 子上下文信息(可选)
|
||||
* @returns {Promise<boolean>} 页面是否加载成功
|
||||
*/
|
||||
async waitForPageLoadWithRetry(context, subContext = '') {
|
||||
const pageName = this.getContextName(context, subContext);
|
||||
console.log(`等待页面 ${pageName} 数据加载...`);
|
||||
|
||||
let retryCount = 0;
|
||||
const {maxRetries, retryInterval, stabilityDelay} = this.config.pageLoad;
|
||||
|
||||
try {
|
||||
while (retryCount < maxRetries) {
|
||||
// 检查错误状态
|
||||
const hasError = await this.checkPageError(pageName);
|
||||
if (hasError) return false;
|
||||
|
||||
// 检查加载状态
|
||||
const isLoading = await this.elementExists(this.selectors.loadingMask);
|
||||
if (!isLoading) {
|
||||
await this.wait(stabilityDelay);
|
||||
console.log(`✅ 页面 ${pageName} 加载完成`);
|
||||
return true;
|
||||
}
|
||||
|
||||
retryCount++;
|
||||
await this.wait(retryInterval);
|
||||
}
|
||||
|
||||
console.error(`页面加载超时: ${pageName}, 重试次数: ${maxRetries}`);
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error(`页面加载出错: ${pageName}, 错误信息: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查页面是否有错误
|
||||
* @param {string} pageName 页面名称
|
||||
* @returns {Promise<boolean>} 是否有错误
|
||||
* @private
|
||||
*/
|
||||
async checkPageError(pageName) {
|
||||
const errorSelectors = [this.selectors.errorBox, this.selectors.errorMessage];
|
||||
|
||||
for (const selector of errorSelectors) {
|
||||
const elements = await this.page.locator(selector).all();
|
||||
if (elements.length > 0) {
|
||||
const errorText = await this.getElementText(elements[0]);
|
||||
console.error(`页面加载出现错误: ${pageName}, 错误信息: ${errorText}`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上下文名称
|
||||
* @param {Object} context 上下文信息对象
|
||||
* @param {string} [subContext] 子上下文信息
|
||||
* @returns {string} 格式化的上下文名称
|
||||
* @private
|
||||
*/
|
||||
getContextName(context, subContext = '') {
|
||||
if (typeof context === 'string') {
|
||||
return context;
|
||||
}
|
||||
const mainText = context.text || context.path || 'Unknown';
|
||||
return subContext ? `${mainText} > ${subContext}` : mainText;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取页面标题
|
||||
* @returns {Promise<string>} 页面标题
|
||||
@ -218,15 +296,14 @@ class BasePage {
|
||||
/**
|
||||
* 安全点击元素
|
||||
* @param {Object} element Playwright元素对象
|
||||
* @param {string} description 元素描述,用于日志
|
||||
* @returns {Promise<boolean>} 是否点击成功
|
||||
*/
|
||||
async safeClick(element, description) {
|
||||
async safeClick(element) {
|
||||
try {
|
||||
await element.click();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`点击${description}失败:`, error.message);
|
||||
console.error(`点击失败:`, error.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,14 +63,14 @@ class LongiLoginPage extends BasePage {
|
||||
try {
|
||||
// 方法1: 使用更精确的选择器,指定包含特定类的按钮
|
||||
await this.click(this.selectors.loginButton);
|
||||
console.log('使用 container-button 类选择器成功点击登录按钮');
|
||||
// console.log('使用 container-button 类选择器成功点击登录按钮');
|
||||
await this.waitForPageLoad();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log('第一种方法失败,尝试备用方法...');
|
||||
try {
|
||||
// 方法2: 使用精确文本匹配
|
||||
await this.safeClick(await this.page.locator(this.selectors.loginButtonByText), '登录按钮(精确文本匹配)');
|
||||
await this.safeClick(await this.page.locator(this.selectors.loginButtonByText));
|
||||
// console.log('使用精确文本匹配成功点击登录按钮');
|
||||
await this.waitForPageLoad();
|
||||
return true;
|
||||
@ -78,7 +78,7 @@ class LongiLoginPage extends BasePage {
|
||||
console.log('第二种方法也失败,尝试第三种方法...');
|
||||
try {
|
||||
// 方法3: 使用first()选择第一个匹配的按钮
|
||||
await this.safeClick(await this.page.locator(this.selectors.loginButtonFirst).first(), '登录按钮(first方法)');
|
||||
await this.safeClick(await this.page.locator(this.selectors.loginButtonFirst).first());
|
||||
// console.log('使用first()方法成功点击登录按钮');
|
||||
await this.waitForPageLoad();
|
||||
return true;
|
||||
|
||||
@ -210,7 +210,7 @@ class LongiMainPage extends BasePage {
|
||||
const uniqueId = `menu_${i}_${text.trim().replace(/\s+/g, '_')}`;
|
||||
|
||||
// 获取菜单路径
|
||||
const menuPath = await this.getMenuPath(item);
|
||||
const menuPath = this.getMenuPath(item);
|
||||
|
||||
menuItems.push({
|
||||
index: i,
|
||||
@ -228,27 +228,14 @@ class LongiMainPage extends BasePage {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单项的路径信息
|
||||
* @param {Object} menuItem 菜单项元素
|
||||
* @returns {Promise<string>} 菜单路径
|
||||
* 获取菜单路径
|
||||
* @param {Object} menuInfo 菜单信息对象
|
||||
* @param {Object} parentMenu 父级菜单(可选)
|
||||
* @returns {string} 菜单路径
|
||||
* @private
|
||||
*/
|
||||
async getMenuPath(menuItem) {
|
||||
// 尝试获取父级菜单的文本
|
||||
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();
|
||||
return parentText ? `${parentText} > ${itemText}` : itemText;
|
||||
async getMenuPath(menuInfo, parentMenu = null) {
|
||||
return parentMenu ? `${parentMenu.text} > ${menuInfo.text}` : menuInfo.text;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -420,7 +407,7 @@ class LongiMainPage extends BasePage {
|
||||
const menuPath = this.getMenuPath(menuInfo, parentMenu);
|
||||
console.log(`点击菜单: ${menuPath}`);
|
||||
|
||||
if (!await this.safeClick(menuInfo.element, menuPath)) {
|
||||
if (!await this.safeClick(menuInfo.element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -430,18 +417,7 @@ class LongiMainPage extends BasePage {
|
||||
}
|
||||
|
||||
await this.handleAllTabs(menuInfo);
|
||||
await this.closeActiveTab(menuPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单路径
|
||||
* @param {Object} menuInfo 菜单信息对象
|
||||
* @param {Object} parentMenu 父级菜单(可选)
|
||||
* @returns {string} 菜单路径
|
||||
* @private
|
||||
*/
|
||||
getMenuPath(menuInfo, parentMenu = null) {
|
||||
return parentMenu ? `${parentMenu.text} > ${menuInfo.text}` : menuInfo.text;
|
||||
await this.closeActiveTab(menuInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -506,86 +482,25 @@ class LongiMainPage extends BasePage {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 等待页面加载完成,带重试机制
|
||||
* @param {Object} menu 菜单对象
|
||||
* @param {string} subMenuText 子菜单文本(可选)
|
||||
* @returns {Promise<boolean>} 页面是否加载成功
|
||||
*/
|
||||
async waitForPageLoadWithRetry(menu, subMenuText = '') {
|
||||
const pageName = this.getMenuPath(menu, {text: subMenuText});
|
||||
console.log(`等待页面 ${pageName} 数据加载...`);
|
||||
|
||||
let retryCount = 0;
|
||||
const {maxRetries, retryInterval, stabilityDelay} = this.config.pageLoad;
|
||||
|
||||
try {
|
||||
while (retryCount < maxRetries) {
|
||||
// 检查错误状态
|
||||
const hasError = await this.checkPageError(pageName);
|
||||
if (hasError) return false;
|
||||
|
||||
// 检查加载状态
|
||||
const isLoading = await this.elementExists(this.selectors.loadingMask);
|
||||
if (!isLoading) {
|
||||
await this.wait(stabilityDelay);
|
||||
console.log(`✅ 页面 ${pageName} 加载完成`);
|
||||
return true;
|
||||
}
|
||||
|
||||
retryCount++;
|
||||
await this.wait(retryInterval);
|
||||
}
|
||||
|
||||
console.error(`页面加载超时: ${pageName}, 重试次数: ${maxRetries}`);
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error(`页面加载出错: ${pageName}, 错误信息: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查页面是否有错误
|
||||
* @param {string} pageName 页面名称
|
||||
* @returns {Promise<boolean>} 是否有错误
|
||||
* @private
|
||||
*/
|
||||
async checkPageError(pageName) {
|
||||
const errorSelectors = [this.selectors.errorBox, this.selectors.errorMessage];
|
||||
|
||||
for (const selector of errorSelectors) {
|
||||
const elements = await this.page.locator(selector).all();
|
||||
if (elements.length > 0) {
|
||||
const errorText = await this.getElementText(elements[0]);
|
||||
console.error(`页面加载出现错误: ${pageName}, 错误信息: ${errorText}`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭当前活动的标签页
|
||||
* @param {string} pageName 页面名称,用于日志显示
|
||||
*/
|
||||
async closeActiveTab(pageName) {
|
||||
async closeActiveTab(parentMenu) {
|
||||
try {
|
||||
console.log(`🗑️ 正在关闭页面 "${pageName}" 的tab...`);
|
||||
console.log(`🗑️ 正在关闭页面 "${parentMenu.text}" 的tab...`);
|
||||
|
||||
const activeTab = this.page.locator(this.selectors.activeTab);
|
||||
const closeButton = activeTab.locator(this.selectors.closeButton);
|
||||
|
||||
if (await this.canCloseTab(activeTab, closeButton)) {
|
||||
await closeButton.waitFor({state: 'visible', timeout: 5000});
|
||||
await this.safeClick(closeButton, `${pageName}的关闭按钮`);
|
||||
await this.safeClick(closeButton);
|
||||
await this.wait(500);
|
||||
} else {
|
||||
console.log(`⚠️ [${pageName}] 没有找到可关闭的tab,继续执行...`);
|
||||
console.log(`⚠️ [${parentMenu.text}] 没有找到可关闭的tab,继续执行...`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`关闭标签页时出错 [${pageName}]:`, error.message);
|
||||
console.error(`关闭标签页时出错 [${parentMenu.text}]:`, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user