# 实现方案 ## 修改文件 - `src/pages/ReportEditor.tsx` - `package.json` / `package-lock.json`(已安装 `diff` 库) ## 依赖安装 ```bash npm install diff --save ``` 已完成。 ## 修改 1:导入 diff 库 + 增加辅助函数 在 `ReportEditor.tsx` 顶部 imports 区域增加: ```tsx import { diffChars } from 'diff'; ``` 在组件内部增加辅助函数(建议放在 `checkAiRegions` 之后): ```tsx const stripHtml = (html: string): string => { const tmp = document.createElement('div'); tmp.innerHTML = html.replace(/<\/p>/gi, '

\n').replace(//gi, '\n'); return (tmp.innerText || tmp.textContent || '').trim(); }; const computeDiffHtml = (oldText: string, newText: string, side: 'left' | 'right'): string => { const diffs = diffChars(oldText, newText); let html = ''; for (const part of diffs) { let value = part.value.replace(//g, '>').replace(/\n/g, '
'); if (side === 'left' && part.removed) { html += `${value}`; } else if (side === 'right' && part.added) { html += `${value}`; } else if (!part.added && !part.removed) { html += value; } } return html; }; ``` ## 修改 2:强化 systemPrompt(约 line 922) 在修改模式的 systemPrompt 中增加第 7 条: ``` 7. ⚠️ 绝对强制:无论用户的修改指令多么微小,你都必须返回 updatedHtml。绝对不允许只返回 reply 而不返回 updatedHtml! ``` ## 修改 3:前端校验兜底(约 line 955) 在 `if (responseJson.updatedHtml && aiModifyEnabled)` 分支之前,增加兜底提示: ```tsx if (aiModifyEnabled && !responseJson.updatedHtml) { setChatMessages(prev => [...prev, { id: Date.now().toString(), role: 'model', content: '【系统提示】AI 未能生成修改内容,请尝试重新描述您的需求。' }]); } ``` ## 修改 4:diffModal 渲染逻辑(约 line 2612-2653) **原代码**: 左侧直接渲染 `diffModal.originalHtml`,右侧直接渲染 `diffModal.newHtml`。 **新代码**: 在 `diffModal` 渲染区域内部,计算 diff 高亮 HTML: ```tsx {diffModal && diffModal.isOpen && (
{/* ... 弹窗头部 ... */} {(() => { const oldText = stripHtml(diffModal.originalHtml); const newText = stripHtml(diffModal.newHtml); const leftDiffHtml = computeDiffHtml(oldText, newText, 'left'); const rightDiffHtml = computeDiffHtml(oldText, newText, 'right'); return (
{/* 左侧:原始版本 + 删除高亮 */}
原始版本
{/* 右侧:AI 版本 + 新增高亮 */}
AI 提议版本 (可直接编辑) 编辑态
setDiffModal(prev => prev ? { ...prev, newHtml: e.target.innerHTML } : null)} dangerouslySetInnerHTML={{ __html: rightDiffHtml }} style={{ fontFamily: 'SimSun, "Microsoft YaHei", serif', fontSize: '12pt', lineHeight: '1.5' }} >
); })()} {/* ... 底部按钮 ... */}
)} ``` **注意**:使用 IIFE(立即执行函数)在 JSX 中计算 diff,避免在渲染外额外处理。 ## 修改 5:confirmAiInjection 清理 diff 高亮(约 line 981) 在注入前去掉 diff 高亮 span: ```tsx const confirmAiInjection = (newHtml: string, regionId: string) => { if (!editorRef.current) return; // 去掉 diff 高亮 span,避免污染编辑器 const cleanHtml = newHtml.replace(/]*>(.*?)<\/span>/gi, '$2'); const targetContent = editorRef.current.querySelector(`.ai-region[data-ai-id="${regionId}"] .ai-content`) as HTMLElement; if (targetContent) { targetContent.focus(); const sel = window.getSelection(); const range = document.createRange(); range.selectNodeContents(targetContent); sel?.removeAllRanges(); sel?.addRange(range); document.execCommand('insertHTML', false, cleanHtml); // ... 后续动画和保存逻辑不变 ```