fix(editor): contentEditable回车导致段落溢出.ai-content
- handleAIGenerate中获取currentHtml前增加溢出段落合并逻辑 - 遍历.ai-content之后的兄弟<p>节点,移回.ai-content内 - 合并后同步更新contentRef和saveDraftToStorage - 确保diff弹窗左侧能显示AI可编辑区域内的全部段落
This commit is contained in:
43
工程分析/经验记录.md
43
工程分析/经验记录.md
@@ -774,3 +774,46 @@ AI 修改确认弹窗右侧出现了不属于目标区域的内容:术后情
|
||||
**D. 后续如何避免问题**
|
||||
- 在向大模型发送局部修改请求时,**必须设置严格的内容边界(Fencing)**。全局上下文可以提供给 AI 作为背景理解,但必须在 Prompt 中明确声明"仅供理解,严禁输出"。
|
||||
- 避免使用"补充完善""基于全局信息扩展"等容易被大模型过度解读的措辞。大模型会尽其所能地"满足"用户的指令,即使这意味着越界生成。
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 记录 34:contentEditable 回车导致段落溢出 .ai-content
|
||||
|
||||
**A. 具体问题**
|
||||
AI 修改确认弹窗的「原始版本」左侧只显示了 AI 可编辑区域中的一段内容,但编辑器中该区域实际上有 2-5 段。从 DOM 源码可以看到:
|
||||
```html
|
||||
<div class="ai-content"><p>第2段</p></div>
|
||||
<p>第3段</p>
|
||||
<p>第4段</p>
|
||||
<p>第5段</p>
|
||||
```
|
||||
第 3-5 段变成了 `.ai-content` 的兄弟节点,不在 `.ai-content` 内部。
|
||||
|
||||
**B. 产生问题原因**
|
||||
浏览器原生 `contentEditable` 机制在用户按回车换行时,会截断当前的块级容器(`.ai-content` div),在同级生成新的 `<p>` 标签。这导致后续段落脱离了 `.ai-content` 父容器,变成了 `.ai-region` 的直接子节点。
|
||||
|
||||
**C. 解决问题方案**
|
||||
在 `handleAIGenerate` 获取 `currentHtml` 之前,增加溢出段落合并逻辑:
|
||||
```ts
|
||||
const aiRegion = editorRef.current?.querySelector(`.ai-region[data-ai-id="${actualTargetId}"]`);
|
||||
if (aiRegion && targetRegionEl) {
|
||||
let nextSibling = targetRegionEl.nextElementSibling;
|
||||
while (nextSibling) {
|
||||
const toMove = nextSibling;
|
||||
nextSibling = nextSibling.nextElementSibling;
|
||||
if (toMove.tagName === 'P') {
|
||||
targetRegionEl.appendChild(toMove);
|
||||
}
|
||||
}
|
||||
if (editorRef.current) {
|
||||
contentRef.current = editorRef.current.innerHTML;
|
||||
saveDraftToStorage();
|
||||
}
|
||||
}
|
||||
```
|
||||
遍历 `.ai-content` 之后的所有兄弟节点,把 `<p>` 标签移回 `.ai-content` 内,然后同步更新 contentRef 和草稿。
|
||||
|
||||
**D. 后续如何避免问题**
|
||||
- `contentEditable` 中的嵌套容器(如 `.ai-content`)在用户输入时极易被浏览器原生编辑行为破坏结构。任何依赖特定 DOM 层级关系的功能,都必须在读取数据前做**结构完整性检查和修复**。
|
||||
- 对于 AI 区域这类核心功能,应考虑在编辑器层面增加 `keydown`/`paste` 事件拦截,或改用更可控的编辑方案(如 ProseMirror/Slate)来替代原生 `contentEditable`。
|
||||
|
||||
Reference in New Issue
Block a user