Browse Source

完善知识图谱

Kevin Jiang 2 years ago
parent
commit
6e2f23dc79

+ 1 - 1
src/stores/knowledge-graph.ts

@@ -2,7 +2,7 @@ import { ref, type Ref } from "vue";
 import { defineStore } from "pinia";
 import * as kgService from "@/services/knowledgeGraph.service";
 import * as searchService from "@/services/search.service";
-import type { GraphData, Property } from "@/types/knowledgeGraph.types";
+import type { Property } from "@/types/knowledgeGraph.types";
 import type { SearchResult } from "@/types/search.types";
 import { message } from "ant-design-vue";
 

+ 65 - 34
src/views/knowledgeGraph/KnowledgeGraphView.vue

@@ -1,21 +1,32 @@
 <script setup lang="ts">
-import { onMounted, ref, computed, type Ref } from "vue";
+import { computed, onMounted, ref, type Ref } from "vue";
 import G6, { type Graph, type Item } from '@antv/g6';
 import type { SearchResult } from "@/types/search.types";
 import type { Request } from "@/types/knowledgeGraph.types";
 import SearchResultList from "../search/components/SearchResultList.vue";
 import PropertyComponent from "./components/PropertyComponent.vue";
-import { useKnowledgeGraphStore } from "@/stores/knowledge-graph";
 import * as knowledgeGraphService from "@/services/knowledgeGraph.service"
+import * as searchService from "@/services/search.service"
 import { GraphDataManager } from "@/models/knowledgeGraph.model";
 import { message } from "ant-design-vue";
+import SpinComponent from "@/components/SpinComponent.vue";
 
-const kgGraphStore = useKnowledgeGraphStore();
+// 搜索结果
+const searchResult: Ref<SearchResult | null> = ref(null);
+const currentPage = ref(1)
+const searchLoading = ref(false)
+const searchNodeName = ref<string | null>(null)
+// 节点搜索统计
+const propertyData = computed(() => {
+  return {
+    name: searchNodeName.value || '',
+    docCount: searchResult.value?.total || 0,
+    keywords: searchResult.value?.aggs["KW"] || [],
+  }
+})
 
 const keyword = ref('');
 
-const currentPage = ref(1);
-
 let graph: Graph | null = null;
 
 const graphDataManager = new GraphDataManager();
@@ -45,33 +56,62 @@ function findName(name: string) {
   find({name, size: 10, findParents: false, findChildren: false})
 }
 
