From bfcbc5bc335734137a9cf489a6329d3e07e36e15 Mon Sep 17 00:00:00 2001 From: yvan Date: Mon, 2 Jun 2025 01:48:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=9D=E5=AD=98=E8=8D=89=E7=A8=BF,=20?= =?UTF-8?q?=E5=9B=9E=E5=86=99=E5=85=B3=E7=B3=BB=E7=BD=91=E5=88=B0=E5=AE=9E?= =?UTF-8?q?=E4=BD=93=E5=B1=9E=E6=80=A7,=20=E4=BE=BF=E4=BA=8E=E4=B8=8B?= =?UTF-8?q?=E6=AC=A1=E6=9B=B4=E6=96=B0=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/engine/Viewport.ts | 17 +++++------ src/core/manager/EntityManager.ts | 28 +++++++++++++++++++ src/core/manager/StateManager.ts | 59 ++++++++++++++++++++++++++++++++------- src/core/manager/WorldModel.ts | 29 +++++++++++++++++-- src/editor/Model2DEditor.vue | 4 +++ 5 files changed, 117 insertions(+), 20 deletions(-) diff --git a/src/core/engine/Viewport.ts b/src/core/engine/Viewport.ts index c422fa5..15a83ed 100644 --- a/src/core/engine/Viewport.ts +++ b/src/core/engine/Viewport.ts @@ -186,12 +186,13 @@ export default class Viewport { itemType.clazz.afterAddViewport(this) }) - // 尝试从草稿中恢复 - const tryGetFromLocal = false // await this.stateManager.tryLoadFromLocalstore() + try { + if (worldModel.state.isDraft) { + await this.stateManager.loadFromLocalstore() + EventBus.dispatch('dataLoadComplete', {}) - if (!tryGetFromLocal) { - // 没有草稿,就找服务器捞数据 - try { + } else { + // 不是从草稿读的数据, 就找服务器捞数据 const vdata = await this.worldModel.getCatalogData(this.scene.catalogCode) if (!vdata) { return @@ -201,10 +202,10 @@ export default class Viewport { } await this.stateManager.load(vdata) EventBus.dispatch('dataLoadComplete', {}) - - } finally { - this.state.isReady = true } + + } finally { + this.state.isReady = true } } diff --git a/src/core/manager/EntityManager.ts b/src/core/manager/EntityManager.ts index 03c782f..0cde12b 100644 --- a/src/core/manager/EntityManager.ts +++ b/src/core/manager/EntityManager.ts @@ -68,6 +68,10 @@ export default class EntityManager { } isUpdating = false + getAllEntities(): Map { + return this.entities + } + init(viewport: Viewport) { this.viewport = viewport } @@ -236,6 +240,30 @@ export default class EntityManager { renderer.endRendererUpdate() } + + // 将 lineDiffs 中新的关系网数据, 更新到实体点里 + const needUpdateIds = new Set() + for (const [lineId, lineDiffItem] of this.lineDiffs.create.entries()) { + needUpdateIds.add(lineDiffItem.startId) + needUpdateIds.add(lineDiffItem.endId) + } + for (const [lineId, lineDiffItem] of this.lineDiffs.update.entries()) { + needUpdateIds.add(lineDiffItem.startId) + needUpdateIds.add(lineDiffItem.endId) + } + for (const [lineId, lineDiffItem] of this.lineDiffs.delete.entries()) { + needUpdateIds.add(lineDiffItem.startId) + needUpdateIds.add(lineDiffItem.endId) + } + for (const id of needUpdateIds) { + const entity = this.entities.get(id) + if (entity) { + entity.dt.center = Array.from(this.relationIndex.get(id)?.center || []) + entity.dt.in = Array.from(this.relationIndex.get(id)?.input || []) + entity.dt.out = Array.from(this.relationIndex.get(id)?.output || []) + } + } + this.viewport.endViewUpdate() this.isUpdating = false } diff --git a/src/core/manager/StateManager.ts b/src/core/manager/StateManager.ts index d5bdd3b..c7719e8 100644 --- a/src/core/manager/StateManager.ts +++ b/src/core/manager/StateManager.ts @@ -3,6 +3,7 @@ import localforage from 'localforage' import type EntityManager from './EntityManager' import { markRaw, reactive, ref } from 'vue' import type Viewport from '@/core/engine/Viewport.ts' +import { getQueryParams, setQueryParam } from '@/utils/webutils.ts' // 差异类型定义 interface DataDiff { @@ -142,7 +143,7 @@ export default class StateManager { /** * 结束用户操作(计算差异并保存) */ - endStateUpdate(): void { + endStateUpdate(option = { autoSave: true }): void { this.calculateDiff() this.saveStep() this.syncDataState(this.changeTracker) @@ -150,7 +151,9 @@ export default class StateManager { this.pendingChanges = true // 标记有需要保存的更改 this.isUpdating = false - this.startAutoSave() // 触发自动保存 + if (option.autoSave) { + this.startAutoSave() // 触发自动保存 + } } // 差异反转方法 @@ -258,6 +261,10 @@ export default class StateManager { } this.entityManager.endEntityUpdate() + + // 从实体管理器中获取最新数据 + const updatedItems = this.entityManager.getAllEntities() + this.vdata.items = Array.from(updatedItems.values()) } /** @@ -369,15 +376,10 @@ export default class StateManager { // 同步到视口 this.fullSync() - - // 初始状态作为第一步 - this.beginStateUpdate() - this.endStateUpdate() - this.isChanged.value = false - this.pendingChanges = false // 强制保存一次初始状态 + await this.saveToLocalstore() console.log('[StateManager] 加载完成,共', data.items.length, '个对象') } finally { @@ -416,6 +418,11 @@ export default class StateManager { this.entityManager.createOrUpdateEntity(item) }) this.entityManager.endEntityUpdate() + + // 初始状态作为第一步 + this.beginStateUpdate() + this.endStateUpdate({ autoSave: false }) + this.pendingChanges = false } undoEnabled() { @@ -445,7 +452,7 @@ export default class StateManager { /** * 从本地存储还原数据 */ - async tryLoadFromLocalstore(): Promise { + async loadFromLocalstore(): Promise { try { this.isLoading.value = true const saved: VData = await localforage.getItem(this.storeKey) @@ -457,7 +464,6 @@ export default class StateManager { this.fullSync() // 同步到视口 console.log('[StateManager] 从本地存储恢复', this.vdata.items.length, '个对象') - this.pendingChanges = false return true } @@ -492,5 +498,38 @@ export default class StateManager { delete this.vdata delete this.historySteps } + + /** + * 尝试从草稿中读取数据 + */ + static async tryLoadCatalogFromLocalstore(): Promise<{ + success: boolean, + catalogCode?: string, + catalog?: Catalog, + stateManagerId?: string + }> { + // 获取 url 中的 stateManagerId + // 从 localforage 中读取草稿数据 + const stateManagerId = getQueryParams()?.get('store') + if (stateManagerId) { + const storeKey = `-tmp-yvan-lcc-${stateManagerId}` + const saved: VData = await localforage.getItem(storeKey) + if (saved && saved.catalog) { + const catalogCode = saved.catalogCode || '' + if (catalogCode) { + return { + success: true, + catalogCode, + catalog: saved.catalog, + stateManagerId + } + } + } + } + + return { + success: false + } + } } diff --git a/src/core/manager/WorldModel.ts b/src/core/manager/WorldModel.ts index 961411f..3e828c9 100644 --- a/src/core/manager/WorldModel.ts +++ b/src/core/manager/WorldModel.ts @@ -1,11 +1,13 @@ import _ from 'lodash' import { reactive, watch } from 'vue' import EventBus from '@/runtime/EventBus' +import localforage from 'localforage' +import StateManager from '@/core/manager/StateManager.ts' export interface WorldModelState { isOpened: boolean // 是否已打开世界模型 catalog: Catalog // 世界模型目录数据 - + isDraft: boolean // 是否是草稿数据, 如果是草稿数据, 则不需要再从服务器加载数据 catalogCode: string // 当前楼层的目录代码 stateManagerId: string // 当前楼层的状态管理器id } @@ -22,6 +24,7 @@ export default class WorldModel { state: WorldModelState = reactive({ isOpened: false, // 是否已打开世界模型 catalogCode: '', + isDraft: false, stateManagerId: '', // 当前楼层的状态管理器id catalog: [] as Catalog // 世界模型目录数据 }) @@ -57,6 +60,17 @@ export default class WorldModel { ]).then(() => { console.log('世界模型初始化完成') + + // 尝试从草稿中加载数据 + StateManager.tryLoadCatalogFromLocalstore().then(data => { + if (data.success) { + this.state.catalog = data.catalog + this.state.isOpened = true + this.state.catalogCode = data.catalogCode + this.state.stateManagerId = data.stateManagerId + this.state.isDraft = true + } + }) }) } @@ -73,6 +87,16 @@ export default class WorldModel { * 当楼层发生改变时, 将事件派发出去 */ onCatalogCodeChanged(catalogCode: string) { + if (this.state.isDraft) { + // 草稿数据, 不需要再从服务器加载数据, 放行 + EventBus.dispatch('catalogChanged', { + catalogCode: this.state.catalogCode, + stateManagerId: this.state.stateManagerId + }) + return + } + + if (!catalogCode) { this.state.stateManagerId = '' EventBus.dispatch('catalogChanged', { @@ -112,9 +136,10 @@ export default class WorldModel { isChanged: false, server: '', projectId: '', - catalogCode: catalogCode, + catalogCode: catalogCode } + console.log('从服务器返回数据, 一共' + vdata.items.length + '个') return Promise.resolve(vdata) } return Promise.reject('楼层不存在, catalogCode=' + catalogCode) diff --git a/src/editor/Model2DEditor.vue b/src/editor/Model2DEditor.vue index 0ee5ef5..b7d355d 100644 --- a/src/editor/Model2DEditor.vue +++ b/src/editor/Model2DEditor.vue @@ -89,6 +89,10 @@ export default defineComponent({ } }, mounted() { + if (worldModel.state.isDraft) { + // 如果是草稿状态, 则不加载视口 + this.initByFloor() + } EventBus.on('catalogChanged', (floor) => { // 当楼层加载完成后, 初始化视口 this.initByFloor()