新编辑器开发手册.md 4.7 KB

块编辑器开发手册

1. 开发环境

当前项目使用:

工具 版本或范围
Node.js 使用团队当前 LTS 版本
React 18.3.1
TypeScript 6.0.x,strict 模式
Vite 8.x
Ant Design 5.22.x
Zustand 4.5.x

安装并启动:

npm install
npm run dev

不要根据旧文档安装 @mdxeditor/editor、Slate、@dnd-kitreact-windowuse-debounce,这些不是当前项目依赖。

2. 目录结构

src/
├── components/
│   ├── ChatPanel/
│   ├── Editor/
│   │   ├── blocks/
│   │   ├── RichTextEditor/
│   │   └── toolbar/
│   ├── EditorPanel/
│   ├── ExportRecordList/
│   ├── Layout/
│   └── SessionList/
├── hooks/
├── services/
├── stores/
├── types/
└── utils/

编辑器相关职责:

  • types/editor.ts:block、RichText、表格和 API 类型。
  • stores/editorStore.ts:文档状态、修改追踪、保存和重试。
  • services/blockService.ts:blocks API。
  • utils/blockOperations.ts:块顺序和表格结构算法。
  • utils/richTextConverter.ts:RichText 与 HTML 转换。
  • utils/styleResolver.ts:Word 样式和块样式转 CSS。
  • components/Editor/BlockRenderer.tsx:block 类型分发。

3. 新增或修改 Block

新增 block 类型时至少同步修改:

  1. src/types/editor.tsBlockType 和具体接口。
  2. BlockRenderer.tsx 的分发分支。
  3. 插入菜单或创建逻辑。
  4. editorStore 的加载、更新和保存兼容性。
  5. Markdown、PDF 或 Word 导出策略。
  6. 大纲或只读渲染逻辑(如果该 block 影响标题结构)。
  7. 相关 CSS 和可访问性属性。

保持公共组件 Props 小而明确。EditorPanelProps 是 App 与编辑器之间的稳定边界,不要为了局部功能破坏它。

4. 富文本开发规则

RichTextEditor 使用 contenteditable,不是 Markdown 编辑器。修改它时注意:

  • 使用 richTextToHtml 生成内容,避免手工拼接未转义文本。
  • 使用 htmlToRichText 读取选区和粘贴结果。
  • 格式化前保存 Range,格式化后恢复选区。
  • 不要引入 dangerouslySetInnerHTML 绕过转换器。
  • 表格单元格通过 tableContext 传递上下文,但不显示普通浮动工具栏。
  • 工具栏 Portal、颜色 Popover 和 Dropdown 的关闭逻辑要覆盖外部点击、Escape 和离开相关区域。

5. 表格开发规则

表格编辑必须围绕视觉坐标实现:

原始 rows/cells
  -> getTableVisualCellPositions
  -> 选择或计算视觉范围
  -> 合并/拆分/增删操作
  -> rebuildTableRows
  -> 更新 metadata 和 content

修改后至少手动检查普通 2 x 2 表格、横向合并后拆分、纵向合并后拆分、横向和纵向合并同时存在、插入/删除行列后再合并,以及调整列宽和行高后保存并重新加载。

不要恢复已经删除的 TableStylePanelTableBorderControl,当前需求只保留表格结构操作工具栏。

6. 状态和保存

组件通过 selector 读取 store,避免订阅无关状态。编辑操作调用 updateBlock,不要在组件中直接调用 API 保存。需要立即保存时调用 store 的保存方法,并正确处理 loading、失败和取消状态。

保存相关字段包括 dirtyBlocksfailedBlockshasModifiedisSavingsavingProgresslastSaveTime。自动保存默认延迟 3 秒,保存并发限制为 3。

7. 性能规则

  • 大面板使用 React.lazySuspense
  • PDF、截图和 mammoth 保持动态导入。
  • 拖动或连续鼠标事件使用 rAF 或合适的节流策略。
  • 长消息列表保留 content-visibility 优化。
  • 图片保留宽高比例,使用 loading="lazy"decoding="async"
  • 不要在渲染期间写 localStorage 或触发网络请求。

8. 验证命令

npm run build
npm run lint
npm run format:check
npm run test

当前 package.json 中的 test:documenttest:export 仍引用仓库中不存在的测试文件。恢复测试前不要把这两个命令当作成功的验证依据,应先修正测试脚本或补回对应测试。

生产包检查:

npm run build:analyze
npm run serve:prod

9. 安全规则

  • VITE_* 变量不是秘密,API key 应迁移到后端代理。
  • 用户文本必须经过富文本转换器转义。
  • 文件上传同时检查 MIME、大小和图片实际尺寸。
  • 外部下载地址必须经过 API 服务层处理,不要直接拼接未验证的用户输入。