Home.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. <template>
  2. <div class="search">
  3. <div id="home">
  4. <img alt="数据检索中心" src="../../assets/images/search/610.png"/>
  5. <router-link to="/">
  6. <a >返回后台</a>
  7. </router-link>
  8. </div>
  9. <div v-if="engines" id="site-main">
  10. <div id="search-bar">
  11. <div id="container">
  12. <div id="headline-content">
  13. <el-row class="headline-center" >
  14. <div id="search-tab">
  15. <span
  16. v-for="engine_name in engine_names"
  17. v-bind:key="engine_name"
  18. :class="{ active: get_search_engine() === engine_name }"
  19. @click="set_search_engine(engine_name)"
  20. >{{ engines[engine_name][3] }}</span
  21. >
  22. </div>
  23. </el-row>
  24. <form
  25. id="search-form"
  26. ref="search_form"
  27. onsubmit="return false;"
  28. style="height: 50px;"
  29. class="headline-center"
  30. >
  31. <input
  32. id="search-keyword"
  33. ref="search_input"
  34. v-model="keyword"
  35. :name="engines[search_engine][1]"
  36. :placeholder="engines[search_engine][2]"
  37. autocomplete="off"
  38. autofocus
  39. class="float-left"
  40. type="search"
  41. @blur="blur()"
  42. @focus="focus()"
  43. @input="get_hot_keyword()"
  44. @keydown.down="down()"
  45. @keydown.prevent.up="up()"
  46. />
  47. <input
  48. id="search-form-submit"
  49. class="float-right"
  50. type="submit"
  51. value="搜索"
  52. @click="doSearch"
  53. />
  54. </form>
  55. <a-spin v-show="search_engine == '图谱'" :spinning="loadingChecked" class="flex1 panel flex-col" style="height: 730px;">
  56. <chart-comp ref="chart"
  57. @="getInfoTooltip"
  58. :isShowContextMenu="true"
  59. @reloadChart="reloadChart"
  60. :nodes="nodes"
  61. :links="links"
  62. :enable="true"
  63. :isShowChart="true"></chart-comp>
  64. </a-spin>
  65. <span v-show="search_engine == '文档'" :spinning="loadingChecked" class="flex1 panel flex-col" style="height: 730px;background-color: transparent;">
  66. <PdfList/>
  67. </span>
  68. <span v-show="search_engine == '图片'" :spinning="loadingChecked" class="flex1 panel flex-col" style="height: 730px;background-color: transparent;">
  69. <ImageList/>
  70. </span>
  71. <span v-show="search_engine == '媒体'" :spinning="loadingChecked" class="flex1 panel flex-col" style="height: 730px;background-color: transparent;">
  72. <VideoList/>
  73. </span>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. </div>
  79. </template>
  80. <script>
  81. import fetchJsonp from "fetch-jsonp";
  82. import chartComp from '@/views/knowledge/common/chart'
  83. import PdfList from '@/views/search/pdf'
  84. import ImageList from '@/views/search/image'
  85. import VideoList from '@/views/search/video'
  86. import { getGraphEntClsTree } from '@/api/graph/statisticalMap'
  87. import { getAllEntityClass } from '@/api/graph/entityClass'
  88. import { getAllRelationClass } from '@/api/graph/relationClass'
  89. const dataList = []
  90. // 根据树生成一个列表
  91. const generateList = (data) => {
  92. for (let i = 0; i < data.length; i++) {
  93. const node = data[i]
  94. const key = node.key
  95. dataList.push({key, title: node.entClsName, entClsName: node.entClsName})
  96. if (node.children) {
  97. generateList(node.children, node.key)
  98. }
  99. }
  100. }
  101. export default {
  102. name: "Home",
  103. components: { chartComp, PdfList, ImageList, VideoList },
  104. data() {
  105. return {
  106. loadingChecked: false,
  107. nodes: null,
  108. links: null,
  109. relClsList: [], // 关系类列表
  110. allRelClsNameList: [],// 所有的关系类名列表
  111. checkedRelClsNameList: [], // 去重的关系类名列表
  112. search_engine: "图谱",
  113. engines: "",
  114. engine_names: "",
  115. keyword: "",
  116. keywords: [],
  117. key_selected: -1,
  118. search_hot_display: "display: none",
  119. };
  120. },
  121. created() {
  122. let engines = {
  123. list: ["文档", "图片", "媒体", "图谱"],
  124. 文档: ["https://www.so.com/s", "q", "word pdf txt", "文档"],
  125. 图片: ["https://www.baidu.com/s", "wd", "jpg png bmp", "图片"],
  126. 媒体: ["https://www.google.com/search", "q", "mp3 mp4", "媒体"],
  127. 图谱: ["https://www.sogou.com/web", "query", "知识图谱", "图谱"],
  128. };
  129. this.engines = engines;
  130. this.engine_names = engines["list"];
  131. this.refreshEntityClassList()
  132. /**
  133. * 请求数据,获取所有实体类的信息,然后根据pid组装出实体类之间的关系
  134. * */
  135. this.loadingChecked = true
  136. Promise.all([getAllEntityClass(true), getAllRelationClass()]).then((resp) => {
  137. let links = []
  138. resp[0].data.forEach((v) => {
  139. v.id = v.entClsID
  140. v.label = v.entClsName
  141. if (v.pid !== null) {
  142. let fromId = v.pid, toId = v.entClsID
  143. const item = {
  144. id: fromId + '_' + toId
  145. }
  146. item.from = v.pid
  147. item.to = v.entClsID
  148. item.classType = 'dashed'
  149. links.push(item)
  150. }
  151. })
  152. var relClassNameTempMap = {}
  153. resp[1].data.forEach((v) => {
  154. const item = {
  155. label: v.relClsName,
  156. value: v.relClsID,
  157. checked: true
  158. }
  159. v.from = v.startID
  160. v.to = v.endID
  161. v.id = v.relClsID
  162. v.label = v.relClsName
  163. this.relClsList.push(item)
  164. relClassNameTempMap[v.relClsName] = true
  165. })
  166. //去掉重复关系类名
  167. for (let name in relClassNameTempMap) {
  168. this.allRelClsNameList.push({
  169. label: name,
  170. value: name
  171. })
  172. this.checkedRelClsNameList.push(name)
  173. }
  174. links = links.concat(resp[1].data)
  175. this.allEntClassCache = resp[0]
  176. this.filLinks = this.allLinksCache = links
  177. // if (clsId) { // 路径中存在实体类id
  178. // this.onCheckEntCls(this.checkedKeys)
  179. // } else {
  180. this.drawChart(resp[0].data, links)
  181. // }
  182. this.loadingChecked = false
  183. })
  184. },
  185. methods: {
  186. goHome(){
  187. this.$router.replace("index");
  188. },
  189. set_search_engine(engine) {
  190. this.search_engine = engine;
  191. this.keyword = ''
  192. },
  193. get_search_engine() {
  194. return this.search_engine;
  195. },
  196. get_hot_keyword() {
  197. if (this.keyword === "") {
  198. this.keywords = [];
  199. return;
  200. }
  201. // https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=golang&cb=xxxxx
  202. if (this.keyword !== "" && this.keyword !== "0") {
  203. clearTimeout(this.timer); // 清除定时器
  204. this.timer = setTimeout(() => {
  205. let api =
  206. "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=" + this.keyword;
  207. fetchJsonp(api, {
  208. jsonpCallback: "cb",
  209. })
  210. .then((response) => {
  211. return response.json();
  212. })
  213. .then((data) => {
  214. this.keywords = data.s; // 用到this一定要注意this指向
  215. })
  216. .catch((error) => {
  217. console.log(error);
  218. });
  219. }, 50);
  220. } else {
  221. this.keywords = [];
  222. }
  223. },
  224. go_submit(val) {
  225. this.keyword = val;
  226. this.$refs.search_input.value = val;
  227. this.$refs.search_form.submit();
  228. },
  229. getData(url) {
  230. fetchJsonp(url, {
  231. jsonpCallback: "callback",
  232. })
  233. .then((response) => {
  234. console.log(response);
  235. console.log(response.json());
  236. return response.json();
  237. })
  238. .then((json) => {
  239. this.users = json; // 在此处进行接收数据之后的操作
  240. })
  241. .catch((error) => {
  242. console.log(error); // 此处是数据请求失败后的处理
  243. });
  244. },
  245. down() {
  246. this.key_selected = (this.key_selected + 1) % this.keywords.length;
  247. this.keyword = this.keywords[this.key_selected];
  248. // this.$refs.search_input.value = this.keywords[this.key_selected];
  249. },
  250. up() {
  251. this.key_selected =
  252. (this.key_selected - 1 + this.keywords.length) % this.keywords.length;
  253. this.keyword = this.keywords[this.key_selected];
  254. // this.$refs.search_input.value = this.keywords[this.key_selected];
  255. },
  256. blur() {
  257. clearTimeout(this.timer); //清除延迟执行
  258. this.timer = setTimeout(() => {
  259. //设置延迟执行
  260. this.search_hot_display = "display: none";
  261. this.key_selected = -1;
  262. }, 100);
  263. },
  264. focus() {
  265. this.search_hot_display = "display: block";
  266. this.key_selected = -1;
  267. this.get_hot_keyword();
  268. },
  269. doSearch() {
  270. },
  271. getInfoTooltip(event, args) {
  272. const vm = this
  273. this.$set(this.tooltip, 'x', event.pageX + 'px')
  274. this.$set(this.tooltip, 'y', event.pageY + 'px')
  275. if (args.clickNode) {
  276. vm.tooltip.entClsID = args.clickNode.data.entClsID
  277. vm.tooltip.relClsID = false
  278. } else if (args.clickLink) {
  279. vm.tooltip.entClsID = false
  280. vm.tooltip.relClsID = args.clickLink.data.relClsID
  281. vm.relClsName = args.clickLink.data.relClsName
  282. } else {
  283. vm.tooltip.entClsID = false
  284. vm.tooltip.relClsID = false
  285. }
  286. },
  287. reloadChart(nodes, links) {
  288. this.drawChart(nodes, links)
  289. },
  290. drawChart(nodes, links) {
  291. this.nodes = nodes
  292. this.links = links
  293. this.$refs.chart.destroyChart() // 先清空chart实例,再绘图
  294. this.$refs.chart.reDraw(undefined, nodes, links)
  295. },
  296. refreshEntityClassList(clsId) {
  297. this.loadingTree = true
  298. getGraphEntClsTree().then((data) => {
  299. for (let i = 0; i < data.length; i++) {
  300. data[i]['key'] = data[i]['entClsID']
  301. data[i]['title'] = data[i]['entClsName']
  302. data[i]['scopedSlots'] = {title: 'custom'}
  303. if (!data[i]['pid']) {
  304. this.checkedKeys.push(data[i]['entClsID'])
  305. }
  306. }
  307. // 此处传固定的option
  308. const option = {
  309. idName: 'entClsID',
  310. pidName: 'pid',
  311. childName: 'children',
  312. returnList: []
  313. }
  314. let treeData = this.$utils.tree.listToTree(data, option) // 数组转成树
  315. if (clsId) { // 如果路径中存在实体类id
  316. for (let z = 0; z < treeData.length; z++) {
  317. if (treeData[z]['entClsID'] === clsId) {
  318. this.checkedKeys = getIdsList(treeData[z])
  319. }
  320. }
  321. }
  322. this.gData = treeData
  323. generateList(treeData) // 生成个列表
  324. const vm = this
  325. // 遍历树找到父节点下面的所有子节点
  326. this.$utils.tree.walk(treeData, function (node, index, way) {
  327. var id = clsId // 路由中的id
  328. var myWay = [] // 需要找到的展开节点key
  329. if (node.key === id) {
  330. for (let i = 0; i < way.length; i++) {
  331. myWay.push(way[i]['key'])
  332. }
  333. vm.expandedKeys = myWay
  334. return false
  335. }
  336. })
  337. this.loadingTree = false
  338. })
  339. },
  340. }
  341. };
  342. </script>
  343. <style lang="less" scoped>
  344. @import "../../assets/styles/common";
  345. @import "../../assets/styles/search";
  346. .search {
  347. height: 100%;
  348. background-image: url("../../assets/search/backgrand.png");
  349. background-size:100% 100%;
  350. background-attachment:fixed;
  351. }
  352. </style>