From 5a5c5e5bf4ebb59e097fa5cdff8ec5171d3338b7 Mon Sep 17 00:00:00 2001 From: yujiangping Date: Tue, 6 Jan 2026 11:22:11 +0800 Subject: [PATCH] feat(knowledgeBase): add knowledge graph rebuild and delete functionality - Add deleteKnowledgeGraph and rebuildKnowledgeGraph API endpoints to knowledgeBase.ts - Add internationalization strings for rebuild confirmation dialog and success/failure messages in both English and Chinese - Implement rebuild mode logic in CreateModal component with confirmation dialog before rebuilding - Add originalType state tracking to distinguish between rebuild and regular edit modes - Update handleSave to trigger graph deletion and rebuild when in rebuild mode with graphrag enabled - Add handleDeleteGraph method to delete existing knowledge graph data before rebuild - Update performSave to use correct type value during save operation in rebuild mode - Enhance Private.tsx to refresh knowledge base details after table data refresh - Import new API functions (deleteKnowledgeGraph, rebuildKnowledgeGraph) in CreateModal - Update KnowledgeGraphCard component timestamp in file header --- web/src/api/knowledgeBase.ts | 10 ++++ web/src/i18n/en.ts | 5 ++ web/src/i18n/zh.ts | 5 ++ .../[knowledgeBaseId]/Private.tsx | 1 + .../KnowledgeBase/components/CreateModal.tsx | 53 +++++++++++++++++-- .../components/KnowledgeGraphCard.tsx | 15 ++++-- 6 files changed, 81 insertions(+), 8 deletions(-) diff --git a/web/src/api/knowledgeBase.ts b/web/src/api/knowledgeBase.ts index a6979b92..5f171a72 100644 --- a/web/src/api/knowledgeBase.ts +++ b/web/src/api/knowledgeBase.ts @@ -295,4 +295,14 @@ export const getKnowledgeGraph = async (kb_id: string) => { export const getKnowledgeGraphEntityTypes = async (query: any) => { const response = await request.get(`${apiPrefix}/knowledges/knowledge_graph_entity_types`,query); return response ; +}; +// 删除图谱 +export const deleteKnowledgeGraph = async (kb_id: string) => { + const response = await request.delete(`${apiPrefix}/knowledges/${kb_id}/knowledge_graph`); + return response; +}; +// 知识库图谱重建 +export const rebuildKnowledgeGraph = async (kb_id: string) => { + const response = await request.post(`${apiPrefix}/knowledges/${kb_id}/knowledge_graph`); + return response; }; \ No newline at end of file diff --git a/web/src/i18n/en.ts b/web/src/i18n/en.ts index 0f3f5898..e679bcee 100644 --- a/web/src/i18n/en.ts +++ b/web/src/i18n/en.ts @@ -726,6 +726,11 @@ export const en = { graphTips: 'Explore the entity nodes in the knowledge base and their relationship networks', sourceDocuments: 'Source Documents', rebuildGraph: 'Rebuild Graph', + rebuildConfirmTitle: 'Confirm the rebuild graph', + rebuildConfirmContent: 'The rebuild graph will erase the existing map data and rebuild it from scratch. This operation is irreversible. Are you sure you want to proceed?', + deleteGraphSuccess: 'Knowledge graph deletion successful', + deleteGraphFailed:'Knowledge graph deletion failed', + graphEmpty: 'At the foot of the mountain of books, the journey begins.', createForm:{ name: 'Name', embedding_id: 'Embedding', diff --git a/web/src/i18n/zh.ts b/web/src/i18n/zh.ts index 4aa03990..abb95a79 100644 --- a/web/src/i18n/zh.ts +++ b/web/src/i18n/zh.ts @@ -336,6 +336,11 @@ export const zh = { graphTitle: '知识图谱:实体、关系与属性的关联网络', graphTips: '探索知识库中的实体节点及其关系脉络', rebuildGraph: '重建图谱', + rebuildConfirmTitle: '确认重建图谱', + rebuildConfirmContent: '重建图谱将清除现有的图谱数据并重新构建,此操作不可逆。确定要继续吗?', + deleteGraphSuccess: '删除知识图谱成功', + deleteGraphFailed:'删除知识图谱失败', + graphEmpty: '书山有路,此处为始', createForm: { name: '名称', embedding_id: '嵌入模型', diff --git a/web/src/views/KnowledgeBase/[knowledgeBaseId]/Private.tsx b/web/src/views/KnowledgeBase/[knowledgeBaseId]/Private.tsx index d6d5ee4f..8087e596 100644 --- a/web/src/views/KnowledgeBase/[knowledgeBaseId]/Private.tsx +++ b/web/src/views/KnowledgeBase/[knowledgeBaseId]/Private.tsx @@ -657,6 +657,7 @@ const Private: FC = () => { const handleRefreshTable = () => { // 刷新表格数据 + fetchKnowledgeBaseDetail(knowledgeBase.id) tableRef.current?.loadData(); } return ( diff --git a/web/src/views/KnowledgeBase/components/CreateModal.tsx b/web/src/views/KnowledgeBase/components/CreateModal.tsx index 2349233f..ce228fa4 100644 --- a/web/src/views/KnowledgeBase/components/CreateModal.tsx +++ b/web/src/views/KnowledgeBase/components/CreateModal.tsx @@ -7,7 +7,9 @@ import { getModelList, createKnowledgeBase, updateKnowledgeBase, - getKnowledgeGraphEntityTypes + getKnowledgeGraphEntityTypes, + deleteKnowledgeGraph, + rebuildKnowledgeGraph } from '@/api/knowledgeBase' import RbModal from '@/components/RbModal' const { TextArea } = Input; @@ -31,6 +33,7 @@ const CreateModal = forwardRef(({ const [activeTab, setActiveTab] = useState('basic'); const [generatingEntityTypes, setGeneratingEntityTypes] = useState(false); const [isRebuildMode, setIsRebuildMode] = useState(false); + const [originalType, setOriginalType] = useState(''); // 保存原始的 type 参数 // 监听 parser_config.graphrag 相关字段的变化 const parserConfig = Form.useWatch('parser_config', form); @@ -47,6 +50,7 @@ const CreateModal = forwardRef(({ setLoading(false); setActiveTab('basic'); setIsRebuildMode(false); // 重置重建模式标识 + setOriginalType(''); // 重置原始 type setVisible(false); }; @@ -224,9 +228,12 @@ const CreateModal = forwardRef(({ const handleOpen = (record?: KnowledgeBaseListItem | null, type?: string) => { setDatasets(record || null); - const nextType = type || currentType; - setCurrentType(nextType as any); + + // 如果是重建模式,使用记录的实际类型,否则使用传入的类型 + const actualType = type === 'rebuild' ? (record?.type || 'General') : (type || currentType); + setCurrentType(actualType as any); setIsRebuildMode(type === 'rebuild'); // 设置重建模式标识 + setOriginalType(type || ''); // 保存原始的 type 参数 // 如果是重建模式,默认切换到知识图谱标签页 if (type === 'rebuild') { @@ -235,7 +242,7 @@ const CreateModal = forwardRef(({ setActiveTab('basic'); } - setBaseFields(record || null, nextType); + setBaseFields(record || null, actualType); getTypeList(record || null); setVisible(true); }; @@ -260,6 +267,39 @@ const CreateModal = forwardRef(({ // 封装保存方法,添加提交逻辑 const handleSave = () => { + // 获取当前表单中的知识图谱开启状态 + const currentFormValues = form.getFieldsValue(); + const isGraphragEnabled = currentFormValues?.parser_config?.graphrag?.use_graphrag || false; + + // 如果原始 type 是 'rebuild' 并且知识图谱开启为true,显示确认弹框 + if (originalType === 'rebuild' && isGraphragEnabled) { + confirm({ + title: t('knowledgeBase.rebuildConfirmTitle'), + content: t('knowledgeBase.rebuildConfirmContent'), + onOk: async() => { + handleDeleteGraph() + performSave(); + await rebuildKnowledgeGraph(datasets?.id || '') + }, + onCancel: () => { + // 用户取消,不执行任何操作 + }, + }); + } else { + // 非重建模式或知识图谱未开启,直接保存 + performSave(); + } + }; + const handleDeleteGraph = () => { + try{ + deleteKnowledgeGraph(datasets?.id || '') + console.log(t('knowledgeBase.deleteGraphSuccess')) + }catch(e){ + messageApi.error(t('knowledgeBase.deleteGraphFailed')) + } + }; + // 实际的保存逻辑 + const performSave = () => { form .validateFields() .then(() => { @@ -276,9 +316,12 @@ const CreateModal = forwardRef(({ formValues.parser_config.graphrag.entity_types = entityTypesArray; } + // 确保保存时使用正确的类型(不是 'rebuild') + const saveType = originalType === 'rebuild' ? currentType : (formValues.type || currentType); + const payload: KnowledgeBaseFormData = { ...formValues, - type: formValues.type || currentType, + type: saveType, permission_id: formValues.permission_id || 'Private', parent_id: datasets?.parent_id || undefined, }; diff --git a/web/src/views/KnowledgeBase/components/KnowledgeGraphCard.tsx b/web/src/views/KnowledgeBase/components/KnowledgeGraphCard.tsx index a485bacc..3dd7ab22 100644 --- a/web/src/views/KnowledgeBase/components/KnowledgeGraphCard.tsx +++ b/web/src/views/KnowledgeBase/components/KnowledgeGraphCard.tsx @@ -4,7 +4,7 @@ * @Author: yujiangping * @Date: 2025-12-30 15:07:37 * @LastEditors: yujiangping - * @LastEditTime: 2026-01-05 16:18:53 + * @LastEditTime: 2026-01-05 20:28:51 */ import React, { useState, useEffect } from 'react' import { useTranslation } from 'react-i18next'; @@ -38,7 +38,13 @@ const KnowledgeGraphCard: React.FC = ({ knowledgeBase, setLoading(true) try { const res = await getKnowledgeGraph(knowledgeBase?.id) - setData(res as KnowledgeGraphResponse) + // 判断 res.graph 是否为空对象或不存在 + const graphResponse = res as KnowledgeGraphResponse; + if (!graphResponse || !graphResponse.graph || Object.keys(graphResponse.graph).length === 0) { + setData(undefined) // 设置为 undefined 以显示 empty 状态 + } else { + setData(graphResponse) + } } catch (error) { console.error('获取知识图谱数据失败:', error) } finally { @@ -68,7 +74,10 @@ const KnowledgeGraphCard: React.FC = ({ knowledgeBase,
- {knowledgeBase?.parser_config?.graphrag?.use_graphrag ? () : } + {knowledgeBase?.parser_config?.graphrag?.use_graphrag ? + () + : + }