fix(editor): AI注入后Ctrl+Z失效 + 字体格式统一

- confirmAiInjection改用Range.selectNodeContents + execCommand('insertHTML')保留浏览器撤销栈
- handleAIGenerate中对cleanHtml增加<p>标签内联样式注入:padding 0px、font-family SimSun、font-size 12pt、line-height 1.5
- 确保AI替换后的文字字体与原有文字完全一致
This commit is contained in:
2026-04-19 20:33:43 +08:00
parent b24ba08658
commit 7275906f3c
5 changed files with 208 additions and 1 deletions

View File

@@ -0,0 +1,94 @@
# 实现方案
## 修改文件
- `src/pages/ReportEditor.tsx`
## 修改 1`confirmAiInjection` 保留撤销栈(约 line 981-998
**原代码**
```tsx
const confirmAiInjection = (newHtml: string, regionId: string) => {
if (!editorRef.current) return;
const targetContent = editorRef.current.querySelector(`.ai-region[data-ai-id="${regionId}"] .ai-content`) as HTMLElement;
if (targetContent) {
targetContent.innerHTML = newHtml;
targetContent.style.transition = 'background-color 0.3s ease';
targetContent.style.backgroundColor = '#bfdbfe';
setTimeout(() => {
targetContent.style.backgroundColor = '#eff6ff';
setTimeout(() => {
targetContent.style.backgroundColor = 'transparent';
}, 800);
}, 400);
contentRef.current = editorRef.current.innerHTML;
saveDraftToStorage();
}
setDiffModal(null);
};
```
**新代码**
```tsx
const confirmAiInjection = (newHtml: string, regionId: string) => {
if (!editorRef.current) return;
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, newHtml);
targetContent.style.transition = 'background-color 0.3s ease';
targetContent.style.backgroundColor = '#bfdbfe';
setTimeout(() => {
targetContent.style.backgroundColor = '#eff6ff';
setTimeout(() => {
targetContent.style.backgroundColor = 'transparent';
}, 800);
}, 400);
contentRef.current = editorRef.current.innerHTML;
saveDraftToStorage();
}
setDiffModal(null);
};
```
**变更点**
1. 去掉 `targetContent.innerHTML = newHtml;`
2. 增加 `targetContent.focus()`
3. 使用 `Range.selectNodeContents(targetContent)` 选中区域内所有旧内容
4. 使用 `document.execCommand('insertHTML', false, newHtml)` 执行替换
5. 浏览器撤销栈会记录这次替换Ctrl+Z 可正常撤销
## 修改 2`handleAIGenerate` 中 `<p>` 标签注入样式(约 line 955-970
**原代码**
```tsx
if (responseJson.updatedHtml && aiModifyEnabled) {
let cleanHtml = responseJson.updatedHtml;
cleanHtml = cleanHtml.replace(/<br\s*\/?>/gi, '');
cleanHtml = cleanHtml.replace(/<\/p>\s*<p>/gi, '</p><p>');
cleanHtml = cleanHtml.trim();
if (targetRegionEl) {
```
**新代码**
```tsx
if (responseJson.updatedHtml && aiModifyEnabled) {
let cleanHtml = responseJson.updatedHtml;
cleanHtml = cleanHtml.replace(/<br\s*\/?>/gi, '');
cleanHtml = cleanHtml.replace(/<\/p>\s*<p>/gi, '</p><p>');
cleanHtml = cleanHtml.trim();
cleanHtml = cleanHtml.replace(/<p>/gi, '<p style="padding: 0px; font-family: SimSun; font-size: 12pt; line-height: 1.5;">');
if (targetRegionEl) {
```
**变更点**:在 `cleanHtml.trim()` 后增加一行正则替换,将所有 `<p>` 标签替换为带标准内联样式的 `<p>` 标签。
**样式值说明**
- `padding: 0px`:与原始段落一致
- `font-family: SimSun`:宋体
- `font-size: 12pt`12pt 字号
- `line-height: 1.5`1.5 倍行高