|
|
@@ -1,49 +1,31 @@
|
|
|
<script setup lang="ts">
|
|
|
-import type { SearchResult } from "@/types/search.types";
|
|
|
-import { onMounted, ref, type Ref } from "vue";
|
|
|
+import { onMounted, ref, computed, type Ref } from "vue";
|
|
|
import G6 from '@antv/g6';
|
|
|
+
|
|
|
+import * as searchService from "@/services/search.service";
|
|
|
+import type { SearchResult } from "@/types/search.types";
|
|
|
+import type { GraphData } from "@/types/knowledgeGraph.types";
|
|
|
import SearchResultList from "../search/components/SearchResultList.vue";
|
|
|
import PropertyComponent from "./components/PropertyComponent.vue";
|
|
|
+import { message } from "ant-design-vue";
|
|
|
+import { useKnowledgeGraphStore } from "@/stores/knowledge-graph";
|
|
|
+
|
|
|
+const kgGraphStore = useKnowledgeGraphStore();
|
|
|
|
|
|
const keyword = ref('');
|
|
|
|
|
|
+const currentPage = ref(1);
|
|
|
+
|
|
|
function onSearch() {
|
|
|
console.log('keyword', keyword);
|
|
|
}
|
|
|
|
|
|
// 搜索结果
|
|
|
-const searchResult: Ref<SearchResult | null> = ref(null);
|
|
|
-
|
|
|
-const data = {
|
|
|
- // 点集
|
|
|
- nodes: [
|
|
|
- {
|
|
|
- id: 'node1',
|
|
|
- label: 'node1',
|
|
|
- },
|
|
|
- {
|
|
|
- id: 'node2',
|
|
|
- label: 'node2',
|
|
|
- },
|
|
|
- {
|
|
|
- id: 'node3',
|
|
|
- label: 'node3',
|
|
|
- }
|
|
|
- ],
|
|
|
- // 边集
|
|
|
- edges: [
|
|
|
- {
|
|
|
- source: 'node1',
|
|
|
- target: 'node2',
|
|
|
- },
|
|
|
- {
|
|
|
- source: 'node1',
|
|
|
- target: 'node3',
|
|
|
- }
|
|
|
- ],
|
|
|
-};
|
|
|
+const searchResult: Ref<SearchResult | null> = computed(() => kgGraphStore.searchResult);
|
|
|
|
|
|
-onMounted(() => {
|
|
|
+const data = computed(() => kgGraphStore.graphData);
|
|
|
+
|
|
|
+function initGraph(data: GraphData) {
|
|
|
const graph = new G6.Graph({
|
|
|
container: 'graph',
|
|
|
layout: {
|
|
|
@@ -52,44 +34,66 @@ onMounted(() => {
|
|
|
kr: 20,
|
|
|
},
|
|
|
modes: {
|
|
|
- default: ['drag-canvas', 'zoom-canvas', 'drag-node'], // 允许拖拽画布、放缩画布、拖拽节点
|
|
|
+ // 允许拖拽画布、放缩画布、拖拽节点
|
|
|
+ default: ['drag-canvas', 'zoom-canvas', 'drag-node'],
|
|
|
},
|
|
|
nodeStateStyles: {
|
|
|
- // 鼠标 hover 上节点,即 hover 状态为 true 时的样式
|
|
|
hover: {
|
|
|
fill: 'lightsteelblue',
|
|
|
},
|
|
|
},
|
|
|
defaultNode: {
|
|
|
- size: 60,
|
|
|
+ size: 56,
|
|
|
type: 'circle',
|
|
|
style: {
|
|
|
- stroke: '#666',
|
|
|
- fill: 'steelblue'
|
|
|
+ stroke: '#F36924',
|
|
|
+ fill: '#F79767'
|
|
|
}
|
|
|
},
|
|
|
defaultEdge: {
|
|
|
label: '下级学科',
|
|
|
size: 1,
|
|
|
- color: '#e2e2e2',
|
|
|
+ color: '#b6bbc5',
|
|
|
style: {
|
|
|
endArrow: {
|
|
|
path: 'M 0,0 L 8,4 L 8,-4 Z',
|
|
|
- fill: '#e2e2e2',
|
|
|
+ fill: '#b6bbc5',
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
- graph.data(data); // 读取 Step 2 中的数据源到图上
|
|
|
- graph.render(); // 渲染图
|
|
|
+ // 读取数据源到图上
|
|
|
+ graph.data(data as any);
|
|
|
+ // 渲染图
|
|
|
+ graph.render();
|
|
|
+ // 监听节点点击事件
|
|
|
graph.on('node:click', event => {
|
|
|
- console.log('node:click', event.item?.getID());
|
|
|
- const index = data['nodes'].findIndex(n => n.id == event.item?.getID())
|
|
|
+ const nodes = data['nodes']
|
|
|
+ const index = nodes.findIndex(n => n.id == event.item?.getID())
|
|
|
if (index > -1) {
|
|
|
- console.log(data['nodes'][index])
|
|
|
+ const node = nodes[index];
|
|
|
+ searchSubject(node.label);
|
|
|
+
|
|
|
+ kgGraphStore.search(node.label);
|
|
|
}
|
|
|
});
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ kgGraphStore.fetchGraph(keyword.value).then((resp) => {
|
|
|
+ message.info(resp as string);
|
|
|
+ initGraph(data.value);
|
|
|
+ });
|
|
|
});
|
|
|
+
|
|
|
+function searchSubject(name: string) {
|
|
|
+ searchService.search({ "query": `TP=(${name})` }).then((resp) => {
|
|
|
+ searchResult.value = resp.data.data;
|
|
|
+ }).catch((err) => {
|
|
|
+ console.error(err);
|
|
|
+ message.warning('搜索学科分类遇到问题,请稍后再试');
|
|
|
+ })
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
@@ -115,8 +119,17 @@ onMounted(() => {
|
|
|
</a-col>
|
|
|
</a-row>
|
|
|
<div class="articles-wrap">
|
|
|
- <SearchResultList :data="searchResult" v-if="searchResult" />
|
|
|
- <a-empty v-else description="暂无数据" />
|
|
|
+ <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="暂无数据,请点击学科导航节点" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
@@ -130,7 +143,7 @@ onMounted(() => {
|
|
|
}
|
|
|
|
|
|
.graph-container {
|
|
|
- margin-top: 10px;
|
|
|
+ margin-top: 20px;
|
|
|
|
|
|
.graph-wrap,
|
|
|
.property-wrap {
|
|
|
@@ -140,7 +153,7 @@ onMounted(() => {
|
|
|
}
|
|
|
|
|
|
.graph-wrap {
|
|
|
- height: 600px;
|
|
|
+ height: 460px;
|
|
|
|
|
|
.graph {
|
|
|
width: 100%;
|
|
|
@@ -154,9 +167,28 @@ onMounted(() => {
|
|
|
}
|
|
|
|
|
|
.articles-wrap {
|
|
|
- margin-top: 10px;
|
|
|
- padding: 10px;
|
|
|
- background-color: white;
|
|
|
- border: 1px solid $border-color;
|
|
|
+ margin-top: 20px;
|
|
|
+
|
|
|
+ .articles {
|
|
|
+ padding: 10px 20px;
|
|
|
+ background-color: white;
|
|
|
+ border: 1px solid $border-color;
|
|
|
+ }
|
|
|
+
|
|
|
+ .empty {
|
|
|
+ background-color: white;
|
|
|
+ border: 1px solid $border-color;
|
|
|
+ margin: 0;
|
|
|
+ padding: 30px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .pagination {
|
|
|
+ float: right;
|
|
|
+ margin-top: 20px;
|
|
|
+
|
|
|
+ ::after {
|
|
|
+ clear: both;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|