- Add undoStack/redoStack refs with pushHistory/handleUndo/handleRedo
- Replace execCmd('undo')/execCmd('redo') with custom stack handlers
- Call pushHistory before structural changes (delete, insert field/table/image, formatting)
- Add onMouseDown preventDefault to toolbar and field library buttons to stop focus loss
- Implement saveSelection/restoreSelection using savedRangeRef
- Bind onBlur/onMouseUp/onKeyUp on editor to persist cursor position
- Restore selection in insertSmartField and insertImage before insertHTML
- Update experience record (#20)
2.4 KiB
2.4 KiB
需求分析 — TemplateManage 撤销/重做修复与插入字段光标定位(2026-04-17-12-51-47)
一、需求来源
用户反馈 TemplateManage 中存在两个严重的交互体验问题:
- 删除智能字段(包括默认模板自带的和手动插入的)后,撤销/重做按钮完全失效。
- 点击右侧字段库插入字段时,字段经常跳到下一行或错误位置。
二、具体需求拆解
需求 1:撤销/重做功能修复
问题:即使已经将删除逻辑改为 execCommand('delete'),撤销/重做按钮仍然无法恢复被删除的字段。
原因:浏览器原生的 undo stack 在 contentEditable 中结合 React 状态更新和强制 Range 操作时非常脆弱,容易被清空或打断。
期望:实现一个自定义的 undo/redo 历史栈,完全接管撤销/重做逻辑,确保任何内容变更(键盘输入、插入字段、删除字段)都能被正确撤销和恢复。
需求 2:插入字段光标定位修复
问题:点击右侧字段库按钮时,编辑器失去焦点(blur),浏览器内部光标位置丢失。再次 focus() 后,光标往往被重置到文档开头/末尾或新块级位置,导致 insertHTML 插入的字段跳到下一行。
期望:
- 点击字段库按钮时不让编辑器失去焦点。
- 若焦点仍丢失,则在插入前恢复上一次保存的光标位置(Range)。
- 插入的字段必须紧跟在插入前的光标位置,不强制换行。
三、影响范围分析
| 文件 | 改动说明 |
|---|---|
src/pages/TemplateManage.tsx |
新增 undoStack / redoStack refs;重写 handleUndo / handleRedo;替换 execCmd('undo') / execCmd('redo') 的调用;在关键操作(删除、插入)前增加 pushHistory;增加 saveSelection 和 restoreSelection;字段按钮增加 onMouseDown={(e) => e.preventDefault()} 阻止焦点流失。 |
四、验收标准
- 在模板中删除任意智能字段后,点击"撤销"按钮能立即恢复该字段。
- 撤销恢复后,点击"重做"按钮能再次删除该字段。
- 连续输入文字、插入字段、删除字段后,撤销/重做能按正确的历史顺序回退/前进。
- 在文字中间点击插入字段,字段紧跟光标位置,不跳到下一行或文档末尾。
- 多次在不同位置插入字段,每次都能准确定位。
npm run lint无编译错误。