Feat:新增节点数据更新明细事件
This commit is contained in:
parent
1ad1538699
commit
541606b2eb
@ -1,4 +1,10 @@
|
|||||||
import { copyRenderTree, simpleDeepClone, throttle } from '../../utils'
|
import {
|
||||||
|
copyRenderTree,
|
||||||
|
simpleDeepClone,
|
||||||
|
throttle,
|
||||||
|
isSameObject,
|
||||||
|
transformTreeDataToObject
|
||||||
|
} from '../../utils'
|
||||||
|
|
||||||
// 命令类
|
// 命令类
|
||||||
class Command {
|
class Command {
|
||||||
@ -84,15 +90,14 @@ class Command {
|
|||||||
if (this.mindMap.opt.readonly) {
|
if (this.mindMap.opt.readonly) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let data = this.getCopyData()
|
const lastData =
|
||||||
|
this.history.length > 0 ? this.history[this.history.length - 1] : null
|
||||||
|
const data = this.getCopyData()
|
||||||
// 此次数据和上次一样则不重复添加
|
// 此次数据和上次一样则不重复添加
|
||||||
if (
|
if (lastData && JSON.stringify(lastData) === JSON.stringify(data)) {
|
||||||
this.history.length > 0 &&
|
|
||||||
JSON.stringify(this.history[this.history.length - 1]) ===
|
|
||||||
JSON.stringify(data)
|
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
this.emitDataUpdatesEvent(lastData, data)
|
||||||
// 删除当前历史指针后面的数据
|
// 删除当前历史指针后面的数据
|
||||||
this.history = this.history.slice(0, this.activeHistoryIndex + 1)
|
this.history = this.history.slice(0, this.activeHistoryIndex + 1)
|
||||||
this.history.push(simpleDeepClone(data))
|
this.history.push(simpleDeepClone(data))
|
||||||
@ -115,13 +120,15 @@ class Command {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.activeHistoryIndex - step >= 0) {
|
if (this.activeHistoryIndex - step >= 0) {
|
||||||
|
const lastData = this.history[this.activeHistoryIndex]
|
||||||
this.activeHistoryIndex -= step
|
this.activeHistoryIndex -= step
|
||||||
this.mindMap.emit(
|
this.mindMap.emit(
|
||||||
'back_forward',
|
'back_forward',
|
||||||
this.activeHistoryIndex,
|
this.activeHistoryIndex,
|
||||||
this.history.length
|
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)
|
this.mindMap.emit('data_change', data)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
@ -134,13 +141,15 @@ class Command {
|
|||||||
}
|
}
|
||||||
let len = this.history.length
|
let len = this.history.length
|
||||||
if (this.activeHistoryIndex + step <= len - 1) {
|
if (this.activeHistoryIndex + step <= len - 1) {
|
||||||
|
const lastData = this.history[this.activeHistoryIndex]
|
||||||
this.activeHistoryIndex += step
|
this.activeHistoryIndex += step
|
||||||
this.mindMap.emit(
|
this.mindMap.emit(
|
||||||
'back_forward',
|
'back_forward',
|
||||||
this.activeHistoryIndex,
|
this.activeHistoryIndex,
|
||||||
this.history.length
|
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)
|
this.mindMap.emit('data_change', data)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
@ -165,6 +174,53 @@ class Command {
|
|||||||
walk(data)
|
walk(data)
|
||||||
return 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
|
export default Command
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { keyMap } from './keyMap'
|
import { keyMap } from './keyMap'
|
||||||
|
|
||||||
// 快捷按键、命令处理类
|
// 快捷按键、命令处理类
|
||||||
export default class KeyCommand {
|
export default class KeyCommand {
|
||||||
// 构造函数
|
// 构造函数
|
||||||
|
|||||||
@ -1,6 +1,13 @@
|
|||||||
import * as Y from 'yjs'
|
import * as Y from 'yjs'
|
||||||
import { WebrtcProvider } from 'y-webrtc'
|
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 {
|
class Cooperate {
|
||||||
@ -39,7 +46,7 @@ class Cooperate {
|
|||||||
// 创建共享数据
|
// 创建共享数据
|
||||||
this.ymap = this.ydoc.getMap()
|
this.ymap = this.ydoc.getMap()
|
||||||
// 思维导图树结构转平级对象结构
|
// 思维导图树结构转平级对象结构
|
||||||
this.currentData = this.transformTreeDataToObject(data)
|
this.currentData = transformTreeDataToObject(data)
|
||||||
// 将思维导图数据添加到共享数据中
|
// 将思维导图数据添加到共享数据中
|
||||||
Object.keys(this.currentData).forEach(uid => {
|
Object.keys(this.currentData).forEach(uid => {
|
||||||
this.ymap.set(uid, this.currentData[uid])
|
this.ymap.set(uid, this.currentData[uid])
|
||||||
@ -108,7 +115,7 @@ class Cooperate {
|
|||||||
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 = transformObjectToTreeData(data)
|
||||||
if (!res) return
|
if (!res) return
|
||||||
// 更新思维导图画布
|
// 更新思维导图画布
|
||||||
this.mindMap.renderer.setData(res)
|
this.mindMap.renderer.setData(res)
|
||||||
@ -118,7 +125,7 @@ class Cooperate {
|
|||||||
|
|
||||||
// 当前思维导图改变后的处理,触发同步
|
// 当前思维导图改变后的处理,触发同步
|
||||||
onDataChange(data) {
|
onDataChange(data) {
|
||||||
const res = this.transformTreeDataToObject(data)
|
const res = transformTreeDataToObject(data)
|
||||||
this.updateChanges(res)
|
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() {
|
beforePluginRemove() {
|
||||||
this.unBindEvent()
|
this.unBindEvent()
|
||||||
|
|||||||
@ -1074,3 +1074,108 @@ export const handleInputPasteText = (e, text) => {
|
|||||||
selection.getRangeAt(0).insertNode(node)
|
selection.getRangeAt(0).insertNode(node)
|
||||||
selection.collapseToEnd()
|
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
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user