协同编辑

插件信息

让多个用户打开同一个 Base,共同修改表、字段、记录和视图。用户可以在不同视图中工作,修改仍作用于同一份文档。

接入步骤

  1. 按协同集成运行协同示例,接入登录、权限和数据库。
  2. 在已有 Bases 编辑器中加入 Collaboration Client 配置。前端配置方式见 协同快速开始,但后端创建和保存的文档类型应为 Bases,不能直接使用示例中的 Sheets 数据。
  3. 由业务后端创建 Base 文档,将返回的 ID 交给前端加载。

打开服务端 Base

先设置当前用户,再加载文档;详见协同集成。

TypeScript
import '@univerjs-pro/bases/facade'import { UserManagerService } from '@univerjs/core'import '@univerjs-pro/collaboration-client/facade'univer.__getInjector().get(UserManagerService).setCurrentUser({ userID, name, avatar })const base = await univerAPI.getCollaboration().loadBaseAsync('your-base-id')if (!base) throw new Error('Base could not be loaded')

重新打开或分享文档时使用同一个 ID。不要再用 createBase() 创建本地空白文档来代替服务端加载。

通过同步状态、重发与冲突恢复实现保存提示,并在刷新前保护尚未确认的修改。

移除内置 URL 加载协同文档

注意事项

从 1.2.0 版本开始,Univer 移除了内置的 URL 协同文档加载逻辑,不再自动读取 URL 中的 unit 和 type 参数来加载协同文档。

如果你的应用依赖这一行为,可以通过自定义插件恢复。

接入自定义插件

将下方四个文件按以下目录结构复制到项目中:

text
custom-url-load/├── plugin.ts├── controllers/│   └── data-loader.controller.ts└── services/    ├── url.service.ts    └── web-url.service.ts

在完成编辑器和协同插件初始化后,先设置当前用户,再注册 CustomUrlLoadPlugin。

TypeScript
import { UserManagerService } from '@univerjs/core'import { CustomUrlLoadPlugin } from './custom-url-load/plugin'univer.__getInjector().get(UserManagerService).setCurrentUser({ userID, name, avatar })univer.registerPlugin(CustomUrlLoadPlugin)

注册该插件后,由插件负责加载文档,无需再为同一文档调用 loadBaseAsync()。如果应用已经通过 Facade 加载文档,可以继续使用上一节的方式,并根据业务需要自行处理 URL。

完整插件代码

TypeScript
import { UniverCollaborationClientPlugin } from '@univerjs-pro/collaboration-client'import { DependentOn, Inject, Injector, Plugin } from '@univerjs/core'import { CollaborationDataLoaderController } from './controllers/data-loader.controller'import { IURLService } from './services/url.service'import { WebURLService } from './services/web-url.service'@DependentOn(UniverCollaborationClientPlugin)export class CustomUrlLoadPlugin extends Plugin {  static override pluginName = 'CUSTOM_URL_LOAD_PLUGIN'  constructor(    _config: undefined,    @Inject(Injector) protected override readonly _injector: Injector  ) {    super()  }  override onStarting(): void {    this._injector.add([IURLService, { useClass: WebURLService }])    this._injector.add([CollaborationDataLoaderController])    this.disposeWithMe(this._injector.get(IURLService))    this.disposeWithMe(this._injector.get(CollaborationDataLoaderController))  }}

验证同步和保存

用两个独立浏览器会话加载同一份文档,在一端添加记录或修改字段,确认另一端能收到变化;刷新页面并重启服务后,修改仍应保留。

查看者和无权限用户都需要由服务端校验。本地只读设置只控制编辑器行为。导入导出、评论和历史记录还需要各自的后端功能,见导入导出、评论和历史记录。

你觉得这篇文档如何?

© 2026 DreamNum Co., Ltd.