在写auto.js很容易碰到的问题是查找控件的问题,往往是控件查找不到或查找到的点击失败,导致一连串的操作失败,这里出问题的往往是菜单是动态加载的,而查找的时候可能是页面并未加载完成,导致查找到的控件是加载过程中的,去点击的时候就会出错。为了解决这个问题,我的思路是第一次查找到后,等500毫秒再查找一次,如果两次的位置相同,那就可以判断是最终加载完成的控件,此时点击就不会失败。代码见下
/**
* 查找控件并执行指定动作。
* @param {object|string} selector - 控件选择器对象或包含文本的字符串。
* @param {number} timeout - 查找控件的超时时间(毫秒)。
* @param {string|object} action - 要执行的动作,可以是字符串或对象。
* @returns {boolean|object} - 返回查找到的控件,找不到返回false,如果有动作,返回操作是否成功的布尔值。
*/
function findControl(selector, timeout, action) {
log("进入findControl函数,参数selector, timeout, action分别为", selector.toString(), timeout, action);
timeout = typeof timeout === 'number' && timeout >= 2000 ? timeout : 3000;
if (timeout === 3000) log("超时时间被设置为默认值3000ms");
var element = null;
var startTime = Date.now();
var previousBounds = null;
// 同步查找控件
while (Date.now() - startTime < timeout) {
if (selector && typeof selector.findOne === 'function') {
element = selector.findOne(timeout);
} else if (typeof selector === 'string') {
element = textContains(selector).findOne(timeout);
} else if (typeof selector === 'object' && selector !== null) {
if (selector.className) {
element = className(selector.className).findOne(timeout);
} else if (selector.id) {
element = id(selector.id).findOne(timeout);
} else if (selector.text) {
element = text(selector.text).findOne(timeout);
}
} else {
log("错误:findControl 输入的selector参数不正确", selector.toString());
errCount++;
//handleError("输入的selector参数不正确" + selector.toString());
return false;
}
if (element !== null && previousBounds !== null && element.bounds().equals(previousBounds)) {
// 边界一致,说明加载完成,跳出循环
break;
}
if (element === null) {
sleep(500);
} else if (previousBounds !== null && !element.bounds().equals(previousBounds)) {
//log('提示:还真遇到了弹出式菜单未加载完成的情况,所以找到的控件是未加载完成的', previousBounds, element.bounds());
previousBounds = element.bounds();
sleep(500);
} else {
previousBounds = element.bounds();
sleep(500);
}
}
if (element === null) {
log("错误:查找控件超时,未找到控件。");
return false;
}
if (action) {
// 执行动作
return performAction(element, action);
} else {
return element;
}
}
/**
* 对找到的控件执行指定动作。
* @param {object} control - 找到的控件对象。
* @param {string|object} action - 要执行的动作。
* @returns {boolean} - 返回操作是否成功的布尔值。
*/
function performAction(control, action) {
log("进入performAction,执行动作:", JSON.stringify(action));
try {
if (action == 'click') {
//log("对控件采用点击操作");
if (control.clickable()) {
//log("找到控件并点击");
return (control.click());
} else {
//log("找到的控件不可点击,使用坐标点击");
return (click(control.bounds().centerX(), control.bounds().centerY()));
}
} else if (action == 'longclick') {
//log("对控件采用长按操作");
if (control.longClickable()) {
//log("找到控件并长按");
return (control.longClick());
} else {
//log("找到的控件不可长按,使用坐标长按");
return (longClick(control.bounds().centerX(), control.bounds().centerY()));
}
} else if (typeof action == 'object' && action !== null) {
if (typeof action.setText !== 'undefined') {
//log("执行setText动作,文本为:", action.setText);
// 执行setText动作的代码逻辑
if (control.setText(action.setText)) {
//log("setText动作执行成功。");
return true;
} else {
log("错误:setText动作执行失败。");
return false;
};
} else if (typeof action.input !== 'undefined') {
//log("执行input动作,文本为:", action.input);
// 执行input动作的代码逻辑
setClip(action.input);
// 找到可点击的父控件
let parent = control;
while (parent && !parent.clickable()) {
parent = parent.parent();
}
if (parent && parent.click()) {
sleep(500); // 等待输入框响应
// 尝试粘贴文本,这通常需要文本框已经获得焦点
paste();
//log("input动作已执行。");
return true;
} else {
log("错误:无法点击控件输入文本" + action.input + "或控件不存在。");
return false;
}
} else if (action.swipe && Array.isArray(action.swipe) && action.swipe.length === 5) {
//log("执行swipe动作,参数为:", action.swipe);
// 执行swipe动作的代码逻辑
if (swipe(action.swipe[0], action.swipe[1], action.swipe[2], action.swipe[3], action.swipe[4])) {
//log("swipe动作执行成功。");
return true;
} else {
log("错误:swipe动作执行失败。");
return false;
};
} else {
log("提示:未识别的动作参数:", JSON.stringify(action));
return false;
}
} else {
log("提示:没有传入动作参数,直接返回找到的控件");
return control;
}
} catch (error) {
errCount++;
log("错误:执行动作时发生错误: " + error.name + error.message + error.stack);
//handleError("错误:执行动作时发生错误: ", error);
return false;
}
}
以上代码在auto.js4.1.1版本中运行通过,没有遇到过异常。