协同编辑
📊 Univer Sheet
🏆
本功能包含闭源代码,允许任何用户免费商用。此外也包含了可选的商业升级计划,可提供更丰富的功能和服务。
💻
本功能依赖 Univer 后端服务,在使用前请先确保你已经阅读了相关文档,并完成了部署。
Univer 提供了协同编辑功能,支持多人同时编辑同一个工作簿。
安装
pnpm add @univerjs-pro/collaboration @univerjs-pro/collaboration-client
引入
import '@univerjs-pro/collaboration-client/lib/index.css';
import { UniverCollaborationPlugin } from '@univerjs-pro/collaboration';
import { UniverCollaborationClientPlugin } from '@univerjs-pro/collaboration-client';
国际化
import { LocaleType, Tools } from '@univerjs/core';
import CollaborationClientZhCN from '@univerjs-pro/collaboration-client/locale/zh-CN';
const univer = new Univer({
theme: defaultTheme,
locale: LocaleType.ZH_CN,
locales: {
[LocaleType.ZH_CN]: Tools.deepMerge(
CollaborationClientZhCN
),
},
});
注册
// 通过将 override 选项设置为 [[IAuthzIoService, null]],可以告诉 Univer 不要注册内置的 IAuthzIoService。
// 通过将 override 选项设置为 [[IUndoRedoService, null]],可以告诉 Univer 不要注册内置的 IUndoRedoService
// 这样,Univer 将使用 UniverCollaborationPlugin 中提供的服务作为权限、重做恢复服务的实现。
const univer = new Univer({
override: [
[IAuthzIoService, null]
[IUndoRedoService, null],
],
});
univer.registerPlugin(UniverCollaborationPlugin);
univer.registerPlugin(UniverCollaborationClientPlugin, {
authzUrl: 'http://localhost:3010/universer-api/authz',
snapshotServerUrl: 'http://localhost:3010/universer-api/snapshot',
collabSubmitChangesetUrl: 'http://localhost:3010/universer-api/comb',
collabWebSocketUrl: 'ws://localhost:3010/universer-api/comb/connect',
});
协同文档数据
协同编辑插件依赖 Univer 服务,协同文档的数据存储在 Univer 服务中。
unitId
每篇协同文档在 Univer 服务中都有一个唯一的 unitId
。
Univer 协同客户端(协同编辑插件)使用 unitId
可从 Univer 服务获取到对应的协同文档数据进行协同编辑。
type
type
是协同文档的类型,协同文档的类型决定了协同文档的初始数据结构。
创建协同文档
有多种方式在 Univer 服务中创建协同文档:
- 通过 创建文档 接口可以创建一篇空白文档。
- 通过 导入插件 提供的 Facade API
importXLSXToUnitId
方法,将 XlSX 文件导入到 Univer 服务。
加载协同文档
@univerjs-pro/collaboration-client
插件内部提供了根据 URL 参数 unit
和 type
自动加载对应的数据的功能,这可以简化一些场景下的数据加载逻辑。
如果你想使用该特性,你需要适当地修改一下原有的加载数据逻辑,并将 unit
和 type
参数添加到 URL 中,如下所示:
import { UniverInstanceType } from '@univerjs/core';
# 原有逻辑,只适用于非协同文档
- univer.createUnit(UniverInstanceType.UNIVER_SHEET, {});
# 修改后的逻辑,适用于协同文档
+ const url = new URL(window.location.href);
+ const unit = url.searchParams.get('unit');
+ if (unit) {
+ // 如果 URL 中包含 unit 参数,则自动加载数据
+ } else {
+ // 创建一个新的表格
+ fetch(`/universer-api/snapshot/${UniverInstanceType.UNIVER_SHEET}/unit/-/create`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ type: UniverInstanceType.UNIVER_SHEET, // instance type
+ name: 'New Sheet By Univer', // sheet name
+ creator: 'user', // creator name
+ }),
+ }).then((response) => {
+ if (!response.ok) {
+ throw new Error('create unit failed');
+ }
+
+ return response.json();
+ }).then((data) => {
+ if (!data.unitID) {
+ throw new Error('create unit failed');
+ }
+
+ url.searchParams.set('unit', data.unitID);
+ url.searchParams.set('type', String(UniverInstanceType.UNIVER_SHEET));
+ window.location.href = url.toString();
+ }).catch((error) => {
+ console.error(error);
+ })
+ }
拓展阅读
如果你想进一步了解协同编辑的工作原理,可以阅读以下文章: