fix(editor): chatInput草稿恢复 + AI请求content条件格式

- 草稿恢复分支增加chatInput恢复,避免路由切换后聊天输入框内容丢失
- handleAIGenerate中messageContent改为条件判断:无图片时发送string,有图片时发送vision数组,修复Kimi文本模型400 Bad Request
This commit is contained in:
2026-04-19 03:23:49 +08:00
parent 9173aa7733
commit da2ecdc224

View File

@@ -77,6 +77,10 @@ export default function ReportEditor() {
stateRef.current.chatMessages = chatMessages; stateRef.current.chatMessages = chatMessages;
}, [chatMessages]); }, [chatMessages]);
useEffect(() => {
stateRef.current.chatInput = chatInput;
}, [chatInput]);
useEffect(() => { useEffect(() => {
if (!editorRef.current) return; if (!editorRef.current) return;
const allFields = editorRef.current.querySelectorAll('.field-value'); const allFields = editorRef.current.querySelectorAll('.field-value');
@@ -122,7 +126,7 @@ export default function ReportEditor() {
const videoInputRef = useRef<HTMLInputElement>(null); const videoInputRef = useRef<HTMLInputElement>(null);
const contentLoadedRef = useRef(false); const contentLoadedRef = useRef(false);
const contentRef = useRef(''); const contentRef = useRef('');
const stateRef = useRef({ reportData, videos, capturedFrames, activeTab, loadedTemplateId, chatMessages }); const stateRef = useRef({ reportData, videos, capturedFrames, activeTab, loadedTemplateId, chatMessages, chatInput });
const draftKey = currentUser ? `reportEditorDraft_${currentUser.username}` : ''; const draftKey = currentUser ? `reportEditorDraft_${currentUser.username}` : '';
@@ -148,7 +152,8 @@ export default function ReportEditor() {
capturedFrames: stateRef.current.capturedFrames, capturedFrames: stateRef.current.capturedFrames,
activeTab: stateRef.current.activeTab, activeTab: stateRef.current.activeTab,
loadedTemplateId: stateRef.current.loadedTemplateId, loadedTemplateId: stateRef.current.loadedTemplateId,
chatMessages: stateRef.current.chatMessages chatMessages: stateRef.current.chatMessages,
chatInput: stateRef.current.chatInput
}); });
} }
}, [reportId]); }, [reportId]);
@@ -193,13 +198,15 @@ export default function ReportEditor() {
} }
if (draft.activeTab) setActiveTab(draft.activeTab); if (draft.activeTab) setActiveTab(draft.activeTab);
if (draft.chatMessages) setChatMessages(draft.chatMessages); if (draft.chatMessages) setChatMessages(draft.chatMessages);
if (typeof draft.chatInput === 'string') setChatInput(draft.chatInput);
stateRef.current = { stateRef.current = {
...stateRef.current, ...stateRef.current,
reportData: draft.reportData, reportData: draft.reportData,
videos: draft.videos, videos: draft.videos,
capturedFrames: draft.capturedFrames, capturedFrames: draft.capturedFrames,
loadedTemplateId: draft.loadedTemplateId || '', loadedTemplateId: draft.loadedTemplateId || '',
chatMessages: draft.chatMessages || [] chatMessages: draft.chatMessages || [],
chatInput: draft.chatInput || ''
}; };
if (editorRef.current && typeof draft.content === 'string' && draft.content.trim().length > 0) { if (editorRef.current && typeof draft.content === 'string' && draft.content.trim().length > 0) {
editorRef.current.innerHTML = draft.content; editorRef.current.innerHTML = draft.content;
@@ -869,17 +876,22 @@ export default function ReportEditor() {
} }
const targetRegionEl = editorRef.current?.querySelector(`.ai-region[data-ai-id="${aiTargetRegion}"] .ai-content`) as HTMLElement | null; const targetRegionEl = editorRef.current?.querySelector(`.ai-region[data-ai-id="${aiTargetRegion}"] .ai-content`) as HTMLElement | null;
const currentHtml = targetRegionEl ? targetRegionEl.innerHTML : ''; const currentHtml = targetRegionEl ? targetRegionEl.innerHTML : '';
const messageContent: any[] = []; let messageContent: any;
const selectedFrameUrls = aiSelectedFrames.map(id => capturedFrames.find(f => f.id === id)?.dataUrl).filter(Boolean); const selectedFrameUrls = aiSelectedFrames.map(id => capturedFrames.find(f => f.id === id)?.dataUrl).filter(Boolean);
const allImages = [...selectedFrameUrls, ...aiUploadedImages.map(i => i.dataUrl)]; const allImages = [...selectedFrameUrls, ...aiUploadedImages.map(i => i.dataUrl)];
allImages.forEach(url => {
messageContent.push({ type: 'image_url', image_url: { url } });
});
let promptText = `【医生指令】: ${text}`; let promptText = `【医生指令】: ${text}`;
if (aiModifyEnabled && targetRegionEl) { if (aiModifyEnabled && targetRegionEl) {
promptText = `【当前区域 HTML 源码】:\n${currentHtml}\n\n${promptText}`; promptText = `【当前区域 HTML 源码】:\n${currentHtml}\n\n${promptText}`;
} }
messageContent.push({ type: 'text', text: promptText }); if (allImages.length > 0) {
messageContent = [];
allImages.forEach(url => {
messageContent.push({ type: 'image_url', image_url: { url } });
});
messageContent.push({ type: 'text', text: promptText });
} else {
messageContent = promptText;
}
const systemPrompt = aiModifyEnabled && targetRegionEl const systemPrompt = aiModifyEnabled && targetRegionEl
? '你是一名专业的外科医生助理。你需要根据用户的指令及可能提供的截图,修改给定的 HTML 源码。\n重要指令你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记(如 ```json。\nJSON 格式如下:\n{ "reply": "简短的回复话术", "updatedHtml": "修改后的完整内部 HTML 代码" }' ? '你是一名专业的外科医生助理。你需要根据用户的指令及可能提供的截图,修改给定的 HTML 源码。\n重要指令你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记(如 ```json。\nJSON 格式如下:\n{ "reply": "简短的回复话术", "updatedHtml": "修改后的完整内部 HTML 代码" }'
: '你是一名专业的外科医生助理。请根据用户的指令和截图进行分析解答。\n重要指令你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记。\nJSON 格式如下:\n{ "reply": "你的分析和回答" }'; : '你是一名专业的外科医生助理。请根据用户的指令和截图进行分析解答。\n重要指令你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记。\nJSON 格式如下:\n{ "reply": "你的分析和回答" }';
@@ -1160,7 +1172,8 @@ export default function ReportEditor() {
videos: draft.videos, videos: draft.videos,
capturedFrames: draft.capturedFrames, capturedFrames: draft.capturedFrames,
loadedTemplateId: draft.loadedTemplateId || '', loadedTemplateId: draft.loadedTemplateId || '',
chatMessages: draft.chatMessages || [] chatMessages: draft.chatMessages || [],
chatInput: draft.chatInput || ''
}; };
setTimeout(() => updatePageHeight(), 0); setTimeout(() => updatePageHeight(), 0);
return; return;