完善协同插件

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) { constructor(opt) {
this.opt = opt this.opt = opt
this.mindMap = opt.mindMap this.mindMap = opt.mindMap
// yjs文档
this.ydoc = new Y.Doc() this.ydoc = new Y.Doc()
this.ymap = this.ydoc.getMap() // 共享数据
this.provider = new WebrtcProvider('demo-room', this.ydoc, { this.ymap = null
signaling: ['ws://10.16.83.11:4444'] // 连接提供者
}) this.provider = null
this.awareness = this.provider.awareness // 感知数据
this.currentData = null this.awareness = null
this.userInfo = null
this.currentAwarenessData = [] this.currentAwarenessData = []
// 当前的平级对象类型的思维导图数据
// 处理数据 this.currentData = null
if (this.mindMap.opt.data) { // 用户信息
this.currentData = this.transformTreeDataToObject(this.mindMap.opt.data) this.userInfo = null
Object.keys(this.currentData).forEach(uid => { // 绑定事件
this.ymap.set(uid, this.currentData[uid])
})
}
this.bindEvent() 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() { bindEvent() {
// 监听数据同步
this.onObserve = this.onObserve.bind(this)
this.ymap.observe(this.onObserve)
// 监听思维导图改变 // 监听思维导图改变
this.onDataChange = this.onDataChange.bind(this) this.onDataChange = this.onDataChange.bind(this)
this.mindMap.on('data_change', this.onDataChange) this.mindMap.on('data_change', this.onDataChange)
@ -42,31 +79,33 @@ class Cooperate {
this.onNodeActive = this.onNodeActive.bind(this) this.onNodeActive = this.onNodeActive.bind(this)
this.mindMap.on('node_active', this.onNodeActive) this.mindMap.on('node_active', this.onNodeActive)
// 监听状态同步事件 // 监听设置思维导图数据事件
this.onAwareness = this.onAwareness.bind(this) this.initData = this.initData.bind(this)
this.awareness.on('change', this.onAwareness) this.mindMap.on('set_data', this.initData)
} }
// 解绑事件 // 解绑事件
unBindEvent() { unBindEvent() {
this.ymap.unobserve(this.onObserve) if (this.ymap) {
this.ymap.unobserve(this.onObserve)
}
this.mindMap.off('data_change', this.onDataChange) this.mindMap.off('data_change', this.onDataChange)
this.mindMap.off('node_active', this.onNodeActive)
this.mindMap.off('set_data', this.initData)
this.ydoc.destroy() this.ydoc.destroy()
} }
// 数据同步时的处理,更新当前思维导图 // 数据同步时的处理,更新当前思维导图
onObserve(event) { onObserve(event) {
const data = event.target.toJSON() const data = event.target.toJSON()
// 如果数据没有改变直接返回
if (isSameObject(data, this.currentData)) return if (isSameObject(data, this.currentData)) return
this.currentData = data this.currentData = data
// 平级对象转树结构
const res = this.transformObjectToTreeData(data) const res = this.transformObjectToTreeData(data)
if (!res) return if (!res) return
if (this.mindMap.richText) { // 更新思维导图画布
this.mindMap.renderer.renderTree = this.mindMap.renderer.setData(res)
this.mindMap.richText.handleSetData(res)
} else {
this.mindMap.renderer.renderTree = res
}
this.mindMap.render() this.mindMap.render()
this.mindMap.command.addHistory() this.mindMap.command.addHistory()
} }
@ -77,16 +116,37 @@ class Cooperate {
this.updateChanges(res) 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) { onNodeActive(node, nodeList) {
if (this.userInfo) { if (this.userInfo) {
this.awareness.setLocalStateField(this.userInfo.name, { this.awareness.setLocalStateField(this.userInfo.name, {
// 用户信息
userInfo: { userInfo: {
// 用户信息
...this.userInfo ...this.userInfo
}, },
// 当前激活的节点id列表
nodeIdList: nodeList.map(item => { nodeIdList: nodeList.map(item => {
// 当前激活的节点id列表
return item.uid return item.uid
}) })
}) })
@ -112,7 +172,7 @@ class Cooperate {
this.userInfo = userInfo || null this.userInfo = userInfo || null
} }
// 监听状态同步事件 // 监听感知数据同步事件
onAwareness() { onAwareness() {
const walk = (list, callback) => { const walk = (list, callback) => {
list.forEach(value => { list.forEach(value => {
@ -129,11 +189,11 @@ class Cooperate {
}) })
}) })
} }
// 清除之前的状态 // 清除之前的数据
walk(this.currentAwarenessData, (node, userInfo) => { walk(this.currentAwarenessData, (node, userInfo) => {
node.removeUser(userInfo) node.removeUser(userInfo)
}) })
// 设置当前状态 // 设置当前数据
const data = Array.from(this.awareness.getStates().values()) const data = Array.from(this.awareness.getStates().values())
this.currentAwarenessData = data this.currentAwarenessData = data
walk(data, (node, userInfo) => { walk(data, (node, userInfo) => {
@ -246,27 +306,6 @@ class Cooperate {
return res 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() { beforePluginRemove() {
this.unBindEvent() this.unBindEvent()

View File

@ -96,7 +96,7 @@ MindMap.usePlugin(MiniMap)
.usePlugin(Painter) .usePlugin(Painter)
.usePlugin(ScrollbarPlugin) .usePlugin(ScrollbarPlugin)
.usePlugin(Formula) .usePlugin(Formula)
.usePlugin(Cooperate) // .usePlugin(Cooperate)//
// //
customThemeList.forEach(item => { customThemeList.forEach(item => {
@ -389,16 +389,8 @@ export default {
if (hasFileURL) { if (hasFileURL) {
this.$bus.$emit('handle_file_url') this.$bus.$emit('handle_file_url')
} }
if (this.$route.query.userName) { //
this.mindMap.cooperate.setUserInfo({ this.cooperateTest()
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' : ''
})
}
}, },
// url // url
@ -591,6 +583,24 @@ export default {
// //
// this.mindMap.execCommand('REMOVE_NODE', this.mindMap.renderer.root.children[0]) // this.mindMap.execCommand('REMOVE_NODE', this.mindMap.renderer.root.children[0])
}, 5000) }, 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' : ''
})
}
} }
} }
} }