mirror of
https://github.com/NaiboWang/EasySpider.git
synced 2026-10-16 21:13:18 +08:00
Change trail to trial, fix typo
This commit is contained in:
@@ -222,12 +222,12 @@ function addEl(e, node = global.NowNode, handle = true) {
|
||||
}
|
||||
|
||||
//清除选择项
|
||||
function clearEl(trail=false) {
|
||||
function clearEl(trial=false) {
|
||||
//如果最后停留的元素被选中,则调整此元素的style为原始style,否则不进行调整
|
||||
for (let node of global.nodeList) {
|
||||
node["node"].style.backgroundColor = node["bgColor"];
|
||||
node["node"].style.boxShadow = node["boxShadow"];
|
||||
if (global.NowNode == node["node"] && !trail) ;
|
||||
if (global.NowNode == node["node"] && !trial) ;
|
||||
}
|
||||
for (let node of global.markElements) {
|
||||
let element = node.element;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { global as global$1, addEl, clearEl, isInIframe, getElementXPaths, readXPath, handleElement, handleDescendents, clearParameters, generateParameters, clearReady, selectAllElements, LANG } from './global.js';
|
||||
import { collectSingle, collectMultiNoPattern, collectMultiWithPattern, sendSingleClick, sendChangeOption, sendMouseMove, sendLoopMouseMove, sendLoopClickSingle, sendLoopClickEvery, input } from './messageInteraction.js';
|
||||
import { createNotification } from './trail.js';
|
||||
import { createNotification } from './trial.js';
|
||||
|
||||
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { global, LANG, clearEl, readXPath, getElementXPaths } from './global.js';
|
||||
import { createNotification, trial } from './trail.js';
|
||||
import { createNotification, trial } from './trial.js';
|
||||
|
||||
//实现与后台和流程图部分的交互
|
||||
|
||||
|
||||
@@ -1,328 +0,0 @@
|
||||
import { global, clearEl, addEl, LANG } from './global.js';
|
||||
|
||||
//试运行操作标记
|
||||
function trial(evt) {
|
||||
// if(global.justSend){ //如果是刚刚发送的消息到流程图,不处理
|
||||
// global.justSend = false;
|
||||
// return;
|
||||
// }
|
||||
let node = JSON.parse(evt["message"]["message"]["node"]);
|
||||
let parentNode = JSON.parse(evt["message"]["message"]["parentNode"]);
|
||||
let parameters = node.parameters;
|
||||
let type = evt["message"]["message"]["type"];
|
||||
// console.log("parameters", parameters);
|
||||
for (let node of global.markElements) {
|
||||
let element = node.element;
|
||||
element.style.boxShadow = "none";
|
||||
}
|
||||
// 删除所有class为highlight_of_easyspider的元素
|
||||
let elements = document.getElementsByClassName('highlight_of_easyspider');
|
||||
while (elements.length > 0) {
|
||||
elements[0].parentNode.removeChild(elements[0]);
|
||||
}
|
||||
global.markElements = [];
|
||||
if (type == 0) {
|
||||
let option = node.option;
|
||||
console.log("option", option);
|
||||
if (option == 2 || option == 4 || option == 6 || option == 7) {
|
||||
let xpath = parameters.xpath;
|
||||
if (parameters.useLoop && option != 4 && option != 6) {
|
||||
let parentXPath = parentNode.parameters.xpath;
|
||||
if (parentNode.parameters.loopType == 2) { //循环项列表
|
||||
parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
|
||||
}
|
||||
xpath = parentXPath + xpath;
|
||||
}
|
||||
let point = parameters.xpath;
|
||||
if (xpath.includes("point(")) {
|
||||
xpath = "//body";
|
||||
}
|
||||
let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (parameters.xpath.includes("point(")) {
|
||||
point = point.substring(6, point.length - 1).split(",");
|
||||
let x = parseInt(point[0]);
|
||||
let y = parseInt(point[1]);
|
||||
highlightAt(x, y);
|
||||
} else if (element != null) {
|
||||
clearEl(true);
|
||||
addEl(null, element);
|
||||
}
|
||||
// if (element != null) {
|
||||
// //移动到元素位置
|
||||
// element.scrollIntoView({block: "center", inline: "center"});
|
||||
// }
|
||||
} else if (option == 3) {
|
||||
let params = parameters.params; //所有的提取数据参数
|
||||
clearEl(true);
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
let param = params[i];
|
||||
let xpath = param.relativeXPath;
|
||||
let parentXPaths = "";
|
||||
let xpaths = [];
|
||||
if (param.relative) {
|
||||
if (parentNode.parameters.loopType <= 1) {
|
||||
parentXPaths = [parentNode.parameters.xpath];
|
||||
} else if (parentNode.parameters.loopType == 2) { //循环项列表
|
||||
parentXPaths = parentNode.parameters.pathList.split("\n");
|
||||
}
|
||||
for (let j = 0; j < parentXPaths.length; j++) {
|
||||
let parentXPath = parentXPaths[j];
|
||||
let realXPath = parentXPath + xpath;
|
||||
xpaths.push(realXPath);
|
||||
}
|
||||
} else {
|
||||
xpaths.push(xpath);
|
||||
}
|
||||
for (let j = 0; j < xpaths.length; j++) {
|
||||
let xpath = xpaths[j];
|
||||
try {
|
||||
let elementList = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
console.log(xpath);
|
||||
for (let k = 0; k < elementList.snapshotLength; k++) {
|
||||
let element = elementList.snapshotItem(k);
|
||||
if (element != null) {
|
||||
global.markElements.push({
|
||||
"element": element, "bgColor": element.style.backgroundColor,
|
||||
"boxShadow": element.style.boxShadow
|
||||
});
|
||||
// element.style.backgroundColor = global.selectedColor;
|
||||
element.style.boxShadow = "0 0 0 1px #00a8ff";
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("跳过错误的xpath", xpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (option == 11) {
|
||||
let params = parameters.params; //所有的提取数据参数
|
||||
let i = parameters.index;
|
||||
let param = params[i];
|
||||
let xpath = param.relativeXPath;
|
||||
if (param.relative) {
|
||||
let parentXPath = parentNode.parameters.xpath;
|
||||
if (parentNode.parameters.loopType == 2) {
|
||||
parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
|
||||
}
|
||||
xpath = parentXPath + xpath;
|
||||
}
|
||||
let elementList = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
clearEl(true);
|
||||
for (let j = 0; j < elementList.snapshotLength; j++) {
|
||||
let element = elementList.snapshotItem(j);
|
||||
if (element != null) {
|
||||
addEl(null, element);
|
||||
}
|
||||
}
|
||||
} else if (option == 8) {
|
||||
let loopType = parameters.loopType;
|
||||
if (loopType <= 2) {
|
||||
let xpath = "";
|
||||
if (loopType == 0) {
|
||||
xpath = parameters.xpath;
|
||||
let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
clearEl(true);
|
||||
addEl(null, element);
|
||||
}
|
||||
} else if (loopType == 1) {
|
||||
let elementList = document.evaluate(parameters.xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
elementList.snapshotItem(0);
|
||||
// if (element != null) {
|
||||
// clearEl(true);
|
||||
// addEl(null, element);
|
||||
// if (elementList.snapshotLength > 1) {
|
||||
// selectAllElements();
|
||||
// }
|
||||
// }
|
||||
clearEl(true);
|
||||
for (let i = 0; i < elementList.snapshotLength; i++) {
|
||||
let element = elementList.snapshotItem(i);
|
||||
if (element != null) {
|
||||
addEl(null, element);
|
||||
}
|
||||
}
|
||||
} else if (loopType == 2) {
|
||||
clearEl(true);
|
||||
let pathList = parameters.pathList.split("\n");
|
||||
for (let i = 0; i < pathList.length; i++) {
|
||||
let path = pathList[i].trim();
|
||||
let element = document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
addEl(null, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (option == 10) { //条件分支
|
||||
let condition = parameters.class;
|
||||
let result = 0;
|
||||
let additionalInfo = "";
|
||||
if (condition == 3 || condition == 4 || condition == 7) { //当前循环项判断时,选中当前循环项
|
||||
let xpath = parentNode.parameters.xpath;
|
||||
if (parentNode.parameters.loopType == 2) {
|
||||
let pathList = parentNode.parameters.pathList.split("\n")[0].trim();
|
||||
xpath = pathList;
|
||||
}
|
||||
let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
clearEl(true);
|
||||
addEl(null, element);
|
||||
}
|
||||
}
|
||||
if (condition == 0) { //无条件
|
||||
result = 1;
|
||||
} else if (condition == 1) { //当前页面包含文本
|
||||
let value = parameters.value;
|
||||
let element = document.getElementsByTagName("body")[0];
|
||||
let bodyText = element.innerText;
|
||||
let outcome = bodyText.indexOf(value) >= 0;
|
||||
if (outcome) {
|
||||
result = 1;
|
||||
}
|
||||
} else if (condition == 2) { //当前页面包含元素,xpath
|
||||
let xpath = parameters.value;
|
||||
let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
result = 1;
|
||||
}
|
||||
} else if (condition == 3) { //当前循环项包含文本,xpath
|
||||
let value = parameters.value;
|
||||
let parentXPath = parentNode.parameters.xpath;
|
||||
if (parentNode.parameters.loopType == 2) { //循环项列表
|
||||
parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
|
||||
}
|
||||
let element = document.evaluate(parentXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
let elementText = element.innerText;
|
||||
let outcome = elementText.indexOf(value) >= 0;
|
||||
if (outcome) {
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
if (result == 0) {
|
||||
additionalInfo = LANG(",注意只会检索第一个匹配到的循环项", ", note that only the first matching loop item will be retrieved");
|
||||
}
|
||||
} else if (condition == 4) { //当前循环项包含元素,xpath
|
||||
let parentXPath = parentNode.parameters.xpath;
|
||||
if (parentNode.parameters.loopType == 2) { //循环项列表
|
||||
parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
|
||||
}
|
||||
let value = parameters.value;
|
||||
// full_path = "(" + parentPath + ")" + \
|
||||
// "[" + str(index + 1) + "]" + \
|
||||
// relativeXPath + content_type
|
||||
let xpath = "(" + parentXPath + ")" + "[" + "1" + "]" + value;
|
||||
let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
result = 1;
|
||||
}
|
||||
if (result == 0) {
|
||||
additionalInfo = LANG(",注意只会检索第一个匹配到的循环项", ", note that only the first matching loop item will be retrieved");
|
||||
}
|
||||
} else if (condition == 5 || condition == 7) { //从主程序传入的结果
|
||||
result = evt["message"]["message"]["result"];
|
||||
if (condition == 7 && result == 0) {
|
||||
additionalInfo = LANG(",注意只会检索第一个匹配到的循环项", ", note that only the first matching loop item will be retrieved");
|
||||
}
|
||||
} else {
|
||||
result = 2;
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
createNotification(LANG("当前页面下,条件分支“" + node.title + "”的条件未满足" + additionalInfo, "The condition of the conditional branch: " + node.title + " is not met on the current page" + additionalInfo), "warning");
|
||||
} else if (result == 1) {
|
||||
createNotification(LANG("当前页面下,条件分支“" + node.title + "”的条件已满足" + additionalInfo, "The condition of the conditional branch: " + node.title + " is met on the current page" + additionalInfo), "success");
|
||||
} else if (result == 2) {
|
||||
createNotification(LANG("不支持此条件判断类型的动态调试,请在任务正式运行阶段测试是否有效。", "Dynamic debugging of this condition judgment type is not supported. Please test whether it is valid in the formal call stage."), "info");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function createNotification(text, type = "info") {
|
||||
// 创建通知元素
|
||||
let notification = document.createElement('div');
|
||||
notification.className = 'notification_of_easyspider'; // 使用 class 方便后续添加样式
|
||||
notification.setAttribute("data-timestamp", new Date().getTime()); // 用于清除通知
|
||||
// 设置通知文本
|
||||
notification.innerText = text;
|
||||
|
||||
// 定义与添加样式
|
||||
let cssText = `
|
||||
position: fixed;
|
||||
bottom: 20px; /* 距底部20px */
|
||||
right: -320px; /* 初始位置在屏幕右侧,假设通知框宽度320px */
|
||||
min-width: 300px;
|
||||
padding: 10px 20px;
|
||||
color: white;
|
||||
z-index: 2147483641;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.3);
|
||||
transition: right 0.5s ease-in-out; /* 动画效果 */
|
||||
`;
|
||||
notification.style.cssText = cssText;
|
||||
|
||||
if (type === "success") {
|
||||
notification.style.backgroundColor = 'rgb(103, 194, 58)';
|
||||
} else if (type === "info") {
|
||||
notification.style.backgroundColor = '#00a8ff';
|
||||
} else if (type === "warning") {
|
||||
notification.style.backgroundColor = 'rgb(230, 162, 60)';
|
||||
} else if (type === "error") {
|
||||
notification.style.backgroundColor = '#ff6b6b';
|
||||
notification.style.bottom = '70px';
|
||||
}
|
||||
|
||||
// 将通知添加到页面中
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// 触发动画,通知从右向左滑入
|
||||
setTimeout(function () {
|
||||
notification.style.right = '20px'; // 调整距离左边的位置
|
||||
}, 100);
|
||||
// let removeXPathText = text.split("是否正确:")[0].split("is correct:")[0];
|
||||
// let timeoutInterval = 1500 * removeXPathText.length / 5;
|
||||
let timeoutInterval = 1500 * text.length / 5;
|
||||
// 设置退出动画,通知从右向左滑出
|
||||
setTimeout(function () {
|
||||
notification.style.right = '-320px'; // 向左退出
|
||||
// 确定动画结束后移除通知
|
||||
notification.addEventListener('transitionend', function () {
|
||||
if (notification.parentNode === document.body) {
|
||||
document.body.removeChild(notification); // 避免移除已经不存在的元素
|
||||
}
|
||||
});
|
||||
}, timeoutInterval + 500); // 通知停留时间加上动画时间
|
||||
}
|
||||
|
||||
function highlightAt(x, y) {
|
||||
// 创建一个新元素
|
||||
let element = document.createElement('div');
|
||||
|
||||
element.className = 'highlight_of_easyspider'; // 使用 class 方便后续添加样式
|
||||
|
||||
// 设置样式
|
||||
element.style.position = 'absolute';
|
||||
element.style.left = x + 'px';
|
||||
element.style.top = y + 'px';
|
||||
element.style.width = '10px'; // 你可以根据需要设置大小
|
||||
element.style.height = '10px';
|
||||
element.style.backgroundColor = 'blue'; // 高亮颜色
|
||||
element.style.zIndex = '999999999'; // 确保在最上层
|
||||
element.style.pointerEvents = 'none'; // 避免阻挡点击事件
|
||||
//圆形
|
||||
element.style.borderRadius = '50%';
|
||||
// 设置动画
|
||||
element.style.animation = 'blinkAnimation 2s infinite'; // 2秒一个周期的无限循环动画
|
||||
// element.style.border = '1px solid '; // 边框样式
|
||||
|
||||
// 将元素添加到文档
|
||||
document.body.appendChild(element);
|
||||
}
|
||||
|
||||
export { createNotification, trial };
|
||||
@@ -222,12 +222,12 @@ function addEl(e, node = global.NowNode, handle = true) {
|
||||
}
|
||||
|
||||
//清除选择项
|
||||
function clearEl(trail=false) {
|
||||
function clearEl(trial=false) {
|
||||
//如果最后停留的元素被选中,则调整此元素的style为原始style,否则不进行调整
|
||||
for (let node of global.nodeList) {
|
||||
node["node"].style.backgroundColor = node["bgColor"];
|
||||
node["node"].style.boxShadow = node["boxShadow"];
|
||||
if (global.NowNode == node["node"] && !trail) ;
|
||||
if (global.NowNode == node["node"] && !trial) ;
|
||||
}
|
||||
for (let node of global.markElements) {
|
||||
let element = node.element;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { global as global$1, addEl, clearEl, isInIframe, getElementXPaths, readXPath, handleElement, handleDescendents, clearParameters, generateParameters, clearReady, selectAllElements, LANG } from './global.js';
|
||||
import { collectSingle, collectMultiNoPattern, collectMultiWithPattern, sendSingleClick, sendChangeOption, sendMouseMove, sendLoopMouseMove, sendLoopClickSingle, sendLoopClickEvery, input } from './messageInteraction.js';
|
||||
import { createNotification } from './trail.js';
|
||||
import { createNotification } from './trial.js';
|
||||
|
||||
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { global, LANG, clearEl, readXPath, getElementXPaths } from './global.js';
|
||||
import { createNotification, trial } from './trail.js';
|
||||
import { createNotification, trial } from './trial.js';
|
||||
|
||||
//实现与后台和流程图部分的交互
|
||||
|
||||
|
||||
@@ -1,328 +0,0 @@
|
||||
import { global, clearEl, addEl, LANG } from './global.js';
|
||||
|
||||
//试运行操作标记
|
||||
function trial(evt) {
|
||||
// if(global.justSend){ //如果是刚刚发送的消息到流程图,不处理
|
||||
// global.justSend = false;
|
||||
// return;
|
||||
// }
|
||||
let node = JSON.parse(evt["message"]["message"]["node"]);
|
||||
let parentNode = JSON.parse(evt["message"]["message"]["parentNode"]);
|
||||
let parameters = node.parameters;
|
||||
let type = evt["message"]["message"]["type"];
|
||||
// console.log("parameters", parameters);
|
||||
for (let node of global.markElements) {
|
||||
let element = node.element;
|
||||
element.style.boxShadow = "none";
|
||||
}
|
||||
// 删除所有class为highlight_of_easyspider的元素
|
||||
let elements = document.getElementsByClassName('highlight_of_easyspider');
|
||||
while (elements.length > 0) {
|
||||
elements[0].parentNode.removeChild(elements[0]);
|
||||
}
|
||||
global.markElements = [];
|
||||
if (type == 0) {
|
||||
let option = node.option;
|
||||
console.log("option", option);
|
||||
if (option == 2 || option == 4 || option == 6 || option == 7) {
|
||||
let xpath = parameters.xpath;
|
||||
if (parameters.useLoop && option != 4 && option != 6) {
|
||||
let parentXPath = parentNode.parameters.xpath;
|
||||
if (parentNode.parameters.loopType == 2) { //循环项列表
|
||||
parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
|
||||
}
|
||||
xpath = parentXPath + xpath;
|
||||
}
|
||||
let point = parameters.xpath;
|
||||
if (xpath.includes("point(")) {
|
||||
xpath = "//body";
|
||||
}
|
||||
let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (parameters.xpath.includes("point(")) {
|
||||
point = point.substring(6, point.length - 1).split(",");
|
||||
let x = parseInt(point[0]);
|
||||
let y = parseInt(point[1]);
|
||||
highlightAt(x, y);
|
||||
} else if (element != null) {
|
||||
clearEl(true);
|
||||
addEl(null, element);
|
||||
}
|
||||
// if (element != null) {
|
||||
// //移动到元素位置
|
||||
// element.scrollIntoView({block: "center", inline: "center"});
|
||||
// }
|
||||
} else if (option == 3) {
|
||||
let params = parameters.params; //所有的提取数据参数
|
||||
clearEl(true);
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
let param = params[i];
|
||||
let xpath = param.relativeXPath;
|
||||
let parentXPaths = "";
|
||||
let xpaths = [];
|
||||
if (param.relative) {
|
||||
if (parentNode.parameters.loopType <= 1) {
|
||||
parentXPaths = [parentNode.parameters.xpath];
|
||||
} else if (parentNode.parameters.loopType == 2) { //循环项列表
|
||||
parentXPaths = parentNode.parameters.pathList.split("\n");
|
||||
}
|
||||
for (let j = 0; j < parentXPaths.length; j++) {
|
||||
let parentXPath = parentXPaths[j];
|
||||
let realXPath = parentXPath + xpath;
|
||||
xpaths.push(realXPath);
|
||||
}
|
||||
} else {
|
||||
xpaths.push(xpath);
|
||||
}
|
||||
for (let j = 0; j < xpaths.length; j++) {
|
||||
let xpath = xpaths[j];
|
||||
try {
|
||||
let elementList = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
console.log(xpath);
|
||||
for (let k = 0; k < elementList.snapshotLength; k++) {
|
||||
let element = elementList.snapshotItem(k);
|
||||
if (element != null) {
|
||||
global.markElements.push({
|
||||
"element": element, "bgColor": element.style.backgroundColor,
|
||||
"boxShadow": element.style.boxShadow
|
||||
});
|
||||
// element.style.backgroundColor = global.selectedColor;
|
||||
element.style.boxShadow = "0 0 0 1px #00a8ff";
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("跳过错误的xpath", xpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (option == 11) {
|
||||
let params = parameters.params; //所有的提取数据参数
|
||||
let i = parameters.index;
|
||||
let param = params[i];
|
||||
let xpath = param.relativeXPath;
|
||||
if (param.relative) {
|
||||
let parentXPath = parentNode.parameters.xpath;
|
||||
if (parentNode.parameters.loopType == 2) {
|
||||
parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
|
||||
}
|
||||
xpath = parentXPath + xpath;
|
||||
}
|
||||
let elementList = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
clearEl(true);
|
||||
for (let j = 0; j < elementList.snapshotLength; j++) {
|
||||
let element = elementList.snapshotItem(j);
|
||||
if (element != null) {
|
||||
addEl(null, element);
|
||||
}
|
||||
}
|
||||
} else if (option == 8) {
|
||||
let loopType = parameters.loopType;
|
||||
if (loopType <= 2) {
|
||||
let xpath = "";
|
||||
if (loopType == 0) {
|
||||
xpath = parameters.xpath;
|
||||
let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
clearEl(true);
|
||||
addEl(null, element);
|
||||
}
|
||||
} else if (loopType == 1) {
|
||||
let elementList = document.evaluate(parameters.xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
elementList.snapshotItem(0);
|
||||
// if (element != null) {
|
||||
// clearEl(true);
|
||||
// addEl(null, element);
|
||||
// if (elementList.snapshotLength > 1) {
|
||||
// selectAllElements();
|
||||
// }
|
||||
// }
|
||||
clearEl(true);
|
||||
for (let i = 0; i < elementList.snapshotLength; i++) {
|
||||
let element = elementList.snapshotItem(i);
|
||||
if (element != null) {
|
||||
addEl(null, element);
|
||||
}
|
||||
}
|
||||
} else if (loopType == 2) {
|
||||
clearEl(true);
|
||||
let pathList = parameters.pathList.split("\n");
|
||||
for (let i = 0; i < pathList.length; i++) {
|
||||
let path = pathList[i].trim();
|
||||
let element = document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
addEl(null, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (option == 10) { //条件分支
|
||||
let condition = parameters.class;
|
||||
let result = 0;
|
||||
let additionalInfo = "";
|
||||
if (condition == 3 || condition == 4 || condition == 7) { //当前循环项判断时,选中当前循环项
|
||||
let xpath = parentNode.parameters.xpath;
|
||||
if (parentNode.parameters.loopType == 2) {
|
||||
let pathList = parentNode.parameters.pathList.split("\n")[0].trim();
|
||||
xpath = pathList;
|
||||
}
|
||||
let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
clearEl(true);
|
||||
addEl(null, element);
|
||||
}
|
||||
}
|
||||
if (condition == 0) { //无条件
|
||||
result = 1;
|
||||
} else if (condition == 1) { //当前页面包含文本
|
||||
let value = parameters.value;
|
||||
let element = document.getElementsByTagName("body")[0];
|
||||
let bodyText = element.innerText;
|
||||
let outcome = bodyText.indexOf(value) >= 0;
|
||||
if (outcome) {
|
||||
result = 1;
|
||||
}
|
||||
} else if (condition == 2) { //当前页面包含元素,xpath
|
||||
let xpath = parameters.value;
|
||||
let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
result = 1;
|
||||
}
|
||||
} else if (condition == 3) { //当前循环项包含文本,xpath
|
||||
let value = parameters.value;
|
||||
let parentXPath = parentNode.parameters.xpath;
|
||||
if (parentNode.parameters.loopType == 2) { //循环项列表
|
||||
parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
|
||||
}
|
||||
let element = document.evaluate(parentXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
let elementText = element.innerText;
|
||||
let outcome = elementText.indexOf(value) >= 0;
|
||||
if (outcome) {
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
if (result == 0) {
|
||||
additionalInfo = LANG(",注意只会检索第一个匹配到的循环项", ", note that only the first matching loop item will be retrieved");
|
||||
}
|
||||
} else if (condition == 4) { //当前循环项包含元素,xpath
|
||||
let parentXPath = parentNode.parameters.xpath;
|
||||
if (parentNode.parameters.loopType == 2) { //循环项列表
|
||||
parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
|
||||
}
|
||||
let value = parameters.value;
|
||||
// full_path = "(" + parentPath + ")" + \
|
||||
// "[" + str(index + 1) + "]" + \
|
||||
// relativeXPath + content_type
|
||||
let xpath = "(" + parentXPath + ")" + "[" + "1" + "]" + value;
|
||||
let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
||||
if (element != null) {
|
||||
result = 1;
|
||||
}
|
||||
if (result == 0) {
|
||||
additionalInfo = LANG(",注意只会检索第一个匹配到的循环项", ", note that only the first matching loop item will be retrieved");
|
||||
}
|
||||
} else if (condition == 5 || condition == 7) { //从主程序传入的结果
|
||||
result = evt["message"]["message"]["result"];
|
||||
if (condition == 7 && result == 0) {
|
||||
additionalInfo = LANG(",注意只会检索第一个匹配到的循环项", ", note that only the first matching loop item will be retrieved");
|
||||
}
|
||||
} else {
|
||||
result = 2;
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
createNotification(LANG("当前页面下,条件分支“" + node.title + "”的条件未满足" + additionalInfo, "The condition of the conditional branch: " + node.title + " is not met on the current page" + additionalInfo), "warning");
|
||||
} else if (result == 1) {
|
||||
createNotification(LANG("当前页面下,条件分支“" + node.title + "”的条件已满足" + additionalInfo, "The condition of the conditional branch: " + node.title + " is met on the current page" + additionalInfo), "success");
|
||||
} else if (result == 2) {
|
||||
createNotification(LANG("不支持此条件判断类型的动态调试,请在任务正式运行阶段测试是否有效。", "Dynamic debugging of this condition judgment type is not supported. Please test whether it is valid in the formal call stage."), "info");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function createNotification(text, type = "info") {
|
||||
// 创建通知元素
|
||||
let notification = document.createElement('div');
|
||||
notification.className = 'notification_of_easyspider'; // 使用 class 方便后续添加样式
|
||||
notification.setAttribute("data-timestamp", new Date().getTime()); // 用于清除通知
|
||||
// 设置通知文本
|
||||
notification.innerText = text;
|
||||
|
||||
// 定义与添加样式
|
||||
let cssText = `
|
||||
position: fixed;
|
||||
bottom: 20px; /* 距底部20px */
|
||||
right: -320px; /* 初始位置在屏幕右侧,假设通知框宽度320px */
|
||||
min-width: 300px;
|
||||
padding: 10px 20px;
|
||||
color: white;
|
||||
z-index: 2147483641;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.3);
|
||||
transition: right 0.5s ease-in-out; /* 动画效果 */
|
||||
`;
|
||||
notification.style.cssText = cssText;
|
||||
|
||||
if (type === "success") {
|
||||
notification.style.backgroundColor = 'rgb(103, 194, 58)';
|
||||
} else if (type === "info") {
|
||||
notification.style.backgroundColor = '#00a8ff';
|
||||
} else if (type === "warning") {
|
||||
notification.style.backgroundColor = 'rgb(230, 162, 60)';
|
||||
} else if (type === "error") {
|
||||
notification.style.backgroundColor = '#ff6b6b';
|
||||
notification.style.bottom = '70px';
|
||||
}
|
||||
|
||||
// 将通知添加到页面中
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// 触发动画,通知从右向左滑入
|
||||
setTimeout(function () {
|
||||
notification.style.right = '20px'; // 调整距离左边的位置
|
||||
}, 100);
|
||||
// let removeXPathText = text.split("是否正确:")[0].split("is correct:")[0];
|
||||
// let timeoutInterval = 1500 * removeXPathText.length / 5;
|
||||
let timeoutInterval = 1500 * text.length / 5;
|
||||
// 设置退出动画,通知从右向左滑出
|
||||
setTimeout(function () {
|
||||
notification.style.right = '-320px'; // 向左退出
|
||||
// 确定动画结束后移除通知
|
||||
notification.addEventListener('transitionend', function () {
|
||||
if (notification.parentNode === document.body) {
|
||||
document.body.removeChild(notification); // 避免移除已经不存在的元素
|
||||
}
|
||||
});
|
||||
}, timeoutInterval + 500); // 通知停留时间加上动画时间
|
||||
}
|
||||
|
||||
function highlightAt(x, y) {
|
||||
// 创建一个新元素
|
||||
let element = document.createElement('div');
|
||||
|
||||
element.className = 'highlight_of_easyspider'; // 使用 class 方便后续添加样式
|
||||
|
||||
// 设置样式
|
||||
element.style.position = 'absolute';
|
||||
element.style.left = x + 'px';
|
||||
element.style.top = y + 'px';
|
||||
element.style.width = '10px'; // 你可以根据需要设置大小
|
||||
element.style.height = '10px';
|
||||
element.style.backgroundColor = 'blue'; // 高亮颜色
|
||||
element.style.zIndex = '999999999'; // 确保在最上层
|
||||
element.style.pointerEvents = 'none'; // 避免阻挡点击事件
|
||||
//圆形
|
||||
element.style.borderRadius = '50%';
|
||||
// 设置动画
|
||||
element.style.animation = 'blinkAnimation 2s infinite'; // 2秒一个周期的无限循环动画
|
||||
// element.style.border = '1px solid '; // 边框样式
|
||||
|
||||
// 将元素添加到文档
|
||||
document.body.appendChild(element);
|
||||
}
|
||||
|
||||
export { createNotification, trial };
|
||||
@@ -244,7 +244,7 @@
|
||||
<p><button type="button" data-toggle="modal" data-target="#myModal_XPath" @click="changeXPaths(params.parameters[paraIndex]['allXPaths'])" class="btn btn-primary" style="margin-top: 10px">Click here to view other equivalent XPath expressions</button></p>
|
||||
<label>Final XPath of this field when the task is running:</label>
|
||||
<textarea spellcheck="false" onkeydown="inputDelete(event)" class="form-control" rows="2" readonly style="background:ghostwhite">{{getFinalXPath(params.parameters[paraIndex]['relativeXPath'], params.parameters[paraIndex]['relative'])}}</textarea>
|
||||
<div style="margin-top: 10px"><a href="#" v-on:mousedown="trailParam(paraIndex)" style="text-decoration: none">Trail Run (only test the first matched element)</a></div>
|
||||
<div style="margin-top: 10px"><a href="#" v-on:mousedown="trialParam(paraIndex)" style="text-decoration: none">Trial Run (only test the first matched element)</a></div>
|
||||
<p style="margin-top: 10px">
|
||||
<a class="btn btn-primary" data-toggle="collapse" href="#elementAdvanced" role="button" aria-expanded="false" aria-controls="collapseExample">
|
||||
Click here to expand/collapse advanced operations
|
||||
|
||||
@@ -337,13 +337,13 @@ let app = new Vue({
|
||||
let clone_node = DeepClone(this.nowNode);
|
||||
clone_node.option = 11; //单独的提取数据参数节点
|
||||
clone_node.parameters.index = i;
|
||||
trailElement(clone_node, 0);
|
||||
trialElement(clone_node, 0);
|
||||
},
|
||||
trailParam: function (i) { //试运行第i个参数
|
||||
trialParam: function (i) { //试运行第i个参数
|
||||
let clone_node = DeepClone(this.nowNode);
|
||||
clone_node.option = 11; //单独的提取数据参数节点
|
||||
clone_node.parameters.index = i;
|
||||
trailElement(clone_node, 1);
|
||||
trialElement(clone_node, 1);
|
||||
},
|
||||
deleteParam: function (i) { //删除第i个参数
|
||||
this.nowNode["parameters"]["params"].splice(i, 1);
|
||||
@@ -485,7 +485,7 @@ function operationChange(e, theNode) {
|
||||
theNode.style.borderColor = "blue";
|
||||
handleElement(); //处理元素
|
||||
if (debuggable && e.button == 0) {
|
||||
trailElement(app._data.nowNode, 0);
|
||||
trialElement(app._data.nowNode, 0);
|
||||
} else {
|
||||
debuggable = true;
|
||||
}
|
||||
@@ -517,7 +517,7 @@ function elementDblClick(e) {
|
||||
if (nodeType == 5 && (app._data.nowNode["parameters"]["codeMode"] != 0 && app._data.nowNode["parameters"]["codeMode"] != 2 && app._data.nowNode["parameters"]["codeMode"] != 8)) {
|
||||
showInfo(LANG("试运行自定义操作功能只适用于执行JavaScript和刷新页面操作。", "The trial run custom action function is only applicable to run JavaScript and refresh page operations."));
|
||||
} else {
|
||||
trailElement(app._data.nowNode, 1);
|
||||
trialElement(app._data.nowNode, 1);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
<p><button type="button" data-toggle="modal" data-target="#myModal_XPath" @click="changeXPaths(params.parameters[paraIndex]['allXPaths'])" class="btn btn-primary" style="margin-top: 10px">点此查看其他等价的XPath</button></p>
|
||||
<label>任务运行时最终定位的本字段XPath:</label>
|
||||
<textarea spellcheck=false onkeydown="inputDelete(event)" class="form-control" rows="2" readonly style="background:ghostwhite">{{getFinalXPath(params.parameters[paraIndex]['relativeXPath'], params.parameters[paraIndex]['relative'])}}</textarea>
|
||||
<div style="margin-top: 10px"><a href="#" v-on:mousedown="trailParam(paraIndex)" style="text-decoration: none">试运行(只测试第一个匹配到的元素)</a></div>
|
||||
<div style="margin-top: 10px"><a href="#" v-on:mousedown="trialParam(paraIndex)" style="text-decoration: none">试运行(只测试第一个匹配到的元素)</a></div>
|
||||
<p style="margin-top: 10px">
|
||||
<a class="btn btn-primary" data-toggle="collapse" href="#elementAdvanced" role="button" aria-expanded="false" aria-controls="collapseExample">
|
||||
点此展开/折叠自定义操作
|
||||
|
||||
@@ -213,7 +213,7 @@ function updateParentNode() {
|
||||
app._data.parentNode = parentNode;
|
||||
}
|
||||
|
||||
function trailElement(node, type = 1) {
|
||||
function trialElement(node, type = 1) {
|
||||
// type=0代表标记节点,type=1代表试运行
|
||||
// let parentNode = nodeList[actionSequence[node["parentId"]]];
|
||||
// if (node.option == 10) { //条件分支的话,传父元素的父元素
|
||||
|
||||
@@ -220,12 +220,12 @@ export function addEl(e, node = global.NowNode, handle = true) {
|
||||
}
|
||||
|
||||
//清除选择项
|
||||
export function clearEl(trail=false) {
|
||||
export function clearEl(trial=false) {
|
||||
//如果最后停留的元素被选中,则调整此元素的style为原始style,否则不进行调整
|
||||
for (let node of global.nodeList) {
|
||||
node["node"].style.backgroundColor = node["bgColor"];
|
||||
node["node"].style.boxShadow = node["boxShadow"];
|
||||
if (global.NowNode == node["node"] && !trail) {
|
||||
if (global.NowNode == node["node"] && !trial) {
|
||||
// global.style = node["bgColor"];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
} from "./global.js";
|
||||
import ToolKit from "./toolkit.vue";
|
||||
import iframe from "./iframe.vue";
|
||||
import {createNotification} from './trail.js';
|
||||
import {createNotification} from './trial.js';
|
||||
|
||||
//表现逻辑层的处理
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//实现与后台和流程图部分的交互
|
||||
|
||||
import {getElementXPaths, global, readXPath, isInIframe, clearEl, LANG} from "./global.js";
|
||||
import {trial, createNotification} from "./trail.js";
|
||||
import {trial, createNotification} from "./trial.js";
|
||||
|
||||
global.ws = new WebSocket("ws://localhost:8084");
|
||||
global.ws.onopen = function () {
|
||||
|
||||
Reference in New Issue
Block a user