+function searchSubject(name: string) {
+  searchLoading.value = true
+  const from = Math.max(currentPage.value - 1, 0) * 10
+  const request = {
+    "query": `TP=(${name})`,
+    from,
+    size: 10,
+    aggs: {
+      "KW": {
+        "sort": "count/desc"
+      }
+    }
+  }
+  searchService.search(request).then((resp) => {
+    searchResult.value = resp;
+    searchLoading.value = false
+  }).catch(() => {
+    message.warning('搜索学科分类遇到问题,请稍后再试');
+    searchLoading.value = false
+  })
+}
+
+function onPaginationChange(p: number) {
+  currentPage.value = p
+  if ( searchNodeName.value) {
+    searchSubject(searchNodeName.value)
+  }
+}
+
 const menu = new G6.Menu({
   offsetX: 6,
   offsetY: 10,
   itemTypes: ['node'],
-  getContent(e) {
+  getContent() {
     const outDiv = document.createElement('div');
     outDiv.style.width = '100px';
     outDiv.innerHTML = `<ul class='graph-context-menu'>
         <li name='parent' class='graph-context-menu-item'>上级学科</li>
         <li name='child' class='graph-context-menu-item'>下级学科</li>
+        <li name='search' class='graph-context-menu-item'>搜索</li>
       </ul>`
     return outDiv
   },
   handleMenuClick(target: HTMLElement, item: Item) {
-    console.log(target, item)
     const menuName = target.getAttribute("name")
     const model = item.getModel()
     if (model.label) {
       if (menuName == 'parent') {
         findParents(model.label as string)
-        console.log("请求parent")
       } else if (menuName == 'child') {
         findChildren(model.label as string)
-        console.log("请求child")
+      } else if (menuName == 'search') {
+        searchNodeName.value = model.label as string
+        searchSubject(searchNodeName.value)
       }
     }
-    console.log('menu name', menuName, 'label', item.getModel().label)
   },
 });
 
@@ -138,22 +178,10 @@ function onSearch() {
   findName(keyword.value);
 }
 
-// 搜索结果
-const searchResult: Ref<SearchResult | null> = computed(() => kgGraphStore.searchResult);
-
 onMounted(() => {
   graph = initGraph()
   findName("")
 });
-
-// function searchSubject(name: string) {
-//   searchService.search({ "query": `TP=(${name})` }).then((resp) => {
-//     searchResult.value = resp;
-//   }).catch((err) => {
-//     console.error(err);
-//     message.warning('搜索学科分类遇到问题,请稍后再试');
-//   })
-// }
 </script>
 
 <template>
@@ -174,22 +202,25 @@ onMounted(() => {
     </a-col>
     <a-col :span="6">
       <div class="property-wrap">
-        <PropertyComponent :data="{name: 'a', docCount: 10, keywords: {'a': 1}}" />
+        <PropertyComponent :data="propertyData" />
       </div>
     </a-col>
   </a-row>
   <div class="articles-wrap">
-    <div v-if="searchResult">
-      <SearchResultList :data="searchResult" class="articles" />
-      <a-pagination
-        v-model:current="currentPage"
-        :total="searchResult.total"
-        :show-total="(total: number) => `共 ${total} 条`"
-        :show-size-changer="false"
-        class="pagination"
-      />
-    </div>
-    <a-empty class="empty" v-else description="暂无数据,请点击学科导航节点" />
+    <SpinComponent :spinning="searchLoading">
+      <div v-if="searchResult">
+        <SearchResultList :data="searchResult" class="articles" />
+        <a-pagination
+          v-model:current="currentPage"
+          :total="searchResult.total"
+          :show-total="(total: number) => `共 ${total} 条`"
+          :show-size-changer="false"
+          class="pagination"
+          @change="onPaginationChange"
+        />
+      </div>
+      <a-empty class="empty" v-else description="暂无数据,请点击学科导航节点" />
+    </SpinComponent>
   </div>
 </template>
 

+ 47 - 7
src/views/knowledgeGraph/components/PropertyComponent.vue

@@ -2,19 +2,59 @@
 export interface Props {
   name: string;
   docCount: number,
-  keywords: {[index: string]: number}
+  keywords: {key: string, count: number}[]
 }
 
 defineProps<{
   data: Props
 }>();
+
+function getKeywordLink(keyword: string) {
+  return {
+    name: 'SearchResult',
+    query: {
+      type: 'simple',
+      field: 'TP',
+      kw: keyword,
+      page: 1,
+      size: 10,
+      sort: 'Relevance'
+    }
+  }
+}
 </script>
 
 <template>
-  <p><span>学科名称:</span><span>{{ data.name }}</span></p>
-  <p><span>文献数量:</span><span>{{ data.docCount }}</span></p>
-  <p>
-    <div>关键词排名</div>
-    <div v-for="(value, key) of data.keywords" :key="key">{{ key }} {{ value }}</div>
-  </p>
+  <div class="row">
+    <h3><span>学科名称:</span><span>{{ data.name }}</span></h3>
+  </div>
+  <div class="row">
+    <h3>
+      <span>文献数量:</span><span>{{ data.docCount }}</span>
+    </h3>
+  </div>
+  <div class="row">
+    <h3>关键词排名</h3>
+    <div v-for="(item, key) of data.keywords" :key="key" class="keyword-item-wrap">
+      <RouterLink :to="getKeywordLink(item.key)" target="_blank">{{ item.key }}</RouterLink> {{ item.count }}
+    </div>
+  </div>
 </template>
+
+<style scoped lang="scss">
+.row {
+  margin-top: 1.5em;
+
+  &:first-child {
+    margin-top: 0em;
+  }
+}
+
+.keyword-item-wrap {
+  margin-top: 5px;
+
+  &:first-child {
+    margin-top: 0;
+  }
+}
+</style>