精华内容
下载资源
问答
  • 共享文档多人编辑
    千次阅读
    2021-01-14 03:59:37

    加Q1647658274

    2019-07-09 10:18

    3416

    自己先看看哦~在工具--共享工作区

    文档工作区网站是 Microsoft Windows SharePoint Services 网站,可集中一个或多个文档。不管是通过直接处理文档工作区副本,还是通过处理自己的副本,同事们都可以很容易协同处理文档,他们可以使用已保存到文档工作区网站上副本的更改定期更新他们自己的副本。

    文档工作区的创建

    通常,使用电子邮件将文档作为共享附件发送时,会创建文档工作区。作为共享附件的发件人,您将成为该文档工作区的管理员,而所有的收件人都会成为文档工作区的成员,他们会被授予参与该网站相关讨论的权限。

    创建文档工作区的另一种常见的方法是使用 Microsoft Office 程序中的“共享工作区”任务窗格(“工具”菜单)。也可使用 Windows SharePoint Services 网站上的命令来创建文档工作区。

    从共享附件创建文档工作区时,网站会使用与它所基于的文档相同的名称。从“共享工作区”任务窗格或通过使用 Windows SharePoint Services 网站上的命令创建文档工作区时,则可为网站指定任何名称。

    注释 使用“共享工作区”任务窗格时,仅可在 Microsoft Office Word 2003、Microsoft Office Excel 2003、Microsoft Office PowerPoint 2003 和 Microsoft Office Visio 2003 中创建文档工作区。

    创建文档工作区时,您的 Office 文档会存储在新文档工作区中的文档库 (文档库:一个文件夹,其中的文件集被共享而且文件经常使用同一模板。库中的每个文件都与该库的内容列表中显示的用户定义信息相关联。)中,在该工作区中成员可以通过在 Web 浏览器 (Web 浏览器:解释 HTML 文件、将其设置为网页格式并加以显示的软件。Microsoft Internet Explorer 等 Web 浏览器可以访问超链接、传输文件并播放嵌入到网页中的声音或视频文件。)或某 Microsoft Office 程序中打开您的文档来访问它。

    文档工作区功能

    因为文档工作区是 Windows SharePoint Services 网站,所以成员可以使用 Windows SharePoint Services 功能,如使用“任务”列表来彼此分配待办项目,使用“链接”列表来创建指向资源相关材料的超链接,以及在文档库中存储相关或支持文档。

    在 Web 浏览器中打开文档工作区时,可以像自定义任何 Windows SharePoint Services 网站一样来自定义它。

    文档更新

    注释 文档更新仅对于 Microsoft Office Word 2003、Microsoft Office Excel 2003 和 Microsoft Office PowerPoint 2003 中的文档和单个文件网页 (MHTML) (单个文件网页 (MHTML):以 MHTML 格式保存的 HTML 文档,其中集成有嵌入式图片、Java 小程序、链接文档以及文档中所引用的其他支持项目。)、Microsoft Office Visio 2003 中的文档以及 Word 和 Excel 中的 XML 文件可用。

    使用 Word、Excel、PowerPoint 或 Visio 打开文档工作区所基于的文档的本地副本时,Microsoft Office 程序会定期从文档工作区获取更新并使它们对您可用,例如,如果其他成员已编辑他们自己的文档副本并已将那些更改保存到文档工作区中。

    如果对工作区副本的更改与您对您的副本所做的更改有冲突,您可以选择保留哪个副本。

    当完成编辑您的副本时,您可将更改保存到文档工作区,在那里其他成员可获取这些更改并将它们合并到他们的文档副本中。

    注释 对于 Word、Excel、PowerPoint 和 Visio,在文档的副本之间合并更改和解决冲突的详细方法会有所不同。

    更多相关内容
  • 多人协同编辑一直是我们 PingCode Wiki 不太敢触碰的一个功能,因为技术实现上有挑战。但协同编辑技术本身已经发展多年,解决方案已经相对成熟,我们团队也是在刚刚结束的 Q3 里完成...

    多人协同编辑一直是我们 PingCode Wiki 不太敢触碰的一个功能,因为技术实现上有挑战。但协同编辑技术本身已经发展多年,解决方案已经相对成熟,我们团队也是在刚刚结束的 Q3 里完成了基于 PingCode Wiki 编辑器协同编辑的方案落地,所以这里想结合我们的技术选

    型及落地实践经验谈谈我对这块技术的理解。主要内容以协同编辑技术为主,中间也会谈谈对技术发展演进的理解。

    一个场景

    一个常见的场景,页面发布冲突,这个交互在我们产品中真实存在过

    a11a80e9b71ccfb7fa31647944d690d8.png

    两个用户基于相同的文章内容进行了修改,一个用户先发布,后一个用户在发布的时候就会有这样的提醒,虽然有提示,这其实对用户来说是不友好的。通常产品的解决方案有以下三种:

    1. 悲观锁 - 一个文档只能同时有一个用户在编辑

    2. 内容自动合并、冲突处理

    3. 协同编辑

    第二种方案也有国外产品在做就是 Gitbook265f30fdc9bd79dff28498d82a2b57ae.pngGitbook 也是一种解决问题的方式。

    然后下面我们产品协同编辑的最终的交互截图:

    202c4a1caa9e9d26cc0d87fcf0f8a4b8.png

    主流的协同编辑交互就是这样,可以看到协作者列表以及每个协作者的正在输入的位置,实时看到他们输入了什么内容,我们甚至可以直接相互对话,这种方式可以有效避免冲突。

    虽然协同编辑最终呈现给用户的就这一个界面,但是它背后却有复杂的技术作为支持,接下来就一起看看协同编辑是如何运作的。

    认识协同编辑

    指导思想:系统不需要是正确的,它只需要保持一致,并且需要努力保持你的意图。

    我觉得这句话可以作为协同编辑冲突处理的一个指导思想,它很简洁明了的阐述了一个事情,就是协同编辑的冲突处理不一定是完全正确的,因为冲突本来就意味着操作是互斥的,互斥双方的操作意图不可能完全保留。冲突处理最重要的是保证协同双方最终数据的一致性,然后在这个基础上努力保持各自的操作意图。

    聊聊富文本数据模型

    协同编辑是构建在富文本编辑器之上的技术,它的实现一定程度上依赖于富文本数据模型的设计,这里介绍两个比较有代表性的数据模型:

    2012 年 Quill -> Delta

    2016 年 Slate -> JSON

    Delta 数据模型

    Quill 编辑器显示一段文字

    04b8625aea35cafe9be613ab58bbf4af.png它的数据表示是这样的

    12c3e07640587a28e48d5854cd13dada.png它定义三种操作(insert、retain、delete),编辑器产生的每一个操作记录都保存了对应的操作数据,然后用一些列的操作表达富文本内容,操作列表即最终的结果。

    Slate 数据模型(JSON)

    模型定义:

    d95350d7f22088139313e6202cbbe80b.png编辑器中有一个图片类型的节点,对应的数据结构

    969d6ffe68b9d411822736fba6261945.png属性修改操作

    36743170b252c9c75ee5dbb766e8cbf5.png我们可以看出虽然 Delta 和 Slate 数据的表现形式不同,但是他们都有一个共同点,就是针对数据的修改都可以由操作对象表达,这个操作对象可以在网络中传输,实现基于操作的内容更新,这个是协同编辑的一个基础。

    下面的部分我想聊聊在实现协同编辑时所面临的最核心的问题。

    协同编辑面临的问题

    这里先抛出问题,带大家了解协同编辑所面临的问题的具体场景,从问题出发,而后再讨论解决方法。

    问题一:脏路径问题

    假如编辑器中有三个段落,如下图所示

    e22d48c60c8c18a3eeadc7d898eb7afa.png这里用数组简单模拟上面的三个段落,下图展示了两个用户同时对数据修改产生的操作序列

    2d59fadf9a6b48a013f2ad22598ceaea.png可以看到左边插入的段落「Testhub」插入位置是错误的

    最上面的是原始的数据结构,左右两边代表两个用户的操作序列,开始时他们的状态一致。左边用户在 Index=2 的位置插入一个新的段落「Access」、右边用户在 Index=4 的位置插入一个新的段落「Testhub」,他们各自应用完自己的操作后,分别把操作通过消息服务传给对方,这个时候左边用户接收到右边用户同步过来的消息「在 Index=4 插入 Texthub」直接应用就会出现左边的结果,这个结果是与用户原本的意图是不一致的,而且与右边最终的数据不一致。

    究其原因就是左边用户先进行的插入操作导致了它后面数据的索引发生变化,那么基于同步过来的操作直接应用就会出现上图的异常,我把这种情况称为脏路径问题。问题二:并发冲突问题这里以前面介绍的图片数据结构为例说明并发冲突的问题,下图展示问题出现的过程,为了方便表达,图片节点仅保留 type 和 align 两个字段

    1ddec209508ab6ad568c352390e3fcd3.png最上面的数据结构展示了两个用户开始时基于相同的状态,图片 align = ‘center’。左边用户修改 align 属性为 left、右边用户修改 align 属性为 right,按照默认处理他们把各自的操作通过消息服务传给对方,则会造成左边最终显示居右、右边最终显示居左,数据出现不一致,这种情况称为并发冲突,他们基于相同的位置修改了相同的属性。问题三:undos/redos 问题

    undos/redos 问题本质还是前面所说的「脏路径问题」+ 「并发冲突问题」,但是问题出现的场景有些不一样,又相对复杂,所以这里单独提出来了。

    还是前面「脏路径问题」的数据操作,这里只看右边部分,分析它的撤回栈:

    1f557c38e0ed7f37cc114268f6459535.png右边用户的操作列表:

    5a8046f2ff7fc4c530073c32b608ffe1.png右边用户撤回栈(序列与操作列表相反):

    • ① 删除 Index=2 位置的 节点

    • ② 删除 Index=4 位置的 节点 执行这种撤回逻辑其实是有问题,原因是撤回操作 ① 所对应的操作的触发者(Origin)是左边用户,如果按照这种撤回逻辑执行左边用户可能就蒙了:” 我刚刚输入的内容怎么没了 !",虽然逻辑上可以解释,但它不符合用户的使用习惯,所以对于协同编辑场景:撤回应当只撤回自己的操作,协同者的操作应当被忽略。

    右边用户撤回栈修复版:

    • ① 删除 Index=4 位置的节点

    可以看到撤回栈只包含右边的操作了,但是这又带来了另外一个问题,大家仔细观察可以发现现在 Index=4 对应的节点是「Plan」,这个时候撤回会把「Plan」删除掉,而右边用户在插入时插入的实际节点是「Testhub」,又出现了脏路径。

    除了这种「脏路径」问题,「并发冲突」问题也会以类似的方式出现在,具体的逻辑就不再详细分析了。

    撤回栈忽略协同者操作后,撤回栈中的操作路径会出现「脏路径」问题 +「并发冲突」问题。

    • 问题四:工程落地问题

    这个问题比较好理解,就是协同编辑具体的落地问题:

    1. 操作的同步

    2. 光标的同步

    3. 网络不可知(网络抖动、网络延时、消息重连以及重连后的各种情况处理)

    4. 文档版本历史

    5. 离线编辑

    6. ...

    简单归纳下上面所提到问题,其实可以分为两类:

    第一类:主要包含脏路径、并发冲突、Undos/Redos等,可以统称为数据一致性问题 ,它属于学术问题的范畴,因为并发冲突的处理结果需要保证最终数据的一致性 ,这个需要经过大量的学术研究、论证。

    第二类:工程问题,重点是在解决「数据一致性」的基础上实现一套具体的落地方案,除了前面提到的具体落地开发的功能点,还要考虑性能问题、数据传输效率问题等,这块其实包含很大的工作量,是理论研究是否可以真正落地到生产实践的关键.

    第一类学术问题的解决方案就是数据一致性算法 ,学术界主要有两个方面的研究:OT 算法 和 CRDT。8eae0cf84a6c4b7974c282916d6824c0.png

    数据一致性算法

    这里不会过多介绍算法的实现细节,只是提供它处理冲突的思路,以及从问题的本身出发去看待它处理问题的一个思路,至于具体的算法实现大家有兴趣可以去Github查找相关的资料去自己实践。

    OT

    OT 全称是 Operational Transformation,它的核心思想是操作转换,通过转换数据修改操作解决协同编辑中的各种问题。

    发展历史 OT是最早(1989年)被提出的协同冲突处理算法 2006 年被应用到 Google docs 2011 年被应用到 Office 365 至今 OT 仍然是实现协同编辑的最主要的技术选择,Google docs 以及 Office 365 至今仍在采用 OT 的方案,国内近些年来的出现的一些文档类产品,包括石墨、钉钉、腾讯文档等等,他们的协同编辑技术也都是基于 OT 的。

    核心思想

    就像它的名称一样,它的核心思想是对用户协同编辑中产生的并发操作进行转换,通过转换对其中产生的 并发冲突 和 脏路径 进行修正,然后把修正后的操作重新应用到文档中,保证操作的正确性和最终数据一致性。

    原理图

    可以用 diamon 图表示 OT 的核心原理

    133a7689cab287763ac2887538816e82.png

    左图解释:

    • a 标识左边用户的 operation

    • b 表示右边用户的 operation

    • 二者交叉的点表示文档基于相同的初始状态

    左图状态:

    两边用户分别应用操作 a 和 b 后 ,这时两边的文档内容都发生变化,且不一致;

    操作转换:

    为了左右两边的文档达到一致的状态,我们需要对 a 和 b 进行操作转换 transfrom(a, b) => (a', b') 得到两个衍生的操作作 a' 和 b' 。

    右图应用操作转换的结果:

    左边 a 操作的衍生操作 a' 在右边应用,b' 在左边应用,最终文档内容达到一致。

    这里说明的只是最基础的 OT 模型,每个客户端只有一个操作的情况(1 : 1),还有每个客户端对应多个操作的情况(M : N),还有 OT 控制算法等等。并且在真正实现 OT 时有可能每一次操作转换只得到一个衍生操作(ottypes 定义的操作变换就是这样),跟前面的 transforms 有些不一样,但这些不是特别重要,具体实现的时候在仔细理解,这里描述的只是 OT 算法的最基础思路。

    用 OT 解决「脏路径」问题

    如上图所示 OT 在操作同步的过程中增加一层操作转换的逻辑,用于纠正并发操作产生的脏路径。

    左边同步右边操作时索引由 4 转换为 5。

    操作转换逻辑分析:

    对于左边用户:

    因为在协同操作「在 Index= 4 插入 Testhub」到达之前,已经执行了本地操作「在 Index=2 插入 Access」,而本地操作的索引 Index=2 小于协同操作的索引 Index=4,所以协同操作的索引路径应当加上本地新增的节点长度,也就是1,索引发生变化由 4 变成 5。

    对于右边用户:

    因为协同操作的索引路径小于本地操作的索引路径,本地操作不对协同操作产生影响,所以不需要做任何的转换,直接应用源操作即可。

    用 OT 解决「并发冲突」问题

    4f7ba8389b7e65fd269c58eae5d95c8b.png

    可以看到基于 OT 解决「并发冲突」同样是使用操作转换逻辑,只不过这次的操作转换并不转换脏路径,而是协调冲突的属性修改,上图的处理结果是假定右边操作后到达服务器的,最终结果收拢到居右显示。

    • 从上面的两种场景分析可以看出这个操作转换过程并没有太复杂,虽然真实的场景下要考虑的情况会比这要多,但是也就是一层逻辑转换。还有就是真实的场景需要对每一种操作类型做交叉操作转换,比如 Delta 支持三种操作,那么可能要支持 33 种操作变换,Slate 支持9种原子操作,可能要实现 99 种操作变换,复杂度大概就是这样。

    OT 解决 undos/redos 问题

    前面已经说过 undos/redos 问题 本质就是 「脏路径」+「并发冲突」问题,所以 OT 的处理方案就是当编辑器接收到协同操作时,需要对 Undo栈、Redo栈中的所有操作循环执行操作转换逻辑,undo 或者 redo 时最终执行的是转换后的操作,具体的逻辑不再意义赘述。

    算法说明

    可以看出 OT 是对编辑器的数据操作进行转换,所以 OT 算法的实现依赖于编辑器数据模型的设计,不同的数据模型需要实现不同的操作转换算法。

    OT 算法大概就说到这里,下面看看 CRDT 是如何处理数据一致性问题的。

    CRDT

    CRDT (Conflict-free Replicated Data Type)即“无冲突复制数据类型”,它主要被应用在分布式系统中,保证分布式应用的数据一致性,文档协同编辑可以理解为分布式应用的一种,它的本质是数据结构,通过数据结构的设计保证并发操作数据的最终一致性。

    CRDT 于 2011 年正式被提出。基于 CRDT 的协同编辑框架 Yjs 大概在2015年开源,Yjs 是专门为在 web 上构建协同应用程序而设计的。

    核心思想

    大多数的 CRDT 为在文档中创建的每个字符分配一个唯一的标识符。

    为了确保文档始终能够收敛,CRDT 模型即使在删除字符时也会保留元数据。

    CRDT 最初是为了解决分布式系统最终数据一致性而提出的,它支持各个主机副本之间数据修改的直接同步,而且数据修改的同步顺序以及同步的次数不影响最终结果,只要修改操作一致,数据的最终状态就是一致的,也就是通常大家说的 CRDT 数据的满足交换性和幂等性。

    简单介绍 CRDT 是如何处理冲突的

    下图描述了 Yjs 中处理冲突的算法模型,它是一个支持点对点传输的冲突处理模型。

    05ab0a1eec7171caaef299bab985c8b8.png                                 上图基础说明

    • 最下面的 “AB” 标识初始状态

    • 上面的每一根线代表一个插入操作

    • 每一个操作都有一个唯一标识符 比如 C0,0 操作中的 0,0 就是一个标识符

    第一个 0 指示用户编号

    第二个 0 指示操作序列

    例如,以下标识符表示 user 0 插入 “C” 在 “A” 和 “B” 之间

    C0,0

    相同的用户 user 0 插入 “D” 在 “B” 和 “C” 之间,可以使用下面的操作

    D0,1

    这时候另外一个用户期望插入 “E” 在 ”A“ 和 ”B“ 之间,但是这个操作是与前面插入 ”C“ 的操作(C0, 0)是并发操作。

    此时用户的唯一标识应该与前面的不同,但是 clock 应该是与前面的插入操作类似:

    E1,0

    由于存在并发冲突,Yjs 执行与 OT 相同的冲突解决,并比较各自插入的用户标识符。由于用户标识符 1 大于 0,因此生成的文档为:

    ACDEB

    以上就是 Yjs 处理并发冲突的算法介绍,其实也不难理解,首先它的插入操作是基于已有字符的相对位置,在 OT 中使用的相当于是基于索引的绝对位置,然后就是冲突的处理,主要是比较用户标识符,标识符小的先应用,标识符大的后应用。

    上面是以 Yjs 为例介绍 CRDT 的冲突处理模型,下面看看 CRDT 是如何解决前面所提出的问题的。

    用 CRDT 的思想解决脏路径问题

    首先我们使用类似于 CRDT 的方式描述刚才的数组:

    0d3fd7eca66f6b7224e2ac874f9d27ba.png

    可以看到右边的列表使用唯一 Id 替换了原本数组的索引,然后描述内容修改的操作也相应的做一下调整

    左边操作:

    在 Index=2 的位置插入 Access -> 在 111 之后插入 Access

    右边操作:

    在 Index=4 的位置插入 Testhub -> 在 333 之后插入 Testhub 同步操作之后左边和右边最终的数据结构应该都是一样的:

    504ec8f8ca944d5a532397b93e666009.png
    • 因为这里只是模拟 CRDT ,解释 CRDT 的思想,真实的 CRDT 通常是使用双向链表,这里为了好理解所以仍然沿用数组,只是给数组中的每一个段落节点数据增加一个唯一标识。

    CRDT 解决并发冲突

    这里还是以图片设置 align 属性为例介绍,首先看看CRDT如何描述对象属性及属性修改:

    e9473c2d01bea4bb25f747e3a1d0760a.png

    左边是图片数据模型,右边是模拟 CRDT 对应的数据结构,图片对象中的每一个字段都使用结构对象去描述内容及内容的修改,这里以 align 字段的代表看它的表达

    操作 ①:

    930e5b50c336b04f7cc701dbca495ef2.png

    最上面蓝色部分表示 align 的初始值是 center ,(140, 20)是这个初始数据结构的标识,它也是基于某一个用户的操作产生的。

    这个时候一个用户执行了操作 ①,把 align 属性修改为 left,产生了一个新的结构对象,就是图中橙色部分的表示。操作完成后,Map 中的 align 字段指向了新产生的结构对象上,标识符是(141,0),因为(141,0)这个结构对象是基于(140,20)的修改,所以它的 left 指向(140,20)这个结构对象。

    这个示例会有一些歧义,就是链表的数据结构本身会有 left、right 两个指针(在结构对象左右两边),然后中间部分其实是内容,但是我的内容存储的是图片的 align 属性,它的值可能是 left、center、right,跟链表在 left、right 指针在一起可能产生混淆,这里标记下,就是结构对象中的第二个块描述的是属性内容。

    操作②:

    9bb6e8dc0de7eb3398fd4fbcb83f69e2.png

    这个时候另外一个用户基于刚刚产生的结构对象(141,0)进行了操作 ②,把 align 属性修改为right,产生了一个新的结构对象,就是图中橙红色部分的表示。

    图片下半部分是这两个操作之后最终的数据结构,它是一个双向链表的表达(这种表达已经很接近 Yjs 真实的数据结构了),它不仅可以描述最终的数据状态(right),还可以表达出数据修改的顺序:center -> left -> right。

    这个示例其实描述的是顺序操作,每一个操作基于的状态都是最新状态,两个用户执行的操作是有确定先后顺序的。

    下面看看两个用户并发的执行属性修改时产生的数据结构:

    9033d544d497c48bf874164a0ed8e5d7.png

    与前面最大的不同就是执行操作 ② 和执行操作 ① 所基于的状态是一致的,都是基于 align = 'center' 进行修改的,这种情况表达的就是并发数据的修改。接下来就是并发处理的逻辑了,跟前面介绍的一致,这个时候操作 ① 的对应的用户标识 141 小于操作 ② 对应用户标识 142,所以先应用操作 ①,后应用操作 ②,所以最终图片的 align 属性状态是 right。

    CRDT 解决 undso/redos问题

    CRDT 可以理解为完全没有「脏路径」问题,然后并发冲突问题也完全可以基于 CRDT 的标识符(时间戳)去解决,那么基于 CRDT 的方案中,实现 undos/redos 应该就比较简单了,只需要根据 CRDT 的数据结构的新增或者删除去实现 undos/redos 栈就可以有效解决问题。假如进行了一个生成结构对象的操作,那么撤回的时候可能就把它标记删除。

    假如进行一个删除结构对象的操作,在执行撤回操作时可能就对应于重新执行结构对象的插入操作。

    CRDT 算法说明

    与 OT 不同,CRDT是一种全新的解决方案,它不依赖于编辑器实现,对于任何的编辑器数据模型都可以使用一套 CRDT 数据结构去处理冲突,也是因为数据结构的性质,它也可以不依赖中心化的服务器,而且稳定性非常高,这区别于 OT,OT可以理解为是通过算法控制保证数据一致性,CRDT 通过数据结构设计保证数据一致性,它在复杂的网络环境中的处理是更稳健的,CRDT 的代价就是要保存更多的元数据,这会带来一定内存消耗,但是这是可优化的,事实证明这个代价在协同编辑场景是完全可忽略不计的。

    Yjs 优化

    其实基于 CRDT 的协同编辑方案一直是被质疑的,而且质疑的声音到现在都一直还在,Yjs 也受其影响。尽管基于 CRDT 实现的 Yjs 已经如此强大了,大家还总是拿 CRDT 的内存开销、性能开销说事,以我目前的了解:内存开销、性能问题对于 Yjs 来说早已不是问题,所以这里简单介绍下 Yjs 的优化,这部分内容的整理基于官方对 Yjs 优化的介绍,性能问题和内存占用问题每一个点都有大量的基准测试去验证,这里只对优化方式进行一些简单的介绍。

    一、结构表示优化

    当用户从左到右键入内容“ABC”时,它将执行以下操作:insert(0, "A") • insert(1, "B") • insert(2, "C")。对文本内容建模的 YATA CRDT 的链表将如下所示:

    24d8a960fdad079ae04bf85ad2b3ff32.png

    插入内容“ABC”的CRDT模型(假设用户具有唯一的客户端标识符“1”) 所有的 CRDT 都会为每个字符分配某种唯一的 ID 和附加的元数据,这对于大型文档来说非常消耗内存。我们不能删除元数据,因为它是解决冲突的必要条件。

    Yjs 也唯一地标识每个字符和分配元数据,有效地表示了这些信息。较大的文档插入表示为单个 Item 对象,使用字符偏移量唯一地单独标识每个字符。

    然后这块是有优化空间,下面的 Item 也可以将字符“A”唯一标识为 {client:1,clock:0},字符“B”为 {client:1,clock:1},依此类推......

    Item {
        id: { client: 1, clock: 0 },
        content: 'ABC',
        length: 3,
        ...
    }

    如果用户将大量内容复制/粘贴到文档中,则插入的内容由单个 Item 表示。此外,从左到右写入的单字符插入可以合并为单个 Item。重要的是,我们能够在不丢失任何元数据的情况下拆分和合并项。这就是 Yjs 对于数据表示的优化,通过这种方式可以有效减少 Yjs 数据结构中结构对象的数量,从而有效减少内存的占用。

    然而,这种方法最重要的缺点是处理单个字符变得更加复杂(也没关系,因为这是 Yjs 框架做的事情)。

    当另一个用户希望在“B”和“C”之间插入一个字符时,需要将操作的“BC”部分拆分为两个单独的操作。我们不能重新组合这些操作,因为在 CRDT 中我们永远不能删除字符或从文档树中删除它们。

    二、删除优化

    我们可以指示需要删除字符的唯一方法是将其标记为已删除。虽然如此,这块还是有优化空间,以 Slate 的段落结构为例,当你将段落标记为删除时,你也可以将段落下的所有文本结构标记为删除。比如,一个段落包含文本 ”ABC“,当标记段落删除时:

    (Paragraph)D

    相当于将以下所有文本节点(字符)也标记为删除:

    AD    BD    CD

    这是我们可以完全从内存中删除所有字符节点对应的结构,因为字符节点是被删除段落的子节点。基于这种方式也可以有效减少 Yjs 的内存占用。

    三、操作定义

    这块其实是从 V8 的角度去优化 Yjs 结构对象的创建,整体思路就是让 Yjs 创建对象的过程能够被浏览器优化,无论是内存占用还是对象创建速度。

    四、查询优化

    大家应该都知道使用双向链表最大的弊端就是查询性能,因为每一个操作你都需要遍历整个链表去查询某一个结构对象,当 Yjs 结构对象数据非常巨大时,执行的每一个操作有可能会因此损耗一定的时间,Yjs 对此也是有优化措施的,目前我从源代码中看到的是,Yjs 会对用户经常操作的结构对象进行缓存(其实就是缓存位置),查找过程中优先重缓存中去匹配,通过如果缓存命中则可以有效提高数据的查询速度。

    五、编码优化

    Yjs 会对网络中传输以及存储在数据库中结构对象进行统一的二进制编码,当然也会提供相应的解码操作,通过二进制编码可以有效的提高数据的传输效率。

    OT vs CRDT

    e806e85c1207b4c2ac9f473d4abdb08c.png

    OT 和 CRDT 算法的部分就到这里,下面介绍下基于 OT 和 CRDT 算法在实际开发中的工程落地方案。

    开源解决方案

    这里主要介绍两种方案,一种是基于 OT 的 ShareDB 方案,另外一种是基于 CRDT 的 Yjs 方案。

    3cc71cfd3b1cc7ab46d7789c5de51adc.png

    ShareDB 方案

    针对 OT 其实社区一直有一个对应的解决方案 - sharedb,只是比较遗憾的是 slate 和 sharedb 该怎么结合缺少明确方案,我在 Github 上搜索发现也有人研究过,只不过是针对的是 slate 比较旧的版本,也不怎么维护了,但是它的实现给了我一些思路,加上原本的理解就有了现在的方案:slate + ottype-slate + sharedb。

    ShareDB ShareDB 是基于 OT 实现协同编辑的一套解决方案,提供协同消息转发、光标同步、数据持久化、OT 控制算法等等。

    ShareDB 架构图如下

    611b51137b60545151079e414e027a17.png

    下边浅蓝色部分是 ShareDB 包含的主要模块,ShareDB 会提供基于 WebScoket 的消息服务实现以及对应的前端链接消息服务的SDK,可以同步操作和光标,ShareDB 也包含数据持久化部分的实现。

    最左边的 OTType 是核心的操作转换的部分,因为不同编辑器的数据模型需要实现单独 OT 的算法,所以 ShareDB 本身不包含 OT 的实现,而是提供了标准的接入接口,任何数据类型只要基于这个接口实现了对应的操作转换算法,那么它就可以通过注册的方式接入到 ShareDB 中,这个标准接口的定义可以参考 ottypes 中的实现。

    上面紫色部分是目前 ShareDB 可以支持的编辑器,编辑器想要接入最终的任务就是基于编辑器的数据模型实现一个自己的 OTType 就可以,然后 Quill 编辑器的 Delta 数据模型本身就实现了操作转换的逻辑,所以 Quill 是最容易接入的。

    ottypes

    前面有提到的 ottypes 其实是定了一种标准的 OT 的接口,根据这种标准实现的的类型转换可以都可以完美的与 ShareDB 配合使用,共同完成数据的协同编辑,前面方案中提到的 ottype-slate 其实就是 ottypes 的一种实现。

    ottype-slate

    个人感觉 slate 中定义的数据模型以及数据变换可读性非常高,它的表达方式以及提供的工具函数式非常清晰且完善,并且每种原子操作都是可逆的,我大概看了 sharedb 默认支持的基于 JSON 的操作变换实现(ot-json0),ot-json 针对数据修改的表达,可读性还是非常差的,所以我感觉可以自己写一个针对 slate 数据模型的 OTType 实现,所以就有了ottype-slate。

    • ottype-slate 当前只是初步实现了部分操作变换函数,然后结合 slate-angular 和 sharedb 搭建了一个协同编辑的测试 Demo,剩余的部分操作变换函数后续慢慢补充。

    ShareDB 方案流程图

    aa3dd5600a5c25cc99da26570bc5148d.png

    从上面开始看,假如用户在基于 Slate 编辑器进行协同编辑,可以看到用户内容修改产生的 operations 在传递给 ShareDB Serve 之前可能会经过操作转换,这取决于操作所基于的文档版本和服务器的文档版本是否一致,不一致就需要计算出两个版本差异的部分操作,拿差异的操作与新产生的操作进行操作转换,基于操作转换的结果去同步内容的修改,这个过程之后就是把最终的操作通过消息服务转发给其它客户端,其它客户端在应用这个操作,实现协同编辑。

    从这个流程可以看出操作转换最终有可能是在服务端进行,也有可能在客户端进行。因为操作转换的过程需要通过 OT 控制算法实现多客户端的操作变换的协调,这个过程必须走一个中心化的服务器,否则过程很难控制,所以基于 OT 算法这个方案是不能实现点对点通讯的。

    Yjs 方案

    Yjs 是基于 CRDT 的开源解决方案,它提供了比较完善的生态,在2020年的时候社区也出现了基于 Slate 编辑器的中间绑定层。

    Yjs 架构图

    6a12440b60edc68130d67e9d6e702b7d.png

    y-websocket - 提供协同编辑时的消息通讯,包含服务端实现和前端集成的SDK

    y-protocols - 定义消息通讯协议,包括消息服务初始化、内容更新、鉴权、感知系统等

    y-redis - 持久化数据到 Redis

    y-indexeddb - 持久化数据到 IndexedDB

    在上层 Yjs 支持任何大部分主流编辑器的接入,因为 Yjs 也可以理解为一套独立的数据模型,它与每种编辑器本身的数据模型是不同的,所以每种编辑器想要接入 Yjs 都必须实现一个中间绑定层,用于编辑器数据模型与 Yjs 数据模型转换,这个转换是双向的,官方目前提供了 Prosemirror、Quill、Ace等编辑器的中间绑定层,基于 Slate 编辑器的中间绑定层是由社区开发者提供的。

    Yjs 方案流程图

    99d7dd8ba315866f490ea55438f972e8.png

    从上到下描述一下用户操作的同步过程,假如上面用户在基于 Slate 编辑器进行一些数据的修改,它产生的 operations 需要先经 Yjs Bindings 把基于 Slate 的操作转换为 Yjs 的数据修改(使用applySlate),更新本地 Yjs 的数据结构,当 Yjs 的数据结构被修改后它可以通过一种网络传输协议把数据结构的变更同步给协作者,协作者直接应用这个远程的数据同步到本地的 Yjs 数据结构上,然后 Yjs Bindings 中还有一个订阅操作,就是订阅远程的 Yjs 数据修改,然后通过 applyYjs 方法把 Yjs 数据修改的表达转化成 Slate 的 operations,最终 Slate 应用这个 operations 实现内容的同步,中间并发冲突的问题完全交给 Yjs 数据结构去处理,转化到 Slate 的操作永远跟 Yjs 的处理结果一致。

    从流程图可以看出每一个客户端都维护了一个 Yjs 数据结构的副本,这个数据结构副本所表达的内容与Slate编辑器数据所表达的内容完全一样,只是它们承担职责不同,Slate 数据供编辑器及其插件渲染使用,然后 Yjs 数据结构用于处理冲突、保证数据一致性,数据的修改最终是通过 Yjs 的数据结构来进行同步的。

    值得一提的是 Yjs 数据结构本身支持端端数据的直接同步,可以不借助中心化的服务器。

    PingCode Wiki 协同方案选择

    2021年了,技术应该变一变了,协同编辑方案不应该只有OT,下面简单谈谈我们做技术选型时的考量。

    今年 Q3 我们团队正式开始做协同编辑,我们的编辑器是基于Slate框架实现的,虽然在这之前我对协同编辑有一些调研,但都不成体系,所以在 Q3 开始的时候我们又重新进行了一次调研,核心问题还是选 OT 还是 CRDT,下面是我们当时掌握的一些情况:

    OT 方案

    • TinyMCE 编辑器基于 Slate 模型 + OT 实现协同编辑,但是他们的不开源

    • 大厂产品的协同编辑方案都是基于 OT 实现的

    • 对于 OT 当时只是了解思路,不知道如何落地 ,准确的说都不知道协同编辑应该包含哪些基础模块

    CRDT 方案

    • 社区对于 CRDT 一直有一些质疑的声音

    • CRDT 缺少商业产品上的应用案例(文档类)

    • Yjs 生态比较完善 基于Slate编辑器有成熟的Demo

    • 翻译了部分 Yjs 技术资料、对 Yjs 印象不错

    • 基于我们的编辑器搭建了Yjs的协同编辑Demo,可以跑通

    当时调研的 slate-yjs 提供的 Demo 截图如下

    bc1d8862ef858ed42b84a486f001908a.png

    这个Demo可以说功能非常完善,而且技术栈跟我们基本是完全吻合。虽然对于 CRDT 社区有一些质疑的声音,但是事实总要验证一下,因为 Yjs 完善的 Demo 以及对它的初步印象,我们决定按照 Yjs 的方案试一试。

    这基本上是我们选型的过程了,因为之后的过程就很顺利,首先是我们基于 Yjs 的生态快速在测试环境上搭建了协同编辑的初步版本,逐渐的我们在官方提供的消息服务的基础上重新实现了一个我们自己的消息服务,加上鉴权,然后基于就是逐步排查和修复协同编辑的一些细节问题,包括消息服务连接的控制、undos/redos 的问题、弹框处理等等,总之就是没有太大的问题,而且性能上基本没有损耗,大文档的加载(大概5-6万字的内容) Yjs 基本可以在毫秒级去处理完成。

    现在重新来看Yjs方案的选择,我觉得我们这套方案的选择非常正确,在这个过程中没有浪费一点团队的时间,而且在Q3实现协同编辑的过程中,大家都很轻松,而且在 Yjs 上我们还可以学到很多东西,下面是我总结的 Yjs 在功能以及设计上的一些优势:

    功能上:

    • 设计了完善的感知体系,用户同步用户在线状态、光标位置等

    • 支持离线编辑

    • 网络不可知,可以非常稳健的处理网络抖动、网络延时等问题

    • 提供 undos/redos 的管理

    • 版本历史

    设计上:

    • 模块职责划分清楚,尤其是抽取独立的协议库 y-protocols,让复杂的消息同步变得非常的清晰可控

    • 网络协议/数据持久化 实现松耦合,网络协议支持接入 y-websocket、y-webrtc,持久化 y-redis、社区有提供 y-mongodb

    • 可以很快的与任意编辑器集成

    可以这么说现在 Yjs 对于我们的意义,就之于两年前 Slate 对我们的意义,是我们这个阶段了解和学习协同编辑的重要支柱,实现协同编辑到底包含哪些东西、都有什么问题、Yjs 是怎么解决的、Yjs 有什么缺点、它是如何优化的等等,就像一个老师帮助你完成你的工作,然后让你在这个过程中有所进步。

    谈谈技术的演进

    e41b9f26acd71f3b741bb7bef857b97b.png

    1989 年 OT 算法正式提出,代表着协同编辑技术的开始,但是当时编辑器的架构设计远不能达到现在的水平,它的理念在那个时期一定是非常超前的,现在协同编辑数据模型的演变我觉得一定程度上也有受 OT 算法的影响。

    2006 年 Google 把 OT 真正到带到了商业产品中,这个过程经历大概十多年,然后就是 2011 微软紧接着基于 OT 实现了协同编辑,这中间也经历了大概5年的时间,我觉得这个时间跨度一定跟当时的编辑器技术背景有关系,这个时期其实协同编辑技术也只是在这些顶尖科技公司得到发展和应用。2011 年 CRDT 算法提出代表着一种新的协同编辑方案的出现。

    2012 年 Quill 编辑器开源,它的数据模型 Delta 就是基于 OT 算法设计的,个人觉得 Quill 编辑器的开源对于协同编辑以及 OT 的发展是一个重要的里程碑,在以前协同编辑可能是少数大公司在研究的技术,Quill 编辑之后协同编辑就逐渐应用更多的中小公司产品中,比如国内的石墨文档整个核心技术包括协同编辑可能就是基于 Quill 和 Delta 实现的。

    2013年 ShareDB 开源,代表着基于 OT 的一套完整解决方案的落地。

    2015 年 Yjs 开源代表着基于 CRDT 的协同方案正式得到发展。2019 年 Slate 框架基于 TypeScript 完全重构,它的数据模型得到进一步优化,目前已经极其简洁优雅,我觉得这也代表着一种变化。

    2020 年 slate-yjs 开源,它是 Yjs 和 Slate 的一个结合,有了这个结合其实就有了一个基于 Slate 的完整协同方案。

    2021 年我觉得我们在这个时间选择 Yjs 也很合理,不同的时期技术的选择一定是不同的。

    这里想延伸一点就是 OT 算法其实是在现有的编辑器数据模型的基础上实现的协同编辑,它的思想也很好理解,其实反过来想,现在协同编辑所遇到的数据一致性的问题也有一部分原因是由于数据模型中「数据修改操作」的表达所引起的,比如数据修改操作中基于索引的方式去定位要修改的数据所产生的脏路径问题,总之 OT 可以理解现有技术思路下的解决方案。然后 CRDT 其实是一种独立于现有编辑器架构的解决方案,是一种技术上的创新,它为实现协同编辑提供了一种新的思路,并且它有很多优秀的特性,比如支持点到点的数据同步,并且基于数据结构的冲突处理其实是更稳健的,虽然基于 CRDT 的数据结构在实现起来复杂度比较高,但是这个复杂度可以完全由框架层去完成,使用者其实对这块可以是无感的。

    收尾

    这篇文章其实是为我们公司今年举办的 「PingCode 开发者大会 2021」而准备的主题内容,然后我本身其实也想对协同编辑这块的内容做一个整理,趁这个机会就一起做了,主要是阐述了我对这块技术的一个认识,包括协同编辑是什么,协同编辑所遇到的一些问题或者说挑战,然后主流协同编辑冲突处理算法是怎么工作的,再到后面的基于冲突处理算法的开源解决方案等等,这里面提到的大部分技术其实都是开源的,内心其实是非常佩服这些开源作品的贡献者的,也在督促自己努力的去做更多的开源输出。

    • 来源:https://juejin.cn/post/7030327005665034247

    最后

    最后, 送人玫瑰,手留余香,觉得有收获的朋友可以点赞,关注一波 ,相关 文档资料 已上传至 React 中文社区交流群, 请关注公众号,点击菜单栏 入群学习,入群就送前端精选100本电子书 添加 入群小助手 后入群领取。陆续更新前端超硬核文章。

    推荐阅读

    (点击标题可跳转阅读)

    [极客前沿]-你不知道的 React 18 新特性

    [极客前沿]-写给前端的 K8s 上手指南

    [极客前沿]-写给前端的Docker上手指南

    [面试必问]-你不知道的 React Hooks 那些糟心事

    [面试必问]-一文彻底搞懂 React 调度机制原理

    [面试必问]-一文彻底搞懂 React 合成事件原理

    [面试必问]-全网最简单的React Hooks源码解析

    [面试必问]-一文掌握 Webpack 编译流程

    [面试必问]-一文深度剖析 Axios 源码

    [面试必问]-一文掌握JavaScript函数式编程重点

    [面试必问]-阿里,网易,滴滴,头条等20家面试真题

    [面试必问]-全网最全 React16.0-16.8 特性总结

    [架构分享]- 微前端qiankun+docker+nginx自动化部署

    [架构分享]-石墨文档 Websocket 百万长连接技术实践

    [自我提升]-Javascript条件逻辑设计重构

    [自我提升]-页面可视化工具的前世今生

    [大前端之路]-连前端都看得懂的《Nginx 入门指南》

    [软实力提升]-金三银四,如何写一份面试官心中的简历

    觉得本文对你有帮助?请分享给更多人

    关注「React中文社区」加星标,每天进步

    be34691d84f5c450418d15a13532de7f.png   点个👍🏻,顺便点个 在看 支持下我吧!

    展开全文
  • 石墨文档这个很多人应该都用过,石墨文档 是一款优雅,轻便的在线协作文档工具,支持多人同时对文档编辑和评论,多端实时更新,让你与他人轻松完成协作撰稿/方案讨论/会议记录和资料共享等工作。石墨文档可以用来做项目...

    最近使用了下石墨文档,简直就是在线版的Word,Excel,PPT,而且可以多人实时编辑预览,真的太好用了,搜索了下发现这种在线文档工具还挺多的,这里做个整理推荐。

    石墨文档

    这个很多人应该都用过,石墨文档 是一款优雅,轻便的在线协作文档工具,支持多人同时对文档编辑和评论,多端实时更新,让你与他人轻松完成协作撰稿/方案讨论/会议记录和资料共享等工作。

    石墨文档可以用来做项目策划, 编写入职指南, 写简历等,https://shimo.im/blog 这里列出了一些企业的使用案例。

    支持三种标题、有序列表、无序列表、代码块等基本 Markdown 样式,

    Word、Excel、txt、Markdown 一键导入,还能导出成 PDF 和 JPG,

    最好用的功能是邀请团队成员一起协作, 和你的团队一起查看和编辑同一个文档或表格,提升沟通效率。

    比如我新建一个文档:

    写好后可以分享出公开链接,设置可以编辑模式。

    编辑后你就可以实时看到效果(不用刷新)。

    腾讯文档

    腾讯文档是一款可多人协作的在线文档。支持Word、Excel和PPT类型,打开网页就能查看和编辑,云端实时保存;可多人实时编辑文档,权限安全可控。https://docs.qq.com/

    如果你本机没有装Word,可以通过腾讯文档导入Word文件打开,写好保存后再导出为Word。

    另外腾讯文档还有小程序

    点击打开腾讯文档

    谷歌文档

    语雀

    一个专业的云端知识库,号称十万阿里人都在用的笔记与文档知识库 https://www.yuque.com 支持markdown编写,这个我最需要。

    它有个好用的功能就是历史版本,还支持回滚,类似git。

    一起写

    耳目一新的云端Office ,打开网页就能写 https://yiqixie.com/

    飞书

    https://www.feishu.cn/ 这个是字节跳动出的,号称强大易用的文档协作云空间,企业文档散乱、共享困难又无法同时编辑?飞书云空间汇集文档、电子表格、思维笔记等多种在线工具,汇聚企业知识资源于一处,支持多人实时协同编辑、@同事、评论等丰富的互动功能,让团队协作更便捷、沟通更充分。

    最后总结下,推荐使用石墨文档和腾讯文档,当然如果你是分享技术文档建议使用gitbook,或者之前我分享的 Python 文档生成器 mkdocs

    推荐阅读:

    公众号:苏生不惑

    扫描二维码关注或搜索微信susheng_buhuo

    展开全文
  • office共享——多人编辑

    万次阅读 2018-10-29 17:50:29
    Office共享(word,excel等)  团队做项目写策划书很容易遇到每个人各写各的文件,哪怕是指定好部分,在整合的时候,也是非常麻烦的,而且可能造成不必要的重复修改,文件太多。  所以在做团队项目的时候最好...

                                                                     Office共享(word,excel等)

       团队做项目写策划书很容易遇到每个人各写各的文件,哪怕是指定好部分,在整合的时候,也是非常麻烦的,而且可能造成不必要的重复修改,文件太多。

       所以在做团队项目的时候最好使用一些共享软件,如office的onedrive共享功能,有道云笔记等。能实现多人合作,一份文件,从最开始到结束。这里只讲office的共享(office几乎每个人的电脑里面都有,没激活的激活就好,而且文件能通过office365(www.office.com)在线修改(注意有的人的账号在线版的onedrive是看不了的,因为无法访问https://onedrive.live.com,这个域名很久之前就被墙了,要访问就要挂代理之类的能上谷歌的东西,不然只能客户端使用,office教育版亲测在线版和桌面版都可以直接使用,原因是它的域名不是https://onedrive.live.com

    每个人都能使用自己的账号修改团队共享的文件(后面会讲这么做)。共享文件最好是由一个人完成,在最开始修改,就由一个人发布(包括发布和给权限),然后其他人进行修改。最好开始共享的是一个写好了各个部分标题的模板,然后每个人写指定的部分,多人同时编辑一个文件,注意不要两个人同时编辑同一行之类的,它分不清到底听谁的,还要注意保存,保存的时候大家可能会卡一下,因为文件在同步中,同步完,别人修改的东西你就能看到了(同步只会同步修改的部分,别的部分还是和最开始一样),每次保存都会有版本号,方便在出错的时候回退,一般不会使用回退的。

    操作是很简单的,难的地方是团队统一性,在最开始统一使用符合共享要求的office,有的人可能非要用wps之类的,或者觉得没有使用共享的必要,或者在最开始没习惯使用它,又或者因为office安装版本之类的问题不愿意更换,那么每次让它整合,就知道到底有多么麻烦的,很多时候都不是简单的复制粘贴那么简单。每个人改了发,你要找他们改的部分,可能还要修改格式,还有可能出现遗漏,后期重复修改。完全再做一些无用功。

     

    使用office共享要求:

    1、要求激活office(可以使用kms激活,但最好使用正版,闲鱼上不指定名字也就差不多就5rmb一个,一个账号的下载链接,可以给5台电脑激活。账号里面可以管理给谁激活了(会显示机型),还有安装完成后选择添加账号以登录个人账号(不可能每个人一样的),登录后它还是激活状态,office365是只要有订阅就能一直更新到最新版的,能用多久说不准的,看卖家,不太可能存在永久的,但是你们可以永久激活office2016,那个office365安装后有的能找到永久激活秘钥,不会的查资料吧。office安装前先卸载office,卸载office要卸载干净,注意方法。这不多说了,自己上网找,有些专门的卸载器)

     

    2、office2013以上(office2010有的没有共享功能)

     

    3、一个微软账号(这里说下账号是怎样的,免得问,一般来说在你刚买回电脑的时候,windows10会要求你注册个账号,要求填写邮箱密码,那个东西就是微软账号了,没有的去官网www.office.com注册)

     

         团队里面几乎每个人都能看到别人编辑的版本,在历史版本或者历史记录里,发布者一定看的到的。出现情况可以版本回退。教程分三部分:office共享者、office编辑者、office最后的保存。

    使用office共享发布者需要做的(我使用的是目前最新版的office365excel那些也差不了多少的)

           1、打开word->文件->账户,检查是否登录,没登录微软账号的登录

     

    2、找到共享文件,有两个地方有,功能都一样,你图标可能和我不一样

    上面的菜单里 有

     

    文件->共享里 也有

     

    3、一般会出现下图,点击那个被选中的onedrive,没有的话,就看看后面的有没有,有时会直接跳过这个步骤(它的问题)

    1. 可能过程中会有卡顿,第一次的时候,等等就好了。出现下图,可以在框里搜索你团队其他人的微软账号,或者点击那个人型小框(点这个就是添加联系人,新建下联系人,方便以后再共享东西,共享的时候再选联系人点下收件人),还有种是获取共享链接,但是有的人会出现打不开的情况(上文写过原因了),所以不说了

    1. 邀请人员那里会显示队友的账号,再在下面给他们权限,选可编辑,不然你发的东西,队友不能改。最后点下共享就好了。

     

    Office共享后编辑

    1. 和上面一样,第一步先确定是否登录。
    2. 文件->打开->与我共享->别人共享给你的文件,就能看到队友共享给你的文件了,点开,然后就能编辑。然后注意保存就可以了,有的会自动保存的,自己设置好,或者自己点保存。下次修改还是这样的。Office本地保存(之前文件会存在onedrive里):最后在文档完成后,打开文档,文件->保存副本->这台电脑->浏览->本地文件位置(或者文件->保存副本->浏览->本地文件位置)选一个你的本地文件目录(最后的成品保存到本地,如:我的电脑)

    转载请注明出处https://blog.csdn.net/qq_38243612/article/details/83510374,谢谢!

    展开全文
  • 使用该压缩包可以使Vue或uniapp使用luckysheet免费开发多人在线编辑Excel档 ...或在论坛中搜索“Vue或uniapp使用luckysheet免费开发多人在线编辑Excel文档”里面有详细说明,如有疑问也可在文章下方留言
  • 2. 如何实现多人同时编辑一份文档在Word文档(比如说:123.doc)中预先设置好多个数据区域(“PO_”开头的书签),当以表单模式(WebOpen方法的第二个参数使用docSubmitForm)打开Word文件时,只有设置了Editing...
  • 在使用Python编写的应用的过程中,有时会遇到多个文件之间传递同一个全局变量... 以上这篇python通过配置文件共享全局变量的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持聚米学院。
  • 作为最为基础的功能,Microsoft SharePoint Server 2010的文档分享功能得到了加强,比如多人共同协作的加入就让企业异地的小组讨论或者是多人同时编辑完成一篇文章变得非常容易,如果再结合OCS即时聊天工具,将为...
  • excel怎么实现多人共同编辑一个文档

    千次阅读 2021-02-11 23:06:51
    针对“ excel怎么实现多人共同编辑一个文档 ”的问题,下面由一级教师-李微竹为您解答:非常多时候我们也许需要多人在相同个Excel图表中进行编辑,可是当一个人在编辑的时候,另一个人打开则只能是只读,不能编辑,...
  • 局域网多人同步编辑EXCEL文档的方法.pdf
  • 有道云协作为用户提供了多人实时协同编辑功能,可以让协作群组中的多个用户在同一时间编辑同一份文档,互不干扰。下面,小编就为大家介绍一下这一功能,以前来了解一下吧!类别:信息管理 大小:68.25M 语言:简体...
  • 多人同时编辑一个文档,能够在不刷新页面的情况下实时地看到他人的编辑。典型例子有石墨文档、腾讯文档、Google Docs等。 主要需要解决的技术难点有: 实时通信 编辑冲突 2.可选的解决方案 实时通信有long pull...
  • 集成开源前端表格LuckySheet,后台使用SpringBoot和Mongodb数据存储,实现多人在线协同编辑Excel。此为可运行jar包,源代码见博客:https://blog.csdn.net/qilei2010/article/details/118882714
  • 如何让多人同时编辑共享文件夹里的EXCEL表格我们可以设置工作簿的共享来加快数据的录入速度,而且在工作过程中还可以随时查看各自所做的改动。当多人一起在共享工作簿上工作时,Excel会自动保持信息不断更新。在一个...
  • 一、下载wps安装 1.进入官网首页,网下滚鼠标滚轮 ... 2.下载之后,下一步安装 二、创建共享文件夹 ...2.设置云文件夹 为共享的 ...四、多人实时编辑文件 1.进入实时编辑文件 的方式 五、修改权限 ...
  • 如何实现多人协同在线编辑

    千次阅读 2021-01-14 03:59:36
    ​工作中,我们都免不了要和他人进行协作,有时候由于工作上方式、工作进展等某些层面的差异性,团队内部的信息同步、文件协同和软件项目...跨地域文档的合作编写更为艰难,统计数据没法立即共享,造成信息孤岛状况...
  • excel多人共享编辑使用方法.doc
  • ONLYOFFICE免费开源多人在线文档协作系统的部署与开发细节
  • 怎样多人协同在线编辑文档

    千次阅读 2021-06-25 09:22:21
    我想很多办公或者做项目的小伙伴都遇到过,很多时候想在线编辑一个文档,却发现很多都不支持,更别说多人协同在线编辑了,那么如何实现这一系列功能,今天企业网盘坚果云的干货分享就来帮大家解决该类问题。...
  • 1.本项目后端技术采用基于SpringBoot框架,MySQL数据库,前端技术采用html,css,js。 2.本项目是一个类似腾讯文档在线编辑模块的实时协同编辑系统。 3.系统源码连同sql文件一起打包放在我的资源包里了。
  • office文档多人共享编辑

    千次阅读 2012-01-03 10:48:46
    以下方法可以在局域网中,多人同时对一个word文档或excel文档进行编辑: 第一步:随便打开word文档或excel文档,点击审阅,点击共享工作薄 第二步:在允许多用户同时编辑,同时允许工作簿合并打“√”,在这边还...
  • 接下来我要实现多人编辑同一个Excel文件,这里以Source.xlsx为例,右键选择共享 设置共享权限以及共享给谁 权限有如下,如果是发送给别人看,就选择任何人(可向收到此链接的任何人授予访问权限,无论他们是直接收到...
  • 近期Leangoo领歌敏捷开发工具出了一个脑图功能,我们恰好用了起来。... Leangoo脑图可以支持多人在线编辑与协作。 Leangoo脑图的节点和Leangoo看板上的卡片是一样的,支持富文本文档,可以添加附件,添加检查项,添加
  • 1,将excel表格搞好。 2,QQ最下面一栏找到腾讯文档 3 点开进入后选 导入功能 4, 修改权限,然后分享就可以了。
  • WPS⁺云办公是金山办公为企业提供的一站式云办公SaaS服务,包括多平台的WPS Office...点击登录WPS⁺云办公账号一、多人协同编辑您可点击文档右侧【共享】然后选择获得链接的人【可编辑文档,然后将文档链接发送给...
  • 越来越多的办公软件开始蜂拥而至,而小编最近发现一款简单而又好用的协作办公软件——石墨文档,这款软件支持多人协作,对云端的文档或表格进行有效的编辑,同时还支持多人同时编辑同一表格或文档,这大大方便了多人...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,647
精华内容 3,058
关键字:

共享文档多人编辑