历史记录

例如,修改段落文字、样式或表格后,可以打开历史记录查看先前版本、比较变化,并在有权限时恢复版本。历史记录读取服务端保存的版本;当前页面的撤销、重做不需要历史服务,两者不能互相替代。

先准备协同和历史服务

先按协同集成连接编辑器,并完成许可证配置。确认两端能编辑同一份 Docs 文档,刷新后内容仍然保留。

然后按 Office 协同扩展模块History 示例接入历史服务、存储和权限。核心协同不会自动启用历史记录;后端还需提供历史列表、版本内容和恢复操作所需的能力。

添加历史记录插件

在已有产品、许可证和协同插件配置中添加以下代码。若预设或现有配置已注册这些插件,修改原配置即可,不要重复注册。

Shell
pnpm add @univerjs-pro/edit-history @univerjs-pro/edit-history-ui @univerjs-pro/docs-history @univerjs-pro/docs-history-ui
TypeScript
import { UniverEditHistoryPlugin } from '@univerjs-pro/edit-history'import EditHistoryLocale from '@univerjs-pro/edit-history-ui/locale/zh-CN'import { UniverDocsHistoryPlugin } from '@univerjs-pro/docs-history'import { UniverDocsHistoryUIPlugin } from '@univerjs-pro/docs-history-ui'import HistoryLocale from '@univerjs-pro/docs-history-ui/locale/zh-CN'import { LocaleType, mergeLocales } from '@univerjs/core'import '@univerjs-pro/edit-history-ui/lib/index.css'const historyServerUrl = '/api/history'univerAPI.loadLocales(LocaleType.ZH_CN, mergeLocales(EditHistoryLocale, HistoryLocale))univer.registerPlugin(UniverEditHistoryPlugin, { historyServerUrl })univer.registerPlugin(UniverDocsHistoryPlugin)univer.registerPlugin(UniverDocsHistoryUIPlugin, {  univerContainerId: 'app',  historyServerUrl,})

/api/history 是示例地址,请替换成应用实际提供的历史接口地址,并确保接口与客户端请求匹配。两个 historyServerUrl 保持一致,univerContainerId 与编辑器容器的 DOM ID 一致。语言资源应与编辑器当前语言一致。

历史查看器会创建独立的只读编辑器。如果文档包含自定义内容,通过 viewerPlugins 添加查看器尚未内置的插件;不要重复添加内置插件。

查看和恢复版本

从编辑器菜单打开历史记录,选择版本查看内容和变化。恢复版本会修改当前共享文档,应只向有恢复权限的用户开放,并由服务端再次检查权限。

接入后,修改段落文字、样式或表格,等待协同确认,再检查历史列表和版本内容。重新打开应用及重启服务后再次读取;恢复一个旧版本后,确认另一个浏览器会话也收到恢复结果。

如果面板为空,先检查历史服务是否记录了当前文档,以及请求中的文档 ID 和服务地址是否正确。版本能查看但无法恢复时,检查恢复权限和协同连接。历史版本可能包含后来删除的数据,读取历史也必须执行权限检查。

比较快照

如果需要构建审阅界面,或向 AI Agent 提供变更信息,可以调用 compareUnitData(),也可以用 prepareUnitComparison() 只计算一次并重复查询。先注册本品类的 History 插件并导入 Facade 入口,再将同一文档的两份完整快照作为 beforeSnapshotafterSnapshot 传入。只读比较不需要历史服务,也不会恢复或合并内容。

TypeScript
import { UnitComparisonDetailLevel, UnitComparisonFidelity } from '@univerjs-pro/edit-history'import { UniverInstanceType } from '@univerjs/core'import '@univerjs-pro/edit-history/facade'const comparison = univerAPI.prepareUnitComparison({  comparisonId: 'review-1',  unitId: beforeSnapshot.id,  type: UniverInstanceType.UNIVER_DOC,  fidelity: UnitComparisonFidelity.SNAPSHOT,  leftData: beforeSnapshot,  rightData: afterSnapshot,})const overview = comparison.query({ detail: UnitComparisonDetailLevel.SUMMARY })const scope = overview.scopes[0]const page = comparison.query({ scope, offset: 0, limit: 100 })console.log(page.items, page.page.hasMore, page.diagnostics)

通过 scopes 获取可用视图,再将选中的范围传给 query(),即可筛选结果而不重新计算差异。默认每页返回 100 项,最多 1,000 项;结合 page.hasMoreoffset 获取后续内容。summary 始终描述整个比较,不随条目筛选变化。使用结果前检查 diagnostics.readinessdiagnostics.codes,避免将降级结果当作完整比较。无需编辑器的 Node.js 或 CLI 用法见无界面比较 API

你觉得这篇文档如何?

© 2026 DreamNum Co., Ltd.