trail.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. import { global, clearEl, addEl, LANG } from './global.js';
  2. //试运行操作标记
  3. function trial(evt) {
  4. // if(global.justSend){ //如果是刚刚发送的消息到流程图,不处理
  5. // global.justSend = false;
  6. // return;
  7. // }
  8. let node = JSON.parse(evt["message"]["message"]["node"]);
  9. let parentNode = JSON.parse(evt["message"]["message"]["parentNode"]);
  10. let parameters = node.parameters;
  11. let type = evt["message"]["message"]["type"];
  12. // console.log("parameters", parameters);
  13. for (let node of global.markElements) {
  14. let element = node.element;
  15. element.style.boxShadow = "none";
  16. }
  17. // 删除所有class为highlight_of_easyspider的元素
  18. let elements = document.getElementsByClassName('highlight_of_easyspider');
  19. while (elements.length > 0) {
  20. elements[0].parentNode.removeChild(elements[0]);
  21. }
  22. global.markElements = [];
  23. if (type == 0) {
  24. let option = node.option;
  25. console.log("option", option);
  26. if (option == 2 || option == 4 || option == 6 || option == 7) {
  27. let xpath = parameters.xpath;
  28. if (parameters.useLoop && option != 4 && option != 6) {
  29. let parentXPath = parentNode.parameters.xpath;
  30. if (parentNode.parameters.loopType == 2) { //循环项列表
  31. parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
  32. }
  33. xpath = parentXPath + xpath;
  34. }
  35. let point = parameters.xpath;
  36. if (xpath.includes("point(")) {
  37. xpath = "//body";
  38. }
  39. let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  40. if (parameters.xpath.includes("point(")) {
  41. point = point.substring(6, point.length - 1).split(",");
  42. let x = parseInt(point[0]);
  43. let y = parseInt(point[1]);
  44. highlightAt(x, y);
  45. } else if (element != null) {
  46. clearEl(true);
  47. addEl(null, element);
  48. }
  49. // if (element != null) {
  50. // //移动到元素位置
  51. // element.scrollIntoView({block: "center", inline: "center"});
  52. // }
  53. } else if (option == 3) {
  54. let params = parameters.params; //所有的提取数据参数
  55. clearEl(true);
  56. for (let i = 0; i < params.length; i++) {
  57. let param = params[i];
  58. let xpath = param.relativeXPath;
  59. let parentXPaths = "";
  60. let xpaths = [];
  61. if (param.relative) {
  62. if (parentNode.parameters.loopType <= 1) {
  63. parentXPaths = [parentNode.parameters.xpath];
  64. } else if (parentNode.parameters.loopType == 2) { //循环项列表
  65. parentXPaths = parentNode.parameters.pathList.split("\n");
  66. }
  67. for (let j = 0; j < parentXPaths.length; j++) {
  68. let parentXPath = parentXPaths[j];
  69. let realXPath = parentXPath + xpath;
  70. xpaths.push(realXPath);
  71. }
  72. } else {
  73. xpaths.push(xpath);
  74. }
  75. for (let j = 0; j < xpaths.length; j++) {
  76. let xpath = xpaths[j];
  77. try {
  78. let elementList = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  79. console.log(xpath);
  80. for (let k = 0; k < elementList.snapshotLength; k++) {
  81. let element = elementList.snapshotItem(k);
  82. if (element != null) {
  83. global.markElements.push({
  84. "element": element, "bgColor": element.style.backgroundColor,
  85. "boxShadow": element.style.boxShadow
  86. });
  87. // element.style.backgroundColor = global.selectedColor;
  88. element.style.boxShadow = "0 0 0 1px #00a8ff";
  89. }
  90. }
  91. } catch (e) {
  92. console.log("跳过错误的xpath", xpath);
  93. }
  94. }
  95. }
  96. } else if (option == 11) {
  97. let params = parameters.params; //所有的提取数据参数
  98. let i = parameters.index;
  99. let param = params[i];
  100. let xpath = param.relativeXPath;
  101. if (param.relative) {
  102. let parentXPath = parentNode.parameters.xpath;
  103. if (parentNode.parameters.loopType == 2) {
  104. parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
  105. }
  106. xpath = parentXPath + xpath;
  107. }
  108. let elementList = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  109. clearEl(true);
  110. for (let j = 0; j < elementList.snapshotLength; j++) {
  111. let element = elementList.snapshotItem(j);
  112. if (element != null) {
  113. addEl(null, element);
  114. }
  115. }
  116. } else if (option == 8) {
  117. let loopType = parameters.loopType;
  118. if (loopType <= 2) {
  119. let xpath = "";
  120. if (loopType == 0) {
  121. xpath = parameters.xpath;
  122. let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  123. if (element != null) {
  124. clearEl(true);
  125. addEl(null, element);
  126. }
  127. } else if (loopType == 1) {
  128. let elementList = document.evaluate(parameters.xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  129. elementList.snapshotItem(0);
  130. // if (element != null) {
  131. // clearEl(true);
  132. // addEl(null, element);
  133. // if (elementList.snapshotLength > 1) {
  134. // selectAllElements();
  135. // }
  136. // }
  137. clearEl(true);
  138. for (let i = 0; i < elementList.snapshotLength; i++) {
  139. let element = elementList.snapshotItem(i);
  140. if (element != null) {
  141. addEl(null, element);
  142. }
  143. }
  144. } else if (loopType == 2) {
  145. clearEl(true);
  146. let pathList = parameters.pathList.split("\n");
  147. for (let i = 0; i < pathList.length; i++) {
  148. let path = pathList[i].trim();
  149. let element = document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  150. if (element != null) {
  151. addEl(null, element);
  152. }
  153. }
  154. }
  155. }
  156. } else if (option == 10) { //条件分支
  157. let condition = parameters.class;
  158. let result = 0;
  159. let additionalInfo = "";
  160. if (condition == 3 || condition == 4 || condition == 7) { //当前循环项判断时,选中当前循环项
  161. let xpath = parentNode.parameters.xpath;
  162. if (parentNode.parameters.loopType == 2) {
  163. let pathList = parentNode.parameters.pathList.split("\n")[0].trim();
  164. xpath = pathList;
  165. }
  166. let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  167. if (element != null) {
  168. clearEl(true);
  169. addEl(null, element);
  170. }
  171. }
  172. if (condition == 0) { //无条件
  173. result = 1;
  174. } else if (condition == 1) { //当前页面包含文本
  175. let value = parameters.value;
  176. let element = document.getElementsByTagName("body")[0];
  177. let bodyText = element.innerText;
  178. let outcome = bodyText.indexOf(value) >= 0;
  179. if (outcome) {
  180. result = 1;
  181. }
  182. } else if (condition == 2) { //当前页面包含元素,xpath
  183. let xpath = parameters.value;
  184. let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  185. if (element != null) {
  186. result = 1;
  187. }
  188. } else if (condition == 3) { //当前循环项包含文本,xpath
  189. let value = parameters.value;
  190. let parentXPath = parentNode.parameters.xpath;
  191. if (parentNode.parameters.loopType == 2) { //循环项列表
  192. parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
  193. }
  194. let element = document.evaluate(parentXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  195. if (element != null) {
  196. let elementText = element.innerText;
  197. let outcome = elementText.indexOf(value) >= 0;
  198. if (outcome) {
  199. result = 1;
  200. }
  201. }
  202. if (result == 0) {
  203. additionalInfo = LANG(",注意只会检索第一个匹配到的循环项", ", note that only the first matching loop item will be retrieved");
  204. }
  205. } else if (condition == 4) { //当前循环项包含元素,xpath
  206. let parentXPath = parentNode.parameters.xpath;
  207. if (parentNode.parameters.loopType == 2) { //循环项列表
  208. parentXPath = parentNode.parameters.pathList.split("\n")[0].trim();
  209. }
  210. let value = parameters.value;
  211. // full_path = "(" + parentPath + ")" + \
  212. // "[" + str(index + 1) + "]" + \
  213. // relativeXPath + content_type
  214. let xpath = "(" + parentXPath + ")" + "[" + "1" + "]" + value;
  215. let element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  216. if (element != null) {
  217. result = 1;
  218. }
  219. if (result == 0) {
  220. additionalInfo = LANG(",注意只会检索第一个匹配到的循环项", ", note that only the first matching loop item will be retrieved");
  221. }
  222. } else if (condition == 5 || condition == 7) { //从主程序传入的结果
  223. result = evt["message"]["message"]["result"];
  224. if (condition == 7 && result == 0) {
  225. additionalInfo = LANG(",注意只会检索第一个匹配到的循环项", ", note that only the first matching loop item will be retrieved");
  226. }
  227. } else {
  228. result = 2;
  229. }
  230. if (result == 0) {
  231. createNotification(LANG("当前页面下,条件分支“" + node.title + "”的条件未满足" + additionalInfo, "The condition of the conditional branch: " + node.title + " is not met on the current page" + additionalInfo), "warning");
  232. } else if (result == 1) {
  233. createNotification(LANG("当前页面下,条件分支“" + node.title + "”的条件已满足" + additionalInfo, "The condition of the conditional branch: " + node.title + " is met on the current page" + additionalInfo), "success");
  234. } else if (result == 2) {
  235. createNotification(LANG("不支持此条件判断类型的动态调试,请在任务正式运行阶段测试是否有效。", "Dynamic debugging of this condition judgment type is not supported. Please test whether it is valid in the formal call stage."), "info");
  236. }
  237. }
  238. }
  239. }
  240. function createNotification(text, type = "info") {
  241. // 创建通知元素
  242. let notification = document.createElement('div');
  243. notification.className = 'notification_of_easyspider'; // 使用 class 方便后续添加样式
  244. notification.setAttribute("data-timestamp", new Date().getTime()); // 用于清除通知
  245. // 设置通知文本
  246. notification.innerText = text;
  247. // 定义与添加样式
  248. let cssText = `
  249. position: fixed;
  250. bottom: 20px; /* 距底部20px */
  251. right: -320px; /* 初始位置在屏幕右侧,假设通知框宽度320px */
  252. min-width: 300px;
  253. padding: 10px 20px;
  254. color: white;
  255. z-index: 2147483641;
  256. border-radius: 4px;
  257. text-align: center;
  258. font-size: 15px;
  259. box-shadow: 0 2px 6px rgba(0,0,0,0.3);
  260. transition: right 0.5s ease-in-out; /* 动画效果 */
  261. `;
  262. notification.style.cssText = cssText;
  263. if (type === "success") {
  264. notification.style.backgroundColor = 'rgb(103, 194, 58)';
  265. } else if (type === "info") {
  266. notification.style.backgroundColor = '#00a8ff';
  267. } else if (type === "warning") {
  268. notification.style.backgroundColor = 'rgb(230, 162, 60)';
  269. } else if (type === "error") {
  270. notification.style.backgroundColor = '#ff6b6b';
  271. notification.style.bottom = '70px';
  272. }
  273. // 将通知添加到页面中
  274. document.body.appendChild(notification);
  275. // 触发动画,通知从右向左滑入
  276. setTimeout(function () {
  277. notification.style.right = '20px'; // 调整距离左边的位置
  278. }, 100);
  279. // let removeXPathText = text.split("是否正确:")[0].split("is correct:")[0];
  280. // let timeoutInterval = 1500 * removeXPathText.length / 5;
  281. let timeoutInterval = 1500 * text.length / 5;
  282. // 设置退出动画,通知从右向左滑出
  283. setTimeout(function () {
  284. notification.style.right = '-320px'; // 向左退出
  285. // 确定动画结束后移除通知
  286. notification.addEventListener('transitionend', function () {
  287. if (notification.parentNode === document.body) {
  288. document.body.removeChild(notification); // 避免移除已经不存在的元素
  289. }
  290. });
  291. }, timeoutInterval + 500); // 通知停留时间加上动画时间
  292. }
  293. function highlightAt(x, y) {
  294. // 创建一个新元素
  295. let element = document.createElement('div');
  296. element.className = 'highlight_of_easyspider'; // 使用 class 方便后续添加样式
  297. // 设置样式
  298. element.style.position = 'absolute';
  299. element.style.left = x + 'px';
  300. element.style.top = y + 'px';
  301. element.style.width = '10px'; // 你可以根据需要设置大小
  302. element.style.height = '10px';
  303. element.style.backgroundColor = 'blue'; // 高亮颜色
  304. element.style.zIndex = '999999999'; // 确保在最上层
  305. element.style.pointerEvents = 'none'; // 避免阻挡点击事件
  306. //圆形
  307. element.style.borderRadius = '50%';
  308. // 设置动画
  309. element.style.animation = 'blinkAnimation 2s infinite'; // 2秒一个周期的无限循环动画
  310. // element.style.border = '1px solid '; // 边框样式
  311. // 将元素添加到文档
  312. document.body.appendChild(element);
  313. }
  314. export { createNotification, trial };