1
0

toolkit.vue 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
  1. <template>
  2. <div id="realcontent">
  3. <!-- <div id="EasySpiderResizer" style="width: 10px; height: 10px; background-color: black; position: absolute; left: 0; bottom: 0; cursor: ne-resize;"></div>-->
  4. <div id="EasySpiderResizer"
  5. style="width: 10px; height: 10px; position: absolute; left: 0; top: 0; cursor: nw-resize;"></div>
  6. <span id="closeButton">&#x2716;</span>
  7. <div v-if="lang == 'zh'">
  8. <div class="tooldrag">✍操作台(点此拖动,左上角调整大小)</div>
  9. <div class="realcontent">
  10. <div v-if="page==0">
  11. <div v-if="list.nl.length==0" :style="{overflow: 'auto', maxHeight: winHeight * 0.4 + 'px'}">
  12. <!-- <input style="width:15px;height:15px;vertical-align:middle;" type="checkbox"-->
  13. <!-- v-on:mousedown="specialSelect"/>-->
  14. <!-- <p style="margin-bottom:10px;display:inline-block">特殊点选模式<span-->
  15. <!-- title="普通模式下如果不能选中元素可以勾选此项">☺</span></p>-->
  16. <p style="color: darkviolet;" v-if="nextPage==1">
  17. ● 检测到您添加了采集数据操作,如需设置采集后的翻页操作,请点击下方设置翻页操作选项。</p>
  18. <div class="innercontent" v-if="list.nl.length==0">
  19. <div v-if="nextPage==1" class="nextPage">
  20. <a v-on:mousedown="setNextPage">设置翻页操作</a><span title="可根据提示指定翻页按钮">☺</span></div>
  21. <div><a v-on:mousedown="getCurrentTitle">采集当前页面的标题</a><span title="当前页面标题">☺</span></div>
  22. <div><a v-on:mousedown="getCurrentURL">采集当前页面的网址</a><span title="当前页面URL地址">☺</span></div>
  23. </div>
  24. <p style="color:black; margin-top: 10px">● 鼠标移动到笑脸<span style="font-size: 20px">☺</span>查看操作提示。</p>
  25. <p style="color:black; margin-top: 10px">●
  26. 鼠标移动到元素上后,请<strong>右键</strong>点击或者按<strong>F7</strong>键选中页面元素。
  27. </p>
  28. <p style="color:black; margin-top: 10px">●
  29. 如果此操作台把页面元素挡住了,可以点击此操作台右下角的×按钮键关闭操作台。</p>
  30. <p style="color:black; margin-top: 10px">●
  31. 通过鼠标左键进行点击时,页面也会有反应,但左键点击发生的操作不会被记录在任务流程中;同理,如果想输入文本框但并不想将动作记录,可以鼠标移动到文本框,并按键盘的<strong>F9</strong>进行输入。
  32. </p>
  33. <p style="color:black; margin-top: 10px">●
  34. 如果不小心左键点选了元素导致页面跳转,直接后退或者切换回标签页即可。</p>
  35. <p style="color:black; margin-top: 10px">● 操作完成后,如点击”确认采集“后任务流程图内没有”提取数据“操作被添加,<strong>重试一次</strong>即可。
  36. </p>
  37. {{ initial() }}
  38. </div>
  39. <div v-if="list.nl.length==1">
  40. <div v-if="tname()!='null'">
  41. ● 已选中{{ numOfList() }}个{{ tname() }},<span
  42. v-if="numOfReady()>0&&tname()!='下一页元素'">同时发现{{
  43. numOfReady()
  44. }}个同类元素(如果不全或不准请继续手动选择其余您认为的同类元素),</span>您可以:
  45. <div class="innercontent">
  46. <div v-if="numOfReady()>0 && !selectStatus"><a v-on:mousedown="selectAll">选中全部</a> <span
  47. title=""></span></div>
  48. <div v-if="existDescendents()&& !selectStatus &&(tname()=='元素' || tname()=='链接')"><a
  49. v-on:mousedown="selectDescendents">选中子元素</a> <span
  50. title="应选尽选模式,如想使用其他模式请先选中全部再选中子元素">☺</span></div>
  51. <div v-if="!selectedDescendents && !selectStatus" id="Single">
  52. <div v-if="tname()=='选择框'"><a v-on:mousedown="changeSelect">切换下拉选项</a><span title=""></span>
  53. </div>
  54. <div v-if="tname()=='文本框'"><a v-on:mousedown="setInput(false)">输入文字</a><span title=""></span>
  55. </div>
  56. <div v-if="tname()=='文本框'"><a v-on:mousedown="setInput(true)">批量输入文字</a><span
  57. title=""></span></div>
  58. <div v-if="tname()!='图片'"><a v-on:mousedown="getText">采集该{{ tname() }}的文本</a><span
  59. title="采集文本"></span></div>
  60. <div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedValue">采集当前选中项的值</a><span
  61. title=""></span></div>
  62. <div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedText">采集当前选中项的文本</a><span
  63. title=""></span></div>
  64. <div v-if="tname()=='链接'||tname()=='图片'"><a
  65. v-on:mousedown="getLink">采集该{{ tname() }}的地址</a><span title=""></span></div>
  66. <div><a
  67. v-on:mousedown="clickElement">点击该{{ tname() }}</a><span title=""></span></div>
  68. <div v-if="tname()!='选择框' && tname()!='文本框'"><a
  69. v-on:mousedown="loopClickSingleElement">循环点击该{{ tname() }}</a><span
  70. title="常用于循环点击下一页场景">☺</span></div>
  71. <div><a v-on:mousedown="getBackgroundPic">采集该{{ tname() }}的背景图片地址</a><span
  72. title="部分元素的图片是设定为背景图像的">☺</span></div>
  73. <div v-if="tname()=='链接'||tname()=='元素'"><a v-on:mousedown="getInnerHtml">采集该{{
  74. tname()
  75. }}的Inner
  76. Html</a><span title="不包括元素自身标签的HTML">☺</span></div>
  77. <div><a v-on:mousedown="getOuterHtml">采集该{{ tname() }}的Outer Html</a><span
  78. title="包括元素自身标签的HTML">☺</span></div>
  79. <div><a href="#" v-on:mousedown="mouseMove">鼠标移动到该{{ tname() }}上</a><span title=""></span>
  80. </div>
  81. <!-- <div v-if="tname()=='文本框'"><a>识别验证码</a><span title="">☺</span></div>-->
  82. </div>
  83. <div v-if="selectedDescendents" id="Single">
  84. <div><a v-on:mousedown="confirmCollectSingle">采集数据</a><span title=""></span></div>
  85. </div>
  86. <div v-if="selectStatus" id="Confirm">
  87. <div><a v-on:mousedown="confirmCollectSingle">确认采集</a><span title=""></span></div>
  88. </div>
  89. </div>
  90. </div>
  91. </div>
  92. <div v-if="list.nl.length>1">
  93. <div v-if="option==100">
  94. ● 已选择了以下元素,您可以:
  95. <div class="innercontent">
  96. <div><a v-on:mousedown="confirmCollectMulti">采集数据</a><span title=""></span></div>
  97. <div><a v-on:mousedown="revoke">撤销本次选择</a><span title=""></span></div>
  98. </div>
  99. </div>
  100. <div v-if="option!=100">
  101. ● 已选择了{{ numOfList() }}个同类元素,<span
  102. v-if="numOfReady()>0">另外发现{{
  103. numOfReady()
  104. }}个同类元素(如果不全或不准请继续手动选择其余您认为的同类元素),</span>您可以:
  105. <div class="innercontent">
  106. <div v-if="numOfReady()>0"><a v-on:mousedown="selectAll">选中全部</a><span title=""></span></div>
  107. <div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
  108. v-on:mousedown="selectDescendents">选中子元素(应选尽选)</a><span
  109. title="每个块的每个子元素都选中进来">☺</span></div>
  110. <div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
  111. v-on:mousedown="selectDescendents(1,1)">选中子元素(相对首选块共同元素)</a><span
  112. title="只选中和第一个选中块的子元素共同的子元素">☺</span></div>
  113. <div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
  114. v-on:mousedown="selectDescendents(1,2)">选中子元素(所有块共同元素)</a><span
  115. title="只选中所有块都有的子元素">☺</span></div>
  116. <div><a v-on:mousedown="confirmCollectMultiAndDescendents">采集数据</a><span title=""></span></div>
  117. <div v-if="tname()!='选择框' && tname()!='文本框' && !selectedDescendents"><a
  118. v-on:mousedown="loopClickEveryElement">循环点击每个{{ tname() }}</a><span
  119. title="常用于循环点击列表中的链接打开详情页采集场景">☺</span></div>
  120. <div v-if="tname()!='选择框' && tname()!='文本框' && !selectedDescendents"><a
  121. v-on:mousedown="loopMouseMove">循环移动到每个{{ tname() }}</a><span title=""></span></div>
  122. <div><a v-on:mousedown="revoke">撤销本次选择</a><span title=""></span></div>
  123. </div>
  124. </div>
  125. </div>
  126. <div v-if="valTable.length>0">
  127. <div class="toolkitcontain">
  128. <table cellSpacing="0" class="toolkittb2">
  129. <tbody>
  130. <th v-for="(i, index) in list.opp">
  131. <div>{{ i["name"] }}</div>
  132. <span v-bind:index="index" v-on:mousedown="removeField" title="删除此字段">×</span></th>
  133. <th style="width:40px">删除</th>
  134. </tbody>
  135. </table>
  136. <table cellSpacing="0" class="toolkittb4">
  137. <tbody>
  138. <tr v-for="i in valTable[0].length">
  139. <td v-for="j in list.opp.length">{{ valTable[j - 1][i - 1] }}</td>
  140. <td style="font-size: 22px!important;width:40px;cursor:pointer" v-bind:index="i-1"
  141. v-on:mousedown="deleteSingleLine">×
  142. </td>
  143. </tr>
  144. </tbody>
  145. </table>
  146. </div>
  147. </div>
  148. <!-- <div v-if="valTable.length==0&&tname()!='下一页元素'"></div>-->
  149. <div v-if="list.nl.length>0"
  150. style="bottom:12px;position:absolute;color:black!important;left:17px;font-size:13px">
  151. <div style="margin-bottom:5px">
  152. <button v-on:mousedown="cancel">取消选择</button>
  153. <button v-if="!selectStatus" v-on:mousedown="enlarge">扩大选区</button>
  154. </div>
  155. <p style="margin-left:16px;margin-bottom:0px">{{ lastElementXPath() }}</p>
  156. </div>
  157. </div>
  158. <div v-else-if="page==1">
  159. ● 请输入文字:
  160. <input id="WTextBox" v-model="text" autoFocus="autofocus" type="text"></input>
  161. <button style="margin-left:0px!important;" v-on:click="getInput">确定</button>
  162. <button style="margin-left:0px!important;" v-on:click="cancelInput">取消</button>
  163. <div style="text-align: justify;margin-top: 15px;padding-right: 15px;margin-left: 4px">
  164. 输入&lt;enter&gt;或&lt;ENTER&gt;表示输入完成后模拟按下回车键,适用于只能通过回车键获得数据的情况。
  165. </div>
  166. </div>
  167. <div v-else-if="page==2">
  168. <span style="font-size: 15px"> ● 切换模式 </span>
  169. <select v-model="optionMode" @change="handleSelectChange">
  170. <option value=0>切换到下一个选项</option>
  171. <option value=1>按索引值切换选项</option>
  172. <option value=2>按选项值切换选项</option>
  173. <option value=3>按选项文本切换选项</option>
  174. </select>
  175. <span style="font-size: 15px" v-if="optionMode == 3"> ● 选项文本</span>
  176. <span style="font-size: 15px" v-if="optionMode == 1"> ● 索引值</span>
  177. <span style="font-size: 15px" v-if="optionMode == 2"> ● 选项值</span>
  178. <input id="selectValue" v-if="optionMode != 0" v-model="optionValue" autoFocus="autofocus"
  179. type="text"></input>
  180. <div>
  181. <button style="margin-left:0px!important;" v-on:click="sendChangeSelect">确定</button>
  182. <button style="margin-left:0px!important;" v-on:click="cancelInput">取消</button>
  183. </div>
  184. </div>
  185. <div v-else-if="page==3">
  186. <span
  187. style="font-size: 15px"> ● 请在页面上右键选择要点击的下一页按钮/链接,如要取消设置翻页操作,请点击下方取消选项。</span>
  188. <div style="font-size: 15px" v-if="list.nl.length==1">
  189. ● 已选中一个元素:<span style="color:darkviolet">{{getSelectedInnerText()}}</span>,您可以点击下方选项确认设置翻页操作。
  190. </div>
  191. <div style="font-size: 15px; color: #c82333;" v-else-if="list.nl.length>1">
  192. ● 翻页操作只能设置一个元素,请点击下方取消翻页操作选项并重新选择。
  193. </div>
  194. <div class="innercontent">
  195. <div><a href="#" v-on:mousedown="confirmNextPage" v-if="list.nl.length==1" style="margin-bottom: 5px">确认设置翻页操作</a>
  196. </div>
  197. <div><a href="#" v-on:mousedown="cancelNextPage">取消设置翻页操作</a></div>
  198. </div>
  199. </div>
  200. </div>
  201. </div>
  202. <div v-else-if="lang=='en'">
  203. <div class="tooldrag">✍Toolbox (Can drag, resize at left corner)</div>
  204. <div class="realcontent">
  205. <div v-if="page==0">
  206. <div v-if="list.nl.length==0" :style="{overflow: 'auto', maxHeight: winHeight * 0.4 + 'px'}">
  207. <!-- <input style="width:15px;height:15px;vertical-align:middle;" type="checkbox"-->
  208. <!-- v-on:mousedown="specialSelect"> </input>-->
  209. <!-- <p style="margin-bottom:10px;display:inline-block">Special click mode<span-->
  210. <!-- title="If cannot select element by mouse, select this option">☺</span></p>-->
  211. <p style="color: darkviolet;" v-if="nextPage==1">
  212. ● A data collection operation has just been detected. If you need to configure pagination after data collection, please click
  213. the option below to set up pagination.</p>
  214. <div class="innercontent" v-if="list.nl.length==0">
  215. <div v-if="nextPage==1" class="nextPage">
  216. <a v-on:mousedown="setNextPage">Set up pagination</a><span
  217. title="Follow the prompt to specify the paging button">☺</span></div>
  218. <div><a v-on:mousedown="getCurrentTitle">Collect Title of current page</a><span
  219. title="Title of this page">☺</span></div>
  220. <div><a v-on:mousedown="getCurrentURL">Collect URL of current page</a><span
  221. title="URL of this page">☺</span></div>
  222. </div>
  223. <p style="color:black; margin-top: 10px">● Mouse move to smiling face <span style="font-size: 20px">☺</span> to see operation help.</p>
  224. <p style="color:black; margin-top: 10px">● When your mouse moves to the element, please
  225. <strong>right-click</strong> your
  226. mouse button or press <strong>F7</strong> on the keyboard to select it.</p>
  227. <p style="color:black; margin-top: 10px">● If this toolbox blocks the page element, you can click the ×
  228. button in the
  229. lower right corner of this toolbox to close it.</p>
  230. <p style="color:black; margin-top: 10px">● When clicked with the left mouse button, the page will also
  231. respond, but this click operation will not be recorded in the task flow. Similarly, if you want to input
  232. in a text box but do not want the action to be recorded , you can move the mouse to the text box and
  233. press
  234. <strong>F9</strong> on the keyboard to input.</p>
  235. <p style="color:black; margin-top: 10px">● If you accidentally left-click on an element and cause the page
  236. to jump, simply go back or switch back to the tab.</p>
  237. <p style="color:black; margin-top: 10px">● After the operation is completed, such as if no "Collect Data"
  238. operation is added in the task flowchart after clicking "Confirm Collect", just <strong> retry </strong>
  239. again.</p>
  240. {{ initial() }}
  241. </div>
  242. <div v-if="list.nl.length==1">
  243. <div v-if="tname()!='null'">
  244. ● Already selected {{ numOfList() }} {{ tname() | toEng }}, <span
  245. v-if="numOfReady()>0&&tname()!='下一页元素'"> meanwhile we find {{ numOfReady() }} element with the same type (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
  246. can:
  247. <div class="innercontent">
  248. <div v-if="numOfReady()>0 && !selectStatus"><a v-on:mousedown="selectAll">Select All</a><span
  249. title=""></span></div>
  250. <div v-if="existDescendents()&& !selectStatus &&(tname()=='元素' || tname()=='链接')"><a
  251. v-on:mousedown="selectDescendents">Select child elements</a> <span
  252. title="Greedy Mode, if you want to use other modes, please select 'Select All' option first">☺</span>
  253. </div>
  254. <div v-if="!selectedDescendents && !selectStatus" id="Single">
  255. <!-- <div v-if="tname()=='selection box'"> <a>循环切换该下拉项</a><span title="">☺</span></div> -->
  256. <div v-if="tname()=='选择框'"><a v-on:mousedown="changeSelect">Change selection option</a><span
  257. title=""></span></div>
  258. <div v-if="tname()=='文本框'"><a v-on:mousedown="setInput(false)">Input Text</a><span
  259. title=""></span>
  260. </div>
  261. <div v-if="tname()=='文本框'"><a v-on:mousedown="setInput(true)">Input Text (Batch)</a><span
  262. title=""></span>
  263. </div>
  264. <div v-if="tname()!='图片'"><a v-on:mousedown="getText">Extract {{ tname() | toEng }}'s
  265. text</a><span
  266. title="collect text"></span></div>
  267. <div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedValue">Collect selected option
  268. value</a><span
  269. title=""></span></div>
  270. <div v-if="tname()=='选择框'"><a v-on:mousedown="getSelectedText">Collect selected option
  271. text</a><span title=""></span></div>
  272. <div v-if="tname()=='链接'||tname()=='图片'"><a v-on:mousedown="getLink">Collect address of this
  273. {{ tname() | toEng }}</a><span title=""></span></div>
  274. <div><a v-on:mousedown="clickElement">Click
  275. this {{ tname() | toEng }}</a><span title=""></span></div>
  276. <div v-if="tname()!='选择框' && tname()!='文本框'"><a
  277. v-on:mousedown="loopClickSingleElement">Loop-click this {{ tname() | toEng }}</a><span
  278. title="Usually used to loop-click the next-page button">☺</span>
  279. </div>
  280. <div><a v-on:mousedown="getBackgroundPic">Collect background image URL</a><span
  281. title="Some elements have background images">☺</span></div>
  282. <div v-if="tname()=='链接'||tname()=='元素'"><a v-on:mousedown="getInnerHtml">Collect Inner Html of
  283. this {{ tname() | toEng }}</a><span
  284. title="HTML not including the tag of this selected element">☺</span></div>
  285. <div><a v-on:mousedown="getOuterHtml">Collect Outer Html of this element</a><span
  286. title="HTML including the tag of this selected element">☺</span>
  287. </div>
  288. <div><a href="#" v-on:mousedown="mouseMove">Move mouse to this element</a><span title=""></span>
  289. </div>
  290. <!-- <div v-if="tname()=='text box'"> <a>识别验证码</a><span title="">☺</span></div> -->
  291. </div>
  292. <div v-if="selectedDescendents" id="Single">
  293. <div><a v-on:mousedown="confirmCollectSingle">Collect Data</a><span title=""></span></div>
  294. </div>
  295. <div v-if="selectStatus" id="Confirm">
  296. <div><a v-on:mousedown="confirmCollectSingle">Confirm Collect</a><span title=""></span></div>
  297. </div>
  298. </div>
  299. </div>
  300. </div>
  301. <div v-if="list.nl.length>1">
  302. <div v-if="option==100">
  303. ● Already selected the following element, you can:
  304. <div class="innercontent">
  305. <div><a v-on:mousedown="confirmCollectMulti">Collect Data</a><span title=""></span></div>
  306. <div><a v-on:mousedown="revoke">Revoke selection</a><span title=""></span></div>
  307. </div>
  308. </div>
  309. <div v-if="option!=100">
  310. ● Already selected {{ numOfList() }} similar elements, <span
  311. 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
  312. can:
  313. <div class="innercontent">
  314. <div v-if="numOfReady()>0"><a v-on:mousedown="selectAll">Select All</a><span title=""></span></div>
  315. <div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
  316. v-on:mousedown="selectDescendents">Select child elements (Greedy)</a><span
  317. title="Select All child elements for all blocks">☺</span></div>
  318. <div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
  319. v-on:mousedown="selectDescendents(1,1)">Select child elements (RFSE)</a><span
  320. 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>
  321. </div>
  322. <div v-if="existDescendents()&&(tname()=='元素' || tname()=='链接')"><a
  323. v-on:mousedown="selectDescendents(1,2)">Select child elements (RASE)</a><span
  324. title="Relative to All Selected Elements, will select only the common child elements that exist in all blocks">☺</span>
  325. </div>
  326. <div><a v-on:mousedown="confirmCollectMultiAndDescendents">Collect Data</a><span title=""></span>
  327. </div>
  328. <div v-if="tname()!='选择框' && tname()!='文本框' && !selectedDescendents"><a
  329. v-on:mousedown="loopClickEveryElement">Loop-click every {{ tname() | toEng }}</a><span
  330. title="Usually used to click every link in a list to open detail page to collect data">☺</span>
  331. </div>
  332. <div v-if="tname()!='选择框' && tname()!='文本框' && !selectedDescendents"><a
  333. v-on:mousedown="loopMouseMove">Loop-mouse-move to every {{ tname() | toEng }}</a><span
  334. title=""></span></div>
  335. <div><a v-on:mousedown="revoke">Revoke selection</a><span title=""></span></div>
  336. </div>
  337. </div>
  338. </div>
  339. <div v-if="valTable.length>0">
  340. <div class="toolkitcontain">
  341. <table cellspacing="0" class="toolkittb2">
  342. <tbody>
  343. <th v-for="(i, index) in list.opp">
  344. <div>{{ i["name"] }}</div>
  345. <span v-bind:index="index" v-on:mousedown="removeField" title="Remove this field">×</span></th>
  346. <th style="width:40px">Delete</th>
  347. </tbody>
  348. </table>
  349. <table cellspacing="0" class="toolkittb4">
  350. <tbody>
  351. <tr v-for="i in valTable[0].length">
  352. <td v-for="j in list.opp.length">{{ valTable[j - 1][i - 1] }}</td>
  353. <td style="font-size: 22px!important;width:40px;cursor:pointer" v-bind:index="i-1"
  354. v-on:mousedown="deleteSingleLine">×
  355. </td>
  356. </tr>
  357. </tbody>
  358. </table>
  359. </div>
  360. </div>
  361. <div v-if="valTable.length==0&&tname()!='下一页元素'"></div>
  362. <div v-if="list.nl.length>0"
  363. style="bottom:12px;position:absolute;color:black!important;left:17px;font-size:13px">
  364. <div style="margin-bottom:5px">
  365. <button v-on:mousedown="cancel">Deselect</button>
  366. <button v-if="!selectStatus" v-on:mousedown="enlarge">Expand Path</button>
  367. </div>
  368. <p style="margin-left:16px;margin-bottom:0px">{{ lastElementXPath() }}</p>
  369. </div>
  370. </div>
  371. <div v-else-if="page==1">
  372. ● Please input text:
  373. <input id="WTextBox" v-model="text" autofocus="autofocus" type="text"></input>
  374. <button style="margin-left:0px!important;" v-on:click="getInput">Confirm</button>
  375. <button style="margin-left:0px!important;" v-on:click="cancelInput">Cancel</button>
  376. <div style="text-align: justify;margin-top: 15px;padding-right: 15px;margin-left: 4px">
  377. Inputting &lt;enter&gt; or &lt;ENTER&gt; represents the simulation of pressing the Enter key after input
  378. is complete, which is applicable in situations where data can only be obtained through pressing the Enter
  379. key.
  380. </div>
  381. </div>
  382. <div v-else-if="page==2">
  383. <span style="font-size: 15px"> ● Change Mode </span>
  384. <select v-model="optionMode" @change="handleSelectChange">
  385. <option value=0>Change to next option</option>
  386. <option value=1>Change option by index</option>
  387. <option value=2>Change option by value</option>
  388. <option value=3>Change option by text</option>
  389. </select>
  390. <span style="font-size: 15px" v-if="optionMode == 3"> ● Option Text</span>
  391. <span style="font-size: 15px" v-if="optionMode == 1"> ● Option Index</span>
  392. <span style="font-size: 15px" v-if="optionMode == 2"> ● Option Value</span>
  393. <input id="selectValue" v-if="optionMode != 0" v-model="optionValue" autoFocus="autofocus"
  394. type="text"></input>
  395. <div>
  396. <button style="margin-left:0px!important;" v-on:click="sendChangeSelect">Confirm</button>
  397. <button style="margin-left:0px!important;" v-on:click="cancelInput">Cancel</button>
  398. </div>
  399. </div>
  400. <div v-else-if="page==3">
  401. <span style="font-size: 15px"> ● Please right-click on the page and select the next page button/link. To cancel the pagination setup, click the option below.</span>
  402. <div style="font-size: 15px" v-if="list.nl.length==1">
  403. ● A single element has been selected: <span style="color:darkviolet">{{getSelectedInnerText()}}</span>, you can click the option below to confirm the pagination setup.
  404. </div>
  405. <div style="font-size: 15px; color: #c82333;" v-else-if="list.nl.length>1">
  406. ● The page-turning operation can only be set for one element. Please click the option below to cancel the
  407. page-turning operation and reselect.
  408. </div>
  409. <div class="innercontent">
  410. <div><a href="#" v-on:mousedown="confirmNextPage" v-if="list.nl.length==1" style="margin-bottom: 5px">Confirm
  411. Pagination Setup</a>
  412. </div>
  413. <div><a href="#" v-on:mousedown="cancelNextPage">Cancel Pagination Setup</a></div>
  414. </div>
  415. </div>
  416. </div>
  417. </div>
  418. </div>
  419. </template>
  420. <script>
  421. import {
  422. global,
  423. isInIframe,
  424. getOS,
  425. readXPath,
  426. addEl,
  427. clearEl,
  428. clearReady,
  429. handleElement,
  430. clearParameters,
  431. generateParameters,
  432. generateMultiParameters,
  433. handleDescendents,
  434. generateValTable,
  435. findRelated,
  436. pushToReadyList,
  437. readyToList,
  438. combineXpath,
  439. relatedTest, getElementXPaths, selectAllElements
  440. } from "./global.js";
  441. import {
  442. input,
  443. sendSingleClick,
  444. collectSingle,
  445. collectMultiNoPattern,
  446. collectMultiWithPattern,
  447. sendLoopClickSingle,
  448. sendLoopClickEvery,
  449. detectAllSelected, sendChangeOption, sendMouseMove, sendLoopMouseMove
  450. } from "./messageInteraction.js";
  451. import $ from "jquery";
  452. export default {
  453. el: '#realcontent',
  454. data: {
  455. lang: global.lang,
  456. batch: false, //是否为批量输入模式
  457. option: 0,
  458. list: {nl: global.nodeList, opp: global.outputParameters},
  459. valTable: [], // 用来存储转换后的参数列表
  460. special: false, //是否为特殊选择模式
  461. selectedDescendents: false, // 标记是否选中了子元素
  462. selectStatus: false, //标记单个元素是否点击了采集
  463. page: 0, //默认页面,1为输入文字页面
  464. text: "", // 记录输入的文字
  465. tNodeName: "", // 记录临时节点列表
  466. nowPath: "", //现在元素的xpath
  467. nowAllPaths: [], //现在元素的所有xpath
  468. winHeight: window.outerHeight,
  469. optionMode: 0,
  470. optionValue: "",
  471. mode: 0, //记录删除字段模式
  472. nextPage: 0, //是否设置翻页操作
  473. lastAction: "collectData", //记录上一次的操作
  474. global: global,
  475. },
  476. mounted() {
  477. this.$nextTick(() => {
  478. window.addEventListener('resize', this.onResize);
  479. });
  480. if (isInIframe()) {
  481. global.iframe = true;
  482. }
  483. // 获取页面上所有的iframe
  484. let iframes = document.getElementsByTagName('iframe');
  485. // 循环遍历所有的iframe
  486. for (let i = 0; i < iframes.length; i++) {
  487. let iframe = iframes[i];
  488. // 获取iframe的当前高度
  489. let currentHeight = iframe.offsetHeight;
  490. console.log("IFRAME: ", getElementXPaths(iframe), readXPath(iframe));
  491. console.log("IFrame Height: ", currentHeight, "px")
  492. // 如果当前高度小于600px,那么将其设置为600px
  493. if (currentHeight < 600) {
  494. iframe.style.height = '600px!important';
  495. iframe.height = '600';
  496. }
  497. let currentWidth = iframe.offsetWidth;
  498. console.log("IFrame Width: ", currentWidth, "px")
  499. // 如果当前高度小于600px,那么将其设置为600px
  500. if (currentWidth < 600) {
  501. iframe.style.width = '600px!important';
  502. iframe.width = '600';
  503. }
  504. }
  505. },
  506. beforeDestroy() {
  507. window.removeEventListener('resize', this.onResize);
  508. },
  509. watch: {
  510. nowPath: { //变量发生变化的时候进行一些操作
  511. handler: function (newVal, oldVal) {
  512. console.log("xpath:", newVal);
  513. }
  514. }
  515. },
  516. filters: {
  517. toEng: function (value) {
  518. if (value == "下一页元素") {
  519. return "elements in next page";
  520. } else if (value == "链接") {
  521. return "link";
  522. } else if (value == "图片") {
  523. return "image";
  524. } else if (value == "按钮") {
  525. return "button";
  526. } else if (value == "文本框") {
  527. return "text box";
  528. } else if (value == "选择框") {
  529. return "selection box";
  530. } else {
  531. return "element";
  532. }
  533. }
  534. },
  535. methods: {
  536. onResize() {
  537. this.winHeight = window.outerHeight
  538. },
  539. initial: function () { //每当元素是0的时候,执行值的初始化操作
  540. this.selectedDescendents = false;
  541. this.selectStatus = false;
  542. this.nowPath = "";
  543. console.log("initialized")
  544. },
  545. confirmCollectSingle: function () { //单元素确认采集
  546. collectSingle();
  547. clearEl();
  548. this.nextPage = 1;
  549. this.lastAction = "collectData";
  550. },
  551. confirmCollectMulti: function () { //无规律多元素确认采集
  552. collectMultiNoPattern();
  553. clearEl();
  554. this.nextPage = 1;
  555. this.lastAction = "collectData";
  556. },
  557. confirmCollectMultiAndDescendents: function () { //有规律多元素确认采集
  558. collectMultiWithPattern();
  559. clearEl();
  560. this.nextPage = 1;
  561. this.lastAction = "collectDataWithLoop";
  562. },
  563. setNextPage: function () { //设置下一页元素
  564. this.page = 3;
  565. },
  566. confirmNextPage: function () { //确认下一页元素
  567. this.loopClickSingleElement("nextPageFromIndexPage");
  568. },
  569. cancelNextPage: function () { //取消下一页元素
  570. this.cancel();
  571. this.nextPage = 1; //保留下一页元素设置
  572. },
  573. deleteSingleLine: function (event) { //删除单行元素
  574. let at = new Date().getTime()
  575. //流程图送元素的时候,默认的使用不固定循环列表,但是一旦有删除元素的操作发生,则按照固定元素列表采集元素
  576. let index = event.target.getAttribute("index");
  577. let tnode = global.nodeList.splice(index, 1)[0]; //删掉当前元素
  578. tnode["node"].style.backgroundColor = tnode["bgColor"];
  579. tnode["node"].style.boxShadow = tnode["boxShadow"];
  580. if (global.nodeList.length > 1) { // 如果删到没有就没有其他的操作了
  581. handleElement();
  582. if (this.selectedDescendents) {
  583. handleDescendents(this.mode); //如果之前有选中子元素,新加入的节点又则这里也需要重新选择子元素
  584. }
  585. } else {
  586. this.valTable = [];
  587. this.selectStatus = false;
  588. clearParameters(); //直接撤销重选
  589. }
  590. let at2 = parseInt(new Date().getTime());
  591. console.log("delete:", at2, at, at2 - at);
  592. },
  593. removeField: function (event) {
  594. let index = event.target.getAttribute("index");
  595. let tParameter = global.outputParameters.splice(index, 1)[0];
  596. if (global.outputParameters.length == 0) {
  597. this.valTable = [];
  598. clearEl();
  599. } else { //删除对应的列
  600. console.log("remove:", tParameter, global);
  601. this.valTable.splice(index, 1);
  602. for (let i = global.outputParameterNodes.length - 1; i >= 0; i--) {
  603. let node = global.outputParameterNodes[i];
  604. if (node["unique_index"] == tParameter["unique_index"]) {
  605. node["node"].style.backgroundColor = "";
  606. node["node"].style.boxShadow = "";
  607. global.outputParameterNodes.splice(i, 1);
  608. }
  609. }
  610. }
  611. },
  612. clickElement: async function () { //点击元素操作
  613. sendSingleClick();
  614. //先发送数据
  615. global.nodeList[0]["node"].focus(); //获得元素焦点
  616. await new Promise(resolve => setTimeout(resolve, 500)); //因为nodejs点击后又会把当前元素加入到列表中,所以这里需要等待一下再清空
  617. // global.nodeList[0]["node"].click(); //点击元素
  618. clearEl();
  619. this.nextPage = 0;
  620. this.lastAction = "clickElement";
  621. },
  622. changeSelect: function () {
  623. this.page = 2;
  624. this.optionMode = 0;
  625. this.optionValue = global.nodeList[0]["node"].options[global.nodeList[0]["node"].selectedIndex + 1].text;
  626. },
  627. sendChangeSelect: function () {
  628. sendChangeOption(this.optionMode, this.optionValue);
  629. //先发送数据
  630. try {
  631. if (this.optionMode == 0) {
  632. global.nodeList[0]["node"].options[global.nodeList[0]["node"].selectedIndex + 1].selected = true;
  633. } else if (this.optionMode == 1) {
  634. global.nodeList[0]["node"].selectedIndex = this.optionValue;
  635. } else if (this.optionMode == 2) {
  636. global.nodeList[0]["node"].value = this.optionValue;
  637. } else if (this.optionMode == 3) {
  638. global.nodeList[0]["node"].options[global.nodeList[0]["node"].selectedIndex].selected = true;
  639. for (let i = 0; i < global.nodeList[0]["node"].options.length; i++) {
  640. const option = global.nodeList[0]["node"].options[i];
  641. if (option.text === this.optionValue) {
  642. global.nodeList[0]["node"].value = option.value; // 将目标选项的值设置为<select>元素的值
  643. break; // 找到目标选项后跳出循环
  644. }
  645. }
  646. }
  647. } catch (e) {
  648. if (this.lang == "zh") {
  649. alert("切换失败,实际执行时可能失败,请注意。");
  650. } else {
  651. alert("Switch failed, may fail when actually executed, please note.");
  652. }
  653. }
  654. clearEl();
  655. this.nextPage = 0;
  656. this.lastAction = "changeSelect";
  657. },
  658. handleSelectChange: function () {
  659. console.log(this.optionMode, this.optionValue);
  660. if (this.optionMode == 0) {
  661. this.optionValue = global.nodeList[0]["node"].options[global.nodeList[0]["node"].selectedIndex + 1].text;
  662. } else if (this.optionMode == 1) {
  663. this.optionValue = global.nodeList[0]["node"].selectedIndex;
  664. } else if (this.optionMode == 2) {
  665. this.optionValue = global.nodeList[0]["node"].value;
  666. } else if (this.optionMode == 3) {
  667. this.optionValue = global.nodeList[0]["node"].options[global.nodeList[0]["node"].selectedIndex].text;
  668. }
  669. },
  670. mouseMove: function () {
  671. sendMouseMove();
  672. clearEl();
  673. this.nextPage = 0;
  674. this.lastAction = "mouseMove";
  675. },
  676. loopMouseMove: function () {
  677. sendLoopMouseMove();
  678. clearEl();
  679. this.nextPage = 0;
  680. this.lastAction = "loopMouseMove";
  681. },
  682. loopClickSingleElement: async function (type = "") { //循环点击单个元素
  683. let name = this.tname();
  684. if (type == "nextPageFromIndexPage") {
  685. name = "nextPageFromIndexPage"
  686. }
  687. sendLoopClickSingle(name); //识别下一页,循环点击单个元素和点击多个元素
  688. // if (this.tname() != "下一页元素") { //下一页元素不进行点击操作
  689. global.nodeList[0]["node"].focus(); //获得元素焦点
  690. await new Promise(resolve => setTimeout(resolve, 500)); //因为nodejs点击后又会把当前元素加入到列表中,所以这里需要等待一下再清空
  691. // global.nodeList[0]["node"].click(); //点击元素
  692. // }
  693. clearEl();
  694. this.nextPage = 0;
  695. this.lastAction = "clickElementWithLoop";
  696. },
  697. loopClickEveryElement: async function () { //循环点击每个元素
  698. sendLoopClickEvery(); //识别下一页,循环点击单个元素和点击多个元素
  699. global.nodeList[0]["node"].focus(); //获得元素焦点
  700. await new Promise(resolve => setTimeout(resolve, 500)); //因为nodejs点击后又会把当前元素加入到列表中,所以这里需要等待一下再清空
  701. // global.nodeList[0]["node"].click(); //点击元素
  702. clearEl();
  703. this.nextPage = 0;
  704. this.lastAction = "clickEveryElementWithLoop";
  705. },
  706. setInput: function (batch = false) { //输入文字
  707. this.batch = batch;
  708. this.page = 1;
  709. this.$nextTick(function () { //下一时刻获得焦点
  710. document.getElementById("WTextBox").focus();
  711. })
  712. },
  713. getInput: function () { //得到输入的文字
  714. global.nodeList[0]["node"].focus(); //获得文字焦点
  715. // if (getOS() == "Mac") {
  716. // global.nodeList[0]["node"].setAttribute("value", this.text); // 设置输入 box内容
  717. // } else{
  718. // global.nodeList[0]["node"].setAttribute("value", ""); // 先设置为空,再设置输入 box内容
  719. // }
  720. input(this.text, this.batch); // 设置输入
  721. this.text = "";
  722. clearEl();
  723. },
  724. cancelInput: function () {
  725. this.page = 0;
  726. },
  727. setWidth: function (width) { //根据是否出现表格调整最外框宽度
  728. $(".tooltips").css("width", width);
  729. return "";
  730. },
  731. getCurrentURL: function () { //获取当前页面的URL
  732. addEl(); // 添加当前选择元素,只是为了占位
  733. generateParameters(5, true, false);
  734. this.selectStatus = true;
  735. clearReady();
  736. },
  737. getCurrentTitle: function () {
  738. //获取当前页面的Title
  739. // 获取文档中所有元素
  740. // const elements = document.querySelectorAll('*');
  741. // global.nodeList.push(elements[0]); //将页面第一个元素放入列表中
  742. addEl(); // 添加当前选择元素,只是为了占位
  743. generateParameters(6, true, false);
  744. this.selectStatus = true;
  745. clearReady();
  746. },
  747. getText: function () { //采集文字
  748. generateParameters(0, true, false);
  749. this.selectStatus = true;
  750. clearReady();
  751. },
  752. getSelectedValue: function () { //采集选中文字
  753. generateParameters(10, true, false);
  754. this.selectStatus = true;
  755. clearReady();
  756. },
  757. getSelectedInnerText: function () { //提示文字
  758. let l = 10;
  759. return global.nodeList[0]["node"].innerText.trim().length > l ? global.nodeList[0]["node"].innerText.trim().substring(0, l) + "..." : global.nodeList[0]["node"].innerText.trim();
  760. },
  761. getSelectedText: function () { //采集选中文字
  762. generateParameters(11, true, false);
  763. this.selectStatus = true;
  764. clearReady();
  765. },
  766. getLink: function () { //采集链接地址
  767. generateParameters(0, false, true);
  768. this.selectStatus = true;
  769. clearReady();
  770. },
  771. getOuterHtml: function () { //采集OuterHtml
  772. generateParameters(3, true, false);
  773. this.selectStatus = true;
  774. clearReady();
  775. },
  776. getInnerHtml: function () { //采集InnerHtml
  777. generateParameters(2, true, false);
  778. this.selectStatus = true;
  779. clearReady();
  780. },
  781. getBackgroundPic: function () { //采集背景图片
  782. generateParameters(4, true, false);
  783. this.selectStatus = true;
  784. clearReady();
  785. },
  786. tname: function () {
  787. let tag = global.nodeList.length == 0 ? "" : global.nodeList[0]["node"].tagName;
  788. let inputType = global.nodeList.length == 0 ? "" : global.nodeList[0]["node"].getAttribute("type");
  789. if (inputType != null) { //如果没有type属性,则默认为text
  790. inputType = inputType.toLowerCase();
  791. } else {
  792. inputType = "text";
  793. }
  794. if (tag == "") {
  795. return "null";
  796. } else if ($(global.nodeList[0]["node"]).contents().filter(function () {
  797. return this.nodeType === 3;
  798. }).text().indexOf("下一页") >= 0) {
  799. // this.setWidth("280px");
  800. return "下一页元素";
  801. } else if (tag == "A") {
  802. return "链接";
  803. } else if (tag == "IMG") {
  804. return "图片";
  805. } else if (tag == "BUTTON" || (tag == "INPUT" && (inputType == "button" || inputType == "submit"))) {
  806. return "按钮";
  807. } else if (tag == "TEXTAREA" || (tag == "INPUT" && (inputType != "checkbox" || inputType != "ratio"))) { //普通输入框
  808. return "文本框";
  809. } else if (tag == "SELECT") {
  810. return "选择框";
  811. } else {
  812. return "元素";
  813. }
  814. },
  815. existDescendents: function () { //检测选中的元素是否存在子元素,已经选中了子元素也不要再出现了
  816. return global.nodeList.length > 0 && global.nodeList[0]["node"].children.length > 0 && !this.selectedDescendents;
  817. },
  818. numOfReady: function () {
  819. return global.readyList.length;
  820. },
  821. numOfList: function () {
  822. return global.nodeList.length;
  823. },
  824. lastElementXPath: function () { //用来显示元素的最大最后5个xpath路劲元素
  825. let path = global.nodeList[global.nodeList.length - 1]["xpath"];
  826. path = path.split("/");
  827. let tp = "";
  828. if (path.length > 5) { //只保留最后五个元素
  829. path = path.splice(path.length - 5, 5);
  830. tp = ".../"
  831. }
  832. for (let i = 0; i < path.length; i++) {
  833. path[i] = path[i].split("[")[0];
  834. }
  835. path = path.join("/");
  836. path = "Path: " + tp + path;
  837. return path;
  838. },
  839. cancel: function () {
  840. clearEl();
  841. },
  842. specialSelect: function () { //特殊选择模式
  843. // if (mousemovebind) {
  844. // global.tdiv.style.pointerEvents = "none";
  845. // this.special = false;
  846. // } else {
  847. // this.special = true;
  848. // }
  849. // mousemovebind = !mousemovebind;
  850. },
  851. enlarge: function () { // 扩大选区功能,总是扩大最后一个选中的元素的选区
  852. if (global.nodeList[global.nodeList.length - 1]["node"].tagName != "BODY") {
  853. global.nodeList[global.nodeList.length - 1]["node"].style.backgroundColor = global.nodeList[global.nodeList.length - 1]["bgColor"]; //之前元素恢复原来的背景颜色
  854. global.nodeList[global.nodeList.length - 1]["node"].style.boxShadow = global.nodeList[global.nodeList.length - 1]["boxShadow"]; //之前元素恢复原来的背景颜色
  855. let tNode = global.nodeList[global.nodeList.length - 1]["node"].parentNode; //向上走一层
  856. let sty;
  857. if (tNode != global.NowNode) { //扩大选区之后背景颜色的判断,当前正好选中的颜色应该是不同的
  858. sty = tNode.style.backgroundColor;
  859. } else {
  860. sty = global.style;
  861. }
  862. global.nodeList[global.nodeList.length - 1]["node"] = tNode;
  863. global.nodeList[global.nodeList.length - 1]["bgColor"] = sty;
  864. global.nodeList[global.nodeList.length - 1]["xpath"] = readXPath(tNode, 1);
  865. global.nodeList[global.nodeList.length - 1]["allXPaths"] = getElementXPaths(tNode);
  866. //显示框
  867. var pos = tNode.getBoundingClientRect();
  868. global.div.style.display = "block";
  869. global.div.style.height = tNode.offsetHeight + "px";
  870. global.div.style.width = tNode.offsetWidth + "px";
  871. global.div.style.left = pos.left + "px";
  872. global.div.style.top = pos.top + "px";
  873. global.div.style.zIndex = 2147483645;
  874. global.div.style.pointerEvents = "none";
  875. handleElement(); //每次数组元素有变动,都需要重新处理下
  876. global.oe = tNode;
  877. tNode.style.backgroundColor = "rgba(0,191,255,0.5)";
  878. this.selectedDescendents = false;
  879. }
  880. },
  881. selectAll: function () { //选中全部元素
  882. selectAllElements(this);
  883. },
  884. revoke: function () { //撤销选择当前节点
  885. let tstep = global.step;
  886. global.step--; //步数-1
  887. console.log(global.step, global.nodeList)
  888. while (tstep == global.nodeList[global.nodeList.length - 1]["step"]) //删掉所有当前步数的元素节点
  889. {
  890. let node = global.nodeList.splice(global.nodeList.length - 1, 1)[0]; //删除数组最后一项
  891. node["node"].style.backgroundColor = node["bgColor"]; //还原原始属性和边框
  892. node["node"].style.boxShadow = node["boxShadow"];
  893. if (global.NowNode == node["node"]) {
  894. global.style = node["bgColor"];
  895. }
  896. //处理已经有选中子元素的情况
  897. // if (this.selectedDescendents) {
  898. clearParameters(); //直接撤销重选
  899. // }
  900. }
  901. handleElement(); //每次数组元素有变动,都需要重新处理下
  902. },
  903. selectDescendents: function (e, mode = 0) { //选择所有子元素操作
  904. handleDescendents(mode);
  905. this.mode = mode;
  906. }
  907. },
  908. }
  909. </script>
  910. <style>
  911. </style>