diff --git a/frontend-web/src/open-canvas/components/ai-writing/AIWritingForm.tsx b/frontend-web/src/open-canvas/components/ai-writing/AIWritingForm.tsx index 156b0121..cea4e052 100644 --- a/frontend-web/src/open-canvas/components/ai-writing/AIWritingForm.tsx +++ b/frontend-web/src/open-canvas/components/ai-writing/AIWritingForm.tsx @@ -1,5 +1,5 @@ import { useEffect, useMemo, useState } from 'react'; -import { BookOpen, PenLine, X } from 'lucide-react'; +import { PenLine } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Textarea } from '@/components/ui/textarea'; @@ -30,13 +30,14 @@ const INPUT_CLASS = const DEFAULT_KEYWORD_COUNT = 1; const DEFAULT_AUDIENCE = '普通读者'; -const DEFAULT_MATERIAL_SOURCE: 'knowledge_base' | 'skill' = 'knowledge_base'; +type MaterialSource = 'knowledge_base' | 'skill' | 'notebook'; +const DEFAULT_MATERIAL_SOURCE: MaterialSource = 'knowledge_base'; const MAX_INTENT_LENGTH = 500; -// 素材来源选项:知识库=素材专家默认 web/intranet 检索;技能检索=用技能编排去检索 -const MATERIAL_SOURCE_OPTIONS: Array<{ value: 'knowledge_base' | 'skill'; label: string }> = [ - { value: 'knowledge_base', label: '知识库' }, - { value: 'skill', label: '技能检索' }, +const MATERIAL_SOURCE_OPTIONS: Array<{ value: MaterialSource; label: string; desc: string }> = [ + { value: 'knowledge_base', label: '知识库', desc: '默认 web/intranet 检索' }, + { value: 'skill', label: '技能检索', desc: '用已启用的技能编排检索' }, + { value: 'notebook', label: '我的笔记', desc: '从笔记本中检索素材' }, ]; const FIELD_LABEL_CLASS = 'text-[16px] font-semibold leading-none text-[#222]'; @@ -53,8 +54,7 @@ export function AIWritingForm({ const [audience, setAudience] = useState('普通读者'); const [wordCountInput, setWordCountInput] = useState('800'); const [strictMode, setStrictMode] = useState(false); - const [materialSource, setMaterialSource] = - useState<'knowledge_base' | 'skill'>(DEFAULT_MATERIAL_SOURCE); + const [materialSource, setMaterialSource] = useState(DEFAULT_MATERIAL_SOURCE); const [modelName, setModelName] = useState(''); // 笔记来源:选中的 search_space_id 和多个 document_id const [selectedNotebookId, setSelectedNotebookId] = useState(null); @@ -119,9 +119,12 @@ export function AIWritingForm({ setSelectedDocumentIds([]); } - function clearNoteSelection() { - setSelectedNotebookId(null); - setSelectedDocumentIds([]); + function handleMaterialSourceChange(val: MaterialSource) { + setMaterialSource(val); + if (val !== 'notebook') { + setSelectedNotebookId(null); + setSelectedDocumentIds([]); + } } function toggleDocument(docId: number) { @@ -145,9 +148,9 @@ export function AIWritingForm({ writingMode: hideAdvancedFields ? 'loose' : strictMode ? 'strict' : 'loose', materialSource, modelName: selectedModel?.name || modelName || undefined, - noteSearchSpaceId: selectedNotebookId ?? undefined, - // 有勾选文档则传 document_id 列表,否则传空数组(搜整个笔记本) - noteSourceIds: selectedNotebookId != null ? selectedDocumentIds : undefined, + // 只有选了"我的笔记"才传笔记参数 + noteSearchSpaceId: materialSource === 'notebook' ? (selectedNotebookId ?? undefined) : undefined, + noteSourceIds: materialSource === 'notebook' && selectedNotebookId != null ? selectedDocumentIds : undefined, }); } @@ -218,7 +221,7 @@ export function AIWritingForm({ -

- 知识库:素材专家默认检索方式;技能检索:用已启用的技能去编排检索。 -

+ + {/* 选了"我的笔记"才展示笔记本 / 文档选择器 */} + {materialSource === 'notebook' && ( +
+ + + {selectedNotebookId !== null && ( +
+

+ {sourcesLoading + ? '文档加载中…' + : `选择文档(可多选;不选则搜整个笔记本${selectedDocumentIds.length > 0 ? `,已选 ${selectedDocumentIds.length} 篇` : ''})`} +

+ {!sourcesLoading && ( +
+ {sources.filter((s) => s.document?.id != null).map((s) => { + const docId = s.document!.id; + return ( + + ); + })} +
+ )} +
+ )} +
+ )}
@@ -265,82 +319,6 @@ export function AIWritingForm({
- {/* 笔记来源(可选) */} -
-
-
- - 笔记来源(可选) -
- {selectedNotebookId !== null && ( - - )} -
- - - - {selectedNotebookId !== null && ( -
-

- {sourcesLoading - ? '文档加载中…' - : sources.filter((s) => s.document?.id != null).length === 0 - ? '该笔记本暂无文档' - : `选择文档(可多选;不选则搜索整个笔记本${selectedDocumentIds.length > 0 ? `,已选 ${selectedDocumentIds.length} 篇` : ''})`} -

- {!sourcesLoading && ( -
- {sources - .filter((s) => s.document?.id != null) - .map((s) => { - const docId = s.document!.id; - const checked = selectedDocumentIds.includes(docId); - return ( - - ); - })} -
- )} -
- )} -
-