diff --git a/src/pages/ReportEditor.tsx b/src/pages/ReportEditor.tsx index 9f1c06a..e9205e4 100644 --- a/src/pages/ReportEditor.tsx +++ b/src/pages/ReportEditor.tsx @@ -875,14 +875,16 @@ export default function ReportEditor() { return; } 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.replace(/​/g, '').trim() : ''; + const globalContextText = editorRef.current?.innerText || ''; let messageContent: any; const selectedFrameUrls = aiSelectedFrames.map(id => capturedFrames.find(f => f.id === id)?.dataUrl).filter(Boolean); const allImages = [...selectedFrameUrls, ...aiUploadedImages.map(i => i.dataUrl)]; - let promptText = `【医生指令】: ${text}`; + let promptText = `【全局手术报告参考内容】:\n${globalContextText}\n\n`; if (aiModifyEnabled && targetRegionEl) { - promptText = `【当前区域 HTML 源码】:\n${currentHtml}\n\n${promptText}`; + promptText += `【你需要进行修改的目标区域 HTML 源码】:\n${currentHtml || '(当前区域为空)'}\n\n`; } + promptText += `【医生指令】: ${text}`; if (allImages.length > 0) { messageContent = []; allImages.forEach(url => { @@ -893,8 +895,8 @@ export default function ReportEditor() { messageContent = promptText; } const systemPrompt = aiModifyEnabled && targetRegionEl - ? '你是一名专业的外科医生助理。你需要根据用户的指令及可能提供的截图,修改给定的 HTML 源码。\n重要指令:你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记(如 ```json)。\nJSON 格式如下:\n{ "reply": "简短的回复话术", "updatedHtml": "修改后的完整内部 HTML 代码" }' - : '你是一名专业的外科医生助理。请根据用户的指令和截图进行分析解答。\n重要指令:你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记。\nJSON 格式如下:\n{ "reply": "你的分析和回答" }'; + ? '你是一名专业的外科医生助理。我为你提供了当前手术报告的【全局参考内容】作为背景知识,以及你需要修改的【目标区域 HTML 源码】。\n请根据全局内容和用户的【医生指令】,直接重写并输出目标区域的 HTML。\n重要指令:你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记(如 ```json)。\nJSON 格式如下:\n{ "reply": "简短的回复话术", "updatedHtml": "修改后的完整内部 HTML 代码" }' + : '你是一名专业的外科医生助理。请仔细阅读我提供的【全局手术报告参考内容】,并根据【医生指令】进行专业解答。\n重要指令:严格返回合法的 JSON 对象。\nJSON 格式如下:\n{ "reply": "你的分析和回答" }'; const response = await fetch(`${apiEndpoint}/chat/completions`, { method: 'POST', headers: { @@ -2255,17 +2257,20 @@ export default function ReportEditor() { )} -
+
+ + {/* 视觉参考上下文 */} diff --git a/工程分析/20260419_0333/实现方案.md b/工程分析/20260419_0333/实现方案.md new file mode 100644 index 0000000..79805f2 --- /dev/null +++ b/工程分析/20260419_0333/实现方案.md @@ -0,0 +1,97 @@ +# 实现方案 + +## 修改文件 +- `src/pages/ReportEditor.tsx` + +## 修改位置 1:Checkbox 包裹结构(约 line 2258-2268) + +**原代码**: +```tsx +
+ setAiModifyEnabled(e.target.checked)} + className="w-3.5 h-3.5 text-blue-600 rounded border-slate-300 focus:ring-blue-500 cursor-pointer" + /> + +
+``` + +**新代码**: +```tsx + +``` + +**变更点**: +1. 外层 `div` 改为 `label`,直接包裹 `input` +2. 移除 `id`/`htmlFor`,避免绑定冲突 +3. `onChange` 增加 `e.stopPropagation()` 防止事件冒泡被拦截 +4. `label` 文本改为 `span` + +## 修改位置 2:handleAIGenerate Prompt 构建(约 line 877-897) + +**原代码**: +```tsx +const targetRegionEl = editorRef.current?.querySelector(`.ai-region[data-ai-id="${aiTargetRegion}"] .ai-content`) as HTMLElement | null; +const currentHtml = targetRegionEl ? targetRegionEl.innerHTML : ''; +// ... +let promptText = `【医生指令】: ${text}`; +if (aiModifyEnabled && targetRegionEl) { + promptText = `【当前区域 HTML 源码】:\n${currentHtml}\n\n${promptText}`; +} +``` + +**新代码**: +```tsx +const targetRegionEl = editorRef.current?.querySelector(`.ai-region[data-ai-id="${aiTargetRegion}"] .ai-content`) as HTMLElement | null; +const currentHtml = targetRegionEl ? targetRegionEl.innerHTML.replace(/​/g, '').trim() : ''; +const globalContextText = editorRef.current?.innerText || ''; +// ... +let promptText = `【全局手术报告参考内容】:\n${globalContextText}\n\n`; +if (aiModifyEnabled && targetRegionEl) { + promptText += `【你需要进行修改的目标区域 HTML 源码】:\n${currentHtml || '(当前区域为空)'}\n\n`; +} +promptText += `【医生指令】: ${text}`; +``` + +**变更点**: +1. `currentHtml` 增加 `.replace(/​/g, '').trim()` 过滤零宽字符 +2. 新增 `globalContextText` 读取整个编辑器的纯文本 +3. `promptText` 重构:先放全局上下文,再放目标区域(如果存在),最后放医生指令 +4. 目标区域为空时显示 `(当前区域为空)` 提示 + +## 修改位置 3:System Prompt 优化(约 line 895-897) + +**原代码**: +```tsx +const systemPrompt = aiModifyEnabled && targetRegionEl + ? '你是一名专业的外科医生助理。你需要根据用户的指令及可能提供的截图,修改给定的 HTML 源码。\n重要指令:你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记(如 ```json)。\nJSON 格式如下:\n{ "reply": "简短的回复话术", "updatedHtml": "修改后的完整内部 HTML 代码" }' + : '你是一名专业的外科医生助理。请根据用户的指令和截图进行分析解答。\n重要指令:你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记。\nJSON 格式如下:\n{ "reply": "你的分析和回答" }'; +``` + +**新代码**: +```tsx +const systemPrompt = aiModifyEnabled && targetRegionEl + ? '你是一名专业的外科医生助理。我为你提供了当前手术报告的【全局参考内容】作为背景知识,以及你需要修改的【目标区域 HTML 源码】。\n请根据全局内容和用户的【医生指令】,直接重写并输出目标区域的 HTML。\n重要指令:你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记(如 ```json)。\nJSON 格式如下:\n{ "reply": "简短的回复话术", "updatedHtml": "修改后的完整内部 HTML 代码" }' + : '你是一名专业的外科医生助理。请仔细阅读我提供的【全局手术报告参考内容】,并根据【医生指令】进行专业解答。\n重要指令:严格返回合法的 JSON 对象。\nJSON 格式如下:\n{ "reply": "你的分析和回答" }'; +``` + +**变更点**: +1. 修改模式 systemPrompt 明确告知大模型有两个信息源:全局参考内容 + 目标区域源码 +2. 非修改模式 systemPrompt 明确提到「全局手术报告参考内容」 diff --git a/工程分析/20260419_0333/测试方案.md b/工程分析/20260419_0333/测试方案.md new file mode 100644 index 0000000..24fd03d --- /dev/null +++ b/工程分析/20260419_0333/测试方案.md @@ -0,0 +1,55 @@ +# 测试方案 + +## 测试环境 +- 浏览器访问 `http://localhost:4173/` +- 进入「图文报告生成」→ 新建报告 + +## 测试用例 1:Checkbox 可正常切换 + +**步骤**: +1. 打开右侧「AI 撰写」面板 +2. 观察底部「允许修改正文」复选框,当前应为勾选状态(默认 `aiModifyEnabled = true`) +3. 点击复选框,观察勾选状态是否消失 +4. 再次点击,观察勾选状态是否恢复 +5. 点击复选框左侧的文字「允许修改正文」,观察勾选状态是否切换 + +**预期结果**: +- 点击复选框本身:状态正常切换 +- 点击文字标签:状态正常切换 +- 切换时上方「区域锚定」select 的 `disabled` 状态同步变化(禁用/启用) + +## 测试用例 2:AI 能看到全局报告内容 + +**步骤**: +1. 在编辑器中输入一些文本,例如「气腹压力为 12mmHg」 +2. 插入一个 AI 可编辑区域(如「手术步骤」) +3. 在 AI 面板中输入:「你能看到当前气腹压力吗?」 +4. 不勾选「允许修改正文」,直接发送 + +**预期结果**: +- AI 回复中应提到「12mmHg」或「气腹压力」,表明它读取了全局上下文 + +## 测试用例 3:AI 能基于全局上下文修改目标区域 + +**步骤**: +1. 编辑器中有完整报告内容(含患者信息、手术步骤等) +2. 在 AI 可编辑区域(如「手术步骤」)中已有部分内容 +3. 勾选「允许修改正文」 +4. 输入指令:「根据全局报告内容,将手术步骤中提到的止血方法更新为电凝止血」 +5. 发送并查看 diff 确认弹窗 + +**预期结果**: +- AI 返回的 `updatedHtml` 应能引用全局报告中的其他信息 +- Diff 弹窗能正确展示原文 vs 修改后的内容 +- 确认注入后目标区域内容更新 + +## 测试用例 4:编译与部署 + +**步骤**: +1. 执行 `npm run build` +2. 确认无 TypeScript 编译错误 +3. 预览服务正常启动并返回 200 + +**预期结果**: +- `vite build` 成功完成 +- 预览页面可正常访问 diff --git a/工程分析/20260419_0333/需求分析.md b/工程分析/20260419_0333/需求分析.md new file mode 100644 index 0000000..1040e62 --- /dev/null +++ b/工程分析/20260419_0333/需求分析.md @@ -0,0 +1,37 @@ +# 需求分析 + +## 时间戳 +2026-04-19 03:33 + +## 需求来源 +用户反馈 AI 辅助撰写功能存在两个 Bug: +1. 「允许修改正文」复选框无法被点击切换 +2. AI 大模型无法看到编辑器中的报告内容,无法执行修改正文的指令 + +## 问题一:Checkbox 无法切换 + +**现象**:AI 面板底部的「允许修改正文」复选框点击无反应,无法关闭或开启。 + +**根因分析**: +- 当前实现使用独立的 `` + `