//处理表现层 let nodeList = Array(); //所有新生成的节点全部存储在这里,并且有唯一索引号,所有的定位均通过index进行,即将图保存下来了 let root = { index: 0, //在nodeList中的索引号 id: 0, parentId: 0, type: -1, option: 0, title: "root", sequence: [], parameters: { history: 1, tabIndex: 0, useLoop: false, //是否使用循环中的元素 xpath: "", //xpath wait: 0, }, isInLoop: false, //是否处于循环内 }; nodeList.push(root); let queue = new Array(); let actionSequence = new Array(); //存储图结构,每个元素为在nodelist里面的索引值,下面的id和pid根据此数组进行索引,然后再在nodelist里找 let nowNode = null; //存储现在所在的节点 let vueData = { nowNodeIndex: 0 }; //存储目前所在节点的索引号,不能直接使用变量而需要用对象包起来 let option = 0; //工具箱选项 let title = ""; let parameterNum = 1; //记录目前的参数个数 //处理逻辑层 let app = new Vue({ el: '#app', data: { list: { nl: nodeList }, index: vueData, nodeType: 0, // 当前元素的类型 nowNode: null, // 用来临时存储元素的节点 loopType: -1, //点击循环时候用来循环选项 useLoop: false, //记录是否使用循环内元素 nowArrow: { "position": -1, "pId": 0, "num": 0 }, paras: { "parameters": [] }, //提取数据的参数列表 TClass: -1, //条件分支的条件类别 paraIndex: 0, //当前参数的index XPaths: "", //xpath列表 }, watch: { nowArrow: { //变量发生变化的时候进行一些操作 deep: true, handler: function(newVal, oldVal) { let arrlist = document.getElementsByClassName("arrow"); if (oldVal != null) { for (let i = 0; i < arrlist.length; i++) { if (arrlist[i].getAttribute("position") == oldVal["position"] && arrlist[i].getAttribute("pid") == oldVal["pId"]) { arrlist[i].style.backgroundColor = ""; // 时刻指示现在应该插入的节点的位置 break; } } } for (let i = 0; i < arrlist.length; i++) { if (arrlist[i].getAttribute("position") == newVal["position"] && arrlist[i].getAttribute("pid") == newVal["pId"]) { arrlist[i].style.backgroundColor = "lavender"; // 时刻指示现在应该插入的节点的位置 break; } } } }, loopType: { handler: function(newVal, oldVal) { this.nowNode["parameters"]["loopType"] = newVal; } }, TClass: { handler: function(newVal, oldVal) { this.nowNode["parameters"]["class"] = newVal; } }, useLoop: { handler: function(newVal, oldVal) { this.nowNode["parameters"]["useLoop"] = newVal; } }, paras: { handler: function(newVal, oldVal) { this.nowNode["parameters"]["paras"] = newVal["parameters"]; } }, }, methods: { getCookies: function() { //获取cookies let command = new WebSocket("ws://localhost:"+getUrlParam("wsport")) command.onopen = function() { let message = { type: 7, //消息类型,0代表连接操作 }; this.send(JSON.stringify(message)); }; }, changeXPaths: function (XPaths){ let result = ""; for (let i = 0; i < XPaths.length; i++) { result += XPaths[i] + "\n"; } this.XPaths = result; }, addPara: function() { //添加参数 this.nowNode["parameters"]["paras"].push({ "nodeType": 0, "contentType": 0, "relative": false, "name": "自定义参数_" + this.nowNode["parameters"]["paras"].length.toString(), "desc": "", "extractType": 0, "relativeXPath": "", "allXPaths": [], "exampleValues": [ { "num": 0, "value": "自定义字段" } ], "default": "", "beforeJS": "", "beforeJSWaitTime": 0, "JS": "", "JSWaitTime": 0, "afterJS": "", "afterJSWaitTime": 0, "downloadPic": 0 }); this.paraIndex = this.nowNode["parameters"]["paras"].length - 1; }, modifyParas: function(i) { //修改第i个参数 this.paraIndex = i; console.log(this.paras); }, deleteParas: function(i) { //删除第i个参数 this.nowNode["parameters"]["paras"].splice(i, 1); //如果参数删除完了,就把提取数据也删掉 if (this.nowNode["parameters"]["paras"].length == 0) { deleteElement(); } }, upParas: function(i) { //上移第i个参数 if (i != 0) { let t = this.nowNode["parameters"]["paras"].splice(i, 1)[0]; this.nowNode["parameters"]["paras"].splice(i - 1, 0, t); } }, downParas: function(i) { //下移第i个参数 if (i != this.nowNode["parameters"]["paras"].length - 1) { let t = this.nowNode["parameters"]["paras"].splice(i, 1)[0]; this.nowNode["parameters"]["paras"].splice(i + 1, 0, t); } }, getType: function(nodeType, contentType) { //根据类型得到字段名称 if (contentType == 2) { return "InnerHTML"; } else if (contentType == 3) { return "OuterHTML"; } if (nodeType == 2) { return "链接地址"; } else if (nodeType == 1) { return "链接文本"; } else if (nodeType == 4) { return "图片地址"; } else { return "文本"; } } } }) //深复制 function DeepClone(obj) { if (obj === null || typeof obj !== 'object') return obj; let cpObj = obj instanceof Array ? [] : {}; for (let key in obj) cpObj[key] = DeepClone(obj[key]); return cpObj; } // 根据元素类型返回不同元素的样式 function newNode(node) { id = node["id"]; title = node["title"]; type = node["type"]; if (type == 0) //顺序 { return `
${title}
↓
${title}
↓
↓
`; } else if (type == 2) //判断 { return `${title}
点击此处在最左边增加条件分支
↓
`; } else //判断分支 { return `${title}
↓
▶
↓
`); actionSequence.splice(0); queue.splice(0); let idd = 1; queue.push(0); actionSequence.push(0); while (queue.length != 0) { let nd = queue.shift(); //取出父元素并建立对子元素的链接 for (let i = 0; i < nodeList[nd].sequence.length; i++) { nodeList[nodeList[nd].sequence[i]].parentId = nodeList[nd].id; nodeList[nodeList[nd].sequence[i]]["position"] = i; nodeList[nodeList[nd].sequence[i]].id = idd++; //检测元素是否位于循环内 if (nodeList[nd].option == 8 || nodeList[nd].isInLoop) { nodeList[nodeList[nd].sequence[i]].isInLoop = true; } else { nodeList[nodeList[nd].sequence[i]].isInLoop = false; } queue.push(nodeList[nd].sequence[i]); actionSequence.push(nodeList[nd].sequence[i]); } } if (nowArrowReset) //如果要重置锚点位置 { app._data.nowArrow = { "position": nodeList[0].sequence.length - 1, "pId": 0, "num": 0 }; //设置默认要添加的位置是元素流程最开头处 } //第一个元素不渲染 for (let i = 1; i < actionSequence.length; i++) { let parentId = nodeList[actionSequence[i]]["parentId"]; $("#" + parentId).append(newNode(nodeList[actionSequence[i]])); } bindEvents(); } function deleteElement() { if (nowNode.getAttribute("id") == 0) { alert("当前未选中元素!"); //root return; } // if (nodeList[actionSequence[nowNode.getAttribute("data")]]["option"] == 1) { // alert("打开网页操作不可删除!"); // return; // } let position = parseInt(nowNode.getAttribute('position')); let pId = nowNode.getAttribute('pId'); let tnode = nodeList[actionSequence[pId]]["sequence"].splice(position, 1); //在相应位置删除元素 //循环的标记已经被删除的元素,因为删除循环后,循环内的元素也会 let queue = new Array(); queue.push(tnode[0]); while (queue.length > 0) { let index = queue.shift(); nodeList[index]["id"] = -1; //标记服务已被删除 for (let i = 0; i < nodeList[index]["sequence"].length; i++) { queue.push(nodeList[index]["sequence"][i]); } } app._data["nowNode"] = null; app._data["nodeType"] = 0; vueData.nowNodeIndex = 0; if (nowNode.getAttribute("datatype") == 3) { //如果删掉的是条件分支的话 pId = nowNode.parentNode.parentNode.getAttribute('pId'); position = nowNode.parentNode.parentNode.getAttribute('position'); } app.$data.nowArrow = { position: position - 1, "pId": pId, "num": 0 }; //删除元素后锚点跳转到当前元素的上一个节点 refresh(false); //重新渲染页面 nowNode = null; //取消选择 } document.oncontextmenu = function() { return false; } //屏蔽右键菜单 //删除元素 document.onkeydown = function(e) { if (nowNode != null && e.keyCode == 46) { // if (confirm("确定要删除元素吗?")) { deleteElement(); // } } else { //ctrl+s保存服务 let currKey = 0; currKey = e.keyCode || e.which || e.charCode; if (currKey == 83 && (e.ctrlKey || e.metaKey)) { $('#save').click(); return true; } else if (currKey == 116) { location.reload(); } else if (currKey == 123) { console.log("打开devtools") let command = new WebSocket("ws://localhost:"+getUrlParam("wsport")) command.onopen = function() { let message = { type: 6, //消息类型,0代表连接操作 }; this.send(JSON.stringify(message)); }; } } } function inputDelete(e) { if (e.keyCode == 46) { e.stopPropagation(); //输入框按delete应该正常运行 //Electron中如果有alert或者confirm,执行后会卡死输入框,所以最好不要用 } }