Feat:新增节点数据更新明细事件

This commit is contained in:
街角小林 2024-01-04 09:39:44 +08:00
parent 1ad1538699
commit 541606b2eb
4 changed files with 182 additions and 118 deletions

View File

@ -1,4 +1,10 @@
import { copyRenderTree, simpleDeepClone, throttle } from '../../utils'
import {
copyRenderTree,
simpleDeepClone,
throttle,
isSameObject,
transformTreeDataToObject
} from '../../utils'
// 命令类
class Command {
@ -84,15 +90,14 @@ class Command {
if (this.mindMap.opt.readonly) {
return
}
let data = this.getCopyData()
const lastData =
this.history.length > 0 ? this.history[this.history.length - 1] : null
const data = this.getCopyData()
// 此次数据和上次一样则不重复添加
if (
this.history.length > 0 &&
JSON.stringify(this.history[this.history.length - 1]) ===
JSON.stringify(data)
) {
if (lastData && JSON.stringify(lastData) === JSON.stringify(data)) {
return
}
this.emitDataUpdatesEvent(lastData, data)
// 删除当前历史指针后面的数据
this.history = this.history.slice(0, this.activeHistoryIndex + 1)
this.history.push(simpleDeepClone(data))
@ -115,13 +120,15 @@ class Command {
return
}
if (this.activeHistoryIndex - step >= 0) {
const lastData = this.history[this.activeHistoryIndex]
this.activeHistoryIndex -= step
this.mindMap.emit(
'back_forward',
this.activeHistoryIndex,
this.history.length
)
let data = simpleDeepClone(this.history[this.activeHistoryIndex])
const data = simpleDeepClone(this.history[this.activeHistoryIndex])
this.emitDataUpdatesEvent(lastData, data)
this.mindMap.emit('data_change', data)
return data
}
@ -134,13 +141,15 @@ class Command {
}
let len = this.history.length
if (this.activeHistoryIndex + step <= len - 1) {
const lastData = this.history[this.activeHistoryIndex]
this.activeHistoryIndex += step
this.mindMap.emit(
'back_forward',
this.activeHistoryIndex,
this.history.length
)
let data = simpleDeepClone(this.history[this.activeHistoryIndex])
const data = simpleDeepClone(this.history[this.activeHistoryIndex])
this.emitDataUpdatesEvent(lastData, data)
this.mindMap.emit('data_change', data)
return data
}
@ -165,6 +174,53 @@ class Command {
walk(data)
return data
}
// 派发思维导图更新明细事件
emitDataUpdatesEvent(lastData, data) {
// 如果data_change_detail没有监听者那么不进行计算节省性能
const eventName = 'data_change_detail'
const count = this.mindMap.event.listenerCount(eventName)
if (count > 0 && lastData && data) {
const lastDataObj = simpleDeepClone(transformTreeDataToObject(lastData))
const dataObj = simpleDeepClone(transformTreeDataToObject(data))
const res = []
const walkReplace = (root, obj) => {
if (root.children && root.children.length > 0) {
root.children.forEach((childUid, index) => {
root.children[index] = obj[childUid]
walkReplace(root.children[index], obj)
})
}
return root
}
// 找出新增的或修改的
Object.keys(dataObj).forEach(uid => {
// 新增的或已经存在的,如果数据发生了改变
if (!lastDataObj[uid]) {
res.push({
action: 'create',
data: walkReplace(dataObj[uid], dataObj)
})
} else if (!isSameObject(lastDataObj[uid], dataObj[uid])) {
res.push({
action: 'update',
oldData: walkReplace(lastDataObj[uid], lastDataObj),
data: walkReplace(dataObj[uid], dataObj)
})
}
})
// 找出删除的
Object.keys(lastDataObj).forEach(uid => {
if (!dataObj[uid]) {
res.push({
action: 'delete',
data: walkReplace(lastDataObj[uid], lastDataObj)
})
}
})
this.mindMap.emit(eventName, res)
}
}
}
export default Command

View File

@ -1,4 +1,5 @@
import { keyMap } from './keyMap'
// 快捷按键、命令处理类
export default class KeyCommand {
// 构造函数

View File

@ -1,6 +1,13 @@
import * as Y from 'yjs'
import { WebrtcProvider } from 'y-webrtc'
import { isSameObject, simpleDeepClone, getType, isUndef } from '../utils/index'
import {
isSameObject,
simpleDeepClone,
getType,
isUndef,
transformTreeDataToObject,
transformObjectToTreeData
} from '../utils/index'
// 协同插件
class Cooperate {
@ -39,7 +46,7 @@ class Cooperate {
// 创建共享数据
this.ymap = this.ydoc.getMap()
// 思维导图树结构转平级对象结构
this.currentData = this.transformTreeDataToObject(data)
this.currentData = transformTreeDataToObject(data)
// 将思维导图数据添加到共享数据中
Object.keys(this.currentData).forEach(uid => {
this.ymap.set(uid, this.currentData[uid])
@ -108,7 +115,7 @@ class Cooperate {
if (isSameObject(data, this.currentData)) return
this.currentData = data
// 平级对象转树结构
const res = this.transformObjectToTreeData(data)
const res = transformObjectToTreeData(data)
if (!res) return
// 更新思维导图画布
this.mindMap.renderer.setData(res)
@ -118,7 +125,7 @@ class Cooperate {
// 当前思维导图改变后的处理,触发同步
onDataChange(data) {
const res = this.transformTreeDataToObject(data)
const res = transformTreeDataToObject(data)
this.updateChanges(res)
}
@ -224,111 +231,6 @@ class Cooperate {
})
}
// 将树结构转平级对象
/*
{
data: {
uid: 'xxx'
},
children: [
{
data: {
uid: 'xxx'
},
children: []
}
]
}
转为
{
uid: {
children: [uid1, uid2],
data: {}
}
}
*/
transformTreeDataToObject(data) {
const res = {}
const walk = (root, parent) => {
const uid = root.data.uid
if (parent) {
parent.children.push(uid)
}
res[uid] = {
isRoot: !parent,
data: {
...root.data
},
children: []
}
if (root.children && root.children.length > 0) {
root.children.forEach(item => {
walk(item, res[uid])
})
}
}
walk(data, null)
return res
}
// 找到父节点的uid
findParentUid(data, targetUid) {
const uids = Object.keys(data)
let res = ''
uids.forEach(uid => {
const children = data[uid].children
const isParent =
children.findIndex(childUid => {
return childUid === targetUid
}) !== -1
if (isParent) {
res = uid
}
})
return res
}
// 将平级对象转树结构
transformObjectToTreeData(data) {
const uids = Object.keys(data)
if (uids.length <= 0) return null
const rootKey = uids.find(uid => {
return data[uid].isRoot
})
if (!rootKey || !data[rootKey]) return null
// 根节点
const res = {
data: simpleDeepClone(data[rootKey].data),
children: []
}
const map = {}
map[rootKey] = res
uids.forEach(uid => {
const parentUid = this.findParentUid(data, uid)
const cur = data[uid]
const node = map[uid] || {
data: simpleDeepClone(cur.data),
children: []
}
if (!map[uid]) {
map[uid] = node
}
if (parentUid) {
const index = data[parentUid].children.findIndex(item => {
return item === uid
})
if (!map[parentUid]) {
map[parentUid] = {
data: simpleDeepClone(data[parentUid].data),
children: []
}
}
map[parentUid].children[index] = node
}
})
return res
}
// 插件被移除前做的事情
beforePluginRemove() {
this.unBindEvent()

View File

@ -1074,3 +1074,108 @@ export const handleInputPasteText = (e, text) => {
selection.getRangeAt(0).insertNode(node)
selection.collapseToEnd()
}
// 将思维导图树结构转平级对象
/*
{
data: {
uid: 'xxx'
},
children: [
{
data: {
uid: 'xxx'
},
children: []
}
]
}
转为
{
uid: {
children: [uid1, uid2],
data: {}
}
}
*/
export const transformTreeDataToObject = data => {
const res = {}
const walk = (root, parent) => {
const uid = root.data.uid
if (parent) {
parent.children.push(uid)
}
res[uid] = {
isRoot: !parent,
data: {
...root.data
},
children: []
}
if (root.children && root.children.length > 0) {
root.children.forEach(item => {
walk(item, res[uid])
})
}
}
walk(data, null)
return res
}
// 将平级对象转树结构
// transformTreeDataToObject方法的反向操作
// 找到父节点的uid
const _findParentUid = (data, targetUid) => {
const uids = Object.keys(data)
let res = ''
uids.forEach(uid => {
const children = data[uid].children
const isParent =
children.findIndex(childUid => {
return childUid === targetUid
}) !== -1
if (isParent) {
res = uid
}
})
return res
}
export const transformObjectToTreeData = data => {
const uids = Object.keys(data)
if (uids.length <= 0) return null
const rootKey = uids.find(uid => {
return data[uid].isRoot
})
if (!rootKey || !data[rootKey]) return null
// 根节点
const res = {
data: simpleDeepClone(data[rootKey].data),
children: []
}
const map = {}
map[rootKey] = res
uids.forEach(uid => {
const parentUid = _findParentUid(data, uid)
const cur = data[uid]
const node = map[uid] || {
data: simpleDeepClone(cur.data),
children: []
}
if (!map[uid]) {
map[uid] = node
}
if (parentUid) {
const index = data[parentUid].children.findIndex(item => {
return item === uid
})
if (!map[parentUid]) {
map[parentUid] = {
data: simpleDeepClone(data[parentUid].data),
children: []
}
}
map[parentUid].children[index] = node
}
})
return res
}