当前位置: 首页 > news >正文

processflow流程图多人协作预热

前言

在线上办公如火如荼的今天,多人协作功能是每个应用绕不开的门槛。processflow在线流程图(前身基于drawio二次开发)沉寂两年之久,经过长时间设计开发,调整,最终完成了多人协作的核心模块设计。废话不多说,上操作视频展示下效果:

Video_2023-09-04_150131

多人协作技术原理剖析

秉着都2023年了,谁还重复造轮子的理念,这里现学现用,利用了一些商业成熟的技术和软件来实现自己的目标。主要用到了两点技术:

  • 利用websocket的push&subscribe实现多人之间的行为共享(鼠标点击;移动;图标内容变更)
  • 利用onedrive实现历史快照文件的存储

 

client生产事件主要分为以下几种:

                    switch (data.action){//传递鼠标移动和点击事件case 'message':processMsg(data.msg, data.from);break;case 'clientsList':clientsList(data.msg);break;case 'signal':signal(data.msg);break;case 'newClient':newClient(data.msg);break;case 'clientLeft':clientLeft(data.msg);break;case 'sendSignalFailed':sendSignalFailed(data.msg);break;}

 server端主要作用就是接收client端的各个事件,然后对事件进行处理,然后广播出去;

比如:newClient新客户端加入,server端会将clientId和session记录到缓存中,然后将新的clientId广播出去,所有的客户端接收到有新协作者加入后,会进行相关准备操作。

clientLeft:当有客户端下线,也会将session剔除,然后广播出去,所有客户端会将下线的client的光标移除。

push队列主要对各个客户端的事件进行排序。幂等操作,然后发布。 

 存储端:

主要用onedrive进行存储,历史版本管理,冲突解决。这里插一句,不要问为什么用onedrive,因为drawio集成了onedrive,这里不想重写一套新的文件操作api,直接用现成的了。鉴于国内对onedrive网络支持的不太友好,这也是为什么迟迟不上线的原因之一,后续考虑将接口统一走后端代理,由后端统一访问onedrive。

private Response contactOAuthServer(String authSrvUrl, String code, String refreshToken, String secret,String client, String redirectUri, boolean directResp, int retryCount) {HttpURLConnection con = null;Response response = new Response();try {URL obj = new URL(authSrvUrl);con = (HttpURLConnection) obj.openConnection();con.setRequestMethod("POST");boolean jsonResponse = false;StringBuilder urlParameters = new StringBuilder();if (postType == X_WWW_FORM_URLENCODED) {con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");if (withAcceptJsonHeader) {con.setRequestProperty("Accept", "application/json");}urlParameters.append("client_id=");urlParameters.append(Utils.encodeURIComponent(client, "UTF-8"));urlParameters.append("&client_secret=");urlParameters.append(Utils.encodeURIComponent(secret, "UTF-8"));if (code != null) {if (withRedirectUrl) {urlParameters.append("&redirect_uri=");urlParameters.append(Utils.encodeURIComponent(redirectUri, "UTF-8"));}urlParameters.append("&code=");urlParameters.append(Utils.encodeURIComponent(code, "UTF-8"));urlParameters.append("&grant_type=authorization_code");} else {if (withRedirectUrlInRefresh) {urlParameters.append("&redirect_uri=");urlParameters.append(Utils.encodeURIComponent(redirectUri, "UTF-8"));}urlParameters.append("&refresh_token=");urlParameters.append(Utils.encodeURIComponent(refreshToken, "UTF-8"));urlParameters.append("&grant_type=refresh_token");jsonResponse = true;}} else if (postType == JSON) {con.setRequestProperty("Content-Type", "application/json");JsonObject urlParamsObj = new JsonObject();urlParamsObj.addProperty("client_id", client);urlParamsObj.addProperty("redirect_uri", redirectUri);urlParamsObj.addProperty("client_secret", secret);if (code != null) {urlParamsObj.addProperty("code", code);urlParamsObj.addProperty("grant_type", "authorization_code");} else {urlParamsObj.addProperty("refresh_token", refreshToken);urlParamsObj.addProperty("grant_type", "refresh_token");jsonResponse = true;}urlParameters.append(urlParamsObj.toString());}// Send post requestcon.setDoOutput(true);DataOutputStream wr = new DataOutputStream(con.getOutputStream());wr.writeBytes(urlParameters.toString());wr.flush();wr.close();BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));String inputLine;StringBuffer authRes = new StringBuffer();while ((inputLine = in.readLine()) != null) {authRes.append(inputLine);}in.close();response.status = con.getResponseCode();Gson gson = new Gson();JsonObject json = gson.fromJson(authRes.toString(), JsonElement.class).getAsJsonObject();String accessToken = getAccessToken(json);int expiresIn = getExpiresIn(json);response.refreshToken = getRefreshToken(json);response.accessToken = accessToken;JsonObject respObj = new JsonObject();respObj.addProperty("access_token", accessToken);if (expiresIn > -1) {respObj.addProperty("expires_in", expiresIn);}if (directResp) {response.content = respObj.toString();} else {// Writes JavaScript coderesponse.content = processAuthResponse(respObj.toString(), jsonResponse);}} catch (IOException e) {StringBuilder details = new StringBuilder("");if (con != null) {try {BufferedReader in = new BufferedReader(new InputStreamReader(con.getErrorStream()));String inputLine;while ((inputLine = in.readLine()) != null) {System.err.println(inputLine);details.append(inputLine);details.append("\n");}in.close();} catch (Exception e2) {// Ignore}}if (e.getMessage() != null && e.getMessage().contains("401")) {response.status = HttpServletResponse.SC_UNAUTHORIZED;} else if (retryCount > 0 && e.getMessage() != null && e.getMessage().contains("Connection timed out")) {return contactOAuthServer(authSrvUrl, code, refreshToken, secret,client, redirectUri, directResp, --retryCount);} else {response.status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;e.printStackTrace();log.error("AUTH-SERVLET: [" + authSrvUrl + "] ERROR: " + e.getMessage() + " -> " + details.toString());}if (DEBUG) {StringWriter sw = new StringWriter();PrintWriter pw = new PrintWriter(sw);e.printStackTrace(pw);pw.println(details.toString());pw.flush();response.content = sw.toString();}}return response;}

感悟心得

开源不易,请大家多给drawio点点star,没有他,就没有中国繁荣的流程图商业化盛景...拿着人家的代码来挣钱,一个start也不愿意给人家点。可悲。

虽然作者挺操蛋的,多人协作的代码没有开源(我只能靠研究官方网站的协作功能和数据格式一点点猜测用到了哪些逻辑),白板转流程图的代码也没开源。不过我觉得他做的挺对的,农夫与蛇的故事见的太多了。所以我决定和他一样,让白嫖的人踩坑去吧,这里只做原理讲解,不提供源码内容。

相关文章:

processflow流程图多人协作预热

前言 在线上办公如火如荼的今天,多人协作功能是每个应用绕不开的门槛。processflow在线流程图(前身基于drawio二次开发)沉寂两年之久,经过长时间设计开发,调整,最终完成了多人协作的核心模块设计。废话不多…...

PCL点云处理之快速计算多个点到同一直线的距离(二百零五)

PCL点云处理之快速计算多个点到同一直线的距离(二百零五) 一、算法简介二、具体实现1.代码2.结果一、算法简介 点到直线的距离计算,是一种常用的算法,在点云处理中,经常遇到需要计算多个点云到同一条直线的距离计算需求,此时若是逐点计算将耗费大量的时间,熟悉点到直线…...

xxl-job 任务调度搭建及简单使用

xxl-job是开源架构,可以通过它实现调度中心和执行器。 git地址和 官网中进行了详细的技术说明。   xxl-job支持单机部署和集群式部署,在集群式部署中又可以实现调度中心集群式部署和执行器集群式部署。本文主要针对调度中心和执行器分离单机部署方式进…...

mysql数据库使用技巧整理

查看当前数据库已建立的client连接 > SHOW VARIABLES LIKE max_connections; -- 查看数据库允许的最大连接数,不是实时正在使用的连接数 > SHOW STATUS LIKE Threads_connected; -- 查看当前数据库client的连接数 > SHOW PROCESSLIST; -- 查看具体的连接...

车规微控制器的ECC机制及EMU外设

车规微控制器的ECC机制及EMU外设 文章目录 车规微控制器的ECC机制及EMU外设引言ECC的基本原理ECC RAM的访问方式ECC RAM的初始化SRAM ECC错误注入及EMU外设Flash ECC校验参考文献 引言 ECC是微控制器系统中,用于保障信息安全的常用机制,主要是避免存储设…...

Less的强大变量用法

less中的变量应用十分强大,可以灵活的应用到各种不同需求的场景。 一,属性值变量 声明:sass声明变量是用$符号,而less声明变量是用符号 作用域:也区分为全局变量和局部变量,如果引用的变量有定义局部变量&…...

【相机标定】opencv python 标定相机内参时不计算 k3 畸变参数

文章目录 1. 背景2. 完整的 opencv python 标定相机内参过程3. 选择是否计算畸变参数 k3 1. 背景 畸变参数 k3 通常用于描述径向畸变的更高阶效应,即在需要高精度的应用中可以用到,一般的应用中 k1, k2 足矣。 常见的应用中, orbslam3 中是否…...

html 标签简介

概述 标签的效果不重要,重要的是标签的语义。 文本标签 文本标签用于包裹:词汇、短语等。排版标签,比如div,p,h1等。排版标签更宏观(大段的文字),文本标签更微观(词汇、短语)。文…...

dos汇编总结

前言: 计组课本需要学习汇编,可惜自己看不太懂。这里发现一个学习方法交给大家。其实新手可能一些抽象表示难理解,这里我把我学习的疑问点以及思路记录一下。 要点: 这里我以题为例给大家分析 输出输入对应大写字母的小写字母 …...

四川玖璨电子商务有限公司:短视频有什么运营

根据短视频有什么运营,短视频的拍摄工具多种多样。无论是在手机上拍摄还是使用专业摄影设备,拍摄短视频的目的都是为了吸引观众的注意力和提升内容的质量。从小花费到高投入,在不断发展的短视频行业中,拍摄方法也得到了不断创新和…...

混合查询多家快递,快速掌握物流信息

在现代社会,快递服务已成为我们日常生活的重要组成部分。无论是购物还是文件传递,我们都需要快递服务的帮助。然而,不同的快递公司需要不同的查询方法,这无疑增加了我们的查询难度。因此,有没有一种方法可以让我们一次…...

独立站新手引流,谷歌SEO工具汇总

俗话说“工欲善其事,必先利其器”,做谷歌SEO也一样,要想做好并提升SEO效果,卖家就需要了解并利用好SEO工具。那我们今天就来盘点一下,常用的SEO工具有哪些吧~ 网站检测工具 1、PageSpeed Insights:这是谷…...

SpringMvc 与 Lombok 碰撞导致 JSON 反序列化失败

SpringMvc 与 Lombok 中 JSON 反序列化失败 错误复现_1 Data public class User{private Long id;private boolean isOk; }RequestMapping public R<User> getUser(RequestBody User user){return R.success(user); }// 前端传参 - {"id": 123456789,"i…...

怎么样显卡叠加,什么是NVIDIA 显卡 非公、公版、涡轮卡

1、显存叠加的问题&#xff0c;因为这个跟是否是深度学习无关&#xff1a; 先说一下显存叠加的问题&#xff0c;因为这个跟是否是深度学习无关&#xff1a;一台机器有多张显卡&#xff0c;显存不会叠加&#xff01;显卡里面包含了显存、cache、计算单元、通信等&#xff0c;每…...

CentOS安装Elasticsearch集群

前言 之前使用的ES集群是其他公司维护&#xff0c;没有机会安装&#xff0c;后来做其他项目&#xff0c;终于有机会安装ES集群&#xff0c;简单记录一下备用 一、安装jdk 安装jdk1.8就可以&#xff0c;可以参考另一篇文章&#xff0c;这里就不细说了 二、修改系统参数 如果在…...

计算机专业毕业生指南

在大四毕业时&#xff0c;完成计算机毕业设计需要一定的计划和组织。以下是一些建议&#xff0c;帮助你在三个月内快速完成毕业设计&#xff1a; 选择一个合适的主题&#xff1a; 选择一个你感兴趣的主题&#xff0c;这将激发你的热情&#xff0c;使你更有动力完成项目。 确保…...

Springboot集成Docker并将镜像推送linux服务器

案例使用springboot项目&#xff0c;在IDEA 中集成Docker生成镜像&#xff0c;并将镜像发布到linux服务器 具体步骤如下&#xff1a; 1、Centos7安装Docker 更新系统的软件包列表 sudo yum update安装Docker所需的软件包和依赖项&#xff1a; sudo yum install docker完成…...

数字孪生与GIS:智慧城市的未来之路

数字孪生和地理信息系统&#xff08;GIS&#xff09;是两个在现代科技中崭露头角的概念&#xff0c;它们的融合为智慧城市项目带来了革命性的机会。本文将解释数字孪生为何需要融合GIS&#xff0c;并以智慧城市项目为例进行说明。 数字孪生是一种虚拟模型&#xff0c;它精确地…...

nas汇编程序的调试排错方法

nas汇编程序的调试排错方法&#xff1a; 1、查找是哪一步错了 2、查看对应的*.lst文件&#xff0c;本例中是"asmhead.lst" 3、根据*.lst文件的[ERROR #002]提示查看源码&#xff0c;改错。 4、重新运行编译&#xff0c;OK 1、查找是哪一步错了&#xff1a; nask.ex…...

【网络安全带你练爬虫-100练】第21练:批量获取文件夹中文件名

目录 一、目标1&#xff1a;使用python爬取指定文件夹中的文件名 二、目标2&#xff1a;在文件夹指定目录打开命令行 一、目标1&#xff1a;使用python爬取指定文件夹中的文件名 方法一&#xff1a;使用os模块 将/path/to/folder替换为实际的文件夹路径。os.listdir()函数用…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL

ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...

结构化文件管理实战:实现目录自动创建与归类

手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题&#xff0c;进而引发后续程序异常。使用工具进行标准化操作&#xff0c;能有效降低出错概率。 需要快速整理大量文件的技术用户而言&#xff0c;这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB&#xff0c;…...