diff --git a/src/core/manager/StateManager.ts b/src/core/manager/StateManager.ts index 6023cc1..a4da870 100644 --- a/src/core/manager/StateManager.ts +++ b/src/core/manager/StateManager.ts @@ -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 + 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 { - 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 { + 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 -} \ No newline at end of file