- confirmAiInjection改用Range.selectNodeContents + execCommand('insertHTML')保留浏览器撤销栈
- handleAIGenerate中对cleanHtml增加<p>标签内联样式注入:padding 0px、font-family SimSun、font-size 12pt、line-height 1.5
- 确保AI替换后的文字字体与原有文字完全一致
3.4 KiB
3.4 KiB
实现方案
修改文件
src/pages/ReportEditor.tsx
修改 1:confirmAiInjection 保留撤销栈(约 line 981-998)
原代码:
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);
};
新代码:
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);
};
变更点:
- 去掉
targetContent.innerHTML = newHtml; - 增加
targetContent.focus() - 使用
Range.selectNodeContents(targetContent)选中区域内所有旧内容 - 使用
document.execCommand('insertHTML', false, newHtml)执行替换 - 浏览器撤销栈会记录这次替换,Ctrl+Z 可正常撤销
修改 2:handleAIGenerate 中 <p> 标签注入样式(约 line 955-970)
原代码:
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) {
新代码:
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 倍行高