开发文档Umo Editor Next文档表单排障指南

排障指南

本页按“推荐做法 -> 异常兜底 -> 常见问题”组织,重点覆盖 autofillform.valuesfillFormValues()onFillError() 相关接入。

建议的排查顺序

遇到问题时,建议按下面顺序检查:

  1. 模式是否选对:fill / result / autofill
  2. 变量 key 是否稳定且和传值一致
  3. 变量值形态是否匹配字段类型
  4. 富文本内容是否超出当前文档模型可接受范围
  5. 问题发生在“填充”还是“导出”阶段

常见问题速查

现象优先检查什么
调用后没有生成结果模式、传值对象、变量 key 是否匹配
有些字段没被替换值是否为空、字段 key 是否稳定
多选/区间日期显示异常值形态是否是数组
图片变量没有显示是否至少传了合法 url
富文本生成失败内容结构是否合法,是否应走 onFillError 兜底

一、推荐的程序填充链路

如果你的目标是“根据模板批量生成正式文档”,推荐使用这条链路:

  1. 模板制定人先完成模板设计
  2. 后端或业务系统准备变量值对象
  3. 优先使用 form.mode = 'autofill' + form.values
  4. 生成最终内容
  5. 再串联 Word / PDF / 图片导出

fillFormValues(values, options) 更适合放在运行时需要重新生成结果的场景中使用,例如实例已经创建完成后切换单据、切换数据源、点击“重新生成”等操作。

这条链路的优点是:

  • 模板与程序共用同一份文档模型
  • 人工填写与程序填充可以共用同一套字段定义
  • 批量出文时版式更稳定

二、程序填充前的最佳实践

1. 不要依赖变量 id

正式业务中应始终使用稳定的 key 传值,不要依赖模板编辑阶段自动生成的 id

原因:

  • id 更像编辑器内部节点标识
  • 模板调整后自动生成值不够稳定
  • 不利于后端长期维护映射关系

2. 在服务端先做好数据归一化

推荐在调用填充前,就把业务数据整理成与变量类型一致的值形态:

  • 文本:字符串
  • 多选:数组
  • 区间日期:长度为 2 的数组
  • 图片:带 url 的对象或 URL 字符串
  • 富文本:可信的文档内容

不要把“值清洗”的主要责任交给编辑器运行时。

3. 优先使用结构化字段,不要过度依赖富文本

富文本变量适合复杂内容块,不适合承载大量普通字段。

如果能拆成:

  • 日期
  • 金额
  • 选项
  • 文本

就不要先拼成一段富文本再传进去。

4. 批量出文时,模板与导出要分层

推荐分成两层:

  • 第一层:模板填充,得到每份结果文档
  • 第二层:结果导出,导出成 Word / PDF / 图片

这样更容易定位问题:是“填充失败”,还是“导出失败”。

5. 把 onFillError 当成正式能力接入

不要把 onFillError 当成调试期临时日志。

它更适合承担这些职责:

  • 记录生成失败日志
  • 识别无效变量项
  • 触发业务告警
  • 选择回退模板或降级策略

三、推荐的异常兜底策略

方案 1:记录错误并中止出文

适合合同、协议、证明等严肃文档。

form: {
  enabled: true,
  mode: 'autofill',
  async onFillError(errors, context) {
    console.error('文档填充失败', errors, context)
    throw new Error('变量填充失败,请检查模板或数据')
  },
}

适用场景:

  • 正式合同
  • 法务文件
  • 合规归档文档

方案 2:记录错误并降级为普通文本

适合报告说明、补充内容等非关键区块。

思路是:

  • 检测富文本变量失败
  • 改为传普通文本兜底
  • 重新生成

适用场景:

  • 报告补充说明
  • 自动通知正文
  • 低风险展示型文档

方案 3:记录错误并回退到人工处理

适合“批量生成,但允许人工补最后一步”的业务。

例如:

  • 批量先生成 90% 内容
  • 个别失败单据进入人工复核队列

四、哪些情况会触发 onFillError

根据当前源码实现,onFillError(errors, context) 主要用于承接富文本变量内容无效这类情况。

