# 实现方案
## 修改文件
- `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);
// ... 后续动画和保存逻辑不变
```