1. 引言
随着互联网技术的不断提高和技术更新迭代,以及办公和学习场景的变化,团队成员可以远程协作[1],从而降低地域限制,提高工作效率。协同知识库通过提供丰富的知识管理和协作功能,为信息收集、实时协作、知识共享与交流、创新能力的提升等带来了极大的方便,帮助人们更好地适应新的学习和办公场景时代[2],特别是对带有多种支持数据组织结构的编辑器的协同知识库,能够更有效地进行知识和信息管理,其效果优于实时通信软件。
目前被广为使用的知识库协同设计方法有数据冲突处理算法为OT (Operational Transformation)和CRDT (Conflict-free Replicated Data Type)即“无冲突复制数据类型”[3]。OT被应用到Google docs和Office 365,国内近些年来的出现的一些文档类产品,包括石墨、钉钉、腾讯文档等等也都是基于OT的。不同的协同知识库产品根据用户需求和工作场景的不同,具有各自的特点和优势:
(1) 企业微信知识库:针对企业用户,提供了丰富的知识管理功能,包括文档管理、多人协作编辑、权限控制等,帮助企业实现高效协同办公。
(2) 钉钉知识库:作为阿里巴巴旗下的企业级协同办公平台,钉钉知识库同样具备强大的知识管理功能,并通过云端同步,实现了跨平台的知识共享。
(3) Google Docs:Google推出的在线文档协作工具,为用户提供了实时协作编辑、评论、版本管理等功能,支持多种文件格式,方便用户随时随地访问和编辑文档。
(4) 语雀:作为一款国产在线文档协作平台,语雀以Markdown为核心,为用户提供了丰富的文档编辑、管理、协作功能,支持知识库、团队协作空间等多种组织形式,适用于多种场景。
在使用OT时,其压力主要在服务端,每个用户都会将其编辑操作发送给中央服务器。服务器会根据当前的文档状态和接收到的操作,执行操作转换算法来调整操作的顺序和内容,以确保最终的结果是符合用户意图的,客户端无需像CRDT那样存储大量额外元数据,因此压力较小。但是,OT需要中央服务器负责解决操作转换逻辑,以确保转换后的指令能够正确反映用户的编辑意图,这意味着OT对网络的要求较高,并且可以实现强一致性。如果某个用户出现网络异常,导致缺少了一些编辑指令,那么基于已有状态进行的转换可能会出现问题。此外,随着使用场景的复杂性增加,需要考虑多个操作之间的顺序、位置和内容,以及可能的冲突解决策略,OT转换算法的复杂性也会呈指数级增长。随着去中心化的流行,越来越多的产品更多地开始基于CRDT开发协同编辑功能,Yjs正是基于CRDT的协同编辑框架专门为在Web上构建协同应用而推广的新方法,允许多个用户同时进行修改,确保更改的一致和连贯,保持无缝协作和实时更新。
互联网时代,过多的分散信息给员工之间的配合带来麻烦,信息难以共享,团队成员重复劳作,业务经验无法沉淀,知识资产流失严重。为此,本文提出一种基于Yjs的协同知识库设计方法并将其用于现实世界,实现了高效协同工作。
2. 设计方法与架构
协同知识库前端基于Vue.js框架,使用Element-UI组件库完成页面设计,并结合Yjs框架为Tiptap编辑器添加协同编辑功能[4]。后端采用SpringBoot框架作为基础,SpringSecurity实现用户登录认证和权限验证,SpringMVC进行请求分发控制,Mybatis用于与关系型数据库进行数据交互。此外,系统还使用了Redis作为缓存和全局唯一ID生成器[5],同时使用MySQL作为关系型数据库。
图1是多人协同知识库的架构图。知识库编辑功能基于SpringSecurity和MySQL实现了基于角色的访问控制,包含三种角色:创作者、协作者和普通用户。此外,还添加了管理员角色,管理员拥有全部权限,可以对用户、角色、权限、知识库和代码分享片段进行统一管理。
Figure 1. System schematic diagram
图1. 系统架构图
图2为实体关系图,其中,“用户”实体包含基本的编号、用户名和密码,还包含一些个人信息如电话和邮箱;“角色”实体将编号和知识库编号作为唯一主属性,这样做是为了让每个知识库都有自己的管理员、协作者和普通用户角色。角色实体还包含了角色名和角色昵称,角色名是为了在更好的在程序中标示;“角色”和“用户”两个实体之间的“拥有”关系是为了记录角色和用户的多对多关系而设置的,角色编号属性和用户编号属性共同构成唯一主属性;“权限”实体包含基本的编号属性,知识库编号属性是为了区分权限所属不同的知识库,这是由于每个知识库都有相同的权限名,添加了知识库编号就可以唯一对应一个主属性;“角色”和“权限”两个实体之间的“拥有”关系是为了记录角色和用户的多对多关系而设置的,角色编号属性和权限编号属性共同构成唯一主属性;“知识库”库实体包含基本的编号属性,以及知识库信息知识库名、简介、创建者名称;“邀请码”实体包含基本的编号属性,所属的知识库的编号属性,邀请码属性遵循唯一原则,将Redis的自增值进行62进制转换得到,失效时间属性是为了在查询时免去查询Redis而添加;“频道”实体包含基本的编号属性作为唯一主属性,父级编号属性是为了将频道构成树形结构,顶级频道的父级编号属性为0,其它非顶级频道都有父频道,此外还有频道的基本信息属性频道名、频道简介、创建者名称;“代码块”实体包含基本的编号属性,代码块实体的设置是为了让知识库更加适应程序员的应用场景,还包含知识库编号、代码块信息、代码块名称、代码块简介、创建者名称等属性。
Figure 2. Entity relationship diagram
图2.实体关系图
3. 案例研究与讨论
3.1. 认证功能
图3是实现的一款食品加工工业中的多人协同知识库首界面,包含当前知识库名称显示,根据不同的知识库动态的显示不同的名称,还包含更多操作下拉框,根据访问者角色的不同来提供不同的操作。还有探索页面跳转按钮、频道折叠面板以及协同编辑组件。频道折叠面板将频道分为了两种,功能频道和文字频道,功能频道用于适应不同的应用场景,本系统提供了适应程序员场景的代码集锦频道,用于代码块的创建和分享。
当用户首次访问知识库系统时,浏览器向服务器端发送请求。如果用户此时还没有登录,Spring Security将予以检测,并通过Username Password Authentication Filter过滤器抛出一个异常,表示用户未认证。Spring Security接着清除Security Context Holder中的身份认证信息。然后使用自定义的Authentication Entry Point类处理这个未认证请求。自定义的Authentication Entry Point返回401状态码和认证失败的消息。然后,前端重定向用户到登录页面,要求用户输入正确的用户名和密码来登录。一旦用户输入了正确的登录信息,后端会生成一个token,并把这个token存储在Redis数据库中,用于跟踪用户的会话。每次用户的请求都会通过该Redis token验证用户的登录状态。如果用户已登录认证,身份信息会被放入Security Context Holder完成认证过程。
Figure 3. Multi-manned collaborative knowledge repository system homepage
图3. 多人协同知识库首界面
根据角色的不同,每个用户可以进行的操作不同。图4和图5展示了管理员创建者、非管理员创建者的主要操作。管理员功能包括邀请其他人参与协同、设置信息的可见范围、添加频道和修改部落信息、删除部落等;非管理员的功能包括邀请其他人、添加频道和退出部落等。
Figure 4. Display of administrator creator’s functions
图4. 管理员创建者的功能展示
Figure 5. Function display for non administrator creators
图5. 非管理员创建者的功能展示
3.2. 协同邀请
协同知识库的邀请功能通过生成邀请链接来实现,其基本操作步骤为:
(1) 邀请者复制邀请链接给被邀请者。
(2) 为用户分配该知识库的协作者角色,被邀请者将具备该知识库协作者的操作权限,并被重定向到对应的知识库中。
(3) 生成邀请链接:邀请链接由请求路径和邀请码构成,邀请码是长度为6的字符序列,通过对Redis生成的递增序列进行62进制编码生成。编码后的邀请码值包含数字和大小写字母,不包含特殊字符,通过使用Redis生成递增序列可以有效避免并发时的问题。长度为6的62进制序列可生成多达五百六十亿次邀请码。
(4) 生成的邀请码将会被Redis缓存,并设置过期时间,同时也会存储到数据库中。前端发送查询邀请码请求时,后端会先查询数据库中是否存在未过期的邀请链接。如果存在,则刷新缓存和数据库的过期时间,并将邀请码发送给前端。前端收到邀请码后将邀请码与请求路径拼接生成邀请链接。
知识库的创建者和协作者可以使用邀请功能,邀请链接为后端生成的邀请码和前端当前域名和接收邀请的请求路径拼接而成,重置链接按钮将会向后端发送请求,得到后端生成的邀请码后,再将邀请码重新进行拼接,如图6所示。
Figure 6. Invitation function display
图6. 邀请功能展示
3.3. 范围控制
图7是修改控制知识库可见范围的功能展示,修改知识库可见范围表单包含一个单选框和一个更新按钮,将知识库的可见范围设置为公开访问并提交,页面将会向后端发送请求,后端修改数据库中该知识库的可见范围字段后,该知识库将在探索页面被其他非协作者和创建者看到。
Figure 7. Display of visible range control for knowledge base
图7.知识库可见范围控制展示
范围控制的实现包含了前端和后端两个部分。前端部分使用Element-UI的el-pagination组件,主要用到了它的current-page属性以及current-change事件。current-page属性表示当前页面的页数,它支持sync修饰符,可以与自定义的current-page属性进行双向绑定。当切换页面时,current-page的改变会引起current-page属性改变。同时,监听的current-change事件,定义了一个处理器来向后端发送分页查询请求,在current-change事件触发时就会调用处理器方法。后端部分使用MyBatis-PageHelper插件,先从请求中获取请求参数页码和每页显示记录数,调用startPage方法即可实现分页查询。PageHelper为SQL查询语句添加LIMIT子句和参数。
3.4. 树形目录
图8是频道添加的功能展示,顶级频道可以在当前频道的下拉框中进行添加,每个频道的子频道可以点击树形结构导航栏节点的右边+号进行添加。添加表单包含一个输入框和一个创建按钮。
Figure 8. Channel addition function display
图8. 频道添加功能展示
知识库的频道拥有子频道形成树形结构,为了展示该结构使用Element-UI的el-tree组件,后端涉及树形结构数据库表的设计以及树形结构查询。el-tree需要特定的数据结构每个节点需要包含label和children字段,其中children字段为字节点数组,在后端对数据库查询得到的链表进行了结构转换。el-tree使用data属性、node-click事件和slot-scope插槽。它们的作用如下所示。
(1) data用于绑定转换后的数据结构,监听node-click事件可以在el-tree节点被点击时触发自定义处理器的执行。
(2) 处理器可以接收data参数,data参数可以提供当前节点信息,可以使用data参数动态更新当前频道的状态。
(3) 使用slot-scope为el-tree自定义节点元素,传递data、node参数给自定义节点元素,这样节点元素就可以访问当前节点的数据。通过slot-scope为el-tree节点添加了show-more图标,点击图标可以对该节点进行更多操作,如添加子频道、修改频道信息。
在设计数据表时为属性结构表添加perent_id字段来构成树形的表结构,后端查询得到链表后根据id和perent_id进行数据结构的转化将链表结构转化为树形结构。算法逻辑为:先创建一个ResultList,将链表元素都放入HasnMap中,遍历RowList,如果父节点为0则放入ResultLis中,如果父节点不为0则一定有父节点,通过perentId在HashMap中查询父节点,并将自己放入父节点,循环这个过程迟到结束,该算法时间复杂度为O(n)。
3.5. 协同编辑
图9是协同编辑功能展示。协同编辑的主体是Tiptap编辑器,整合了多种插件以提供更多的数据组织显示和功能,例如有序列表、无序列表、引言、代码块、行内代码、代码语法高亮、文本高亮、历史功能、文本内链接和表格等。此外,使用TailWindcss框架为其提供用户体验更好的样式。
Figure 9. Collaborative editing function display
图9. 协同编辑功能展示
协同编辑的实现采用Yjs框架,该框架提供多种无冲突共享数据类型。在此设计中,使用YDoc数据类型,并借助Yjs的Binding功能将YDoc与Tiptap绑定。Tiptap使用Delt数据模型记录编辑器内容的变化,以便第三方组件可以通过Delt操作Tiptap组件。因此,绑定后,Yjs可以将实时协同数据更新到Tiptap中。为了实现该协同功能,还需要网络服务。因此,在本地运行一个WebSocket服务器,并配置相应端口。即可进行冲突处理并将处理后的数据更新到用户端。此外,还添加了离线编辑功能,即使没有网络,也可以继续编辑。新的更改将被存储在本地,并在联网时更新到WebSocket服务器。
完成以上配置后,利用Vue的监听功能以及Tiptap更新时的回调函数实现了协同编辑组件的双向绑定。这样就可以实时获取编辑器更新的数据,并进行持久化保存。此外,还暴露了用户名、频道号码和是否为只读等属性,提供了更好的交互性,使得用户可以看到其他用户的用户名。封装了Tiptap编辑器和Yjs框架的Vue协同编辑组件可以与其他人同时编辑同一份文档,即使在相同区域编辑也不会发生冲突,前端组件集成了Yjs框架的Provider,后端运行了一个WebSocket服务器,可以进行全双工通信实时更新协作者的最新编辑。
4. 结论
基于Yjs框架的多人协同知识库通过访问控制和协同编辑,根据不同的角色访问不同的知识库,并邀请别人进行协同编辑,实现了高效的信息交流与共享,可用于食品合作加工、美工协同设计等需要多人协作以提高设计效率的现实应用场景。
基金项目
江苏省高校哲学社会科学研究课题“基于多模态信息融合的网络舆情监测研究”(2022SJYB0982)。
注 释
文中所有图片均为作者自绘。
NOTES
*通讯作者。