Модули расширения совместной работы

Узнайте, как History, Thread Comment, Worktree, File и серверное преобразование Office расширяют базовую совместную работу.

History, Thread Comment, File и Worktree — независимые расширения, подключаемые по необходимости. Они могут повторно использовать Transport, систему идентификации и физическую базу, но сохраняют собственные границы Service, Middleware, Event, Database Adapter и жизненного цикла.

Серверное преобразование Office объединяет File и Collaboration Service: оно преобразует файлы Office в совместные Units и обратно, имея собственные Service, Endpoint и Middleware.

Связи модулей

100%
РасширениеСвязь с ядром совместной работы
HistoryНаблюдает Events ядра и строит производный индекс истории
Thread CommentИспользует Room Unit ядра; привязки комментариев относятся к основному содержимому
FileХранит изображения, вложения и файлы обмена, на которые ссылается Unit; в данных Unit записаны только ID файлов
Office ExchangeСоздаёт или читает Units через Service ядра, а файлы читает и записывает через File
WorktreeИспользует Unit и OT ядра и сливает черновики в основную ветку

History, Thread Comment, File и Worktree настраивают собственные Middleware, Events и Database Adapters.

История версий

History группирует создание Unit и подтверждённые изменения в записи истории для пользователя. Это производный индекс: источником истины для содержимого Unit остаются подтверждённые изменения основного Collaboration Service.

TypeScript
const historyService = new UniverHistoryService({  collabService,  dbAdapter: historyDatabase,  userProvider,});transport.register(new UniverHistoryEndpoint(historyService));

Конструктор подписывается на Events unitCreated и changesetCommitted основного Service и обновляет индекс. dispose() снимает эти подписки. Политика по умолчанию группирует изменения по временному окну и особым мутациям, а не создаёт запись на каждый набор изменений.

History предоставляет Middleware чтения для getHistoryList, listHistoryCreators и getHistoryChangesets. Индексация выполняется внутри Service. userProvider только дополняет отображаемые данные, например имена и аватары, но не выполняет аутентификацию или авторизацию. Сбой Event Listener не откатывает уже подтверждённые изменения ядра, поэтому History всегда следует считать восстанавливаемыми производными данными.

Ветки комментариев

Comment Service управляет текстом комментариев, ответами, правками, удалением и состоянием решения для Sheets и Docs:

TypeScript
const commentService = new UniverCommentService({  database: commentDatabase,  userProvider,});transport.register(  new UniverCommentEndpoint({    service: commentService,    roomHost: collabEndpoint,  }),);

Текст комментариев принадлежит Comment Adapter. Привязки, перемещающиеся вместе с содержимым Sheet или Doc, остаются частью снимков и изменений ядра. Comment Endpoint может публиковать comment_update через Room Unit основного Collaboration Endpoint, но сообщение реального времени не является эталонным состоянием комментариев. Клиент может восстановиться, повторно запросив список.

Comment Service предоставляет Middleware добавления, списка, ответа, решения/повторного открытия, редактирования и удаления, а также Event commentCommitted. Политики чтения и редактирования основного Service не наследуются.

Хранение файлов

File хранит бинарные файлы, которые загружают клиенты Univer: изображения и вложения, вставленные в Unit, а также исходные и результирующие файлы импорта и экспорта. В данных Unit записывается только ID файла; при загрузке клиент преобразует его в URL скачивания, поэтому снимки и наборы изменений остаются компактными.

TypeScript
const fileService = new UniverFileService({  database: fileDatabase,  blobStore,});transport.register(new UniverFileEndpoint(fileService));

Метаданные и содержимое — два независимых контракта: IFileDatabaseAdapter хранит записи о файлах, IFileBlobStore — содержимое. Временные файлы обмена доступны только загрузившему их пользователю и периодически удаляются Service; изображения и вложения Unit контролируются правами Unit через Middleware upload, signUrl и download.

Серверное преобразование Office

Exchange Service импортирует файлы Office как совместные Units и экспортирует Units в файлы. Для преобразования он опирается на @univerjs-pro/exchange-node, создаёт и читает Units через Collaboration Service, а исходные и результирующие файлы хранит через File Service:

