複数人での共同編集を迅速に実装するにはどうすればよいですか?

導入

共同編集は、成熟したオンライン ドキュメント編集ソフトウェアの重要な機能です。たとえば、Tencent Documents は複数人による共同編集をサポートしています。基本的に、コマンドを監視し、コマンドを他のクライアントに同期します。たとえば、次のシリーズ:

https://gcdn.grapecity.com.cn/showtopic-82517-1-1.html
https://gcdn.grapecity.com.cn/showtopic-82518-1-1.html
https://gcdn.grapecity. com.cn/showtopic-82519-1-1.html

このアプローチでは、ほとんどの機能の連携操作を迅速に実現できますが、いくつかの欠点もあります。大きく分けて次の 2 種類があります。

1 つ目は、コマンドを渡した後に情報が失われ、コマンドを書き直すか、コピー アンド ペースト機能などの変更が必要になることです。

このタイプは、コマンドが有効になるという期待に対応しますが、実際には有効になりません。

2 つ目は、複数人での共同作業に必要な特殊な機能で、次のようなケースが多くあります。

1. たとえば、セルを編集する場合、他の人はこのセルを編集することができず、スタイルのリマインダーが表示されます。

2. ユーザー A が編集中にユーザー B が上に行を挿入すると、A が編集したセルもその場にとどまらずに下に移動します。

3. ズームしても他のページには影響しません。

このタイプは、コマンドを有効にしたくない、またはコマンドが有効になったときの効果を変更したいことに対応します。

あなたもコラボレーションを行っていて上記の問題に遭遇した場合、この記事があなたの質問に答えるかもしれません。

最終的な実装効果を見てみましょう。

共同編集

その前にデモの構造を説明します 今回書いたデモはフロントエンドがHTML、サーバーサイドがnodejsです フロントエンドとバックエンドの通信にはWebSocketを使用しています ディレクトリ構造は次のように:

デモをテストする前に、必ず Readme ファイルをよくお読みください。

次に、コラボレーションのニーズをより適切に満たすために上記の状況を最適化する方法について説明します。全体的なアイデアは実際には比較的単純で、ニーズを満たさないコマンドをインターセプトして個別に処理するだけです。上記の状況は連携を実現するために必要なすべての機能を含んでいるわけではなく、あくまで紹介であり、考慮されていない他の状況がある場合も同様に処理できます。

1. すべてのクライアントに対してコマンドを同期します。

ここでは、commandManager を使用してすべての操作を監視し、WebSocket を使用してそれらの操作をサーバーに送信します。モザイク部分は後続の他のコード ロジックのためのものなので、今は見ないでください。

サーバーは転送を 1 つだけ行います。

他のクライアントはこのメッセージを受信し、次のコマンドを実行します。

この時点で、最初に説明したほとんどの操作の調整の迅速な実現が完了しており、その後の操作はすべて現在のソリューションの欠点を補うことになります。

2、加工ペースト

貼り付けたコマンドが他のクライアントと同期されると、実行に失敗します。送信されたコマンドと受信されたコマンドを注意深く比較すると、次の 2 つのフィールドが変更されていることがわかります。

これら 2 つの配列は内部で Range オブジェクトであるはずですが、別のオブジェクトに変換されました。これは、JSON.stringify メソッドを使用したためです。このメソッドでシリアル化した場合、このメソッドは Range オブジェクトをサポートしないため、この情報を受信すると、再度 Range に復元する必要があります:

実際、fromRanges が存在する場合、コマンドを再実行せずに、copyTo メソッドを直接使用して貼り付けを実装しても、効果は実際には同じであることがわかります。

ここでは別の状況が暗示されています: コンテンツを外部からコピーしてスプレッドに貼り付けます。この時点では、fromRanges オブジェクトは存在しないため、コマンドを実行する必要があります。もちろん、pastedRanges 配列の値は次のように変更する必要があります。実行前の Range タイプ。

