Commit 2a545e24 by junxiang

Initial commit

parents
/node_modules/
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/plan.iml" filepath="$PROJECT_DIR$/.idea/plan.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PrettierConfiguration">
<option name="myConfigurationMode" value="MANUAL" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
{
"name": "plan",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"prettier": "^3.3.3",
"typescript": "^5.6.3"
}
}
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
devDependencies:
prettier:
specifier: ^3.3.3
version: 3.3.3
typescript:
specifier: ^5.6.3
version: 5.6.3
packages:
prettier@3.3.3:
resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==}
engines: {node: '>=14'}
hasBin: true
typescript@5.6.3:
resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
engines: {node: '>=14.17'}
hasBin: true
snapshots:
prettier@3.3.3: {}
typescript@5.6.3: {}
This diff is collapsed. Click to expand it.
import { AlignEnums, BoardElementType } from "./enums";
export interface IBoardState {
version: string; //总版本号
id: string;
creatAt: number;
creator: string; //创建者ID
wrapper: {
scale: number; //缩放
};
cover: string; //封面
elements: ICanvasElement[];//自定义节点列表
}
export interface ICanvasElement extends IRectangle {
creator: string; //创作者id
creatAt: number; //创作id
version: string; //版本,用于比对
elType: BoardElementType; //类型
id: string;
zIndex: number; //层级
lock: boolean; //是否锁定
edit: false; //是否在编辑
rotate: boolean; //旋转
fontSize: number;
textAlign: AlignEnums;
verticalAlign: AlignEnums;
paths?: IVec2[]; //轨迹独有的属性
points?: IVec2[]; //线独有的属性
lineType: string; //线独有属性
fillStyle: IStyleLine;
textFillStyle: IStyleLine;
ext: Dictionary<any>;
}
export interface ICanvasElementChangePayload{
}
export enum AlignEnums {
Left='left',
Right='right',
Center='center'
}
export enum BoardElementType {
Note='Note',//笔记
Text='Text',//文本
Image='Image',//图片
Mind='Mind',//思维导图
Ligature='Ligature',//线条
Shape='Shape',//矩形
//more
}
/**
* key-val键值对
*/
interface Dictionary<T> {
[key: string]: T;
}
/**
* 元素尺寸
*/
interface IRectangle {
x: number;
y: number;
width: number;
height: number;
}
/**
* RGB颜色
*/
interface IRGBColor {
r: number;
g: number;
b: number;
}
/**
* RGBA颜色
*/
interface IRGBAColor {
r: number;
a: number;
g: number;
b: number;
}
/**
* 平面直角坐标 or 二维向量
*/
interface IVec2 {
x: number;
y: number;
}
/**
* 三维坐标 or 三维向量
*/
interface IVec3 {
x: number;
y: number;
z: number;
}
/**
* 截取区域
*/
interface ICrop {
top: number;
bottom: number;
left: number;
right: number;
}
type IStyleLine = string
# 技术路线概要
# 技术路线概要
## 协作白板
### 主要的功能列表
#### 画布管理
##### 新增
##### 查看
##### 删除
##### 查看
#### 权限管理
##### 开通权限
##### 修改/删除权限
#### 协作
#### 新写作者加入
```
1.前端打开一个文档时,发送请求给服务端,服务端检查协作列表中是否有当前文档。
2.如果有则把当前用户加入此文档修改者列表;如果没有就把当前文档加入协作列表,同时把当前用户ID写入其中。
3.服务端通过长链接给文档列表中的所有其他用户推送消息,告知大家有用户加入协作。
```
#### 数据提交
```
1.前端把修改数据发送给服务端
2.服务端暂存多个用户的操作,并根据OT算法把用户操作合并,最后和数据库存储的文档内容合并
3.把合并完的文档内容保存到数据库中
4.服务端根据文档ID,读取协作列表中的用户,给所有用户发送合并结果
5.客户端把合并结果与本地文档内容合并
```
##### 合并冲突
##### 协作通知
##### 离线暂存
### 数据结构化存储/解析
```
通过json存取
```
### 数据建模
```
参见类型描述文档./types/board.ts
```
### 导出
```
//导出成pdf
canvas2pdf
```
### 进阶
如果对传输文件大小或者性能有更高要求,可以基于Protobuf协议来替换json
## 多人协作编辑器
#### 文稿管理
##### 新增
##### 查看
##### 删除
##### 查看
#### 权限管理
##### 权限分类
管理权限、编辑权限、查看权限、无权限
##### 开通权限
##### 修改/删除权限
#### 协作
#### 新写作者加入
```
1.权限校验,如有权限则拉取文档内容。
2.ws通知其他正在修改同一个文稿的人,有新的协作者加入
```
#### 数据提交
```
1.前端把修改数据发送给服务端
1.1 将变更请求变为阻塞的同步请求
1.2 前端每次请求都生成连续递增的ID,服务端判断如果递增ID不连续了,就短暂的等待
1.3 服务端队列接受,按照连续递增的ID消费。
```
##### 合并冲突
```
1.服务端OT算法合并
2.把合并完的文档内容保存到数据库中,并生成修改记录
3.通过ws给所有的协作者同步最新结果
4.客户端merge云端和本地内容,渲染
```
##### 协作通知
ws
##### 离线暂存
本地通过队列暂存请求失败的数据包,每30S重试一次最小序号的包,如果成功提交则进行下一个
#### 备注
OT算法https://zhuanlan.zhihu.com/p/634121875
## 严肃游戏
## PPT
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment