feat: 更新知识图谱组件,优化统计信息显示和图表加载逻辑
This commit is contained in:
parent
f0275aaadc
commit
b8bfc97b80
@ -372,6 +372,7 @@ import { parseToShanghai } from '@/utils/time';
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.file-table-container {
|
.file-table-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@ -2,32 +2,11 @@
|
|||||||
<div class="graph-section" v-if="isGraphSupported">
|
<div class="graph-section" v-if="isGraphSupported">
|
||||||
<div class="graph-toolbar">
|
<div class="graph-toolbar">
|
||||||
<div class="toolbar-left">
|
<div class="toolbar-left">
|
||||||
<div v-if="graphStats.displayed_nodes > 0 || graphStats.displayed_edges > 0" class="graph-stats">
|
<div class="graph-stats">
|
||||||
<a-tag color="blue" size="small">节点: {{ graphStats.displayed_nodes }}</a-tag>
|
<a-tag color="blue" size="small">总节点: {{ graphStats.total_nodes || 0 }}</a-tag>
|
||||||
<a-tag color="green" size="small">边: {{ graphStats.displayed_edges }}</a-tag>
|
<a-tag color="green" size="small">总边: {{ graphStats.total_edges || 0 }}</a-tag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar-right">
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
@click="loadGraph"
|
|
||||||
:disabled="!isGraphSupported"
|
|
||||||
:icon='h(ReloadOutlined)'
|
|
||||||
>
|
|
||||||
加载图谱
|
|
||||||
</a-button>
|
|
||||||
<a-button
|
|
||||||
type="text"
|
|
||||||
size="small"
|
|
||||||
:icon="h(ExpandOutlined)"
|
|
||||||
title="最大化"
|
|
||||||
@click="toggleGraphMaximize"
|
|
||||||
:disabled="!isGraphSupported"
|
|
||||||
>
|
|
||||||
最大化
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="graph-container-compact">
|
<div class="graph-container-compact">
|
||||||
<div v-if="!isGraphSupported" class="graph-disabled">
|
<div v-if="!isGraphSupported" class="graph-disabled">
|
||||||
@ -41,12 +20,10 @@
|
|||||||
v-else
|
v-else
|
||||||
:initial-database-id="databaseId"
|
:initial-database-id="databaseId"
|
||||||
:hide-db-selector="true"
|
:hide-db-selector="true"
|
||||||
:hide-stats="true"
|
|
||||||
:hide-controls="!store.state.isGraphMaximized"
|
|
||||||
:initial-limit="graphLimit"
|
:initial-limit="graphLimit"
|
||||||
:initial-depth="graphDepth"
|
:initial-depth="graphDepth"
|
||||||
@update:stats="handleStatsUpdate"
|
|
||||||
ref="graphViewerRef"
|
ref="graphViewerRef"
|
||||||
|
@update:stats="handleViewerStats"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -115,7 +92,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch, nextTick, onUnmounted } from 'vue';
|
import { ref, computed, watch, nextTick, onUnmounted } from 'vue';
|
||||||
import { useDatabaseStore } from '@/stores/database';
|
import { useDatabaseStore } from '@/stores/database';
|
||||||
import { ReloadOutlined, ExpandOutlined } from '@ant-design/icons-vue';
|
import { ReloadOutlined } from '@ant-design/icons-vue';
|
||||||
import KnowledgeGraphViewer from '@/components/KnowledgeGraphViewer.vue';
|
import KnowledgeGraphViewer from '@/components/KnowledgeGraphViewer.vue';
|
||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
import { getKbTypeLabel } from '@/utils/kb_utils';
|
import { getKbTypeLabel } from '@/utils/kb_utils';
|
||||||
@ -139,7 +116,7 @@ const graphStats = computed({
|
|||||||
|
|
||||||
const graphViewerRef = ref(null);
|
const graphViewerRef = ref(null);
|
||||||
const showSettings = ref(false);
|
const showSettings = ref(false);
|
||||||
const graphLimit = ref(200);
|
const graphLimit = ref(50);
|
||||||
const graphDepth = ref(2);
|
const graphDepth = ref(2);
|
||||||
|
|
||||||
const showExportModal = ref(false);
|
const showExportModal = ref(false);
|
||||||
@ -168,14 +145,6 @@ const clearGraph = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleGraphMaximize = () => {
|
|
||||||
store.state.isGraphMaximized = !store.state.isGraphMaximized;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleStatsUpdate = (stats) => {
|
|
||||||
graphStats.value = stats;
|
|
||||||
};
|
|
||||||
|
|
||||||
const applySettings = () => {
|
const applySettings = () => {
|
||||||
showSettings.value = false;
|
showSettings.value = false;
|
||||||
// 设置已通过props传递给子组件,不需要额外操作
|
// 设置已通过props传递给子组件,不需要额外操作
|
||||||
@ -241,6 +210,20 @@ const scheduleGraphLoad = (delay = 200) => {
|
|||||||
}, delay);
|
}, delay);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理子组件(Viewer)上报的统计信息,将其写入 database store 的 graphStats
|
||||||
|
const handleViewerStats = (stats) => {
|
||||||
|
if (!stats) return;
|
||||||
|
|
||||||
|
// 合并现有 store.graphStats,优先使用来自 viewer 的值
|
||||||
|
store.graphStats = {
|
||||||
|
total_nodes: stats.total_nodes ?? store.graphStats.total_nodes ?? 0,
|
||||||
|
total_edges: stats.total_edges ?? store.graphStats.total_edges ?? 0,
|
||||||
|
displayed_nodes: stats.displayed_nodes ?? store.graphStats.displayed_nodes ?? 0,
|
||||||
|
displayed_edges: stats.displayed_edges ?? store.graphStats.displayed_edges ?? 0,
|
||||||
|
is_truncated: stats.is_truncated ?? store.graphStats.is_truncated ?? false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.active,
|
() => props.active,
|
||||||
(active) => {
|
(active) => {
|
||||||
@ -252,13 +235,17 @@ watch(
|
|||||||
);
|
);
|
||||||
|
|
||||||
watch(databaseId, () => {
|
watch(databaseId, () => {
|
||||||
|
store.graphStats = defaultGraphStats();
|
||||||
scheduleGraphLoad(300);
|
scheduleGraphLoad(300);
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(isGraphSupported, (supported) => {
|
watch(isGraphSupported, (supported) => {
|
||||||
if (supported) {
|
if (!supported) {
|
||||||
scheduleGraphLoad(200);
|
store.graphStats = defaultGraphStats();
|
||||||
|
clearGraph();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
scheduleGraphLoad(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
|||||||
@ -71,24 +71,8 @@
|
|||||||
>
|
>
|
||||||
<SearchOutlined v-if="!loading" /> 加载图谱
|
<SearchOutlined v-if="!loading" /> 加载图谱
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button
|
|
||||||
type="default"
|
|
||||||
size="small"
|
|
||||||
:loading="loading"
|
|
||||||
@click="loadTestData"
|
|
||||||
:disabled="!selectedDatabase"
|
|
||||||
style="margin-left: 6px"
|
|
||||||
title="加载测试数据(用于演示图谱功能)"
|
|
||||||
>
|
|
||||||
<ReloadOutlined v-if="!loading" /> 测试数据
|
|
||||||
</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="!props.hideStats" class="stats-section">
|
|
||||||
<a-tag color="blue" size="small">节点: {{ stats.displayed_nodes || 0 }}</a-tag>
|
|
||||||
<a-tag color="green" size="small">边: {{ stats.displayed_edges || 0 }}</a-tag>
|
|
||||||
<!-- <a-tag v-if="stats.is_truncated" color="red" size="small">已截断</a-tag> -->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Sigma.js图可视化容器 -->
|
<!-- Sigma.js图可视化容器 -->
|
||||||
@ -98,6 +82,11 @@
|
|||||||
:class="{ 'loading': loading }"
|
:class="{ 'loading': loading }"
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
|
<div v-if="!props.hideStats" class="graph-overlay-stats">
|
||||||
|
<a-tag color="blue" size="small">节点: {{ stats.displayed_nodes || 0 }}</a-tag>
|
||||||
|
<a-tag color="green" size="small">边: {{ stats.displayed_edges || 0 }}</a-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 节点详情面板 -->
|
<!-- 节点详情面板 -->
|
||||||
<div
|
<div
|
||||||
v-if="selectedNodeData"
|
v-if="selectedNodeData"
|
||||||
@ -234,7 +223,6 @@ import { ref, reactive, onMounted, onUnmounted, computed, watch, nextTick } from
|
|||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import {
|
import {
|
||||||
SearchOutlined,
|
SearchOutlined,
|
||||||
ReloadOutlined,
|
|
||||||
ClearOutlined,
|
ClearOutlined,
|
||||||
CloseOutlined,
|
CloseOutlined,
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
@ -248,6 +236,7 @@ import { EdgeArrowProgram } from 'sigma/rendering'
|
|||||||
|
|
||||||
import { lightragApi } from '@/apis/graph_api'
|
import { lightragApi } from '@/apis/graph_api'
|
||||||
import { useGraphStore } from '@/stores/graphStore'
|
import { useGraphStore } from '@/stores/graphStore'
|
||||||
|
import { useDatabaseStore } from '@/stores/database'
|
||||||
import '@/assets/css/sigma.css'
|
import '@/assets/css/sigma.css'
|
||||||
|
|
||||||
// 定义 props
|
// 定义 props
|
||||||
@ -283,6 +272,7 @@ const emit = defineEmits(['update:stats', 'refresh-graph', 'clear-graph'])
|
|||||||
|
|
||||||
// 状态管理
|
// 状态管理
|
||||||
const graphStore = useGraphStore()
|
const graphStore = useGraphStore()
|
||||||
|
const databaseStore = useDatabaseStore()
|
||||||
|
|
||||||
// 响应式引用
|
// 响应式引用
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
@ -714,9 +704,13 @@ const loadGraphData = async () => {
|
|||||||
|
|
||||||
// 设置图数据
|
// 设置图数据
|
||||||
graphStore.setRawGraph(rawGraph)
|
graphStore.setRawGraph(rawGraph)
|
||||||
|
// 更新 displayed 计数(当前视图)以及来自后端的 total 计数(整个库)
|
||||||
graphStore.stats = {
|
graphStore.stats = {
|
||||||
displayed_nodes: graphResponse.data.nodes.length,
|
displayed_nodes: graphResponse.data.nodes.length,
|
||||||
displayed_edges: graphResponse.data.edges.length,
|
displayed_edges: graphResponse.data.edges.length,
|
||||||
|
// 从 statsResponse 填充整个知识库的统计信息(后端返回 total_nodes/total_edges)
|
||||||
|
total_nodes: statsResponse.data.total_nodes ?? graphStore.stats.total_nodes ?? 0,
|
||||||
|
total_edges: statsResponse.data.total_edges ?? graphStore.stats.total_edges ?? 0,
|
||||||
is_truncated: graphResponse.data.is_truncated
|
is_truncated: graphResponse.data.is_truncated
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,82 +749,6 @@ const loadGraphData = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载测试数据
|
|
||||||
const loadTestData = async () => {
|
|
||||||
if (!selectedDatabase.value) {
|
|
||||||
message.warning('请先选择数据库')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
loading.value = true
|
|
||||||
loadingMessage.value = '加载测试数据中...'
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/graph/lightrag/test-data?db_id=${selectedDatabase.value}`, {
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const testData = await response.json()
|
|
||||||
|
|
||||||
if (testData.success) {
|
|
||||||
// 创建图数据
|
|
||||||
const rawGraph = graphStore.createGraphFromApiData(
|
|
||||||
testData.data.nodes,
|
|
||||||
testData.data.edges
|
|
||||||
)
|
|
||||||
|
|
||||||
// 设置图数据
|
|
||||||
graphStore.setRawGraph(rawGraph)
|
|
||||||
graphStore.stats = {
|
|
||||||
displayed_nodes: testData.data.nodes.length,
|
|
||||||
displayed_edges: testData.data.edges.length,
|
|
||||||
is_truncated: testData.data.is_truncated
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Test graph created:', {
|
|
||||||
nodes: rawGraph.nodes.length,
|
|
||||||
edges: rawGraph.edges.length,
|
|
||||||
sampleNode: rawGraph.nodes[0],
|
|
||||||
sampleEdge: rawGraph.edges[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
// 创建Sigma图
|
|
||||||
const sigmaGraph = graphStore.createSigmaGraph(rawGraph)
|
|
||||||
graphStore.setSigmaGraph(sigmaGraph)
|
|
||||||
|
|
||||||
// 应用布局
|
|
||||||
await applyLayout(sigmaGraph)
|
|
||||||
|
|
||||||
// 更新Sigma实例
|
|
||||||
if (sigmaInstance) {
|
|
||||||
sigmaInstance.setGraph(sigmaGraph)
|
|
||||||
sigmaInstance.refresh()
|
|
||||||
} else {
|
|
||||||
await nextTick()
|
|
||||||
await initSigma()
|
|
||||||
}
|
|
||||||
|
|
||||||
message.success(`测试数据加载成功:${rawGraph.nodes.length} 个节点,${rawGraph.edges.length} 条边`)
|
|
||||||
} else {
|
|
||||||
throw new Error('Failed to load test data')
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加载测试数据失败:', error)
|
|
||||||
message.error('加载测试数据失败: ' + error.message)
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
loadingMessage.value = '加载图数据中...'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载完整图数据
|
// 加载完整图数据
|
||||||
const loadFullGraph = async () => {
|
const loadFullGraph = async () => {
|
||||||
selectedLabel.value = '*'
|
selectedLabel.value = '*'
|
||||||
@ -1277,7 +1195,7 @@ defineExpose({
|
|||||||
|
|
||||||
.control-panel {
|
.control-panel {
|
||||||
background: white;
|
background: white;
|
||||||
padding: 8px 0; /* Reduced from 16px */
|
padding: 6px 16px; /* Reduced from 16px */
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 12px; /* Reduced from 16px */
|
gap: 12px; /* Reduced from 16px */
|
||||||
@ -1301,9 +1219,9 @@ defineExpose({
|
|||||||
|
|
||||||
.sigma-container {
|
.sigma-container {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
background: white;
|
// background: white;
|
||||||
position: relative; /* 确保子元素可以相对于此容器定位 */
|
position: relative; /* 确保子元素可以相对于此容器定位 */
|
||||||
border: 1px solid var(--main-20);
|
// border: 1px solid var(--main-20);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
@ -1312,6 +1230,16 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.graph-overlay-stats {
|
||||||
|
position: absolute;
|
||||||
|
left: 16px;
|
||||||
|
bottom: 16px;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 1100;
|
||||||
|
}
|
||||||
|
|
||||||
.detail-panel {
|
.detail-panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 240px; /* Reduced from 300px */
|
width: 240px; /* Reduced from 300px */
|
||||||
@ -1546,4 +1474,4 @@ defineExpose({
|
|||||||
font-size: 12px; /* Added smaller font size */
|
font-size: 12px; /* Added smaller font size */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -18,6 +18,8 @@ export const useDatabaseStore = defineStore('database', () => {
|
|||||||
const queryParams = ref([]);
|
const queryParams = ref([]);
|
||||||
const meta = reactive({});
|
const meta = reactive({});
|
||||||
const graphStats = ref({
|
const graphStats = ref({
|
||||||
|
total_nodes: 0,
|
||||||
|
total_edges: 0,
|
||||||
displayed_nodes: 0,
|
displayed_nodes: 0,
|
||||||
displayed_edges: 0,
|
displayed_edges: 0,
|
||||||
is_truncated: false,
|
is_truncated: false,
|
||||||
@ -35,7 +37,6 @@ export const useDatabaseStore = defineStore('database', () => {
|
|||||||
chunkLoading: false,
|
chunkLoading: false,
|
||||||
autoRefresh: false,
|
autoRefresh: false,
|
||||||
queryParamsLoading: false,
|
queryParamsLoading: false,
|
||||||
isGraphMaximized: false,
|
|
||||||
rightPanelVisible: true,
|
rightPanelVisible: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,38 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="database-info-container">
|
<div class="database-info-container">
|
||||||
<!-- Maximize Graph Modal -->
|
|
||||||
<a-modal
|
|
||||||
v-model:open="isGraphMaximized"
|
|
||||||
:footer="null"
|
|
||||||
:closable="false"
|
|
||||||
width="100%"
|
|
||||||
wrap-class-name="full-modal"
|
|
||||||
:mask-closable="false"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<div class="maximized-graph-header">
|
|
||||||
<h3>知识图谱 (最大化)</h3>
|
|
||||||
<a-button type="text" @click="toggleGraphMaximize">
|
|
||||||
<CompressOutlined /> 退出最大化
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div class="maximized-graph-content">
|
|
||||||
<div v-if="!isGraphSupported" class="graph-disabled">
|
|
||||||
<div class="disabled-content">
|
|
||||||
<h4>知识图谱不可用</h4>
|
|
||||||
<p>当前知识库类型 "{{ getKbTypeLabel(database.kb_type || 'lightrag') }}" 不支持知识图谱功能。</p>
|
|
||||||
<p>只有 LightRAG 类型的知识库支持知识图谱。</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<KnowledgeGraphViewer
|
|
||||||
v-else-if="isGraphMaximized"
|
|
||||||
:initial-database-id="databaseId"
|
|
||||||
:hide-db-selector="true"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</a-modal>
|
|
||||||
|
|
||||||
<FileDetailModal />
|
<FileDetailModal />
|
||||||
|
|
||||||
<FileUploadModal
|
<FileUploadModal
|
||||||
@ -79,9 +46,6 @@
|
|||||||
import { onMounted, reactive, ref, watch, onUnmounted, computed } from 'vue';
|
import { onMounted, reactive, ref, watch, onUnmounted, computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useDatabaseStore } from '@/stores/database';
|
import { useDatabaseStore } from '@/stores/database';
|
||||||
import { getKbTypeLabel } from '@/utils/kb_utils';
|
|
||||||
import { CompressOutlined } from '@ant-design/icons-vue';
|
|
||||||
import KnowledgeGraphViewer from '@/components/KnowledgeGraphViewer.vue';
|
|
||||||
import KnowledgeBaseCard from '@/components/KnowledgeBaseCard.vue';
|
import KnowledgeBaseCard from '@/components/KnowledgeBaseCard.vue';
|
||||||
import FileTable from '@/components/FileTable.vue';
|
import FileTable from '@/components/FileTable.vue';
|
||||||
import FileDetailModal from '@/components/FileDetailModal.vue';
|
import FileDetailModal from '@/components/FileDetailModal.vue';
|
||||||
@ -96,11 +60,6 @@ const store = useDatabaseStore();
|
|||||||
const databaseId = computed(() => store.databaseId);
|
const databaseId = computed(() => store.databaseId);
|
||||||
const database = computed(() => store.database);
|
const database = computed(() => store.database);
|
||||||
const state = computed(() => store.state);
|
const state = computed(() => store.state);
|
||||||
const isGraphMaximized = computed({
|
|
||||||
get: () => store.state.isGraphMaximized,
|
|
||||||
set: (val) => store.state.isGraphMaximized = val
|
|
||||||
});
|
|
||||||
|
|
||||||
// 计算属性:是否支持知识图谱
|
// 计算属性:是否支持知识图谱
|
||||||
const isGraphSupported = computed(() => {
|
const isGraphSupported = computed(() => {
|
||||||
const kbType = database.value.kb_type?.toLowerCase();
|
const kbType = database.value.kb_type?.toLowerCase();
|
||||||
@ -110,15 +69,34 @@ const isGraphSupported = computed(() => {
|
|||||||
// Tab 切换逻辑 - 智能默认
|
// Tab 切换逻辑 - 智能默认
|
||||||
const activeTab = ref('query');
|
const activeTab = ref('query');
|
||||||
|
|
||||||
|
|
||||||
|
const resetGraphStats = () => {
|
||||||
|
store.graphStats = {
|
||||||
|
total_nodes: 0,
|
||||||
|
total_edges: 0,
|
||||||
|
displayed_nodes: 0,
|
||||||
|
displayed_edges: 0,
|
||||||
|
is_truncated: false
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// LightRAG 默认展示知识图谱
|
// LightRAG 默认展示知识图谱
|
||||||
watch(
|
watch(
|
||||||
() => [databaseId.value, isGraphSupported.value],
|
() => [databaseId.value, isGraphSupported.value],
|
||||||
([newDbId, supported], oldValue = []) => {
|
([newDbId, supported], oldValue = []) => {
|
||||||
const [oldDbId, previouslySupported] = oldValue;
|
const [oldDbId, previouslySupported] = oldValue;
|
||||||
|
|
||||||
if (!newDbId) {
|
if (!newDbId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newDbId && newDbId !== oldDbId) {
|
||||||
|
resetGraphStats();
|
||||||
|
} else if (!supported && previouslySupported) {
|
||||||
|
resetGraphStats();
|
||||||
|
}
|
||||||
|
|
||||||
if (supported && (newDbId !== oldDbId || previouslySupported === false || previouslySupported === undefined)) {
|
if (supported && (newDbId !== oldDbId || previouslySupported === false || previouslySupported === undefined)) {
|
||||||
activeTab.value = 'graph';
|
activeTab.value = 'graph';
|
||||||
return;
|
return;
|
||||||
@ -149,11 +127,7 @@ const showAddFilesModal = () => {
|
|||||||
addFilesModalVisible.value = true;
|
addFilesModalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换图谱最大化状态
|
// 重置文件选中状态
|
||||||
const toggleGraphMaximize = () => {
|
|
||||||
isGraphMaximized.value = !isGraphMaximized.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const resetFileSelectionState = () => {
|
const resetFileSelectionState = () => {
|
||||||
store.selectedRowKeys = [];
|
store.selectedRowKeys = [];
|
||||||
store.selectedFile = null;
|
store.selectedFile = null;
|
||||||
@ -163,6 +137,7 @@ const resetFileSelectionState = () => {
|
|||||||
watch(() => route.params.database_id, async (newId) => {
|
watch(() => route.params.database_id, async (newId) => {
|
||||||
store.databaseId = newId;
|
store.databaseId = newId;
|
||||||
resetFileSelectionState();
|
resetFileSelectionState();
|
||||||
|
resetGraphStats();
|
||||||
store.stopAutoRefresh();
|
store.stopAutoRefresh();
|
||||||
await store.getDatabaseInfo(newId, false); // Explicitly load query params on initial load
|
await store.getDatabaseInfo(newId, false); // Explicitly load query params on initial load
|
||||||
store.startAutoRefresh();
|
store.startAutoRefresh();
|
||||||
@ -360,47 +335,6 @@ const handleMouseUp = () => {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
:deep(.full-modal) {
|
|
||||||
.ant-modal {
|
|
||||||
max-width: 100%;
|
|
||||||
top: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-modal-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: calc(100vh - 200px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-modal-body {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.maximized-graph-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin: 0;
|
|
||||||
color: var(--gray-800);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.maximized-graph-content {
|
|
||||||
height: calc(100vh - 300px);
|
|
||||||
border-radius: 6px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 全局样式作为备用方案 */
|
/* 全局样式作为备用方案 */
|
||||||
.ant-popover .query-params-compact {
|
.ant-popover .query-params-compact {
|
||||||
width: 220px;
|
width: 220px;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user