3.編集ステータスが独特です

つまり、同じセルを同時に編集できるのは 1 人のユーザーだけです。これは共同編集にはほぼ必須の要件であり、単純そうに見えますが、実際にはより複雑です。クライアントが編集を開始するユーザーを持っている場合、サーバーにメッセージを送信します。

サーバーは配列を維持し、現在編集中のすべてのセル情報を記録し、すべてのクライアントと同期する必要があります。

他のクライアントがメッセージを受信した後、ユーザーがこのセルを編集したい場合、ユーザーは編集状態に入ることが禁止されます。

もちろん、ユーザーは次の効果と同様に、誰がどのセルを編集しているかを確認したい場合があります。

カスタム セルを使用して行う方法は次のとおりです。

この機能は初歩的なものですが、次の状況を考えてみましょう。編集中に別のユーザーが上に行を挿入した場合はどうなるでしょうか。

Lily は A2 を編集していました。Alen が上に行を挿入した後、Lily は A3 を編集する必要がありますが、現在の実装では、Lily はまだ A2 を編集しています。同様に、上の行を削除したり、左側の列を挿入および削除したりしても、同じ問題が発生します。

ここでは、リリーとアレンの両方が影響を受けます。リリーが編集したセルは移動され、アレンがロックしたセルも移動されます。アレン側の処理は比較的単純です。サーバーは、挿入された行と列に従って、ロックされたセルの情報を更新します。 Lily 一方、少し面倒です。Lily が入力した関数を記録し、それを新しいセルで開き、入力ボックスを開く必要があります。コールバック関数は、新しい入力ボックスを選択するロジックです. 状態によって異なりますのでコールバックを使用します 関数の形で実装されています。

4. 行と列の変更の同期

上記の処理では、ランクや列の変更情報が非常に重要であることにもお気づきかと思いますが、ネイティブコマンドをベースに、エディットボックスの処理ロジックも存在するため、ランクや列の変更情報は、列も個別に処理する必要があります。キューと列の変更メッセージを受信したら、それをインターセプトします。

編集したボックスに正しく移動します

エピローグ

この時点で、この記事は終わりに近づいています。全体的な実装アイデアは実際には比較的単純です。調整要件を満たしていないコマンドや、同期中に問題が発生したコマンドをインターセプトし、再実装するだけです。この方法では、簡単なコラボレーションを迅速に実現し、カスタマイズされた変更を行うことができます。

ただし、この方法には、元に戻すスタックをサポートできないなど、いくつかの問題があります。コードを見ると、ユーザーが元に戻す操作を実行できないように、いつでも元に戻すスタックをクリアすることがわかります。スタックに入ります。これにより、ユーザー A の操作がユーザー B の取り消しスタックに表示されます。ユーザー B がキャンセルすると、ユーザー A の操作を取り消すことができます。

上記の問題以外にも、もっと奥深くて難しい問題があるはずなので、実際のプロジェクトで連携を実現するためには、業務に応じてユーザーの操作種類を限定し、その限定された操作に対して連携を展開するのが私の考えです。効率は比較的低いですが、必要な面積が小さいため制御が容易です。

OK、上記がこの記事の全内容です。読者はコメント欄にあなたの意見を残してください〜

シンプルな共同作業コードのダウンロード リンク:

https://gcdn.grapecity.com.cn/forum.php?mod=attachment&aid=MjgzMDk0fGVlNTFkNGQ1fDE2OTA3NjM4Mjl8MHwxNzY0MDU%3D

拡張リンク:

Spring Boot フレームワークでの Excel サーバー側のインポートとエクスポートの実装

Project Combat: オンライン見積調達システム (React +SpreadJS+Echarts)

SpreadJS と組み合わせた洗練されたフレームワークにより、純粋なフロントエンド Excel オンライン レポート デザインを実現

おすすめ

転載: blog.csdn.net/powertoolsteam/article/details/132019507