Переглянути джерело

选中子元素增加多种模式,且可删除字段,删除后页面将更新标记

pull/73/head
naibo 1 рік тому
джерело
коміт
a666797bdf
5 змінених файлів з 467 додано та 201 видалено
  1. +1
    -1
      Extension/manifest_v3/src/content-scripts/config.json
  2. +354
    -138
      Extension/manifest_v3/src/content-scripts/global.js
  3. +92
    -59
      Extension/manifest_v3/src/content-scripts/toolkit.vue
  4. +19
    -2
      Extension/manifest_v3/src/style/toolkit.css
  5. +1
    -1
      Readme.md

+ 1
- 1
Extension/manifest_v3/src/content-scripts/config.json Переглянути файл

@ -1 +1 @@
{"language":"zh"}
{"language":"en"}

+ 354
- 138
Extension/manifest_v3/src/content-scripts/global.js Переглянути файл

@ -65,7 +65,7 @@ export function readXPath(element, type = 1, node = document.body) {
if (element.className != ""){ //如果有class且某个class name只有一个元素,则使用class name生成xpath
console.log("class name: " + element.className);
let names = element.className.split(" ");
for (var i = 0; i < names.length; i++) {
for (let i = 0; i < names.length; i++) {
if (names[i] != "") {
// return '//*[@class=\"' + names[i] + '\"]';
console.log('//*[@contains(@class, \"' + names[i] + '\")]');
@ -86,11 +86,11 @@ export function readXPath(element, type = 1, node = document.body) {
return "";
}
}
var ix = 1, //在nodelist中的位置,且每次点击初始化
let ix = 1, //在nodelist中的位置,且每次点击初始化
siblings = element.parentNode.childNodes; //同级的子元素
for (var i = 0, l = siblings.length; i < l; i++) {
var sibling = siblings[i];
for (let i = 0, l = siblings.length; i < l; i++) {
let sibling = siblings[i];
//如果这个元素是siblings数组中的元素,则执行递归操作;arguments.callee代表当前函数的名称
if (sibling == element) {
return readXPath(element.parentNode, type, node) + '/' + element.tagName.toLowerCase() + '[' + (ix) + ']';
@ -143,7 +143,7 @@ export function addEl() {
handleElement(); //处理新状态
//将虚线框显示在元素上方但屏蔽其鼠标操作
var pos = global.NowNode.getBoundingClientRect();
let pos = global.NowNode.getBoundingClientRect();
global.div.style.display = "block";
global.div.style.height = global.NowNode.offsetHeight + "px";
global.div.style.width = global.NowNode.offsetWidth + "px";
@ -278,7 +278,10 @@ export function generateParameters(type, linktext = true, linkhref = true) {
let nd = global.nodeList[num]["node"];
ndPath = global.nodeList[num]["xpath"];
ndAllXPaths = global.nodeList[num]["allXPaths"];
global.outputParameterNodes.push({ "node": nd, "boxShadow": nd.style.boxShadow == "" || global.boxShadowColor ? "none" : nd.style.boxShadow });
let unique_index = Math.random().toString(36).substring(2) + Date.now().toString(36);; //唯一标识符
global.outputParameterNodes.push({ "node": nd,
"unique_index": unique_index,
"boxShadow": nd.style.boxShadow == "" || global.boxShadowColor ? "none" : nd.style.boxShadow });
nd.style.boxShadow = global.boxShadowColor;
let pname = parameterName("文本");
let ndText = "";
@ -296,7 +299,7 @@ export function generateParameters(type, linktext = true, linkhref = true) {
// ndText = $(nd).contents().filter(function() { return this.nodeType === 3; }).text().replace(/\s+/g, '');
ndText = "";
let ndContents = nd.childNodes;
for (var i = 0; i < ndContents.length; i++) {
for (let i = 0; i < ndContents.length; i++) {
if (ndContents[i].nodeType === 3) { // if it's a text node
ndText += ndContents[i].textContent.trim(); // add its content to the string
}
@ -344,7 +347,8 @@ export function generateParameters(type, linktext = true, linkhref = true) {
"extractType": 0, //提取方式 0 普通 1 OCR
"relativeXPath": global.nodeList.length > 1 ? "" : ndPath,
"allXPaths": global.nodeList.length > 1 ? "" : ndAllXPaths,
"exampleValues": [{ "num": num, "value": ndText }]
"exampleValues": [{ "num": num, "value": ndText }],
"unique_index": unique_index,
});
} else if (nd.tagName == "A") { //如果元素是超链接
if (linktext) {
@ -357,7 +361,8 @@ export function generateParameters(type, linktext = true, linkhref = true) {
"extractType": 0, //提取方式 0 普通 1 OCR
"relativeXPath": global.nodeList.length > 1 ? "" : ndPath,
"allXPaths": global.nodeList.length > 1 ? "" : ndAllXPaths,
"exampleValues": [{ "num": num, "value": ndText }]
"exampleValues": [{ "num": num, "value": ndText }],
"unique_index": unique_index,
});
}
if (linkhref) {
@ -369,7 +374,8 @@ export function generateParameters(type, linktext = true, linkhref = true) {
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? "" : ndPath,
"allXPaths": global.nodeList.length > 1 ? "" : ndAllXPaths,
"exampleValues": [{ "num": num, "value": nd.getAttribute("href") == null ? "" : nd.getAttribute("href") }]
"exampleValues": [{ "num": num, "value": nd.getAttribute("href") == null ? "" : nd.getAttribute("href") }],
"unique_index": unique_index,
});
}
} else if (nd.tagName == "INPUT") { //如果元素是输入项
@ -382,7 +388,8 @@ export function generateParameters(type, linktext = true, linkhref = true) {
"extractType": 0, //提取方式 0 普通 1 OCR
"relativeXPath": global.nodeList.length > 1 ? "" : ndPath,
"allXPaths": global.nodeList.length > 1 ? "" : ndAllXPaths,
"exampleValues": [{ "num": num, "value": ndText }]
"exampleValues": [{ "num": num, "value": ndText }],
"unique_index": unique_index,
});
} else { //其他所有情况
global.outputParameters.push({
@ -394,7 +401,8 @@ export function generateParameters(type, linktext = true, linkhref = true) {
"extractType": 0, //提取方式 0 普通 1 OCR
"relativeXPath": global.nodeList.length > 1 ? "" : ndPath,
"allXPaths": global.nodeList.length > 1 ? "" : ndAllXPaths,
"exampleValues": [{ "num": num, "value": ndText }]
"exampleValues": [{ "num": num, "value": ndText }],
"unique_index": unique_index,
});
}
} else { //如果元素节点已经存在,则只需要插入值就可以了
@ -432,7 +440,8 @@ export function generateMultiParameters() {
let nd = global.nodeList[num]["node"];
ndPath = global.nodeList[num]["xpath"];
ndAllXPaths = global.nodeList[num]["allXPaths"];
global.outputParameterNodes.push({ "node": nd, "boxShadow": nd.style.boxShadow == "" || global.boxShadowColor ? "none" : nd.style.boxShadow });
let unique_index = Math.random().toString(36).substring(2) + Date.now().toString(36);;
global.outputParameterNodes.push({ "node": nd, "unique_index": unique_index, "boxShadow": nd.style.boxShadow == "" || global.boxShadowColor ? "none" : nd.style.boxShadow });
nd.style.boxShadow = global.boxShadowColor;
// ndText = $(nd).text();
ndText = nd.textContent;
@ -445,7 +454,8 @@ export function generateMultiParameters() {
"desc": "", //参数描述
"relativeXPath": ndPath,
"allXPaths": ndAllXPaths,
"exampleValues": [{ "num": 0, "value": nd.getAttribute("src") == null ? "" : nd.getAttribute("src") }]
"exampleValues": [{ "num": 0, "value": nd.getAttribute("src") == null ? "" : nd.getAttribute("src") }],
"unique_index": unique_index,
});
} else if (nd.tagName == "A") { //如果元素是超链接
global.outputParameters.push({
@ -456,7 +466,8 @@ export function generateMultiParameters() {
"desc": "", //参数描述
"relativeXPath": ndPath,
"allXPaths": ndAllXPaths,
"exampleValues": [{ "num": 0, "value": ndText }]
"exampleValues": [{ "num": 0, "value": ndText }],
"unique_index": unique_index,
});
global.outputParameters.push({
"nodeType": 2,
@ -466,7 +477,8 @@ export function generateMultiParameters() {
"desc": "", //参数描述
"relativeXPath": ndPath,
"allXPaths": ndAllXPaths,
"exampleValues": [{ "num": 0, "value": nd.getAttribute("href") == null ? "" : nd.getAttribute("href") }]
"exampleValues": [{ "num": 0, "value": nd.getAttribute("href") == null ? "" : nd.getAttribute("href") }],
"unique_index": unique_index,
});
} else if (nd.tagName == "INPUT") { //如果元素是输入项
global.outputParameters.push({
@ -477,7 +489,8 @@ export function generateMultiParameters() {
"desc": "", //参数描述
"relativeXPath": ndPath,
"allXPaths": ndAllXPaths,
"exampleValues": [{ "num": 0, "value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value") }]
"exampleValues": [{ "num": 0, "value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value") }],
"unique_index": unique_index,
});
} else { //其他所有情况
global.outputParameters.push({
@ -488,7 +501,8 @@ export function generateMultiParameters() {
"desc": "", //参数描述
"relativeXPath": ndPath,
"allXPaths": ndAllXPaths,
"exampleValues": [{ "num": 0, "value": ndText }]
"exampleValues": [{ "num": 0, "value": ndText }],
"unique_index": unique_index,
});
}
}
@ -501,141 +515,342 @@ export function generateMultiParameters() {
}
//处理子元素,对于每个块中多出的特殊元素,需要特殊处理
export function handleDescendents() {
export function handleDescendents(mode = 0) {
let n = 1;
chrome.storage.local.get({ parameterNum: 1 }, function(items) {
let at = parseInt(new Date().getTime());
n = items.parameterNum;
clearParameters(); //清除原来的参数列表
global.app._data.selectedDescendents = true;
let nd, ndText, ndPath, pname, ndAllPaths;
for (let num = 0; num < global.nodeList.length; num++) {
let tnode = global.nodeList[num]["node"];
let stack = new Array(); //深度优先搜索遍历元素
stack.push(tnode); //从此节点开始
while (stack.length > 0) {
let nd = stack.pop(); // 挨个取出元素
if (nd.parentNode.tagName == "A" && nd.tagName == "SPAN") {
continue; //对A标签内的SPAN元素不进行处理,剪枝,此时子元素根本不加入stack,即实现了此功能
}
ndPath = readXPath(nd, 1, tnode);
ndAllPaths = getElementXPaths(nd, tnode);
let index = -1;
for (let i = 0; i < global.outputParameters.length; i++) {
if (global.outputParameters[i]["relativeXPath"] == ndPath) {
index = i;
break;
let nd, ndText, ndPath, pname, ndAllPaths, tmode;
tmode = mode;
if(mode == 2){
let xpath_list = [];
// mode == 1; //如果是选中全部块的共有子元素,则先选中和第一个块相同的子元素,然后最后再删除第一个块中和其他块不同的子元素
for (let num = 0; num < global.nodeList.length; num++) {
let node_xpaths = [];
let tnode = global.nodeList[num]["node"];
let stack = new Array(); //深度优先搜索遍历元素
stack.push(tnode); //从此节点开始
while (stack.length > 0) {
let nd = stack.pop(); // 挨个取出元素
if (nd.parentNode.tagName == "A" && nd.tagName == "SPAN") {
continue; //对A标签内的SPAN元素不进行处理,剪枝,此时子元素根本不加入stack,即实现了此功能
}
ndPath = readXPath(nd, 1, tnode);
node_xpaths.push(ndPath);
for (let i = nd.children.length - 1; i >= 0; i--) {
stack.push(nd.children[i]);
}
}
global.outputParameterNodes.push({
"node": nd,
"boxShadow": nd.style.boxShadow == "" || global.boxShadowColor ? "none" : nd.style.boxShadow
});
nd.style.boxShadow = global.boxShadowColor;
// ndText = $(nd).contents().filter(function() {
// return this.nodeType === 3;
// }).text().replace(/\s+/g, '');
ndText = "";
let ndContents = nd.childNodes;
for (var i = 0; i < ndContents.length; i++) {
if (ndContents[i].nodeType === 3) { // if it's a text node
ndText += ndContents[i].textContent.trim(); // add its content to the string
xpath_list.push(node_xpaths);
}
// 取第一个子数组作为初始的共有元素集合
let commonXPaths = new Set(xpath_list[0]);
// 遍历剩余的子数组
for (let i = 1; i < xpath_list.length; i++) {
// 使用过滤函数来筛选出与共有元素集合中的元素相同的元素
commonXPaths = new Set(xpath_list[i].filter(element => commonXPaths.has(element)));
}
// 将共有元素集合转换为数组
let commonXPathList = Array.from(commonXPaths);
console.log(commonXPathList);
let hash = {}; //记录index和数组位置的对应关系
for (let num = 0; num < global.nodeList.length; num++) {
let tnode = global.nodeList[num]["node"];
let stack = new Array(); //深度优先搜索遍历元素
stack.push(tnode); //从此节点开始
while (stack.length > 0) {
let nd = stack.pop(); // 挨个取出元素
if (nd.parentNode.tagName == "A" && nd.tagName == "SPAN") {
continue; //对A标签内的SPAN元素不进行处理,剪枝,此时子元素根本不加入stack,即实现了此功能
}
ndPath = readXPath(nd, 1, tnode);
ndAllPaths = getElementXPaths(nd, tnode);
let index = -1;
for (let i = 0; i < commonXPathList.length; i++) {
if (commonXPathList[i] == ndPath) {
index = i;
break;
}
}
if (index != -1) { //如果是共有元素
let unique_index = ndPath;
ndText = "";
let ndContents = nd.childNodes;
for (let i = 0; i < ndContents.length; i++) {
if (ndContents[i].nodeType === 3) { // if it's a text node
ndText += ndContents[i].textContent.trim(); // add its content to the string
}
}
ndText = ndText.replace(/\s+/g, ''); // remove any whitespace characters
if (ndText != "" || nd == tnode) {
global.outputParameterNodes.push({
"node": nd,
"unique_index": unique_index,
"boxShadow": nd.style.boxShadow == "" || global.boxShadowColor ? "none" : nd.style.boxShadow
});
nd.style.boxShadow = global.boxShadowColor;
}
console.log("Hash", hash);
if (num == 0) { //从第二个节点开始,只插入那些不在参数列表中的元素,根据xpath进行寻址
//如果当前节点除了子元素外仍然有其他文字或者该元素是图片/表单项,加入子元素节点
if (ndText != "" || nd.tagName == "IMG" || nd.tagName == "INPUT" || nd.tagName == "A") {
hash[index] = global.outputParameters.length;
if (nd.tagName == "IMG") { //如果元素是图片
global.outputParameters.push({
"nodeType": 4, //节点类型
"contentType": 1, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径,注意当只选择了子元素没有选中全部的时候,需要判断
"name": parameterName("参数") + (n++) + parameterName("_图片地址"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd), //同理需要判断
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{
"num": num,
"value": nd.getAttribute("src") == null ? "" : nd.getAttribute("src")
}],
"unique_index": unique_index,
});
} else if (nd.tagName == "A") { //如果元素是超链接
global.outputParameters.push({
"nodeType": 1,
"contentType": 0, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_链接文本"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{"num": num, "value": nd.textContent}], //注意这里的ndtext是整个a的文字!!!
"unique_index": unique_index,
});
global.outputParameters.push({
"nodeType": 2,
"contentType": 0, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_链接地址"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{
"num": num,
"value": nd.getAttribute("href") == null ? "" : nd.getAttribute("href")
}],
"unique_index": unique_index,
});
} else if (nd.tagName == "INPUT") { //如果元素是输入项
global.outputParameters.push({
"nodeType": 3,
"contentType": 1, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_文本"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{
"num": num,
"value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value")
}],
"unique_index": unique_index,
});
} else { //其他所有情况
global.outputParameters.push({
"nodeType": 0,
"contentType": 1, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_文本"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{"num": num, "value": ndText}],
"unique_index": unique_index,
});
}
}
} else //如果元素节点已经存在,则只需要插入值就可以了
{
try{
if (ndText != "" || nd.tagName == "IMG" || nd.tagName == "INPUT" || nd.tagName == "A") {
if (nd.tagName == "IMG") { //如果元素是图片
global.outputParameters[hash[index]]["exampleValues"].push({
"num": num,
"value": nd.getAttribute("src") == null ? "" : nd.getAttribute("src")
});
} else if (nd.tagName == "A") { //如果元素是超链接
global.outputParameters[hash[index]]["exampleValues"].push({
"num": num,
"value": nd.textContent
});
global.outputParameters[hash[index] + 1]["exampleValues"].push({
"num": num,
"value": nd.getAttribute("href") == null ? "" : nd.getAttribute("href")
});
} else if (nd.tagName == "INPUT") { //如果元素是输入项
global.outputParameters[hash[index]]["exampleValues"].push({
"num": num,
"value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value")
});
} else { //其他所有情况
global.outputParameters[hash[index]]["exampleValues"].push({
"num": num,
"value": ndText
});
}
}
} catch (e) {
console.log("Error: -----------------------\n\n", e);
}
}
}
for (let i = nd.children.length - 1; i >= 0; i--) {
stack.push(nd.children[i]);
}
}
ndText = ndText.replace(/\s+/g, ''); // remove any whitespace characters
if (index == -1) { //从第二个节点开始,只插入那些不在参数列表中的元素,根据xpath进行寻址
//如果当前节点除了子元素外仍然有其他文字或者该元素是图片/表单项,加入子元素节点
if (ndText != "" || nd.tagName == "IMG" || nd.tagName == "INPUT" || nd.tagName == "A") {
}
}
else {
for (let num = 0; num < global.nodeList.length; num++) {
let tnode = global.nodeList[num]["node"];
let stack = new Array(); //深度优先搜索遍历元素
stack.push(tnode); //从此节点开始
while (stack.length > 0) {
let nd = stack.pop(); // 挨个取出元素
if (nd.parentNode.tagName == "A" && nd.tagName == "SPAN") {
continue; //对A标签内的SPAN元素不进行处理,剪枝,此时子元素根本不加入stack,即实现了此功能
}
ndPath = readXPath(nd, 1, tnode);
ndAllPaths = getElementXPaths(nd, tnode);
let index = -1;
for (let i = 0; i < global.outputParameters.length; i++) {
if (global.outputParameters[i]["relativeXPath"] == ndPath) {
index = i;
break;
}
}
ndText = "";
let ndContents = nd.childNodes;
for (let i = 0; i < ndContents.length; i++) {
if (ndContents[i].nodeType === 3) { // if it's a text node
ndText += ndContents[i].textContent.trim(); // add its content to the string
}
}
ndText = ndText.replace(/\s+/g, ''); // remove any whitespace characters
let unique_index = ndPath;
if(ndText!= "" || nd == tnode){
if (mode == 0 || (mode == 1 && (index != -1 || num == 0))) { //如果不是应选尽选,则只添加和第一个元素相同类型的子元素
global.outputParameterNodes.push({
"node": nd,
"unique_index": unique_index,
"boxShadow": nd.style.boxShadow == "" || global.boxShadowColor ? "none" : nd.style.boxShadow
});
nd.style.boxShadow = global.boxShadowColor;
} else if(mode == 1 && nd == tnode){ //最外层元素标记一下
nd.style.boxShadow = global.boxShadowColor;
}
}
if (index == -1) { //从第二个节点开始,只插入那些不在参数列表中的元素,根据xpath进行寻址
//如果当前节点除了子元素外仍然有其他文字或者该元素是图片/表单项,加入子元素节点
if (!(mode == 1 && num > 0)) { //如果不是应选尽选,则只添加和第一个元素相同类型的子元素
if (ndText!= "" || nd.tagName == "IMG" || nd.tagName == "INPUT" || nd.tagName == "A") {
if (nd.tagName == "IMG") { //如果元素是图片
global.outputParameters.push({
"nodeType": 4, //节点类型
"contentType": 1, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径,注意当只选择了子元素没有选中全部的时候,需要判断
"name": parameterName("参数") + (n++) + parameterName("_图片地址"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd), //同理需要判断
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{
"num": num,
"value": nd.getAttribute("src") == null ? "" : nd.getAttribute("src")
}],
"unique_index": unique_index,
});
} else if (nd.tagName == "A") { //如果元素是超链接
global.outputParameters.push({
"nodeType": 1,
"contentType": 0, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_链接文本"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{"num": num, "value": nd.textContent}], //注意这里的ndtext是整个a的文字!!!
"unique_index": unique_index,
});
global.outputParameters.push({
"nodeType": 2,
"contentType": 0, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_链接地址"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{
"num": num,
"value": nd.getAttribute("href") == null ? "" : nd.getAttribute("href")
}],
"unique_index": unique_index,
});
} else if (nd.tagName == "INPUT") { //如果元素是输入项
global.outputParameters.push({
"nodeType": 3,
"contentType": 1, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_文本"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{
"num": num,
"value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value")
}],
"unique_index": unique_index,
});
} else { //其他所有情况
global.outputParameters.push({
"nodeType": 0,
"contentType": 1, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_文本"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{"num": num, "value": ndText}],
"unique_index": unique_index,
});
}
}
}
} else //如果元素节点已经存在,则只需要插入值就可以了
{
if (nd.tagName == "IMG") { //如果元素是图片
global.outputParameters.push({
"nodeType": 4, //节点类型
"contentType": 1, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径,注意当只选择了子元素没有选中全部的时候,需要判断
"name": parameterName("参数") + (n++) + parameterName("_图片地址"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd), //同理需要判断
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{
"num": num,
"value": nd.getAttribute("src") == null ? "" : nd.getAttribute("src")
}]
global.outputParameters[index]["exampleValues"].push({
"num": num,
"value": nd.getAttribute("src") == null ? "" : nd.getAttribute("src")
});
} else if (nd.tagName == "A") { //如果元素是超链接
global.outputParameters.push({
"nodeType": 1,
"contentType": 0, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_链接文本"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{ "num": num, "value": nd.textContent }] //注意这里的ndtext是整个a的文字!!!
});
global.outputParameters.push({
"nodeType": 2,
"contentType": 0, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_链接地址"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{
"num": num,
"value": nd.getAttribute("href") == null ? "" : nd.getAttribute("href")
}]
global.outputParameters[index]["exampleValues"].push({ "num": num, "value": nd.textContent });
global.outputParameters[index + 1]["exampleValues"].push({
"num": num,
"value": nd.getAttribute("href") == null ? "" : nd.getAttribute("href")
});
} else if (nd.tagName == "INPUT") { //如果元素是输入项
global.outputParameters.push({
"nodeType": 3,
"contentType": 1, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_文本"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{
"num": num,
"value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value")
}]
global.outputParameters[index]["exampleValues"].push({
"num": num,
"value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value")
});
} else { //其他所有情况
global.outputParameters.push({
"nodeType": 0,
"contentType": 1, // 内容类型
"relative": global.nodeList.length > 1 ? true : false, //是否为相对xpath路径
"name": parameterName("参数") + (n++) + parameterName("_文本"),
"desc": "", //参数描述
"relativeXPath": global.nodeList.length > 1 ? ndPath : readXPath(nd),
"allXPaths": global.nodeList.length > 1 ? ndAllPaths : getElementXPaths(nd),
"exampleValues": [{ "num": num, "value": ndText }]
});
global.outputParameters[index]["exampleValues"].push({ "num": num, "value": ndText });
}
}
} else //如果元素节点已经存在,则只需要插入值就可以了
{
if (nd.tagName == "IMG") { //如果元素是图片
global.outputParameters[index]["exampleValues"].push({
"num": num,
"value": nd.getAttribute("src") == null ? "" : nd.getAttribute("src")
});
} else if (nd.tagName == "A") { //如果元素是超链接
global.outputParameters[index]["exampleValues"].push({ "num": num, "value": nd.textContent });
global.outputParameters[index + 1]["exampleValues"].push({
"num": num,
"value": nd.getAttribute("href") == null ? "" : nd.getAttribute("href")
});
} else if (nd.tagName == "INPUT") { //如果元素是输入项
global.outputParameters[index]["exampleValues"].push({
"num": num,
"value": nd.getAttribute("value") == null ? "" : nd.getAttribute("value")
});
} else { //其他所有情况
global.outputParameters[index]["exampleValues"].push({ "num": num, "value": ndText });
for (let i = nd.children.length - 1; i >= 0; i--) {
stack.push(nd.children[i]);
}
}
for (let i = nd.children.length - 1; i >= 0; i--) {
stack.push(nd.children[i]);
}
}
}
let at2 = parseInt(new Date().getTime());
@ -665,6 +880,7 @@ export function generateValTable(multiline = true) {
paravalues.push(tvalues);
}
global.app._data.valTable = paravalues;
console.log("生成参数表格", paravalues);
}
// 选中第一个节点,自动寻找同类节点
@ -712,7 +928,7 @@ export function findRelated() {
//根据path将元素放入readylist中
export function pushToReadyList(path) {
let result = document.evaluate(path, document, null, XPathResult.ANY_TYPE, null);
var node = result.iterateNext(); //枚举第一个元素
let node = result.iterateNext(); //枚举第一个元素
while (node) { //只添加不在已选中列表内的元素
let exist = false;
for (let o of global.nodeList) {
@ -763,11 +979,11 @@ export function combineXpath(nameList, indexList) {
// /html/body/div[3]/div[1]/div[1]/div[1]/div[3]/div/div[3]/a
export function relatedTest() {
let at = new Date().getTime()
var testList = [];
var testpath = "";
let testList = [];
let testpath = "";
for (let i = 0; i < global.nodeList.length; i++) {
var testnumList = []; //用于比较节点索引号不同
var tpath = global.nodeList[i]["xpath"].split("/").splice(1); //清理第一个空元素
let testnumList = []; //用于比较节点索引号不同
let tpath = global.nodeList[i]["xpath"].split("/").splice(1); //清理第一个空元素
for (let j = 0; j < tpath.length; j++) {
if (tpath[j].indexOf("[") >= 0) { //如果存在索引值
testnumList.push(parseInt(tpath[j].split("[")[1].replace("]", ""))); //只留下数字
@ -785,7 +1001,7 @@ export function relatedTest() {
testList.push(testnumList);
}
testpath = testpath.split("/"); //清理第一个空元素
var indexList = []; //记录新生成的xpath
let indexList = []; //记录新生成的xpath
//如果选中的元素属于同样的序列,则计算出序列的最佳xpath表达式
for (let j = 0; j < testList[0].length; j++) {
indexList.push(testList[0][j]);

+ 92
- 59
Extension/manifest_v3/src/content-scripts/toolkit.vue Переглянути файл

@ -7,11 +7,12 @@
<div v-if="list.nl.length==0" :style="{overflow: 'auto', maxHeight: winHeight * 0.4 + 'px'}">
<input style="width:15px;height:15px;vertical-align:middle;" type="checkbox"
v-on:mousedown="specialSelect"/>
<p style="margin-bottom:10px;display:inline-block">特殊点选模式</p>
<p style="margin-bottom:10px;display:inline-block">特殊点选模式<span title="普通模式下如果不能选中元素可以勾选此项"></span></p>
<div class="innercontent" v-if = "list.nl.length==0">
<div><a v-on:mousedown="getCurrentTitle">采集当前页面的标题</a><span title=""></span></div>
<div><a v-on:mousedown="getCurrentURL">采集当前页面的网址</a><span title=""></span></div>
<div><a v-on:mousedown="getCurrentTitle">采集当前页面的标题</a><span title="当前页面标题"></span></div>
<div><a v-on:mousedown="getCurrentURL">采集当前页面的网址</a><span title="当前页面URL地址"></span></div>
</div>
<p style="color:black; margin-top: 10px"> 鼠标移动到笑脸查看操作提示</p>
<p style="color:black; margin-top: 10px"> 鼠标移动到元素上后<strong>右键</strong>点击或者按<strong>F7</strong>键选中页面元素
</p>
<p style="color:black; margin-top: 10px"> 通过鼠标左键进行点击时页面也会有反应但左键点击发生的操作不会被记录在任务流程中同理如果想输入文本框但并不想将动作记录可以鼠标移动到文本框并按键盘的<strong>F9</strong>进行输入
@ -26,37 +27,37 @@
v-if="numOfReady()>0&&tname()!='下一页元素'">同时发现{{ numOfReady() }}个同类元素如果不全或不准请继续手动选择其余您认为的同类元素</span>您可以:
<div class="innercontent">
<div v-if="numOfReady()>0 && !selectStatus"><a v-on:mousedown="selectAll">选中全部</a> <span
title=""></span></div>
title=""></span></div>
<div v-if="existDescendents()&& !selectStatus &&(tname()=='元素' || tname()=='链接')"><a
v-on:mousedown="selectDescendents">选中子元素</a> <span title=""></span></div>
v-on:mousedown="selectDescendents">选中子元素</a> <span title="应选尽选模式,如想使用其他模式请先选中全部再选中子元素"></span></div>
<div v-if="!selectedDescendents && !selectStatus" id="Single">
<div v-if="tname()=='选择框'"><a v-on:mousedown="changeSelect">切换下拉选项</a><span title=""></span></div>
<div v-if="tname()=='文本框'"><a v-on:mousedown="setInput">输入文字</a><span title=""></span></div>
<div v-if="tname()=='选择框'"><a v-on:mousedown="changeSelect">切换下拉选项</a><span title=""></span></div>
<div v-if="tname()=='文本框'"><a v-on:mousedown="setInput">输入文字</a><span title=""></span></div>
<div v-if="tname()!='图片'"><a v-on:mousedown="getText">采集该{{ tname() }}的文本</a><span
title="采集文本"></span></div>
<div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedValue">采集当前选中项的值</a><span title=""></span></div>
<div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedText">采集当前选中项的文本</a><span title=""></span></div>
title="采集文本"></span></div>
<div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedValue">采集当前选中项的值</a><span title=""></span></div>
<div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedText">采集当前选中项的文本</a><span title=""></span></div>
<div v-if="tname()=='链接'||tname()=='图片'"><a
v-on:mousedown="getLink">采集该{{ tname() }}的地址</a><span title=""></span></div>
v-on:mousedown="getLink">采集该{{ tname() }}的地址</a><span title=""></span></div>
<div v-if="tname()!='选择框' && tname()!='文本框'"><a
v-on:mousedown="clickElement">点击该{{ tname() }}</a><span title=""></span></div>
v-on:mousedown="clickElement">点击该{{ tname() }}</a><span title=""></span></div>
<div v-if="tname()!='选择框' && tname()!='文本框'"><a
v-on:mousedown="loopClickSingleElement">循环点击该{{ tname() }}</a><span title=""></span></div>
<div><a v-on:mousedown="getBackgroundPic">采集该{{ tname() }}的背景图片地址</a><span title=""></span></div>
v-on:mousedown="loopClickSingleElement">循环点击该{{ tname() }}</a><span title="常用于循环点击下一页场景"></span></div>
<div><a v-on:mousedown="getBackgroundPic">采集该{{ tname() }}的背景图片地址</a><span title="部分元素的图片是设定为背景图像的"></span></div>
<div v-if="tname()=='链接'||tname()=='元素'"><a v-on:mousedown="getInnerHtml">采集该{{
tname()
}}的Inner
Html</a><span title=""></span></div>
<div><a v-on:mousedown="getOuterHtml">采集该{{ tname() }}的Outer Html</a><span title=""></span></div>
Html</a><span title="不包括元素自身标签的HTML"></span></div>
<div><a v-on:mousedown="getOuterHtml">采集该{{ tname() }}的Outer Html</a><span title="包括元素自身标签的HTML"></span></div>
<div><a href="#" v-on:mousedown="mouseMove">鼠标移动到该{{ tname() }}</a><span title=""></span></div>
<div><a href="#" v-on:mousedown="mouseMove">鼠标移动到该{{ tname() }}</a><span title=""></span></div>
<!-- <div v-if="tname()=='文本框'"><a>识别验证码</a><span title=""></span></div>-->
</div>
<div v-if="selectedDescendents" id="Single">
<div><a v-on:mousedown="confirmCollectSingle">采集数据</a><span title=""></span></div>
<div><a v-on:mousedown="confirmCollectSingle">采集数据</a><span title=""></span></div>
</div>
<div v-if="selectStatus" id="Confirm">
<div><a v-on:mousedown="confirmCollectSingle">确认采集</a><span title=""></span></div>
<div><a v-on:mousedown="confirmCollectSingle">确认采集</a><span title=""></span></div>
</div>
</div>
</div>
@ -67,8 +68,8 @@
<div v-if="option==100">
已选择了以下元素您可以
<div class="innercontent">
<div><a v-on:mousedown="confirmCollectMulti">采集数据</a><span title=""></span></div>
<div><a v-on:mousedown="revoke">撤销本次选择</a><span title=""></span></div>
<div><a v-on:mousedown="confirmCollectMulti">采集数据</a><span title=""></span></div>
<div><a v-on:mousedown="revoke">撤销本次选择</a><span title=""></span></div>
</div>
</div>
@ -76,15 +77,19 @@
已选择了{{ numOfList() }}个同类元素<span
v-if="numOfReady()>0">另外发现{{ numOfReady() }}个同类元素如果不全或不准请继续手动选择其余您认为的同类元素</span>您可以
<div class="innercontent">
<div v-if="numOfReady()>0"><a v-on:mousedown="selectAll">选中全部</a><span title=""></span></div>
<div v-if="numOfReady()>0"><a v-on:mousedown="selectAll">选中全部</a><span title=""></span></div>
<div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
v-on:mousedown="selectDescendents">选中子元素</a><span title=""></span></div>
<div><a v-on:mousedown="confirmCollectMultiAndDescendents">采集数据</a><span title=""></span></div>
v-on:mousedown="selectDescendents">选中子元素应选尽选</a><span title="每个块的每个子元素都选中进来"></span></div>
<div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
v-on:mousedown="selectDescendents(1,1)">选中子元素相对首选块共同元素</a><span title="只选中和第一个选中块的子元素共同的子元素"></span></div>
<div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
v-on:mousedown="selectDescendents(1,2)">选中子元素所有块共同元素</a><span title="只选中所有块都有的子元素"></span></div>
<div><a v-on:mousedown="confirmCollectMultiAndDescendents">采集数据</a><span title=""></span></div>
<div v-if="tname()!='选择框' && tname()!='文本框' && !selectedDescendents"><a
v-on:mousedown="loopClickEveryElement">循环点击每个{{ tname() }}</a><span title=""></span></div>
v-on:mousedown="loopClickEveryElement">循环点击每个{{ tname() }}</a><span title="常用于循环点击列表中的链接打开详情页采集场景"></span></div>
<div v-if="tname()!='选择框' && tname()!='文本框' && !selectedDescendents"><a
v-on:mousedown="loopMouseMove">循环移动到每个{{ tname() }}</a><span title=""></span></div>
<div><a v-on:mousedown="revoke">撤销本次选择</a><span title=""></span></div>
v-on:mousedown="loopMouseMove">循环移动到每个{{ tname() }}</a><span title=""></span></div>
<div><a v-on:mousedown="revoke">撤销本次选择</a><span title=""></span></div>
</div>
</div>
</div>
@ -92,8 +97,9 @@
<div class="toolkitcontain">{{ setWidth("290px") }}
<table cellSpacing="0" class="toolkittb2">
<tbody>
<th v-for="i in list.opp">{{ i["name"] }}</th>
<th v-for="(i, index) in list.opp"> <div>{{ i["name"] }}</div> <span v-bind:index="index" v-on:mousedown="removeField" title="删除此字段">×</span> </th>
<th style="width:40px">删除</th>
</tbody>
</table>
<table cellSpacing="0" class="toolkittb4">
@ -104,6 +110,7 @@
v-on:mousedown="deleteSingleLine">×
</td>
</tr>
</tbody>
</table>
</div>
</div>
@ -154,11 +161,12 @@
<div v-if="list.nl.length==0" :style="{overflow: 'auto', maxHeight: winHeight * 0.4 + 'px'}">
<input style="width:15px;height:15px;vertical-align:middle;" type="checkbox"
v-on:mousedown="specialSelect"> </input>
<p style="margin-bottom:10px;display:inline-block">Special click mode</p>
<p style="margin-bottom:10px;display:inline-block">Special click mode<span title="If cannot select element by mouse, select this option"></span></p>
<div class="innercontent" v-if = "list.nl.length==0">
<div><a v-on:mousedown="getCurrentTitle">Collect Title of current page</a><span title=""></span></div>
<div><a v-on:mousedown="getCurrentURL">Collect URL of current page</a><span title=""></span></div>
<div><a v-on:mousedown="getCurrentTitle">Collect Title of current page</a><span title="Title of this page"></span></div>
<div><a v-on:mousedown="getCurrentURL">Collect URL of current page</a><span title="URL of this page"></span></div>
</div>
<p style="color:black"> Mouse move to smiling face to see operation help.</p>
<p style="color:black"> When your mouse moves to the element, please <strong>right-click</strong> your
mouse button or press <strong>F7</strong> on the keyboard to select it.</p>
<p style="color:black; margin-top: 10px"> When clicked with the left mouse button, the page will also respond, but this click operation will not be recorded in the task flow. Similarly, if you want to input in a text box but do not want the action to be recorded , you can move the mouse to the text box and press <strong>F9</strong> on the keyboard to input.</p>
@ -173,41 +181,41 @@
can:
<div class="innercontent">
<div v-if="numOfReady()>0 && !selectStatus"><a v-on:mousedown="selectAll">Select All</a><span
title=""></span></div>
title=""></span></div>
<div v-if="existDescendents()&& !selectStatus &&(tname()=='元素' || tname()=='链接')"><a
v-on:mousedown="selectDescendents">Select child elements</a> <span title=""></span></div>
v-on:mousedown="selectDescendents">Select child elements</a> <span title="Greedy Mode, if you want to use other modes, please select 'Select All' option first"></span></div>
<div v-if="!selectedDescendents && !selectStatus" id="Single">
<!-- <div v-if="tname()=='selection box'"> <a>循环切换该下拉项</a><span title=""></span></div> -->
<div v-if="tname()=='选择框'"><a v-on:mousedown="changeSelect">Change selection option</a><span title=""></span></div>
<div v-if="tname()=='文本框'"><a v-on:mousedown="setInput">Input Text</a><span title=""></span>
<div v-if="tname()=='选择框'"><a v-on:mousedown="changeSelect">Change selection option</a><span title=""></span></div>
<div v-if="tname()=='文本框'"><a v-on:mousedown="setInput">Input Text</a><span title=""></span>
</div>
<div v-if="tname()!='图片'"><a v-on:mousedown="getText">Extract {{ tname() | toEng }}'s text</a><span
title="collect text"></span></div>
<div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedValue">Collect selected option value</a><span title=""></span></div>
<div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedText">Collect selected option text</a><span title=""></span></div>
title="collect text"></span></div>
<div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedValue">Collect selected option value</a><span title=""></span></div>
<div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedText">Collect selected option text</a><span title=""></span></div>
<div v-if="tname()=='链接'||tname()=='图片'"><a v-on:mousedown="getLink">Collect address of this
{{ tname() | toEng }}</a><span title=""></span></div>
{{ tname() | toEng }}</a><span title=""></span></div>
<div v-if="tname()!='选择框' && tname()!='文本框'"><a v-on:mousedown="clickElement">Click
this {{ tname() | toEng }}</a><span title=""></span></div>
this {{ tname() | toEng }}</a><span title=""></span></div>
<div v-if="tname()!='选择框' && tname()!='文本框'"><a
v-on:mousedown="loopClickSingleElement">Loop-click this {{ tname() | toEng }}</a><span
title=""></span>
title="Usually used to loop-click the next-page button"></span>
</div>
<div><a v-on:mousedown="getBackgroundPic">Collect background image URL</a><span title=""></span></div>
<div><a v-on:mousedown="getBackgroundPic">Collect background image URL</a><span title="Some elements have background images"></span></div>
<div v-if="tname()=='链接'||tname()=='元素'"><a v-on:mousedown="getInnerHtml">Collect Inner Html of
this {{ tname() | toEng }}</a><span title=""></span></div>
<div><a v-on:mousedown="getOuterHtml">Collect Outer Html of this element</a><span title=""></span>
this {{ tname() | toEng }}</a><span title="HTML not including the tag of this selected element"></span></div>
<div><a v-on:mousedown="getOuterHtml">Collect Outer Html of this element</a><span title="HTML including the tag of this selected element"></span>
</div>
<div><a href="#" v-on:mousedown="mouseMove">Move mouse to this element</a><span title=""></span></div>
<div><a href="#" v-on:mousedown="mouseMove">Move mouse to this element</a><span title=""></span></div>
<!-- <div v-if="tname()=='text box'"> <a>识别验证码</a><span title=""></span></div> -->
</div>
<div v-if="selectedDescendents" id="Single">
<div><a v-on:mousedown="confirmCollectSingle">Collect Data</a><span title=""></span></div>
<div><a v-on:mousedown="confirmCollectSingle">Collect Data</a><span title=""></span></div>
</div>
<div v-if="selectStatus" id="Confirm">
<div><a v-on:mousedown="confirmCollectSingle">Confirm Collect</a><span title=""></span></div>
<div><a v-on:mousedown="confirmCollectSingle">Confirm Collect</a><span title=""></span></div>
</div>
</div>
</div>
@ -218,8 +226,8 @@
<div v-if="option==100">
Already selected the following element, you can:
<div class="innercontent">
<div><a v-on:mousedown="confirmCollectMulti">Collect Data</a><span title=""></span></div>
<div><a v-on:mousedown="revoke">Revoke selection</a><span title=""></span></div>
<div><a v-on:mousedown="confirmCollectMulti">Collect Data</a><span title=""></span></div>
<div><a v-on:mousedown="revoke">Revoke selection</a><span title=""></span></div>
</div>
</div>
@ -227,16 +235,20 @@
Already selected {{ numOfList() }} similar elements, <span
v-if="numOfReady()>0">and we find other{{ numOfReady() }} similar elements (If unsatisfied with auto-detected similar elements, you can continue to manually select the rest of the elements that you think are similar), </span>you can:
<div class="innercontent">
<div v-if="numOfReady()>0"><a v-on:mousedown="selectAll">Select All</a><span title=""></span></div>
<div v-if="numOfReady()>0"><a v-on:mousedown="selectAll">Select All</a><span title=""></span></div>
<div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
v-on:mousedown="selectDescendents">Select child elements (Greedy)</a><span title="Select All child elements for all blocks"></span></div>
<div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
v-on:mousedown="selectDescendents">Select child elements</a><span title=""></span></div>
<div><a v-on:mousedown="confirmCollectMultiAndDescendents">Collect Data</a><span title=""></span></div>
v-on:mousedown="selectDescendents(1,1)">Select child elements (RFSE)</a><span title="Relative to First Selected Element, will only select the common child elements between the first selected block and the rest of the blocks"></span></div>
<div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
v-on:mousedown="selectDescendents(1,2)">Select child elements (RASE)</a><span title="Relative to All Selected Elements, will select only the common child elements that exist in all blocks"></span></div>
<div><a v-on:mousedown="confirmCollectMultiAndDescendents">Collect Data</a><span title=""></span></div>
<div v-if="tname()!='选择框' && tname()!='文本框' && !selectedDescendents"><a
v-on:mousedown="loopClickEveryElement">Loop-click every {{ tname() | toEng}}</a><span title=""></span>
v-on:mousedown="loopClickEveryElement">Loop-click every {{ tname() | toEng}}</a><span title="Usually used to click every link in a list to open detail page to collect data"></span>
</div>
<div v-if="tname()!='选择框' && tname()!='文本框' && !selectedDescendents"><a
v-on:mousedown="loopMouseMove">Loop-mouse-move to every {{ tname() | toEng}}</a><span title=""></span></div>
<div><a v-on:mousedown="revoke">Revoke selection</a><span title=""></span></div>
v-on:mousedown="loopMouseMove">Loop-mouse-move to every {{ tname() | toEng}}</a><span title=""></span></div>
<div><a v-on:mousedown="revoke">Revoke selection</a><span title=""></span></div>
</div>
</div>
@ -246,7 +258,7 @@
<div class="toolkitcontain">{{ setWidth("350px") }}
<table cellspacing="0" class="toolkittb2">
<tbody>
<th v-for="i in list.opp">{{ i["name"] }}</th>
<th v-for="(i, index) in list.opp"><div>{{ i["name"] }}</div> <span v-bind:index="index" v-on:mousedown="removeField" title="Remove this field">×</span> </th>
<th style="width:40px">Delete</th>
</tbody>
</table>
@ -357,6 +369,7 @@ export default {
winHeight: window.outerHeight,
optionMode: 0,
optionValue: "",
mode: 0, //
},
mounted(){
this.$nextTick(() => {
@ -423,7 +436,7 @@ export default {
if (global.nodeList.length > 1) { //
handleElement();
if (this.selectedDescendents) {
handleDescendents(); //
handleDescendents(this.mode); //
}
} else {
this.valTable = [];
@ -433,6 +446,25 @@ export default {
let at2 = parseInt(new Date().getTime());
console.log("delete:", at2, at, at2 - at);
},
removeField: function (event){
let index = event.target.getAttribute("index");
let tParameter = global.outputParameters.splice(index, 1)[0];
if(global.outputParameters.length == 0){
this.valTable = [];
clearEl();
} else { //
console.log("remove:", tParameter, global);
this.valTable.splice(index, 1);
for (let i = global.outputParameterNodes.length - 1; i >= 0; i--) {
let node = global.outputParameterNodes[i];
if(node["unique_index"] == tParameter["unique_index"]){
node["node"].style.backgroundColor = "";
node["node"].style.boxShadow = "";
global.outputParameterNodes.splice(i, 1);
}
}
}
},
clickElement: function () { //
sendSingleClick();
//
@ -705,8 +737,9 @@ export default {
}
handleElement(); //
},
selectDescendents: function () { //
handleDescendents();
selectDescendents: function (e, mode = 0) { //
handleDescendents(mode);
this.mode = mode;
}
},
}

+ 19
- 2
Extension/manifest_v3/src/style/toolkit.css Переглянути файл

@ -134,11 +134,28 @@
font-weight: normal !important;
overflow: hidden !important;
font-size: 11px !important;
padding-left: 1px !important;
padding-right: 0px !important;
padding-left: 10px !important;
padding-right: 10px !important;
padding-top: 0px !important;
padding-bottom: 0px !important;
vertical-align: middle!important;
white-space: nowrap;
}
.toolkitcontain th span{
font-size: 15px;
font-weight: bold;
cursor: pointer;
/*position: absolute;*/
/*position: ;*/
margin-right: 10px;
vertical-align: text-bottom!important;
}
.toolkitcontain th div{
display: inline-block!important;
overflow: hidden!important;
max-width: 90%!important;
}
.toolkitcontain .toolkittb2 {

+ 1
- 1
Readme.md Переглянути файл

@ -1,6 +1,6 @@
## 请您Star/Please Star
如果您觉得此工具不错,请轻轻点击此页面右上角**Star**按钮增加项目曝光度,谢谢!软件完全免费,只求大家Star和宣传给其他需要的朋友,谢谢!
如果您觉得此工具不错,请轻轻点击此页面右上角**Star**按钮增加项目曝光度,谢谢!软件完全免费(商用除外),只求大家Star和宣传给其他需要的朋友,谢谢!
If you think this tool is good, please gently click the **Star** button in the upper right corner at this page to increase the project exposure, thank you! The software is completely free, only ask everyone to Star and promote it to other friends in need, thank you!

Завантаження…
Відмінити
Зберегти