Integración de colaboración
Conecta el editor Univer a un servicio de colaboración para editar el mismo documento entre varios usuarios.
La colaboración conecta los editores del navegador a un servicio de documentos compartidos. Por ejemplo, dos usuarios abren la misma hoja de cálculo y una edición en un navegador aparece en el otro.
Prepara el backend con la integración del servidor y configura el editor y la carga de documentos a continuación. Sigue conjuntamente el código Server y Web de Inicio rápido de colaboración.
Conectar el editor existente
Conserva tu editor Web SDK. Sigue la configuración del navegador del inicio rápido para añadir plugins de colaboración y configurar carga, envío de cambios y direcciones WebSocket. Mantén compatibles las versiones de los paquetes del navegador y del servidor.
Los usuarios fijos y permisos predeterminados son demostrativos. En tu aplicación, incluye las credenciales de inicio de sesión en las solicitudes para que el backend verifique identidad y acceso al documento. Consulta la configuración de la licencia.
Crear y abrir el mismo documento
Crear y abrir son acciones distintas:
- Cuando un usuario crea un documento, el backend lo guarda y devuelve su ID.
- El navegador carga ese ID. Reutilízalo al volver a abrir o compartir el documento.
El unitId de la API es ese ID de documento. No crees un documento local vacío nuevo en cada visita.
Establece el usuario actual antes de cargar un documento. Identifica al colaborador y es propietario de la caché local sin conexión; consulta Identidad y autorización.
Por ejemplo, tras registrar Sheets y los plugins de colaboración, carga una hoja de cálculo del servidor:
import { UserManagerService } from '@univerjs/core'import '@univerjs-pro/collaboration-client/facade'univer.__getInjector().get(UserManagerService).setCurrentUser({ userID, name, avatar })const workbook = await univerAPI.getCollaboration().loadSheetAsync('your-document-id')if (!workbook) throw new Error('Document could not be loaded')Consulta las guías de Sheets, Docs, Slides, Boards, Bases y PDFs para la carga específica. Comprueba la compatibilidad del producto y la versión de backend objetivo.
Verificar sincronización, guardado y permisos
Abre el mismo documento en dos sesiones independientes, como una ventana normal y otra privada. Edita en una y comprueba la otra. Verifica el contenido tras actualizar, reconectar y reiniciar el servidor.
Prueba con un editor, un lector y un usuario sin autorización. Los ajustes UI de solo lectura controlan la interacción de la página; el servidor debe seguir rechazando lecturas y cambios no autorizados.
Si los documentos cargan pero las ediciones no se sincronizan, revisa WebSocket. Si el contenido desaparece al reiniciar, revisa el almacenamiento del backend. Consulta esos ajustes en Integración del servidor.
Añadir intercambio, comentarios o historial
Para editar juntos un archivo importado, crea un documento colaborativo con los datos convertidos; consulta la integración de intercambio de archivos. Los comentarios y el historial necesitan sus propios plugins, servicios y permisos. Sigue los módulos de extensión de Office.
Para configurar el panel de historial, consulta Sheets, Docs, Slides, Boards y Bases. Consulta el alcance actual de PDFs en Historial de PDFs.
Estado de sincronización y reenvíos
Tras importar el Facade, CollaborationStatusChanged informa del estado actual de documentos que ya colaboran al registrar el oyente, y luego de cambios sin estados duplicados consecutivos. hasWritePending(unitId) incluye cambios pendientes de envío, de confirmación y sin conexión. Sin ID comprueba el documento enfocado. Una conexión abierta no implica que todo esté guardado.
import '@univerjs-pro/collaboration-client/facade'const collaboration = univerAPI.getCollaboration()const statusSubscription = univerAPI.addEvent(univerAPI.Event.CollaborationStatusChanged, (event) => { console.info(event.unitId, event.status, collaboration.hasWritePending(event.unitId))})const resendSubscription = univerAPI.addEvent(univerAPI.Event.CollaborationChangesetResend, (event) => { console.info(event.unitId, event.reason, event.attempt, event.unsyncedMutationCount, event.nextDelayMs)})CollaborationChangesetResend solo se emite al reenviar, no en el primer envío. Sus razones son ack_timeout, should_retry y reconnect. attempt, elapsedMs, unsyncedMutationCount y nextDelayMs permiten mostrar guardado y reintentos. Libera las suscripciones al quitar el editor.
La demora de agrupación difiere del tiempo de confirmación. Valores del plugin en milisegundos: sendChangesetTimeout: 2000, changesetAckTimeout: 20000, maxChangesetAckTimeout: 120000. La solicitud usa también el tiempo de confirmación. Los cambios sin confirmar se reenvían con espera exponencial hasta el máximo. Igualar ambos tiempos de confirmación produce un intervalo constante.
import { UniverCollaborationClientPlugin } from '@univerjs-pro/collaboration-client'import { BrowserCollaborationSocketService } from '@univerjs-pro/collaboration-client-ui'univer.registerPlugin(UniverCollaborationClientPlugin, { socketService: BrowserCollaborationSocketService, sendChangesetTimeout: 200, changesetAckTimeout: 20_000, maxChangesetAckTimeout: 120_000,})Añade las opciones al registro existente conservando socket y endpoints. Los presets colaborativos de Sheets y Docs agrupan durante 200 ms y no exponen los tiempos de confirmación; usa el modo plugin para personalizarlos.
Gestionar conflictos en la aplicación
CollaborationConflict se emite una vez al entrar en conflicto, después de intentar limpiar la caché sin conexión. Registra el oyente antes de cargar documentos. reason es transform_failed, apply_failed, changeset_rejected, permission_rejected o remote_revert; message y revert aportan detalles cuando existen.
import type { IEventParamConfig } from '@univerjs/core/facade'import '@univerjs-pro/collaboration-client/facade'const conflicts = new Map<string, IEventParamConfig['CollaborationConflict']>()const conflictSubscription = univerAPI.addEvent(univerAPI.Event.CollaborationConflict, (event) => { conflicts.set(event.unitId, event)})El ejemplo retiene el evento para una pantalla de recuperación. El Map solo está en memoria: guarda o exporta localChanges antes de recargar. Debes conservarlos durante el evento, ya que después no se recupera la caché eliminada. awaitingChangeset puede haberse aplicado en el servidor; no lo repitas sin comprobarlo.
Con cacheCleared: false, recargar reproduciría los cambios de la caché antigua. Resuelve la limpieza antes. Borrar la caché no significa que los cambios se hayan guardado. permission_rejected también exige resolver el acceso; recargar no otorga permisos.
La UI predeterminada muestra una notificación según la razón y ofrece recargar tras limpiar la caché o reintentar si falla. Para gestionar la recuperación, configura enableDefaultConflictUI: false en la inicialización existente y procesa el evento:
import { UniverCollaborationClientUIPlugin } from '@univerjs-pro/collaboration-client-ui'univer.registerPlugin(UniverCollaborationClientUIPlugin, { enableDefaultConflictUI: false })import { UniverSheetsCollaborationPreset } from '@univerjs/preset-sheets-collaboration'const collaborationPreset = UniverSheetsCollaborationPreset({ enableDefaultConflictUI: false })import { UniverDocsCollaborationPreset } from '@univerjs/preset-docs-collaboration'const collaborationPreset = UniverDocsCollaborationPreset({ enableDefaultConflictUI: false })Combina el preset colaborativo con el del editor en el createUniver({ presets: [...] }) existente y conserva endpoints e historial. Consulta los parámetros de eventos y la configuración del cliente.
¿Cómo es esta guía?