import { useState } from "react"; import { useAsyncData } from "../../lib/useAsyncData"; import { adminDeleteRag, adminIndexRag, adminListRag, adminSearchRag } from "../../lib/api"; import type { AdminRagDoc, AdminRagHit } from "../../lib/types"; import { useAuditStore } from "../audit"; import { Notice, PageHeader } from "../components"; import { Button, Surface, Tag } from "../../components/primitives"; export function RagModule(): React.ReactNode { const log = useAuditStore((s) => s.log); const { data, loading, error, reload } = useAsyncData(() => adminListRag(), []); const [query, setQuery] = useState(""); const [hits, setHits] = useState([]); const [searching, setSearching] = useState(false); const [notice, setNotice] = useState(null); // Manual "导入文档" form fields. const [docName, setDocName] = useState(""); const [docDesc, setDocDesc] = useState(""); const [docContent, setDocContent] = useState(""); const [importing, setImporting] = useState(false); const docs: AdminRagDoc[] = data?.documents ?? []; const search = async () => { log("rag.search", "ok"); setSearching(true); setNotice(null); try { const res = await adminSearchRag(query.trim()); setHits(res.hits); } catch (err: unknown) { const msg = err instanceof Error ? err.message : "检索失败"; setNotice(msg); setHits([]); } finally { setSearching(false); } }; const remove = async (d: AdminRagDoc) => { log("rag.delete", "ok"); setNotice(null); try { await adminDeleteRag(d.id); } catch (err: unknown) { setNotice(err instanceof Error ? err.message : "文档删除为后端 M10 写操作"); } }; const importDoc = async () => { if (!docName.trim() || !docContent.trim()) { setNotice("文档名称与内容不能为空"); return; } setImporting(true); setNotice(null); try { await adminIndexRag({ name: docName.trim(), desc: docDesc.trim() || undefined, content: docContent.trim(), }); log("rag.index", "ok"); setDocName(""); setDocDesc(""); setDocContent(""); reload(); setNotice("文档已导入,可按知识库检索。"); } catch (err: unknown) { log("rag.index", "error"); setNotice(err instanceof Error ? err.message : "导入文档失败"); } finally { setImporting(false); } }; return (
刷新 } /> {notice ? {notice} : null}

导入文档(写入项目索引,可分块、可检索)

setDocName(e.target.value)} placeholder="文档名称(如:内部知识库.md)…" className="w-full rounded-[var(--mu-radius)] bg-[var(--mu-surface-2)] px-3 py-2 text-sm outline-none focus:ring-1 focus:ring-[var(--mu-accent)]" /> setDocDesc(e.target.value)} placeholder="描述(可选,作为项目描述)…" className="w-full rounded-[var(--mu-radius)] bg-[var(--mu-surface-2)] px-3 py-2 text-sm outline-none focus:ring-1 focus:ring-[var(--mu-accent)]" />