From cbad129ce4c1159e6c829d257e614fa3bc906d41 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 30 Jan 2026 21:50:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(rag):=20=E6=B7=BB=E5=8A=A0=E7=9B=B8?= =?UTF-8?q?=E5=AF=B9=E8=B7=AF=E5=BE=84=E6=90=9C=E7=B4=A2=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E6=96=87=E4=BB=B6=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在RagFileRepositoryImpl中新增relativePath字段和路径模式构建方法 - 实现buildRelativePathPattern方法用于构建相对路径搜索模式 - 修改page方法添加相对路径模糊查询支持 - 在RagFileReq DTO中添加relativePath参数字段 - 优化KnowledgeBaseDetail页面中的文件名显示逻辑 - 添加normalizePath函数处理文件路径规范化显示 --- .../impl/RagFileRepositoryImpl.java | 18 +++++++ .../indexer/interfaces/dto/RagFileReq.java | 1 + .../Detail/KnowledgeBaseDetail.tsx | 50 ++++++++----------- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/backend/services/rag-indexer-service/src/main/java/com/datamate/rag/indexer/infrastructure/persistence/impl/RagFileRepositoryImpl.java b/backend/services/rag-indexer-service/src/main/java/com/datamate/rag/indexer/infrastructure/persistence/impl/RagFileRepositoryImpl.java index a6afa9e..1724ba7 100644 --- a/backend/services/rag-indexer-service/src/main/java/com/datamate/rag/indexer/infrastructure/persistence/impl/RagFileRepositoryImpl.java +++ b/backend/services/rag-indexer-service/src/main/java/com/datamate/rag/indexer/infrastructure/persistence/impl/RagFileRepositoryImpl.java @@ -20,6 +20,8 @@ import java.util.List; */ @Repository public class RagFileRepositoryImpl extends CrudRepository implements RagFileRepository { + private static final String RELATIVE_PATH_KEY = "\"relativePath\":\""; + private static final String PATH_SEPARATOR = "/"; @Override public void removeByKnowledgeBaseId(String knowledgeBaseId) { lambdaUpdate().eq(RagFile::getKnowledgeBaseId, knowledgeBaseId).remove(); @@ -42,9 +44,25 @@ public class RagFileRepositoryImpl extends CrudRepository page(IPage page, RagFileReq request) { + String relativePathPattern = buildRelativePathPattern(request.getRelativePath()); return lambdaQuery() .eq(RagFile::getKnowledgeBaseId, request.getKnowledgeBaseId()) .like(StringUtils.hasText(request.getFileName()), RagFile::getFileName, request.getFileName()) + .like(StringUtils.hasText(relativePathPattern), RagFile::getMetadata, relativePathPattern) .page(page); } + + private String buildRelativePathPattern(String relativePath) { + if (!StringUtils.hasText(relativePath)) { + return ""; + } + String normalized = relativePath.replace("\\", PATH_SEPARATOR).trim(); + while (normalized.startsWith(PATH_SEPARATOR)) { + normalized = normalized.substring(1); + } + if (!StringUtils.hasText(normalized)) { + return ""; + } + return RELATIVE_PATH_KEY + normalized; + } } diff --git a/backend/services/rag-indexer-service/src/main/java/com/datamate/rag/indexer/interfaces/dto/RagFileReq.java b/backend/services/rag-indexer-service/src/main/java/com/datamate/rag/indexer/interfaces/dto/RagFileReq.java index 55d1988..3f8c7f8 100644 --- a/backend/services/rag-indexer-service/src/main/java/com/datamate/rag/indexer/interfaces/dto/RagFileReq.java +++ b/backend/services/rag-indexer-service/src/main/java/com/datamate/rag/indexer/interfaces/dto/RagFileReq.java @@ -14,5 +14,6 @@ import lombok.Setter; @Getter public class RagFileReq extends PagingQuery { private String fileName; + private String relativePath; private String knowledgeBaseId; } diff --git a/frontend/src/pages/KnowledgeBase/Detail/KnowledgeBaseDetail.tsx b/frontend/src/pages/KnowledgeBase/Detail/KnowledgeBaseDetail.tsx index 4e34da1..880b9bb 100644 --- a/frontend/src/pages/KnowledgeBase/Detail/KnowledgeBaseDetail.tsx +++ b/frontend/src/pages/KnowledgeBase/Detail/KnowledgeBaseDetail.tsx @@ -124,10 +124,14 @@ const KnowledgeBaseDetailPage: React.FC = () => { const pageSize = 200; let page = 0; let combined: KBFile[] = []; + const currentPrefix = normalizePrefix(filePrefix); + const keyword = fileKeyword.trim(); while (true) { const { data } = await queryKnowledgeBaseFilesUsingGet(id, { page, size: pageSize, + ...(currentPrefix ? { relativePath: currentPrefix } : {}), + ...(keyword ? { fileName: keyword } : {}), }); const content = Array.isArray(data?.content) ? data.content : []; combined = combined.concat(content.map(mapFileData)); @@ -146,14 +150,19 @@ const KnowledgeBaseDetailPage: React.FC = () => { } finally { setFilesLoading(false); } - }, [id, message]); + }, [id, filePrefix, fileKeyword, message]); useEffect(() => { if (id) { fetchKnowledgeBaseDetails(id); + } + }, [id, fetchKnowledgeBaseDetails]); + + useEffect(() => { + if (id) { fetchFiles(); } - }, [id, fetchKnowledgeBaseDetails, fetchFiles]); + }, [id, fetchFiles]); // File table logic const handleDeleteFile = async (file: KBFileRow) => { @@ -257,8 +266,7 @@ const KnowledgeBaseDetailPage: React.FC = () => { const normalizedPrefix = useMemo(() => normalizePrefix(filePrefix), [filePrefix]); const { rows: fileRows, total: fileTotal } = useMemo(() => { - const keyword = fileKeyword.trim().toLowerCase(); - const folderMap = new Map(); + const folderMap = new Map(); const fileItems: KBFileRow[] = []; allFiles.forEach((file) => { @@ -271,31 +279,22 @@ const KnowledgeBaseDetailPage: React.FC = () => { return; } const leafName = segments[0]; - const fileMatches = - !keyword || - leafName.toLowerCase().includes(keyword) || - fullPath.toLowerCase().includes(keyword); if (segments.length > 1) { const folderName = leafName; const entry = folderMap.get(folderName) || { name: folderName, fileCount: 0, - hasMatch: false, }; entry.fileCount += 1; - if (fileMatches) { - entry.hasMatch = true; - } folderMap.set(folderName, entry); return; } - if (!fileMatches) { - return; - } - - const displayName = file.fileName || leafName; + const normalizedFileName = normalizePath(file.fileName); + const displayName = normalizedFileName.includes(PATH_SEPARATOR) + ? leafName + : file.fileName || leafName; fileItems.push({ ...file, name: displayName, @@ -304,17 +303,8 @@ const KnowledgeBaseDetailPage: React.FC = () => { }); }); - const folderItems: KBFileRow[] = Array.from(folderMap.values()) - .filter((entry) => { - if (!keyword) { - return true; - } - return ( - entry.hasMatch || - entry.name.toLowerCase().includes(keyword) - ); - }) - .map((entry) => + const folderItems: KBFileRow[] = Array.from(folderMap.values()).map( + (entry) => ({ id: `directory-${normalizedPrefix}${entry.name}`, fileName: entry.name, @@ -333,7 +323,7 @@ const KnowledgeBaseDetailPage: React.FC = () => { fullPath: `${normalizedPrefix}${entry.name}/`, fileCount: entry.fileCount, }) as KBFileRow - ); + ); const sortByName = (a: KBFileRow, b: KBFileRow) => (a.displayName || a.name || "").localeCompare( @@ -346,7 +336,7 @@ const KnowledgeBaseDetailPage: React.FC = () => { const combined = [...folderItems, ...fileItems]; return { rows: combined, total: combined.length }; - }, [allFiles, fileKeyword, knowledgeBase?.id, normalizedPrefix]); + }, [allFiles, knowledgeBase?.id, normalizedPrefix]); const filePageCurrent = filePagination.current; const filePageSize = filePagination.pageSize;