Files
Mdeical_Sur_Report/工程分析/20260419_0333/实现方案.md
admin 854a00c2fa fix(editor): Checkbox点击失效 + AI全局上下文注入
- 将'允许修改正文'复选框从id/htmlFor绑定改为label直接包裹input,增加e.stopPropagation防止事件冒泡被拦截
- handleAIGenerate中新增editorRef.current.innerText作为全局上下文注入prompt
- currentHtml增加过滤​零宽字符
- 优化systemPrompt,明确告知大模型全局参考内容+目标区域源码的双信息源结构
2026-04-19 03:35:52 +08:00

4.6 KiB
Raw Blame History

实现方案

修改文件

  • src/pages/ReportEditor.tsx

修改位置 1Checkbox 包裹结构(约 line 2258-2268

原代码

<div className="flex items-center gap-1.5 shrink-0 pl-2 border-l border-slate-300">
  <input
    type="checkbox" id="aiModifyEnabled"
    checked={aiModifyEnabled}
    onChange={(e) => setAiModifyEnabled(e.target.checked)}
    className="w-3.5 h-3.5 text-blue-600 rounded border-slate-300 focus:ring-blue-500 cursor-pointer"
  />
  <label htmlFor="aiModifyEnabled" className="text-[11px] text-slate-600 cursor-pointer font-bold">
    允许修改正文
  </label>
</div>

新代码

<label className="flex items-center gap-1.5 shrink-0 pl-2 border-l border-slate-300 cursor-pointer">
  <input
    type="checkbox"
    checked={aiModifyEnabled}
    onChange={(e) => {
      e.stopPropagation();
      setAiModifyEnabled(e.target.checked);
    }}
    className="w-3.5 h-3.5 text-blue-600 rounded border-slate-300 focus:ring-blue-500 cursor-pointer"
  />
  <span className="text-[11px] text-slate-600 font-bold">
    允许修改正文
  </span>
</label>

变更点

  1. 外层 div 改为 label,直接包裹 input
  2. 移除 id/htmlFor,避免绑定冲突
  3. onChange 增加 e.stopPropagation() 防止事件冒泡被拦截
  4. label 文本改为 span

修改位置 2handleAIGenerate Prompt 构建(约 line 877-897

原代码

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}`;
}

新代码

const targetRegionEl = editorRef.current?.querySelector(`.ai-region[data-ai-id="${aiTargetRegion}"] .ai-content`) as HTMLElement | null;
const currentHtml = targetRegionEl ? targetRegionEl.innerHTML.replace(/&#8203;/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(/&#8203;/g, '').trim() 过滤零宽字符
  2. 新增 globalContextText 读取整个编辑器的纯文本
  3. promptText 重构:先放全局上下文,再放目标区域(如果存在),最后放医生指令
  4. 目标区域为空时显示 (当前区域为空) 提示

修改位置 3System Prompt 优化(约 line 895-897

原代码

const systemPrompt = aiModifyEnabled && targetRegionEl
  ? '你是一名专业的外科医生助理。你需要根据用户的指令及可能提供的截图,修改给定的 HTML 源码。\n重要指令你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记(如 ```json。\nJSON 格式如下:\n{ "reply": "简短的回复话术", "updatedHtml": "修改后的完整内部 HTML 代码" }'
  : '你是一名专业的外科医生助理。请根据用户的指令和截图进行分析解答。\n重要指令你必须严格返回合法的 JSON 对象,绝对不要包含任何 Markdown 标记。\nJSON 格式如下:\n{ "reply": "你的分析和回答" }';

新代码

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 明确提到「全局手术报告参考内容」