|
|
|
@ -4,20 +4,36 @@ import type EntityManager from './EntityManager' |
|
|
|
import { markRaw, reactive, ref } from 'vue' |
|
|
|
import type Viewport from '@/core/engine/Viewport.ts' |
|
|
|
|
|
|
|
// 差异类型定义
|
|
|
|
interface DataDiff { |
|
|
|
added: ItemJson[] |
|
|
|
removed: string[] |
|
|
|
updated: ItemJson[] |
|
|
|
} |
|
|
|
|
|
|
|
// 历史记录项
|
|
|
|
interface HistoryStep { |
|
|
|
diff: DataDiff |
|
|
|
snapshot: Map<string, ItemJson> |
|
|
|
timestamp: number |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 一种管理 地图数据状态的管理器, 他能够对数据进行增删改查,并且能够进行撤销、重做等操作 |
|
|
|
* 数据状态管理器 |
|
|
|
* 他能够对数据进行载入, 保存草稿, 载入草稿, 数据增删改查,撤销、重做等操作 |
|
|
|
* 最终他会将数据的变化同步到 EntityManager 中 |
|
|
|
* 主要功能包括: |
|
|
|
* 1. 管理场景数据的读取、保存, 以及临时保存、临时读取等功能 |
|
|
|
* 2. 管理撤销、重做功能 |
|
|
|
* 3. 各种 Interaction 交互控制组件通过如下步骤修改数据 |
|
|
|
* 3. 交互控制组件通过如下步骤修改数据 |
|
|
|
* - 1. 调用 beginStateUpdate 开始修改数据 |
|
|
|
* - 2. 直接修改 vdata 数据 |
|
|
|
* - 3. 调用 endStateUpdate 完成数据修改 |
|
|
|
* 4. 内部如果进行了撤销、还原等操作,会通过 syncDataState() 方法将 vdata 数据与 viewport 进行同步 |
|
|
|
* 5. syncDataState 方法会对比 vdata 与 viewport |
|
|
|
* - 分别进行添加、删除、更新等操作 |
|
|
|
* 6. 注意,如果正在读取中,需要设置 isLoading = true,外部需要等待加载完成后再进行操作 |
|
|
|
* 状态管理器,管理内部数据结构的读取、保存、临时保存、临时读取、撤销、重做等功能 |
|
|
|
* 当数据结构发生变化时,只对发生变化的对象进行更新 |
|
|
|
* 4. 内部如果进行了撤销、还原等操作,会通过 syncDataState() 方法将 vdata 数据与 EntityManager 进行同步 |
|
|
|
* 5. 注意,如果正在读取中,需要设置 isLoading = true,外部需要等待加载完成后再进行操作 |
|
|
|
* |
|
|
|
* 主要难点: |
|
|
|
* - 单张地图数据量可能超过 10000 个对象, 需要高效的管理数据状态 |
|
|
|
* |
|
|
|
* // 修改坐标点
|
|
|
|
* stateManager.beginStateUpdate();stateManager.vdata.items[1].tf[0] = [-10, 0, 4];stateManager.endStateUpdate(); |
|
|
|
@ -102,7 +118,6 @@ export default class StateManager { |
|
|
|
* 开始用户操作(创建数据快照) |
|
|
|
*/ |
|
|
|
beginStateUpdate() { |
|
|
|
// 创建当前状态快照(非深拷贝)
|
|
|
|
this.lastSnapshot = new Map( |
|
|
|
this.vdata.items.map(item => [item.id, _.cloneDeep(item)]) |
|
|
|
) |
|
|
|
@ -113,7 +128,6 @@ export default class StateManager { |
|
|
|
* 结束用户操作(计算差异并保存) |
|
|
|
*/ |
|
|
|
endStateUpdate() { |
|
|
|
debugger |
|
|
|
this.calculateDiff() |
|
|
|
this.saveStep() |
|
|
|
this.syncDataState() |
|
|
|
@ -172,6 +186,7 @@ export default class StateManager { |
|
|
|
const nextIndex = (this.historyIndex + 1) % this.maxHistorySteps |
|
|
|
this.historySteps[nextIndex] = { |
|
|
|
diff: _.cloneDeep(this.changeTracker), |
|
|
|
snapshot: _.cloneDeep(this.lastSnapshot), |
|
|
|
timestamp: Date.now() |
|
|
|
} |
|
|
|
|
|
|
|
@ -267,31 +282,9 @@ export default class StateManager { |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 保存数据到外部 |
|
|
|
*/ |
|
|
|
async save(): Promise<Object> { |
|
|
|
return _.cloneDeep(this.vdata) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 强制保存到本地存储 |
|
|
|
*/ |
|
|
|
async forceSave() { |
|
|
|
try { |
|
|
|
await this.saveToLocalstore() |
|
|
|
this.pendingChanges = false |
|
|
|
return true |
|
|
|
} catch (error) { |
|
|
|
console.error('[StateManager] 强制保存失败:', error) |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 撤销 |
|
|
|
*/ |
|
|
|
undo() { |
|
|
|
debugger |
|
|
|
if (!this.undoEnabled()) return |
|
|
|
|
|
|
|
const step = this.historySteps[this.historyIndex] |
|
|
|
@ -301,6 +294,11 @@ export default class StateManager { |
|
|
|
this.historyIndex = (this.historyIndex - 1 + this.maxHistorySteps) % this.maxHistorySteps |
|
|
|
this.isChanged.value = true |
|
|
|
this.pendingChanges = true |
|
|
|
|
|
|
|
this.lastSnapshot = new Map( |
|
|
|
this.vdata.items.map(item => [item.id, _.cloneDeep(item)]) |
|
|
|
) |
|
|
|
|
|
|
|
this.syncDataState() |
|
|
|
} |
|
|
|
|
|
|
|
@ -317,6 +315,11 @@ export default class StateManager { |
|
|
|
this.applyDiff(step.diff) |
|
|
|
this.isChanged.value = true |
|
|
|
this.pendingChanges = true |
|
|
|
|
|
|
|
this.lastSnapshot = new Map( |
|
|
|
this.vdata.items.map(item => [item.id, _.cloneDeep(item)]) |
|
|
|
) |
|
|
|
|
|
|
|
this.syncDataState() |
|
|
|
} |
|
|
|
|
|
|
|
@ -372,12 +375,32 @@ export default class StateManager { |
|
|
|
.filter(([, item]) => !!item) as [string, ItemJson][] |
|
|
|
) |
|
|
|
|
|
|
|
this.vdata.items = this.vdata.items.map(item => |
|
|
|
restoreMap.has(item.id) ? restoreMap.get(item.id)! : item |
|
|
|
) |
|
|
|
for (const [key, itemJson] of restoreMap) { |
|
|
|
const idx = _.findIndex(this.vdata.items, (item => item.id === key)) |
|
|
|
if (idx >= 0) { |
|
|
|
Object.assign(this.vdata.items[idx], itemJson) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private fullSync() { |
|
|
|
this.entityManager.beginEntityUpdate() |
|
|
|
this.vdata.items.forEach(item => { |
|
|
|
this.entityManager.createOrUpdateEntity(item) |
|
|
|
}) |
|
|
|
this.entityManager.endEntityUpdate() |
|
|
|
} |
|
|
|
|
|
|
|
undoEnabled() { |
|
|
|
return this.historyIndex >= 0 && this.historySteps[this.historyIndex] |
|
|
|
} |
|
|
|
|
|
|
|
redoEnabled() { |
|
|
|
const nextIndex = (this.historyIndex + 1) % this.maxHistorySteps |
|
|
|
return !!this.historySteps[nextIndex] |
|
|
|
} |
|
|
|
|
|
|
|
// /**
|
|
|
|
// * 保存到本地存储(防止数据丢失)
|
|
|
|
// */
|
|
|
|
@ -415,6 +438,27 @@ export default class StateManager { |
|
|
|
// }
|
|
|
|
|
|
|
|
/** |
|
|
|
* 保存数据到外部 |
|
|
|
*/ |
|
|
|
async save(): Promise<Object> { |
|
|
|
return _.cloneDeep(this.vdata) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 强制保存到本地存储 |
|
|
|
*/ |
|
|
|
async forceSave() { |
|
|
|
try { |
|
|
|
await this.saveToLocalstore() |
|
|
|
this.pendingChanges = false |
|
|
|
return true |
|
|
|
} catch (error) { |
|
|
|
console.error('[StateManager] 强制保存失败:', error) |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 保存到本地存储 浏览器indexDb(防止数据丢失) |
|
|
|
*/ |
|
|
|
async saveToLocalstore() { |
|
|
|
@ -443,23 +487,6 @@ export default class StateManager { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private fullSync() { |
|
|
|
this.entityManager.beginEntityUpdate() |
|
|
|
this.vdata.items.forEach(item => { |
|
|
|
this.entityManager.createOrUpdateEntity(item) |
|
|
|
}) |
|
|
|
this.entityManager.endEntityUpdate() |
|
|
|
} |
|
|
|
|
|
|
|
undoEnabled() { |
|
|
|
return this.historyIndex >= 0 && this.historySteps[this.historyIndex] |
|
|
|
} |
|
|
|
|
|
|
|
redoEnabled() { |
|
|
|
const nextIndex = (this.historyIndex + 1) % this.maxHistorySteps |
|
|
|
return !!this.historySteps[nextIndex] |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 删除本地存储 |
|
|
|
*/ |
|
|
|
@ -533,16 +560,3 @@ export default class StateManager { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 差异类型定义
|
|
|
|
interface DataDiff { |
|
|
|
added: ItemJson[] |
|
|
|
removed: string[] |
|
|
|
updated: ItemJson[] |
|
|
|
} |
|
|
|
|
|
|
|
// 历史记录项
|
|
|
|
interface HistoryStep { |
|
|
|
diff: DataDiff |
|
|
|
timestamp: number |
|
|
|
} |