CURD.html 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <script src="jquery-3.4.1.min.js"></script>
  5. <meta charset="UTF-8">
  6. <meta name="viewport"
  7. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  8. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  9. <script src="bootstrap/js/bootstrap.js"></script>
  10. <link rel="stylesheet" href="bootstrap/css/bootstrap.css"></link>
  11. <title>设计流程</title>
  12. <style>
  13. @font-face {
  14. font-family: 'Glyphicons Halflings';
  15. src: url('bootstrap/fonts/glyphicons-halflings-regular.eot');
  16. src: url('bootstrap/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('bootstrap/fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
  17. }
  18. * {
  19. margin: 0;
  20. padding: 0;
  21. font-size: 17px!important;
  22. }
  23. div.node {
  24. height: 45px;
  25. width: 120px;
  26. border-radius: 7px;
  27. border:skyblue solid;
  28. background: rgb(73, 156, 189);
  29. color:white;
  30. text-align: center;
  31. padding: 5px;
  32. margin: 10px auto;
  33. }
  34. .arrow
  35. {
  36. margin: 10px auto;
  37. text-align: center;
  38. font-size: 23px!important;
  39. color:black;
  40. }
  41. .arrow:hover
  42. {
  43. background-color: deepskyblue;
  44. cursor: pointer;
  45. color:white;
  46. }
  47. .branchAdd
  48. {
  49. margin: 10px auto;
  50. text-align: center;
  51. font-size: 18px!important;
  52. color:black;
  53. }
  54. .branchAdd:hover
  55. {
  56. background-color: deepskyblue;
  57. cursor: pointer;
  58. color:white;
  59. }
  60. div.node:hover {
  61. cursor: pointer;
  62. background:navy;
  63. }
  64. .loop
  65. {
  66. border:skyblue solid;
  67. text-align: center;
  68. padding: 5px;
  69. width:80%;
  70. margin: 10px auto;
  71. border-radius: 7px;
  72. }
  73. .judge
  74. {
  75. display:flex;
  76. text-align: center;
  77. padding: 5px;
  78. width:100%;
  79. margin: 10px auto;
  80. justify-content: center;
  81. border-radius: 7px;
  82. }
  83. .branch
  84. {
  85. margin: 5px;
  86. border:skyblue solid;
  87. text-align: center;
  88. padding: 5px;
  89. width:200px;
  90. min-width: 100px;
  91. margin: 10px;
  92. border-radius: 7px;
  93. }
  94. .sequence
  95. {
  96. display: block;
  97. }
  98. .toolbox button{
  99. margin-top: 5px;
  100. margin-left: 3px;
  101. margin-bottom: 5px;
  102. width:80%;
  103. font-size:15px!important;
  104. }
  105. .cancel:focus
  106. {
  107. box-shadow: none;
  108. }
  109. </style>
  110. </head>
  111. <body>
  112. <div style="display:flex">
  113. <div style="width: 200px;float:left">
  114. <div class="toolbox" style="text-align:center;margin: 20px;border-radius:10px;border:navy solid;background-color:rgb(242,243,245);z-index: 9999;">
  115. <div style="padding: 10px;border-radius:10px;font-size: 20px;">工具箱</div>
  116. <button type="button" data = 1 class="btn btn-xs btn-outline-primary openPage">打开网页</button>
  117. <button type="button" data = 2 class="btn btn btn-outline-primary openPage">点击元素</button>
  118. <button type="button" data = 3 class="btn btn btn-outline-primary openPage">提取数据</button>
  119. <button type="button" data = 4 class="btn btn btn-outline-primary openPage">输入文字</button>
  120. <button type="button" data = 5 class="btn btn btn-outline-primary openPage">识别验证码</button>
  121. <button type="button" data = 6 class="btn btn btn-outline-primary openPage">切换下拉选项</button>
  122. <button type="button" data = 7 class="btn btn btn-outline-primary openPage">移动到元素</button>
  123. <button type="button" data = 8 class="btn btn btn-outline-primary openPage">循环</button>
  124. <button type="button" data = 9 class="btn btn btn-outline-primary openPage">判断条件</button>
  125. <div>-----------------</div>
  126. <button type="button" data = 10 class="btn btn btn-outline-primary openPage">剪切当前元素</button>
  127. <button type="button" data = 11 class="btn btn btn-outline-primary openPage">复制当前元素</button>
  128. <button type="button" data = 12 class="btn btn btn-outline-primary openPage">删除当前元素</button>
  129. <button type="button" data = 0 class="btn btn btn-outline-primary openPage cancel">取消操作</button>
  130. <div>-----------------</div>
  131. <div style="text-align: left;margin: 10px;font-size:15px!important">提示:点击上方操作按钮后点击要添加/剪切/复制的位置处的箭头,可按取消操作按钮取消。</div>
  132. </div>
  133. </div>
  134. <div style="margin-top:20px;border: solid;height:850px;overflow: auto;width:85%;float:right;min-width:800px">
  135. <div id="0" >
  136. </div>
  137. <div style="border-radius: 50%;width: 40px;height: 40px;border:solid black;margin: 5px auto;background-color:lightcyan">
  138. <p style="font-size: 29px!important;text-align: center;margin-left: 1px;margin-top: -6px;">■</p>
  139. </div>
  140. </div>
  141. </div>
  142. </body>
  143. </html>
  144. <script>
  145. var first = {
  146. id:0,
  147. parentId:0,
  148. type:0,
  149. title:"打开网页1",
  150. sequence:[]
  151. };
  152. var second = {
  153. id:0,
  154. parentId:0,
  155. type:0,
  156. title:"点击元素2",
  157. sequence:[]
  158. };
  159. var fourth = {
  160. id:0,
  161. parentId:0,
  162. type:0,
  163. title:"关闭网页4",
  164. sequence:[]
  165. };
  166. var fifth = {
  167. id:0,
  168. parentId:0,
  169. type:0,
  170. title:"提取数据5",
  171. sequence:[]
  172. };
  173. var seventh = {
  174. id:0,
  175. parentId:0,
  176. type:0,
  177. title:"提取数据7",
  178. sequence:[]
  179. };
  180. var sixth = {
  181. id:0,
  182. parentId:0,
  183. type:1,
  184. title:"循环操作6",
  185. sequence:[seventh]
  186. };
  187. var n1 = {
  188. id:0,
  189. parentId:0,
  190. type:1,
  191. title:"循环操作",
  192. sequence:[fifth]
  193. };
  194. var n2 = {
  195. id:0,
  196. parentId:0,
  197. type:0,
  198. title:"node5",
  199. sequence:[]
  200. };
  201. var n3 = {
  202. id:0,
  203. parentId:0,
  204. type:3, //判断分支
  205. title:"判断分支1",
  206. sequence:[]
  207. };
  208. var n4 = {
  209. id:0,
  210. parentId:0,
  211. type:3,
  212. title:"判断分支2",
  213. sequence:[]
  214. };
  215. var n6 = {
  216. id:0,
  217. parentId:0,
  218. type:0,
  219. title:"正常操作",
  220. sequence:[]
  221. };
  222. var n5 = {
  223. id:0,
  224. parentId:0,
  225. type:3,
  226. title:"判断分支3",
  227. parameters:{
  228. "pdtype":0,//判断的5种类型
  229. "value":"",
  230. },//所有操作的参数都放在这里,这个参数是顺序执行的条件
  231. sequence:[n6]
  232. };
  233. var pd = {
  234. id:0,
  235. parentId:0,
  236. type:2,
  237. title:"判断操作",
  238. parameters:{},
  239. sequence:[n3,n4,n5]//执行的时候按照顺序检测一遍第一个满足条件的语句然后压栈执行
  240. };
  241. var third = {
  242. id:0,
  243. parentId:0,
  244. type:1,
  245. title:"循环操作3",
  246. sequence:[n2,n1,pd]
  247. };
  248. var root = {
  249. id:0,
  250. parentId:0,
  251. type:-1,
  252. title:"root",
  253. sequence:[second,sixth,fourth,third,first]
  254. };
  255. var queue = new Array();
  256. var actionSequence = new Array();
  257. var nowNode = null;//存储现在所在的节点
  258. var lastNode = null;
  259. // 根据元素类型返回不同元素的样式
  260. function newNode(node)
  261. {
  262. id = node["id"];
  263. title = node["title"];
  264. type = node["type"];
  265. if(type==0) //顺序
  266. {
  267. return `<div class="sequence"><div class="node clk" data="${id}" id = "${id}" position=${node["position"]} pId=${node["parentId"]}>
  268. <div >
  269. <p>${title}</p>
  270. </div>
  271. </div>
  272. <p class="arrow" position=${node["position"]} data = "${id}" pId=${node["parentId"]}>↓</p></div>`;
  273. }
  274. else if(type==1) //循环
  275. {
  276. return `<div class="loop clk" data="${id}" id = "${id}" position=${node["position"]} pId=${node["parentId"]}>
  277. <p style="background:#d6d6d6;text-align:left;padding:2px">${title}</p>
  278. <p class="arrow" position=-1 data = "${id}" pId=${id}>↓</p>
  279. </div>
  280. <p class="arrow" data = "${id}" position=${node["position"]} pId=${node["parentId"]}>↓</p></div>`;
  281. }
  282. else if(type==2) //判断
  283. {
  284. return `<div class="loop clk" data="${id}" position=${node["position"]} pId=${node["parentId"]}>
  285. <p style="background:#d6d6d6;text-align:left;padding:2px">${title}</p>
  286. <p class="branchAdd" data="${id}">点击此处在最左边增加条件分支</p>
  287. <div class="judge" id = "${id}">
  288. </div></div>
  289. <p class="arrow" data = "${id}" position=${node["position"]} pId=${node["parentId"]}>↓</p></div>`;
  290. }
  291. else //判断分支
  292. {
  293. return `<div class="branch clk" data="${id}" position=${node["position"]} pId=${node["parentId"]}>
  294. <p style="background:#d6d6d6;text-align:left;padding:2px">${title}</p>
  295. <p data = "${id}" class="arrow" position=-1 pId=${id}>↓</p>
  296. <div id = "${id}">
  297. </div></div>`;
  298. }
  299. }
  300. //增加分支点击事件
  301. function branchClick(e)
  302. {
  303. let judgeId = this.getAttribute('data');
  304. var t = {
  305. id:0,
  306. parentId:0,
  307. type:3,
  308. option:12,
  309. title:"条件分支",
  310. sequence:[]
  311. };
  312. actionSequence[judgeId]["sequence"].splice(0,0,t);
  313. refresh();
  314. e.stopPropagation();//防止冒泡
  315. }
  316. //元素点击事件
  317. function elementClick(e)
  318. {
  319. let title = this.getAttribute('data');
  320. if(nowNode != null)
  321. {
  322. nowNode.style.borderColor="skyblue";
  323. }
  324. nowNode = this;
  325. this.style.borderColor="blue";
  326. e.stopPropagation();//防止冒泡
  327. }
  328. var option = 0;//选择要增加的内容
  329. var title = "";
  330. //箭头点击事件
  331. function arrowClick(e)
  332. {
  333. if(option==10)
  334. {
  335. console.log(nowNode);
  336. if(nowNode==null)
  337. {
  338. e.stopPropagation();//防止冒泡
  339. }
  340. else if($(nowNode).is(".branch"))
  341. {
  342. alert("判断分支不可移动!");
  343. e.stopPropagation();//防止冒泡
  344. }
  345. else
  346. {
  347. let position = parseInt(nowNode.getAttribute('position'));
  348. let pId = nowNode.getAttribute('pId');
  349. var position2 = parseInt(this.getAttribute('position'));
  350. var pId2 = this.getAttribute('pId');
  351. var id = nowNode.getAttribute('data');
  352. var pidt = pId2;
  353. var move = true;
  354. console.log(pidt,id);
  355. while(pidt!=0)
  356. {
  357. if(pidt==id)
  358. {
  359. move=false;
  360. break;
  361. }
  362. pidt = actionSequence[pidt]["parentId"];
  363. }
  364. if(move) //如果自己要移动到自己节点里就不允许移动
  365. {
  366. let element = actionSequence[pId]["sequence"].splice(position,1);//在相应位置删除元素
  367. if(pId==pId2 && position<position2) //如果要移动的位置属于同一层并且是从前往后移动,注意需要控制数组插入位置向前错位
  368. {
  369. position2--;
  370. }
  371. console.log(element);
  372. actionSequence[pId2]["sequence"].splice(position2+1,0,element[0]);//在相应位置添加新元素
  373. refresh();//重新渲染页面
  374. }
  375. else
  376. {
  377. alert("自己不能移动到自己的节点里!");
  378. }
  379. e.stopPropagation();//防止冒泡
  380. }
  381. }
  382. else if(option>0)
  383. {
  384. var t = {
  385. id:0,
  386. parentId:0,
  387. type:0,
  388. option:option,
  389. title:title,
  390. sequence:[]
  391. };
  392. if(option == 8)//循环
  393. {
  394. t["type"]=1;
  395. }
  396. else if(option==9)//判断
  397. {
  398. t["type"]=2;
  399. // 增加两个分支
  400. var nt=
  401. {
  402. id:0,
  403. parentId:0,
  404. type:3,
  405. option:option,
  406. title:"条件分支",
  407. sequence:[]
  408. };
  409. var nt2=
  410. {
  411. id:0,
  412. parentId:0,
  413. type:3,
  414. option:option,
  415. title:"条件分支",
  416. sequence:[]
  417. };
  418. t["sequence"].push(nt);
  419. t["sequence"].push(nt2);
  420. }
  421. let position = parseInt(this.getAttribute('position'));
  422. let pId = this.getAttribute('pId');
  423. actionSequence[pId]["sequence"].splice(position+1,0,t);//在相应位置添加新元素
  424. refresh();//重新渲染页面
  425. e.stopPropagation();//防止冒泡
  426. }
  427. option = 0;
  428. }
  429. $(".openPage").click(function(){
  430. option = this.getAttribute("data");
  431. title = this.innerHTML;
  432. if(option>=10 && nowNode==null)
  433. {
  434. alert("目前未选中元素");
  435. }
  436. else if(option==12)
  437. {
  438. deleteElement();
  439. }
  440. });
  441. function bindEvents()
  442. {
  443. // 清空原来的listener然后再添加新的listener
  444. let rect = document.getElementsByClassName('clk');
  445. for (let i = 0, rule; rule = rect[i++];) {
  446. rule.removeEventListener('click',elementClick);
  447. rule.addEventListener('click',elementClick);
  448. }
  449. let arr = document.getElementsByClassName('arrow');
  450. for (let i = 0, rule; rule = arr[i++];) {
  451. rule.removeEventListener('click',arrowClick);
  452. rule.addEventListener('click',arrowClick);
  453. }
  454. let branch = document.getElementsByClassName('branchAdd');
  455. for (let i = 0, rule; rule = branch[i++];) {
  456. rule.removeEventListener('click',branchClick);
  457. rule.addEventListener('click',branchClick);
  458. }
  459. }
  460. //重新画图
  461. function refresh()
  462. {
  463. $("#0").empty();
  464. $("#0").append(`<div style="border-radius: 50%;width: 40px;height: 40px;border:solid;border-color:seagreen;margin:5px auto;background-color:lightcyan;margin-top:20px">
  465. <p style="font-size: 24px!important;text-align: center;margin-left: 6px;font-family:'Times New Roman'">▶</p>
  466. </div>
  467. <p id="testAdd" class="arrow" position=-1 pId=0>↓</p>`);
  468. actionSequence.splice(0);
  469. queue.splice(0);
  470. var idd = 1;
  471. queue.push(root);
  472. actionSequence.push(root);
  473. while(queue.length!=0)
  474. {
  475. var nd = queue.shift();
  476. for(i = 0;i<nd.sequence.length;i++)
  477. {
  478. nd.sequence[i].parentId = nd.id;
  479. nd.sequence[i]["position"] = i;
  480. nd.sequence[i].id = idd++;
  481. queue.push(nd.sequence[i]);
  482. actionSequence.push(nd.sequence[i]);
  483. }
  484. }
  485. console.log(actionSequence);
  486. //第一个元素不渲染
  487. for(i=1;i<actionSequence.length;i++)
  488. {
  489. parentId = actionSequence[i]["parentId"];
  490. $("#"+parentId).append(newNode(actionSequence[i]));
  491. }
  492. bindEvents();
  493. }
  494. function deleteElement()
  495. {
  496. let position = parseInt(nowNode.getAttribute('position'));
  497. let pId = nowNode.getAttribute('pId');
  498. actionSequence[pId]["sequence"].splice(position,1);//在相应位置删除元素
  499. refresh();//重新渲染页面
  500. e.stopPropagation();//防止冒泡
  501. }
  502. document.oncontextmenu=function(){return false;}//屏蔽右键菜单
  503. //删除元素
  504. document.onkeydown = function (e)
  505. {
  506. if(nowNode!=null && e.keyCode == 46)
  507. {
  508. if(confirm("确定要删除元素吗?"))
  509. {
  510. deleteElement();
  511. }
  512. }
  513. }
  514. refresh();
  515. </script>