How to quickly implement multi-person collaborative editing?

introduction

Collaborative editing is an essential function of mature online document editing software. For example, Tencent Documents supports multi-person collaborative editing. Basically, it monitors the command and then synchronizes the command to other clients. For example, the following series:

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

This approach can quickly realize the collaborative operation of most functions, but there are also some shortcomings, which I roughly divide into two types:

The first is that the information is lost after the command is passed, and the command needs to be rewritten or modified, such as the copy and paste function.

This type corresponds to the hope that the command will take effect, but it does not actually take effect.

The second type is the special functions necessary for multi-person collaboration, and there are many cases:

1. For example, when editing a cell, other people are not allowed to edit this cell, and there is a style reminder;

2. When user A is editing, and user B inserts a row above, the cell edited by A will also move down instead of staying in place;

3. When zooming, it will not affect other pages;

This type corresponds to not wanting the command to take effect, or wanting to change the effect of the command taking effect.

If you are also doing collaboration and encounter the above problems, then this article may answer your questions.

Let's take a look at the final implementation effect:

collaborative editing

Before starting, let me explain the structure of the demo. The demo I wrote this time is HTML as the front end, and nodejs is used as the server side. The front-end and back-end communication uses websocket. The directory structure is as follows:

Before testing the demo, please be sure to read the readme file carefully.

Next, I will talk about how to optimize the above-mentioned situations to better meet the needs of collaboration. The overall idea is actually relatively simple. It is nothing more than intercepting those commands that do not meet the needs and processing them separately. The situation mentioned above does not include all the functions required to achieve collaboration, but it is just an introduction. If there are other situations that have not been considered, they can be handled in the same way.

1. Synchronize command to all clients

Here, commandManager is used to monitor all operations, and send them to the server using websocket. The mosaic part is for subsequent other code logic, so don't look at it for now.

The server does only one forwarding:

Other clients receive this message and execute the command:

At this point, the rapid realization of the coordination of most operations mentioned at the beginning has been completed, and the subsequent operations are all to make up for the shortcomings of the current solution.

Two, processing paste

When the pasted command is synchronized to other clients, it will fail to execute. Carefully compare the sent command with the received command, and you will find that two of the fields have changed:

These two arrays should have been Range objects inside, but they were converted into different Objects. This is because we used the JSON.stringify method, which does not support Range objects when serialized with this method, so we When this information is received, it needs to be restored to Range again:

In fact, you may find that when fromRanges exists, I directly use the copyTo method to implement the paste, without re-executing the command, the effect is actually the same.

Another situation is implied here: copy content from the outside and paste it to the spread. At this time, the fromRanges object does not exist, so we need to execute the command. Of course, the value of the pastedRanges array must be changed to the Range type before execution.

3. The editing status is unique

That is, only one user can edit the same cell at the same time. This is an almost necessary requirement for collaborative editing. It looks simple, but in fact it is more complicated. When the client has a user to start editing, send a message to the server,

The server needs to maintain an array, record all the cell information currently being edited, and synchronize to all clients

After other clients receive the message, if the user wants to edit this cell, the user is prohibited from entering the editing state

Of course, users may want to see who is editing which cells, similar to this effect:

Here's how it's done with custom cells:

This functionality is rudimentary, but consider this situation: what if another user inserts a row above while you are editing?

Lily was editing A2. After Alen inserted a row above, Lily should edit A3, but with our current implementation, Lily is still editing A2. Correspondingly, deleting rows above and inserting and deleting columns on the left will have the same problem.

Both Lily and Alen will be affected here. The cell edited by Lily should be moved, and the cell locked by Alen should also be moved. Alen's side is relatively simple. The server updates the locked cell information according to the inserted row and column. Lily On the other hand, it is a little more troublesome. It needs to record the functions that Lily has entered, and open it in a new cell, and open the input box. The callback function is the logic of selecting a new input box. It varies according to different states, so use a callback Implemented in the form of a function.

4. Synchronization of row and column changes

I believe you have also noticed that in the above processing, the change information of the ranks and columns is very important. On the basis of the native command, there is also the processing logic of the edit box, so the changes of the ranks and columns also need to be processed separately. When the queue and column change message is received, intercept it:

and make the correct movement to the edited box

epilogue

At this point, this article is coming to an end. The overall implementation idea is actually relatively simple. It is nothing more than intercepting those commands that do not meet the coordination requirements or have problems with synchronization, and re-implement them. This method can quickly realize simple collaboration and make customized modifications.

However, there are some problems in this method, such as the inability to support the undo stack. You can see in the code that I will clear the undo stack at any time to prevent users from performing undo operations. It will enter the stack, which will cause the operation of user A to appear in the undo stack of user B. When user B cancels, it is possible to undo the operation of user A.

In addition to the above problem, there must be other deeper and more difficult problems. Therefore, to realize collaboration in actual projects, my idea is to limit the types of operations of users according to the business, and develop collaboration for these limited operations in a targeted manner. Function, so although the efficiency is relatively low, it is easier to control because of the small area involved.

OK, the above is the whole content of this article, readers are welcome to leave your thoughts in the comment area~

Simple collaboration code download link:

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

Extension link:

Implementing Excel server-side import and export under the Spring Boot framework

Project Combat: Online Quotation Procurement System (React +SpreadJS+Echarts)

Svelte framework combined with SpreadJS to realize pure front-end Excel online report design

Guess you like

Origin blog.csdn.net/powertoolsteam/article/details/132019507