diff --git a/web/src/views/GraphView.vue b/web/src/views/GraphView.vue index 03507e80..405a40e6 100644 --- a/web/src/views/GraphView.vue +++ b/web/src/views/GraphView.vue @@ -25,6 +25,8 @@ :options="state.dbOptions" @change="handleDbChange" :loading="state.loadingDatabases" + mode="combobox" + placeholder="选择或输入KB ID" /> - -
-

本页面展示的是 Neo4j 图数据库中的知识图谱信息。

-

具体展示内容包括:

- -

注意:

- -
-
-

本页面展示的是 LightRAG 知识库生成的图谱信息。

-

数据来源于选定的知识库实例。

-

支持通过实体名称进行模糊搜索,输入 "*" 可查看采样全图。

-
-
@@ -252,7 +227,21 @@ const state = reactive({ lightragStats: null, }) -const isNeo4j = computed(() => state.selectedDbId === 'neo4j'); +const isNeo4j = computed(() => { + // 当 selectedDbId 是 'neo4j' 时,或者以 'kb_' 开头时,我们认为它是 Neo4j 驱动的 + // 但是对于 kb_ 开头的,我们可能想要使用 LightRAGInfoPanel 的展示风格(因为它有 stats) + // 或者复用 GraphInfoPanel。 + // GraphInfoPanel 是为 'neo4j' 全局图设计的,包含了 model matching 检查等。 + // KBs (kb_*) 使用 Neo4j 存储,但逻辑上更接近 LightRAG 的"知识库"概念。 + // 为了让 LightRAGInfoPanel 能够展示 stats (get_stats 已经更新支持 kb_), + // 我们这里让 kb_ ID 返回 false,这样会进入 LightRAGInfoPanel 分支。 + return state.selectedDbId === 'neo4j'; +}); + +// 检查是否有有效的已上传文件 +const hasValidFile = computed(() => { + return fileList.value.some(file => file.status === 'done' && file.response?.file_path); +}); // 计算未索引节点数量 const unindexedCount = computed(() => { @@ -293,7 +282,7 @@ const handleDbChange = () => { if (isNeo4j.value) { loadGraphInfo(); } else { - // Also load stats for LightRAG + // Also load stats for LightRAG or KB loadLightRAGStats(); } loadSampleNodes(); @@ -323,13 +312,37 @@ const loadGraphInfo = () => { } const addDocumentByFile = () => { + // 使用计算属性验证文件 + if (!hasValidFile.value) { + message.error('请先等待文件上传完成') + return + } + state.processing = true - const files = fileList.value.filter(file => file.status === 'done').map(file => file.response.file_path) - neo4jApi.addEntities(files[0]) + + // 获取已上传的文件路径 + const uploadedFile = fileList.value.find(file => file.status === 'done' && file.response?.file_path); + const filePath = uploadedFile?.response?.file_path; + + // 再次验证文件路径 + if (!filePath) { + message.error('文件路径获取失败,请重新上传文件') + state.processing = false + return + } + + neo4jApi.addEntities(filePath) .then((data) => { if (data.status === 'success') { message.success(data.message); state.showModal = false; + // 清空文件列表 + fileList.value = []; + // 刷新图谱数据 + setTimeout(() => { + loadGraphInfo(); + loadSampleNodes(); + }, 500); } else { throw new Error(data.message); } @@ -372,11 +385,6 @@ const onSearch = () => { // 可选:提示模型不一致 } - if (!state.searchInput && isNeo4j.value) { - message.error('请输入要查询的实体') - return - } - state.searchLoading = true unifiedApi.getSubgraph({ @@ -409,9 +417,22 @@ onMounted(async () => { loadSampleNodes(); }); -const handleFileUpload = (event) => { - console.log(event) - console.log(fileList.value) +const handleFileUpload = ({ file, fileList: newFileList }) => { + // 更新文件列表 + fileList.value = newFileList; + + // 如果上传失败,显示错误信息 + if (file.status === 'error') { + message.error(`文件上传失败: ${file.name}`); + } + + // 如果上传成功,显示成功信息 + if (file.status === 'done' && file.response?.file_path) { + message.success(`文件上传成功: ${file.name}`); + } + + console.log('File upload status:', file.status, file.name); + console.log('File list:', fileList.value); } const handleDrop = (event) => { @@ -419,6 +440,12 @@ const handleDrop = (event) => { console.log(fileList.value) } +const handleModalCancel = () => { + state.showModal = false; + // 重置文件列表 + fileList.value = []; +}; + const graphStatusClass = computed(() => { if (state.loadingGraphInfo) return 'loading'; return graphInfo.value?.status === 'open' ? 'open' : 'closed';