完善协同插件

This commit is contained in:
wanglin2
2023-10-04 15:39:45 +08:00
parent ccef5fc581
commit b95b6af1b1
2 changed files with 117 additions and 68 deletions

View File

@@ -7,33 +7,70 @@ class Cooperate {
constructor(opt) {
this.opt = opt
this.mindMap = opt.mindMap
// yjs文档
this.ydoc = new Y.Doc()
this.ymap = this.ydoc.getMap()
this.provider = new WebrtcProvider('demo-room', this.ydoc, {
signaling: ['ws://10.16.83.11:4444']
})
this.awareness = this.provider.awareness
this.currentData = null
this.userInfo = null
// 共享数据
this.ymap = null
// 连接提供者
this.provider = null
// 感知数据
this.awareness = null
this.currentAwarenessData = []
// 处理数据
if (this.mindMap.opt.data) {
this.currentData = this.transformTreeDataToObject(this.mindMap.opt.data)
Object.keys(this.currentData).forEach(uid => {
this.ymap.set(uid, this.currentData[uid])
})
}
// 当前的平级对象类型的思维导图数据
this.currentData = null
// 用户信息
this.userInfo = null
// 绑定事件
this.bindEvent()
// 处理实例化时传入的思维导图数据
if (this.mindMap.opt.data) {
this.initData(this.mindMap.opt.data)
}
}
// 初始化数据
initData(data) {
data = simpleDeepClone(data)
// 解绑原来的数据
if (this.ymap) {
this.ymap.unobserve(this.onObserve)
}
// 创建共享数据
this.ymap = this.ydoc.getMap()
// 思维导图树结构转平级对象结构
this.currentData = this.transformTreeDataToObject(data)
// 将思维导图数据添加到共享数据中
Object.keys(this.currentData).forEach(uid => {
this.ymap.set(uid, this.currentData[uid])
})
// 监听数据同步
this.onObserve = this.onObserve.bind(this)
this.ymap.observe(this.onObserve)
}
// 获取yjs doc实例
getDoc() {
return this.ydoc
}
// 设置连接提供者
setProvider(provider, webrtcProviderConfig = {}) {
const { roomName, signalingList, ...otherConfig } = webrtcProviderConfig
this.provider =
provider ||
new WebrtcProvider(roomName, this.ydoc, {
signaling: signalingList,
...otherConfig
})
this.awareness = this.provider.awareness
// 监听状态同步事件
this.onAwareness = this.onAwareness.bind(this)
this.awareness.on('change', this.onAwareness)
}
// 绑定事件
bindEvent() {
// 监听数据同步
this.onObserve = this.onObserve.bind(this)
this.ymap.observe(this.onObserve)
// 监听思维导图改变
this.onDataChange = this.onDataChange.bind(this)
this.mindMap.on('data_change', this.onDataChange)
@@ -42,31 +79,33 @@ class Cooperate {
this.onNodeActive = this.onNodeActive.bind(this)
this.mindMap.on('node_active', this.onNodeActive)
// 监听状态同步事件
this.onAwareness = this.onAwareness.bind(this)
this.awareness.on('change', this.onAwareness)
// 监听设置思维导图数据事件
this.initData = this.initData.bind(this)
this.mindMap.on('set_data', this.initData)
}
// 解绑事件
unBindEvent() {
this.ymap.unobserve(this.onObserve)
if (this.ymap) {
this.ymap.unobserve(this.onObserve)
}
this.mindMap.off('data_change', this.onDataChange)
this.mindMap.off('node_active', this.onNodeActive)
this.mindMap.off('set_data', this.initData)
this.ydoc.destroy()
}
// 数据同步时的处理,更新当前思维导图
onObserve(event) {
const data = event.target.toJSON()
// 如果数据没有改变直接返回
if (isSameObject(data, this.currentData)) return
this.currentData = data
// 平级对象转树结构
const res = this.transformObjectToTreeData(data)
if (!res) return
if (this.mindMap.richText) {
this.mindMap.renderer.renderTree =
this.mindMap.richText.handleSetData(res)
} else {
this.mindMap.renderer.renderTree = res
}
// 更新思维导图画布
this.mindMap.renderer.setData(res)
this.mindMap.render()
this.mindMap.command.addHistory()
}
@@ -77,16 +116,37 @@ class Cooperate {
this.updateChanges(res)
}
// 节点激活状态改变后触发状态显示同步
// 找出更新点
updateChanges(data) {
const oldData = this.currentData
this.currentData = data
this.ydoc.transact(() => {
// 找出新增的或修改的
Object.keys(data).forEach(uid => {
// 新增的或已经存在的,如果数据发生了改变
if (!oldData[uid] || !isSameObject(oldData[uid], data[uid])) {
this.ymap.set(uid, data[uid])
}
})
// 找出删除的
Object.keys(oldData).forEach(uid => {
if (!data[uid]) {
this.ymap.delete(uid)
}
})
})
}
// 节点激活状态改变后触发感知数据同步
onNodeActive(node, nodeList) {
if (this.userInfo) {
this.awareness.setLocalStateField(this.userInfo.name, {
// 用户信息
userInfo: {
// 用户信息
...this.userInfo
},
// 当前激活的节点id列表
nodeIdList: nodeList.map(item => {
// 当前激活的节点id列表
return item.uid
})
})
@@ -112,7 +172,7 @@ class Cooperate {
this.userInfo = userInfo || null
}
// 监听状态同步事件
// 监听感知数据同步事件
onAwareness() {
const walk = (list, callback) => {
list.forEach(value => {
@@ -129,11 +189,11 @@ class Cooperate {
})
})
}
// 清除之前的状态
// 清除之前的数据
walk(this.currentAwarenessData, (node, userInfo) => {
node.removeUser(userInfo)
})
// 设置当前状态
// 设置当前数据
const data = Array.from(this.awareness.getStates().values())
this.currentAwarenessData = data
walk(data, (node, userInfo) => {
@@ -246,27 +306,6 @@ class Cooperate {
return res
}
// 找出更新点
updateChanges(data) {
const oldData = this.currentData
this.currentData = data
this.ydoc.transact(() => {
// 找出新增的或修改的
Object.keys(data).forEach(uid => {
// 新增的或已经存在的,如果数据发生了改变
if (!oldData[uid] || !isSameObject(oldData[uid], data[uid])) {
this.ymap.set(uid, data[uid])
}
})
// 找出删除的
Object.keys(oldData).forEach(uid => {
if (!data[uid]) {
this.ymap.delete(uid)
}
})
})
}
// 插件被移除前做的事情
beforePluginRemove() {
this.unBindEvent()

View File

@@ -96,7 +96,7 @@ MindMap.usePlugin(MiniMap)
.usePlugin(Painter)
.usePlugin(ScrollbarPlugin)
.usePlugin(Formula)
.usePlugin(Cooperate)
// .usePlugin(Cooperate)// 协同插件
// 注册自定义主题
customThemeList.forEach(item => {
@@ -389,16 +389,8 @@ export default {
if (hasFileURL) {
this.$bus.$emit('handle_file_url')
}
if (this.$route.query.userName) {
this.mindMap.cooperate.setUserInfo({
id: Math.random(),
name: this.$route.query.userName,
color: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#909399'][
Math.floor(Math.random() * 5)
],
avatar: Math.random() > 0.5 ? 'https://img0.baidu.com/it/u=4270674549,2416627993&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1696006800&t=4d32871d14a7224a4591d0c3c7a97311' : ''
})
}
// 协同测试
this.cooperateTest()
},
// url中是否存在要打开的文件
@@ -591,6 +583,24 @@ export default {
// 动态删除指定节点
// this.mindMap.execCommand('REMOVE_NODE', this.mindMap.renderer.root.children[0])
}, 5000)
},
// 协同测试
cooperateTest() {
if (this.mindMap.cooperate && this.$route.query.userName) {
this.mindMap.cooperate.setProvider(null, {
roomName: 'demo-room',
signalingList: ['ws://192.168.3.125:4444']
})
this.mindMap.cooperate.setUserInfo({
id: Math.random(),
name: this.$route.query.userName,
color: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#909399'][
Math.floor(Math.random() * 5)
],
avatar: Math.random() > 0.5 ? 'https://img0.baidu.com/it/u=4270674549,2416627993&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1696006800&t=4d32871d14a7224a4591d0c3c7a97311' : ''
})
}
}
}
}