From d996040b7fab030788c505d830affdf57ea23db9 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Thu, 22 Jan 2026 15:09:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(KnowledgeManagement):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=9F=A5=E8=AF=86=E6=9D=A1=E7=9B=AE=E9=98=85=E8=AF=BB=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在知识集详情页面中添加阅读按钮,支持查看知识条目的内容 - 实现文本和Markdown格式知识条目的在线阅读预览 - 集成文件下载功能,支持从数据集文件中读取内容 - 添加内容长度限制,超过50000字符时截断并提示 - 使用模态框展示阅读内容,提供良好的用户体验 - --- .../Detail/KnowledgeSetDetail.tsx | 101 +++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/KnowledgeManagement/Detail/KnowledgeSetDetail.tsx b/frontend/src/pages/KnowledgeManagement/Detail/KnowledgeSetDetail.tsx index 3ca5f2f..60840ac 100644 --- a/frontend/src/pages/KnowledgeManagement/Detail/KnowledgeSetDetail.tsx +++ b/frontend/src/pages/KnowledgeManagement/Detail/KnowledgeSetDetail.tsx @@ -6,10 +6,12 @@ import { Card, Descriptions, Empty, + Modal, Table, Tag, + Tooltip, } from "antd"; -import { DeleteOutlined, EditOutlined, PlusOutlined } from "@ant-design/icons"; +import { DeleteOutlined, EditOutlined, EyeOutlined, PlusOutlined } from "@ant-design/icons"; import { useNavigate, useParams } from "react-router"; import DetailHeader from "@/components/DetailHeader"; import { SearchControls } from "@/components/SearchControls"; @@ -29,6 +31,7 @@ import { import { KnowledgeItem, KnowledgeSet, + KnowledgeContentType, KnowledgeStatusType, } from "../knowledge-management.model"; import CreateKnowledgeSet from "../components/CreateKnowledgeSet"; @@ -36,6 +39,8 @@ import KnowledgeItemEditor from "../components/KnowledgeItemEditor"; import ImportKnowledgeItemsDialog from "../components/ImportKnowledgeItemsDialog"; import { formatDate } from "@/utils/unit"; +const MAX_READ_LENGTH = 50000; + const KnowledgeSetDetail = () => { const navigate = useNavigate(); const { message } = App.useApp(); @@ -44,6 +49,10 @@ const KnowledgeSetDetail = () => { const [showEdit, setShowEdit] = useState(false); const [itemEditorOpen, setItemEditorOpen] = useState(false); const [currentItem, setCurrentItem] = useState(null); + const [readItemId, setReadItemId] = useState(null); + const [readModalOpen, setReadModalOpen] = useState(false); + const [readContent, setReadContent] = useState(""); + const [readTitle, setReadTitle] = useState(""); const fetchKnowledgeSet = useCallback(async () => { if (!id) return; @@ -91,6 +100,55 @@ const KnowledgeSetDetail = () => { fetchData(); }; + const isReadableItem = (record: KnowledgeItemView) => { + return ( + record.contentType === KnowledgeContentType.TEXT || + record.contentType === KnowledgeContentType.MARKDOWN + ); + }; + + const handleReadItem = async (record: KnowledgeItemView) => { + setReadItemId(record.id); + setReadTitle(record.title || "知识条目"); + + if (!record.sourceDatasetId || !record.sourceFileId) { + const content = record.content || ""; + if (content.length > MAX_READ_LENGTH) { + setReadContent( + `${content.slice(0, MAX_READ_LENGTH)}\n\n... (内容过长,仅显示前 ${MAX_READ_LENGTH} 字符)` + ); + } else { + setReadContent(content); + } + setReadModalOpen(true); + setReadItemId(null); + return; + } + + const fileUrl = `/api/data-management/datasets/${record.sourceDatasetId}/files/${record.sourceFileId}/download`; + + try { + const response = await fetch(fileUrl); + if (!response.ok) { + throw new Error("下载失败"); + } + const text = await response.text(); + if (text.length > MAX_READ_LENGTH) { + setReadContent( + `${text.slice(0, MAX_READ_LENGTH)}\n\n... (内容过长,仅显示前 ${MAX_READ_LENGTH} 字符)` + ); + } else { + setReadContent(text); + } + setReadModalOpen(true); + } catch (error) { + console.error("读取知识条目失败", error); + message.error("读取失败,请稍后重试"); + } finally { + setReadItemId(null); + } + }; + const statusMeta = knowledgeSet?.status ? knowledgeStatusMap[knowledgeSet.status] : undefined; @@ -164,9 +222,19 @@ const KnowledgeSetDetail = () => { { title: "操作", key: "actions", - width: 140, + width: 200, render: (_: unknown, record: KnowledgeItemView) => (
+ + , + ]} + > +
+          {readContent}
+        
+
); };