diff --git a/frontend-web/src/open-canvas/components/ai-writing/CompletedInterventionCard.tsx b/frontend-web/src/open-canvas/components/ai-writing/CompletedInterventionCard.tsx index db95fb3c..94f9c682 100644 --- a/frontend-web/src/open-canvas/components/ai-writing/CompletedInterventionCard.tsx +++ b/frontend-web/src/open-canvas/components/ai-writing/CompletedInterventionCard.tsx @@ -46,8 +46,14 @@ function MaterialCompleted({ record, expanded, onToggle }: { record: CompletedIn - 已确认{' '} - {count} 条素材 + {count === 0 && record.action !== 're_search' ? ( + '已在无素材的情况下继续写作' + ) : ( + <> + 已确认{' '} + {count} 条素材 + + )} {count > 0 && ( expanded diff --git a/frontend-web/src/open-canvas/components/ai-writing/InterventionCard.tsx b/frontend-web/src/open-canvas/components/ai-writing/InterventionCard.tsx index 824b9567..65526f27 100644 --- a/frontend-web/src/open-canvas/components/ai-writing/InterventionCard.tsx +++ b/frontend-web/src/open-canvas/components/ai-writing/InterventionCard.tsx @@ -118,6 +118,50 @@ function MaterialConfirmCard({ materials, onSubmit, disabled }: MaterialConfirmC const hasExtra = extraKeywords.length > 0; + // 空数据态:未检索到任何素材,提示用户重新搜索或在无素材情况下继续 + if (materials.length === 0) { + return ( +
+
+ +
+

未检索到任何素材

+

+ 素材收集专家本次没有检索到相关数据。你可以补充关键词重新搜索,或在无素材的情况下直接继续写作(文章将仅依据写作意图生成)。 +

+
+
+ + setSelectedIds(new Set())} + onDeselectAll={() => setSelectedIds(new Set())} + extraKeywords={extraKeywords} + onAddKeyword={(kw) => setExtraKeywords((prev) => [...prev, kw])} + onRemoveKeyword={(kw) => setExtraKeywords((prev) => prev.filter((k) => k !== kw))} + /> + +
+ + +
+
+ ); + } + return (
diff --git a/frontend-web/src/open-canvas/components/ai-writing/MaterialsToolbar.tsx b/frontend-web/src/open-canvas/components/ai-writing/MaterialsToolbar.tsx index 0bd4c08e..aa38973e 100644 --- a/frontend-web/src/open-canvas/components/ai-writing/MaterialsToolbar.tsx +++ b/frontend-web/src/open-canvas/components/ai-writing/MaterialsToolbar.tsx @@ -34,20 +34,22 @@ export function MaterialsToolbar({ return (
- {/* 全选/取消 */} -
- - 已选 {selectedIds.size} / {materials.length} 条素材 - -
- -
+ {/* 全选/取消(无素材时隐藏) */} + {materials.length > 0 && ( +
+ + 已选 {selectedIds.size} / {materials.length} 条素材 + +
+ +
+ )} {/* 补充关键词 */}
diff --git a/frontend-web/src/open-canvas/components/artifact/TextArtifactRenderer.tsx b/frontend-web/src/open-canvas/components/artifact/TextArtifactRenderer.tsx index a2b12ad5..23bca574 100644 --- a/frontend-web/src/open-canvas/components/artifact/TextArtifactRenderer.tsx +++ b/frontend-web/src/open-canvas/components/artifact/TextArtifactRenderer.tsx @@ -204,7 +204,7 @@ export function TextArtifactRenderer({ content, isStreaming }: TextArtifactRende ), p: ({ children }) => ( -

+

{children}

), diff --git a/frontend-web/src/styles/globals.css b/frontend-web/src/styles/globals.css index c7d0036d..3b8f86da 100644 --- a/frontend-web/src/styles/globals.css +++ b/frontend-web/src/styles/globals.css @@ -579,6 +579,7 @@ line-height: 1.8; font-size: 0.9375rem; /* 15px */ color: var(--foreground); + text-indent: 2em; /* 段落首行缩进 */ } .tiptap-writing-editor .ProseMirror h1 { @@ -658,6 +659,7 @@ .tiptap-writing-editor .ProseMirror li > p { margin-bottom: 0.25rem; + text-indent: 0; /* 列表项内段落不缩进 */ } .tiptap-writing-editor .ProseMirror blockquote { @@ -716,6 +718,10 @@ } /* Placeholder */ +.tiptap-writing-editor .ProseMirror p.is-editor-empty:first-child { + text-indent: 0; /* 占位文案不缩进 */ +} + .tiptap-writing-editor .ProseMirror p.is-editor-empty:first-child::before { content: attr(data-placeholder); color: var(--muted-foreground); diff --git a/offline-backend-20260512/backend/packages/harness/deerflow/agents/ai_writing/nodes/researcher.py b/offline-backend-20260512/backend/packages/harness/deerflow/agents/ai_writing/nodes/researcher.py index 59639aa2..361f3394 100644 --- a/offline-backend-20260512/backend/packages/harness/deerflow/agents/ai_writing/nodes/researcher.py +++ b/offline-backend-20260512/backend/packages/harness/deerflow/agents/ai_writing/nodes/researcher.py @@ -140,6 +140,10 @@ async def researcher_node(state: AIWritingState, config: RunnableConfig) -> dict materials = sorted(raw_materials, key=lambda m: m.get("relevance_score", 0), reverse=True)[:_MAX_MATERIALS] summary = f"共搜索到{len(raw_materials)}条素材,精选{len(materials)}条" + # 空结果兜底:未检索到任何素材时给出明确文案,前端据此弹出「无数据继续」选项 + if not materials: + summary = "未检索到相关素材,可重新搜索或在无素材的情况下继续写作" + pkg = MaterialPackage(keywords=keywords, materials=materials, summary=summary) return {