fix graph bugs
This commit is contained in:
parent
b7e65fe108
commit
f9b8d5b2e9
@ -6,11 +6,11 @@
|
|||||||
<span class="filetag item"
|
<span class="filetag item"
|
||||||
v-for="(results, filename) in message.groupedResults"
|
v-for="(results, filename) in message.groupedResults"
|
||||||
:key="filename"
|
:key="filename"
|
||||||
@click="openDetail = true"
|
@click="toggleDrawer(filename)"
|
||||||
>
|
>
|
||||||
<FileTextOutlined /> {{ filename }}
|
<FileTextOutlined /> {{ filename }}
|
||||||
<a-drawer
|
<a-drawer
|
||||||
v-model:open="openDetail"
|
v-model:open="openDetail[filename]"
|
||||||
title="检索详情"
|
title="检索详情"
|
||||||
width="800"
|
width="800"
|
||||||
:contentWrapperStyle="{ maxWidth: '100%'}"
|
:contentWrapperStyle="{ maxWidth: '100%'}"
|
||||||
@ -19,7 +19,7 @@
|
|||||||
rootClassName="root"
|
rootClassName="root"
|
||||||
>
|
>
|
||||||
<div class="fileinfo">
|
<div class="fileinfo">
|
||||||
<p><strong>文件名:</strong> {{ results[0].file.filename }}</p>
|
<p><strong>文件名:</strong> {{ filename }}</p>
|
||||||
<p><strong>文件类型:</strong> {{ results[0].file.type }}</p>
|
<p><strong>文件类型:</strong> {{ results[0].file.type }}</p>
|
||||||
<p><strong>创建时间:</strong> {{ new Date(results[0].file.created_at * 1000).toLocaleString() }}</p>
|
<p><strong>创建时间:</strong> {{ new Date(results[0].file.created_at * 1000).toLocaleString() }}</p>
|
||||||
</div>
|
</div>
|
||||||
@ -47,7 +47,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed, reactive } from 'vue'
|
||||||
import {
|
import {
|
||||||
GlobalOutlined,
|
GlobalOutlined,
|
||||||
FileTextOutlined,
|
FileTextOutlined,
|
||||||
@ -59,7 +59,18 @@ const props = defineProps({
|
|||||||
|
|
||||||
const message = ref(props.message)
|
const message = ref(props.message)
|
||||||
|
|
||||||
const openDetail = ref(false)
|
// 使用 reactive 创建一个响应式对象来存储每个文件的抽屉状态
|
||||||
|
const openDetail = reactive({})
|
||||||
|
|
||||||
|
// 初始化 openDetail 对象
|
||||||
|
for (const filename in message.value.groupedResults) {
|
||||||
|
openDetail[filename] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleDrawer = (filename) => {
|
||||||
|
openDetail[filename] = !openDetail[filename]
|
||||||
|
}
|
||||||
|
|
||||||
const showRefs = computed(() => message.value.role=='received' && message.value.status=='finished')
|
const showRefs = computed(() => message.value.role=='received' && message.value.status=='finished')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -10,18 +10,18 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="graph-container layout-container" v-else>
|
<div class="graph-container layout-container" v-else>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<h2>图数据库 {{ graph?.database_name }}</h2>
|
<h2>图数据库 {{ graphInfo?.database_name }}</h2>
|
||||||
<p>
|
<p>
|
||||||
<span v-if="state.graphloading">加载中</span>
|
<span v-if="state.loadingGraphInfo">加载中</span>
|
||||||
<span class="green-dot" v-if="graph?.status == 'open'"></span>
|
<span class="green-dot" v-if="graphInfo?.status == 'open'"></span>
|
||||||
<span class="red-dot" v-else></span>
|
<span class="red-dot" v-else></span>
|
||||||
<span>{{ graph?.status }}</span> ·
|
<span>{{ graphInfo?.status }}</span> ·
|
||||||
<span>共 {{ graph?.entity_count }} 实体,{{ graph?.relationship_count }} 个关系</span>
|
<span>共 {{ graphInfo?.entity_count }} 实体,{{ graphInfo?.relationship_count }} 个关系</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<div class="actions-left">
|
<div class="actions-left">
|
||||||
<a-button @click="state.showModal = true">上传文件</a-button>
|
<a-button @click="state.showModal = true"><UploadOutlined /> 上传文件</a-button>
|
||||||
<a-modal
|
<a-modal
|
||||||
:open="state.showModal" title="上传文件"
|
:open="state.showModal" title="上传文件"
|
||||||
@ok="addDocumentByFile"
|
@ok="addDocumentByFile"
|
||||||
@ -42,15 +42,15 @@
|
|||||||
>
|
>
|
||||||
<p class="ant-upload-text">点击或者把文件拖拽到这里上传</p>
|
<p class="ant-upload-text">点击或者把文件拖拽到这里上传</p>
|
||||||
<p class="ant-upload-hint">
|
<p class="ant-upload-hint">
|
||||||
目前仅支持上传文本文件,如 .pdf, .txt, .md。且同名文件无法重复添加。
|
目前仅支持上传 jsonl 文件。且同名文件无法重复添加。
|
||||||
</p>
|
</p>
|
||||||
</a-upload-dragger>
|
</a-upload-dragger>
|
||||||
</div>
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<input v-model="sampleNodeCount">
|
<input v-model="sampleNodeCount">
|
||||||
<a-button @click="loadSampleNodes">确定</a-button>
|
<a-button @click="loadSampleNodes">获取节点</a-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-right">
|
<div class="actions-right">
|
||||||
<input
|
<input
|
||||||
v-model="state.searchInput"
|
v-model="state.searchInput"
|
||||||
placeholder="输入要查询的实体"
|
placeholder="输入要查询的实体"
|
||||||
@ -75,21 +75,22 @@ import { Graph } from "@antv/g6";
|
|||||||
import { computed, onMounted, reactive, ref } from 'vue';
|
import { computed, onMounted, reactive, ref } from 'vue';
|
||||||
import { message } from "ant-design-vue";
|
import { message } from "ant-design-vue";
|
||||||
import { useConfigStore } from '@/stores/config';
|
import { useConfigStore } from '@/stores/config';
|
||||||
|
import { UploadOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
const configStore = useConfigStore()
|
const configStore = useConfigStore()
|
||||||
|
|
||||||
let graphInstance
|
let graphInstance
|
||||||
const graph = ref(null)
|
const graphInfo = ref(null)
|
||||||
const container = ref(null);
|
const container = ref(null);
|
||||||
const fileList = ref([]);
|
const fileList = ref([]);
|
||||||
const sampleNodeCount = ref(100);
|
const sampleNodeCount = ref(100);
|
||||||
const subgraph = reactive({
|
const graphData = reactive({
|
||||||
nodes: [],
|
nodes: [],
|
||||||
edges: [],
|
edges: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
graphloading: false,
|
loadingGraphInfo: false,
|
||||||
searchInput: '',
|
searchInput: '',
|
||||||
searchLoading: false,
|
searchLoading: false,
|
||||||
showModal: false,
|
showModal: false,
|
||||||
@ -98,27 +99,27 @@ const state = reactive({
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
const loadGraph = () => {
|
const loadGraphInfo = () => {
|
||||||
state.graphloading = true
|
state.loadingGraphInfo = true
|
||||||
fetch('/api/database/graph', {
|
fetch('/api/database/graph', {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
console.log(data)
|
console.log(data)
|
||||||
graph.value = data.graph
|
graphInfo.value = data.graph
|
||||||
state.graphloading = false
|
state.loadingGraphInfo = false
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
message.error(error.message)
|
message.error(error.message)
|
||||||
state.graphloading = false
|
state.loadingGraphInfo = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const graphData = computed(() => {
|
const getGraphData = () => {
|
||||||
return {
|
return {
|
||||||
nodes: subgraph.nodes.map(node => {
|
nodes: graphData.nodes.map(node => {
|
||||||
return {
|
return {
|
||||||
id: node.id,
|
id: node.id,
|
||||||
data: {
|
data: {
|
||||||
@ -126,7 +127,7 @@ const graphData = computed(() => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
edges: subgraph.edges.map(edge => {
|
edges: graphData.edges.map(edge => {
|
||||||
return {
|
return {
|
||||||
source: edge.source_id,
|
source: edge.source_id,
|
||||||
target: edge.target_id,
|
target: edge.target_id,
|
||||||
@ -136,7 +137,7 @@ const graphData = computed(() => {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
const addDocumentByFile = () => {
|
const addDocumentByFile = () => {
|
||||||
state.precessing = true
|
state.precessing = true
|
||||||
@ -168,13 +169,10 @@ const loadSampleNodes = () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
subgraph.nodes = data.result.nodes
|
graphData.nodes = data.result.nodes
|
||||||
subgraph.edges = data.result.edges
|
graphData.edges = data.result.edges
|
||||||
console.log(data)
|
console.log(graphData)
|
||||||
console.log(subgraph)
|
randerGraph()
|
||||||
setTimeout(() => {
|
|
||||||
randerGraph()
|
|
||||||
}, 500)
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
message.error(error.message);
|
message.error(error.message);
|
||||||
@ -197,10 +195,10 @@ const onSearch = () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
subgraph.nodes = data.result.nodes
|
graphData.nodes = data.result.nodes
|
||||||
subgraph.edges = data.result.edges
|
graphData.edges = data.result.edges
|
||||||
console.log(data)
|
console.log(data)
|
||||||
console.log(subgraph)
|
console.log(graphData)
|
||||||
randerGraph()
|
randerGraph()
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -210,54 +208,58 @@ const onSearch = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const randerGraph = () => {
|
const randerGraph = () => {
|
||||||
graphInstance.setData(graphData.value);
|
|
||||||
|
if (graphInstance) {
|
||||||
|
graphInstance.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
initGraph();
|
||||||
|
graphInstance.setData(getGraphData());
|
||||||
graphInstance.render();
|
graphInstance.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const initGraph = () => {
|
||||||
|
graphInstance = new Graph({
|
||||||
|
container: container.value,
|
||||||
|
width: container.value.offsetWidth,
|
||||||
|
height: container.value.offsetHeight,
|
||||||
|
autoFit: true,
|
||||||
|
autoResize: true,
|
||||||
|
layout: {
|
||||||
|
type: 'd3-force',
|
||||||
|
preventOverlap: true,
|
||||||
|
kr: 20,
|
||||||
|
collide: {
|
||||||
|
strength: 1.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
type: 'circle',
|
||||||
|
style: {
|
||||||
|
labelText: (d) => d.data.label,
|
||||||
|
size: 70,
|
||||||
|
},
|
||||||
|
palette: {
|
||||||
|
field: 'label',
|
||||||
|
color: 'tableau',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
edge: {
|
||||||
|
type: 'line',
|
||||||
|
style: {
|
||||||
|
labelText: (d) => d.data.label,
|
||||||
|
labelBackground: '#fff',
|
||||||
|
endArrow: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],
|
||||||
|
});
|
||||||
|
window.addEventListener('resize', randerGraph);
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadGraph();
|
loadGraphInfo();
|
||||||
loadSampleNodes();
|
loadSampleNodes();
|
||||||
setTimeout(() => {
|
|
||||||
if (state.showPage) {
|
|
||||||
graphInstance = new Graph({
|
|
||||||
container: container.value,
|
|
||||||
width: container.value.offsetWidth,
|
|
||||||
height: container.value.offsetHeight,
|
|
||||||
autoFit: true,
|
|
||||||
autoResize: true,
|
|
||||||
layout: {
|
|
||||||
type: 'd3-force',
|
|
||||||
preventOverlap: true,
|
|
||||||
kr: 100,
|
|
||||||
collide: {
|
|
||||||
strength: 0.5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
node: {
|
|
||||||
type: 'circle',
|
|
||||||
style: {
|
|
||||||
labelText: (d) => d.data.label,
|
|
||||||
size: 40,
|
|
||||||
},
|
|
||||||
palette: {
|
|
||||||
field: 'label',
|
|
||||||
color: 'tableau',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
edge: {
|
|
||||||
type: 'line',
|
|
||||||
style: {
|
|
||||||
labelText: (d) => d.data.label,
|
|
||||||
labelBackground: '#fff',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],
|
|
||||||
});
|
|
||||||
graphInstance.setData(graphData.value);
|
|
||||||
graphInstance.render();
|
|
||||||
window.addEventListener('resize', randerGraph);
|
|
||||||
}
|
|
||||||
}, 400)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -303,7 +305,7 @@ const handleDrop = (event) => {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
.actions-left {
|
.actions-left, .actions-right {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
@ -311,7 +313,6 @@ const handleDrop = (event) => {
|
|||||||
|
|
||||||
input {
|
input {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
margin-right: 10px;
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 4px 12px;
|
padding: 4px 12px;
|
||||||
border: 2px solid var(--main-300);
|
border: 2px solid var(--main-300);
|
||||||
@ -324,6 +325,7 @@ const handleDrop = (event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
border-width: 2px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,7 +42,8 @@
|
|||||||
</a-select>
|
</a-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<span class="label">{{ items?.embed_model.des }}
|
<span class="label">
|
||||||
|
{{ items?.embed_model.des }}
|
||||||
<a-button small v-if="needRestart.embed_model" @click="sendRestart">
|
<a-button small v-if="needRestart.embed_model" @click="sendRestart">
|
||||||
<ReloadOutlined />需要重启
|
<ReloadOutlined />需要重启
|
||||||
</a-button>
|
</a-button>
|
||||||
@ -58,7 +59,8 @@
|
|||||||
</a-select>
|
</a-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<span class="label">{{ items?.reranker.des }}
|
<span class="label">
|
||||||
|
{{ items?.reranker.des }}
|
||||||
<a-button small v-if="needRestart.reranker" @click="sendRestart">
|
<a-button small v-if="needRestart.reranker" @click="sendRestart">
|
||||||
<ReloadOutlined />需要重启
|
<ReloadOutlined />需要重启
|
||||||
</a-button>
|
</a-button>
|
||||||
@ -89,7 +91,11 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<span class="label">{{ items?.enable_knowledge_graph.des }}</span>
|
<span class="label">{{ items?.enable_knowledge_graph.des }}
|
||||||
|
<a-button small v-if="needRestart.enable_knowledge_graph" @click="sendRestart">
|
||||||
|
<ReloadOutlined />需要重启
|
||||||
|
</a-button>
|
||||||
|
</span>
|
||||||
<a-switch
|
<a-switch
|
||||||
:checked="configStore.config.enable_knowledge_graph"
|
:checked="configStore.config.enable_knowledge_graph"
|
||||||
@change="handleChange('enable_knowledge_graph', !configStore.config.enable_knowledge_graph)"
|
@change="handleChange('enable_knowledge_graph', !configStore.config.enable_knowledge_graph)"
|
||||||
@ -194,6 +200,13 @@ const sendRestart = () => {
|
|||||||
|
|
||||||
.label {
|
.label {
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-left: 10px;
|
||||||
|
height: 24px;
|
||||||
|
padding: 0 8px;
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user