当前错误项的 code 为:

invalid-richtext-content

也就是说,最应该重点防守的是:

  • 富文本内容结构不合法
  • 富文本内容无法安全写入当前文档模型

五、常见问题与排查

1. 为什么调用 fillFormValues() 没有效果?

优先检查:

  • 传入的 values 是否真的是对象
  • key 是否与模板中的变量 key 对应
  • 当前模板里是否真的存在这些变量

另外,若你期望它走“正式程序填充链路”,建议让编辑器运行在 form.mode = 'autofill',再调用该方法。

2. 为什么生成后有些变量没有被替换?

常见原因:

  • 传值 key 不匹配
  • 值为空
  • 变量本身没有设置稳定 key,只能依赖 id

建议:

  • 模板里所有正式字段都设置显式 key
  • 在程序侧统一维护字段映射表

3. 为什么多选字段没有显示结果?

多选字段当前应传数组。如果传了字符串或其他类型,运行时不会按多选正确处理。

推荐示例:

{
  notify_channels: ['sms', 'email'],
}

4. 为什么日期区间没有显示结果?

区间日期、时间区间应传长度为 2 的数组;如果只传一端或传入空值,运行时会把它视为空区间。

推荐示例:

{
  service_period: ['2026-08-01', '2026-08-31'],
}

5. 为什么图片类变量填充后还是空的?

根据当前实现,图片类变量至少需要合法的 url

以下两种都可以:

{
  sign_image: 'https://example.com/sign.png',
}

或:

{
  sign_image: {
    url: 'https://example.com/sign.png',
    name: '签名',
  },
}

如果对象里没有 url,该值会被视为空。

6. 为什么富文本变量触发了 onFillError

最常见原因:

  • 传入内容不是当前编辑器可识别的内容结构
  • 结构嵌套不合法
  • 传入了业务拼接出的半成品内容

建议排查顺序:

  1. 先确认是否真的需要富文本变量
  2. 若只是普通字段,改回文本/数字/日期/选项类变量
  3. 若确实需要富文本,由服务端统一生成、统一校验
  4. 失败时通过 onFillError 记录 errorsinvalidItems

7. 为什么生成结果里看不到未填变量?

当运行在 autofill 链路下时,未填充的变量节点会从最终内容中移除。这是当前实现的预期行为,目的是避免占位符泄露到正式文档。

因此如果你希望某些字段即使没值也保留提示,不应依赖“未填变量自动显示占位符”,而应在模板正文里显式写清兜底文案或先在程序侧补默认值。

8. 为什么 onFillError 没有触发,但结果仍然为空?

需要区分两类情况:

  • onFillError 主要处理的是“无效富文本变量”
  • 如果本次根本没有生成出可提交的结果内容,fillFormValues() 可能直接返回 null

这时应优先检查:

  • 源模板内容是否可用
  • 传入格式 format 是否正确
  • 业务是否在外层正确接收了返回值

9. 为什么批量出文时偶尔成功、偶尔失败?

这通常不是编辑器随机失败,而是输入数据不稳定。

优先排查:

  • 不同批次是否用了不同字段 key
  • 某些富文本内容来源是否不一致
  • 某些图片 URL 是否为空或无效
  • 是否把本应为数组的字段传成了字符串

六、批量生成文档的推荐做法

如果你的目标是批量生成 PDF / Word,推荐按下面方式组织:

  1. 维护一份稳定模板
  2. 在服务端统一整理变量值数据
  3. 逐份执行填充
  4. 对每份结果执行导出
  5. 记录每份文档的填充与导出状态

不要把“填充、导出、上传、归档”全部揉成一个黑盒步骤。拆开后,问题会好定位得多。

七、一条简单的接入原则

如果你发现程序填充越来越难维护,通常说明不是“编辑器不够智能”,而是模板字段设计还没收口。

优先回头检查:

  • key 是否稳定
  • 类型是否选对
  • 富文本是否用得过多
  • 业务数据是否先做了归一化

把这几件事做好,程序填充、批量出文、PDF/Word 导出都会稳很多。