TypeScript
const exchangeService = new UniverExchangeService({ collabService, fileService });transport.register(new UniverExchangeEndpoint(exchangeService));

Импорт и экспорт — это task: клиент создаёт task и опрашивает результат. Импорт проходит через Middleware createUnit Core Service, экспорт — через readUnitData; собственные Middleware import и export в Exchange служат для ограничения частоты, квот и аудита.

UnitИмпортЭкспорт
Sheetxls, xlsx, csv, tsvxlsx, csv, tsv
Docdoc, docxdocx
Slideppt, pptxpptx
Basexls, xlsx, csv, tsvxlsx, csv
PDFpdfpdf

Task хранятся в экземпляре Service, поэтому разверните один узел импорта и экспорта и направляйте на него все три маршрута Exchange.

Черновики Worktree и слияние

Worktree добавляет изолированные черновики, заморозку, оценку слияния и слияние по Unit для одной или нескольких Units:

text
create → draft → ready → merging → merged           ↑       │           └ reopen┘draft / ready → discarded
TypeScript
const worktreeService = new UniverCollabWorktreeService({  trunk: {    service: collabService,    dbAdapter: coreDatabase,  },  dbAdapter: worktreeDatabase,});

Worktree хранит независимые изменения черновиков по (worktreeID, unitID), используя движки Unit, OT и отправки основного Service. Дальнейшие правки принимает только состояние draft. markReady() замораживает текущую ревизию черновика, а mergeWorktree() поочерёдно сливает Units в основную ветку.

Worktree Service имеет независимые Middleware жизненного цикла, чтения и submit/apply/commit черновиков, а также Events создания, смены статуса, результатов слияния и фиксации изменений черновиков. Финальная запись в основную ветку по-прежнему проходит через Middleware основного Service.

Слияние нескольких Units не атомарно между Units. Приложение должно показывать результат для каждой Unit.

Независимые точки расширения

При подключении расширения оценивайте каждую границу отдельно:

ГраницаЯдроHistoryCommentFileWorktree
ServiceНезависимНезависимНезависимНезависимНезависим
MiddlewareНе общийНе наследует ядроНе наследует ядроНе наследует ядроНе наследует ядро
EventЖизненный цикл ядраНаблюдает Events ядраcommentCommitted—Жизненный цикл/коммит Worktree
Database AdapterAdapter ядраHistory AdapterComment AdapterFile Adapter и Blob StoreWorktree Adapter

Adapters могут использовать одну базу данных, оставаясь разными объектами с отдельными контрактами. Services и Adapters также освобождаются независимо.

Office Exchange повторно использует хранилища Core и File: после его собственных Middleware import и export импорт и экспорт по-прежнему проходят через Middleware Core и File.

Выбор возможностей

Требование продуктаМодульПервый пример
История версий для пользователяHistory Service, Endpoint, Adapterpnpm example:history
Комментарии Sheet или DocComment Service, Endpoint, Adapterpnpm example:comments
Изображения, вложения и хранение файловFile Service, Endpoint, Adapter, Blob Storepnpm example:file-service
Серверный импорт и экспорт OfficeExchange Service, Endpoint + Filepnpm example:exchange
Изолированные черновики, проверка и слияниеWorktree Service, Endpoint, Client, Adapterpnpm example:worktree

Полные команды запуска и URL страниц приведены в указателе примеров.

Подключение интерфейса истории Web SDK

Подключите History Endpoint вместе с точками входа совместного редактирования. historyServerUrl — общий префикс для /{unitId}/list, /{unitId}/creators и /{unitId}/cs; по умолчанию это /universer-api/history. Для другого пути укажите одинаковый URL в History-плагине основного редактора и History UI плагине продукта.

Восстановление отправляется как mutation совместного редактирования, а не через отдельный REST endpoint истории. Сохраните настройки загрузки, отправки и авторизации совместного редактирования. Сравнение полных снимков через createUnitComparisonEngine() только читает данные, не требует сервиса истории и не сохраняет и не восстанавливает версии.

Насколько полезно это руководство?

© 2026 DreamNum Co., Ltd.