RunSpider.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <template>
  2. <el-dialog title="仅编辑 CSS选择器部分" v-model="dialogVisible" :close-on-click-modal="false" width="80%">
  3. <div class="dialog-content">
  4. <div class="flex gap-2">
  5. <el-space>
  6. <el-tag type="primary"> {{ formData.code }}</el-tag>
  7. <el-tag type="success"> {{ formData.site }}</el-tag>
  8. <el-tag type="info"> {{ formData.channel }}</el-tag>
  9. <el-tag type="warning">{{ formData.href }}</el-tag>
  10. <el-tag type="primary"> {{ formData.modifyuser }}</el-tag>
  11. </el-space>
  12. </div>
  13. <div class="space"></div>
  14. <el-form ref="form" :model="formData" label-width="120px">
  15. <el-form-item label="URL">
  16. <el-input v-model="formData.href"></el-input>
  17. </el-form-item>
  18. <el-row>
  19. <el-col :span="8"><el-form-item label="列表延时(MS)">
  20. <el-input v-model="formData.listDelay"></el-input>
  21. </el-form-item></el-col>
  22. <el-col :span="8"><el-form-item label="详情延时(MS)">
  23. <el-input v-model="formData.contentDelay"></el-input>
  24. </el-form-item></el-col>
  25. <el-col :span="8"><el-form-item label="代理地址">
  26. <el-input v-model="formData.proxyServe"></el-input>
  27. </el-form-item></el-col>
  28. </el-row>
  29. <el-row>
  30. <el-col :span="12"><el-form-item label="浏览器">
  31. <el-radio-group v-model="formData.headless">
  32. <el-radio :value="true">无头</el-radio>
  33. <el-radio :value="false">显式</el-radio>
  34. </el-radio-group> </el-form-item>
  35. </el-col>
  36. <el-col :span="12"><el-form-item label="显示图像">
  37. <el-radio-group v-model="formData.showImage">
  38. <el-radio :value="true">显示</el-radio>
  39. <el-radio :value="false">不显示</el-radio>
  40. </el-radio-group> </el-form-item>
  41. </el-col>
  42. </el-row>
  43. </el-form>
  44. <div style="text-align: center;">
  45. <el-space>
  46. <el-button type="primary" @click="handleDebug"><el-icon>
  47. <VideoPlay />
  48. </el-icon>执行</el-button>
  49. <el-button type="primary" @click="handleStop"><el-icon>
  50. <VideoPause />
  51. </el-icon>终止</el-button>
  52. <el-button type="primary" @click="handleRefersh"><el-icon>
  53. <Refresh />
  54. </el-icon>刷新结果</el-button>
  55. <el-button type="primary" @click="handleCountYestday"><el-icon>
  56. <Refresh />
  57. </el-icon>统计昨日信息发布量</el-button>
  58. <el-dropdown>
  59. <el-button type="primary">
  60. 结果导出<el-icon class="el-icon--right"><arrow-down /></el-icon>
  61. </el-button>
  62. <template #dropdown>
  63. <el-dropdown-menu>
  64. <el-dropdown-item @click="handleExportEpub">导出EPUB格式文件</el-dropdown-item>
  65. <el-dropdown-item>导出JSON格式文件</el-dropdown-item>
  66. <el-dropdown-item>导出Excel格式文件</el-dropdown-item>
  67. <el-dropdown-item>补录/上推至平台</el-dropdown-item>
  68. </el-dropdown-menu>
  69. </template>
  70. </el-dropdown></el-space>
  71. </div>
  72. <el-divider />
  73. <div id="debugEventContian">执行日志:&nbsp;{{ debugLogLine }}</div>
  74. <el-divider />
  75. <el-table :data="tableData" style="width: 100%" height="240" @row-click="handleRowClick">
  76. <el-table-column prop="no" label="序号" width="90" />
  77. <el-table-column prop="title" label="标题" width="240" show-overflow-tooltip />
  78. <el-table-column prop="href" label="链接" show-overflow-tooltip />
  79. <el-table-column prop="contentShort" label="正文" show-overflow-tooltip />
  80. </el-table>
  81. </div>
  82. <ViewArticle ref="articleDialog" />
  83. </el-dialog>
  84. </template>
  85. <script setup>
  86. import { ref } from 'vue';
  87. import { ElMessage } from 'element-plus'
  88. import ViewArticle from "./ViewArticle.vue"
  89. import { ViewCurrentSpiderConfig, DebugSpider, StopDebugSpider } from "../../../wailsjs/go/main/App"
  90. import { ViewResultItemAll, SelectSaveFilePath, ExportEpubFile, CountYestodayArts } from "../../../wailsjs/go/main/App"
  91. import { EventsOn, EventsOff } from "../../../wailsjs/runtime"
  92. const formData = ref({
  93. // tags
  94. code: '',
  95. site: '',
  96. channel: '',
  97. href: '',
  98. modifyuser: '',
  99. // form
  100. listDelay: '',
  101. contentDelay: '',
  102. proxyServe: '',
  103. contentDelay: '',
  104. headless: false,
  105. showImage: false,
  106. })
  107. const articleDialog = ref(null)
  108. const debugLogLine = ref("")
  109. const tableData = ref([])
  110. const dialogVisible = ref(false)
  111. const setPageData = (e) => {
  112. console.log(e)
  113. }
  114. const getPageData = () => {}
  115. //开始调试
  116. const handleDebug = () => {
  117. ElMessage({
  118. message: `${[formData.value.url, formData.value.listDelay, formData.value.contentDelay,
  119. formData.value.headless, formData.value.showImage, formData.value.proxyServe].join("//")}!`,
  120. showClose: true,
  121. duration: 3000,
  122. });
  123. DebugSpider(formData.value.url, parseInt(formData.value.listDelay), parseInt(formData.value.contentDelay),
  124. formData.value.headless == 'true', formData.value.showImage == 'true', formData.value.proxyServe)
  125. }
  126. //停止调试
  127. const handleStop = () => {
  128. StopDebugSpider()
  129. }
  130. //
  131. const truncateString = (str, maxLength) => {
  132. return str.substring(0, maxLength) + "..";
  133. }
  134. //刷新加载数据
  135. const handleRefersh = () => {
  136. ViewResultItemAll().then(result => {
  137. result = result.slice(-20);
  138. result.forEach((v, i) => {
  139. v.contentShort = truncateString(v.content, 50)
  140. })
  141. tableData.value = result
  142. })
  143. }
  144. //handleExportEpub导出文件
  145. const handleExportEpub = () => {
  146. SelectSaveFilePath().then(r => {
  147. if (r == "") return
  148. ExportEpubFile(r).then(d => {
  149. ElMessage({
  150. message: `导出epub文件${r}完成!`,
  151. showClose: true,
  152. duration: 3000,
  153. });
  154. })
  155. })
  156. }
  157. const replaceAll = function (src, search, replacement) {
  158. return src.split(search).join(replacement);
  159. };
  160. //行点击事件
  161. const handleRowClick = (row, column, event) => {
  162. articleDialog.value.dialogVisible = true
  163. row.content = replaceAll(row.content, '\n', '<br/>')
  164. articleDialog.value.formData = row
  165. articleDialog.value.scrollTop()
  166. }
  167. //
  168. const handleCountYestday = () => {
  169. if (formData.value.listNextPageCss != "" && formData.value.listPublishTimeCss != "") {
  170. ElMessage({
  171. message: `${[formData.value.url, formData.value.listDelay, formData.value.contentDelay,
  172. formData.value.headless, formData.value.showImage, formData.value.proxyServe].join("//")}!`,
  173. showClose: true,
  174. duration: 3000,
  175. });
  176. CountYestodayArts(formData.value.url, parseInt(formData.value.listDelay), parseInt(formData.value.contentDelay),
  177. formData.value.headless == 'true', formData.value.showImage == 'true')
  178. } else {
  179. ElMessage({
  180. message: "当前爬虫设置,CSS选择器,不具备列表页发布时间+列表页翻页。",
  181. type: 'error',
  182. showClose: true,
  183. duration: 3000,
  184. });
  185. }
  186. }
  187. //Wails事件绑定
  188. EventsOff('debug_event')
  189. EventsOn("debug_event", data => {
  190. debugLogLine.value = data
  191. })
  192. //加载当前爬虫配置
  193. // ViewCurrentSpiderConfig().then(result => {
  194. // console.log(result)
  195. // // result['listDelay'] = 500
  196. // // result['contentDelay'] = 500
  197. // // result['proxyServe'] = ''
  198. // // result['showImage'] = 'false'
  199. // // result['headless'] = 'false'
  200. // // formData.value = { ...result }
  201. // })
  202. defineExpose({
  203. dialogVisible,
  204. formData,
  205. setPageData,
  206. getPageData,
  207. })
  208. </script>
  209. <style scoped>
  210. .dialog-content {
  211. max-height: 60vh;
  212. overflow-y: scroll;
  213. }
  214. </style>