Merge branch 'xuhd' into 'master'
fix(notebook): 来源搜索导入后立刻显示占位卡并刷新来源列表 See merge request knowledge-base-bj/deerflow-server!148
This commit is contained in:
commit
ed71df1b60
2 files changed
+45
-14
No files matched your search
@@ -405,8 +405,15 @@ const DocumentUploadPopupContent: FC<{
|
||||
if (response.ok) {
|
||||
const data = await response.json() as { imported_count?: number };
|
||||
toast.success(`成功导入 ${data.imported_count || dataList.length} 个来源`);
|
||||
setListData([]);
|
||||
handleBatchDelete();
|
||||
onUploadComplete?.(
|
||||
selectedSearchSources.map((s) => ({
|
||||
id: undefined,
|
||||
title: s.title,
|
||||
task_id: undefined,
|
||||
status: "success" as const,
|
||||
}))
|
||||
);
|
||||
onOpenChange(false);
|
||||
} else {
|
||||
const errorData = await response.json() as { detail?: string };
|
||||
toast.error(errorData.detail || "导入失败,请重试");
|
||||
|
||||
@@ -154,6 +154,7 @@ function SourcesDialog({
|
||||
isLoadingSources,
|
||||
selectedSourceIds,
|
||||
pendingSources,
|
||||
pendingImportTitles,
|
||||
onToggle,
|
||||
onDelete,
|
||||
}: {
|
||||
@@ -164,6 +165,7 @@ function SourcesDialog({
|
||||
isLoadingSources: boolean;
|
||||
selectedSourceIds: number[];
|
||||
pendingSources: Map<string, { id?: number; title: string }>;
|
||||
pendingImportTitles: string[];
|
||||
onToggle: (id: number) => void;
|
||||
onDelete: (id: number) => void;
|
||||
}) {
|
||||
@@ -216,6 +218,14 @@ function SourcesDialog({
|
||||
.map(([taskId, s]) => (
|
||||
<PendingSourceCard key={taskId} title={s.title} />
|
||||
))}
|
||||
{pendingImportTitles
|
||||
.filter((t) => !sources.some((src) => {
|
||||
const srcTitle = src.title ?? (src.document as { title?: string } | undefined)?.title ?? "";
|
||||
return srcTitle === t;
|
||||
}))
|
||||
.map((t) => (
|
||||
<PendingSourceCard key={`import-${t}`} title={t} />
|
||||
))}
|
||||
{sources.map((src) => (
|
||||
<SourceCard
|
||||
key={src.id}
|
||||
@@ -269,6 +279,8 @@ export default function StudioNotebookDetailPage({
|
||||
// 轮询任务管理:task_id -> 来源信息
|
||||
const [pendingSources, setPendingSources] = useState<Map<string, { id?: number; title: string }>>(new Map());
|
||||
const pollingIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
// 同步导入(搜索导入)的占位标题列表,sources 刷新后按标题匹配移除
|
||||
const [pendingImportTitles, setPendingImportTitles] = useState<string[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedModel && models.length > 0) {
|
||||
@@ -287,20 +299,25 @@ export default function StudioNotebookDetailPage({
|
||||
}
|
||||
}, [sources, notebook?.id, initializedForNotebook]);
|
||||
|
||||
// sources 刷新后,将轮询成功的来源(按标题匹配)自动选中
|
||||
// sources 刷新后,将轮询成功/同步导入的来源(按标题匹配)自动选中,并移除占位卡
|
||||
useEffect(() => {
|
||||
if (pendingSelectTitlesRef.current.size === 0) return;
|
||||
const matched = sources.filter((s) => {
|
||||
const title = s.title ?? (s.document as { title?: string } | undefined)?.title ?? "";
|
||||
return pendingSelectTitlesRef.current.has(title);
|
||||
});
|
||||
if (matched.length > 0) {
|
||||
setSelectedSourceIds((prev) => [...new Set([...prev, ...matched.map((s) => s.id)])]);
|
||||
matched.forEach((s) => {
|
||||
const title = s.title ?? (s.document as { title?: string } | undefined)?.title ?? "";
|
||||
pendingSelectTitlesRef.current.delete(title);
|
||||
});
|
||||
const getTitle = (s: SourceItem) =>
|
||||
s.title ?? (s.document as { title?: string } | undefined)?.title ?? "";
|
||||
|
||||
if (pendingSelectTitlesRef.current.size > 0) {
|
||||
const matched = sources.filter((s) => pendingSelectTitlesRef.current.has(getTitle(s)));
|
||||
if (matched.length > 0) {
|
||||
setSelectedSourceIds((prev) => [...new Set([...prev, ...matched.map((s) => s.id)])]);
|
||||
matched.forEach((s) => pendingSelectTitlesRef.current.delete(getTitle(s)));
|
||||
}
|
||||
}
|
||||
|
||||
setPendingImportTitles((prev) => {
|
||||
if (prev.length === 0) return prev;
|
||||
const sourceTitles = new Set(sources.map(getTitle));
|
||||
const remaining = prev.filter((t) => !sourceTitles.has(t));
|
||||
return remaining.length === prev.length ? prev : remaining;
|
||||
});
|
||||
}, [sources]);
|
||||
const citationRehypePlugins = useMemo(() => {
|
||||
const mapped = sources.map((s) => ({
|
||||
@@ -392,6 +409,12 @@ export default function StudioNotebookDetailPage({
|
||||
return newMap;
|
||||
});
|
||||
}
|
||||
// 同步导入(status=success,无 task_id):立刻显示占位卡 + 等 sources 刷新后自动选中
|
||||
const syncTitles = uploadedSources.filter(s => s.status === 'success' && s.title).map(s => s.title);
|
||||
if (syncTitles.length > 0) {
|
||||
syncTitles.forEach(t => pendingSelectTitlesRef.current.add(t));
|
||||
setPendingImportTitles(prev => [...new Set([...prev, ...syncTitles])]);
|
||||
}
|
||||
// 刷新来源列表
|
||||
void queryClient.invalidateQueries({ queryKey: ["studio", "sources", notebook.id] });
|
||||
// 刷新 notebooks 数据以更新 source_count
|
||||
@@ -854,6 +877,7 @@ export default function StudioNotebookDetailPage({
|
||||
isLoadingSources={isLoadingSources}
|
||||
selectedSourceIds={selectedSourceIds}
|
||||
pendingSources={pendingSources}
|
||||
pendingImportTitles={pendingImportTitles}
|
||||
onToggle={handleToggleSource}
|
||||
onDelete={handleDeleteSource}
|
||||
/>
|
||||
|
||||
Reference in new issue
Block a user