Browse Source

保存草稿, 回写关系网到实体属性, 便于下次更新数据

master
修宁 7 months ago
parent
commit
bfcbc5bc33
  1. 13
      src/core/engine/Viewport.ts
  2. 28
      src/core/manager/EntityManager.ts
  3. 57
      src/core/manager/StateManager.ts
  4. 29
      src/core/manager/WorldModel.ts
  5. 4
      src/editor/Model2DEditor.vue

13
src/core/engine/Viewport.ts

@ -186,12 +186,13 @@ export default class Viewport {
itemType.clazz.afterAddViewport(this) itemType.clazz.afterAddViewport(this)
}) })
// 尝试从草稿中恢复
const tryGetFromLocal = false // await this.stateManager.tryLoadFromLocalstore()
if (!tryGetFromLocal) {
// 没有草稿,就找服务器捞数据
try { try {
if (worldModel.state.isDraft) {
await this.stateManager.loadFromLocalstore()
EventBus.dispatch('dataLoadComplete', {})
} else {
// 不是从草稿读的数据, 就找服务器捞数据
const vdata = await this.worldModel.getCatalogData(this.scene.catalogCode) const vdata = await this.worldModel.getCatalogData(this.scene.catalogCode)
if (!vdata) { if (!vdata) {
return return
@ -201,12 +202,12 @@ export default class Viewport {
} }
await this.stateManager.load(vdata) await this.stateManager.load(vdata)
EventBus.dispatch('dataLoadComplete', {}) EventBus.dispatch('dataLoadComplete', {})
}
} finally { } finally {
this.state.isReady = true this.state.isReady = true
} }
} }
}
/** /**
* 2D相机 * 2D相机

28
src/core/manager/EntityManager.ts

@ -68,6 +68,10 @@ export default class EntityManager {
} }
isUpdating = false isUpdating = false
getAllEntities(): Map<string, ItemJson> {
return this.entities
}
init(viewport: Viewport) { init(viewport: Viewport) {
this.viewport = viewport this.viewport = viewport
} }
@ -236,6 +240,30 @@ export default class EntityManager {
renderer.endRendererUpdate() renderer.endRendererUpdate()
} }
// 将 lineDiffs 中新的关系网数据, 更新到实体点里
const needUpdateIds = new Set<string>()
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.viewport.endViewUpdate()
this.isUpdating = false this.isUpdating = false
} }

57
src/core/manager/StateManager.ts

@ -3,6 +3,7 @@ import localforage from 'localforage'
import type EntityManager from './EntityManager' import type EntityManager from './EntityManager'
import { markRaw, reactive, ref } from 'vue' import { markRaw, reactive, ref } from 'vue'
import type Viewport from '@/core/engine/Viewport.ts' import type Viewport from '@/core/engine/Viewport.ts'
import { getQueryParams, setQueryParam } from '@/utils/webutils.ts'
// 差异类型定义 // 差异类型定义
interface DataDiff { interface DataDiff {
@ -142,7 +143,7 @@ export default class StateManager {
/** /**
* *
*/ */
endStateUpdate(): void { endStateUpdate(option = { autoSave: true }): void {
this.calculateDiff() this.calculateDiff()
this.saveStep() this.saveStep()
this.syncDataState(this.changeTracker) this.syncDataState(this.changeTracker)
@ -150,8 +151,10 @@ export default class StateManager {
this.pendingChanges = true // 标记有需要保存的更改 this.pendingChanges = true // 标记有需要保存的更改
this.isUpdating = false this.isUpdating = false
if (option.autoSave) {
this.startAutoSave() // 触发自动保存 this.startAutoSave() // 触发自动保存
} }
}
// 差异反转方法 // 差异反转方法
private invertDiff(diff: DataDiff): DataDiff { private invertDiff(diff: DataDiff): DataDiff {
@ -258,6 +261,10 @@ export default class StateManager {
} }
this.entityManager.endEntityUpdate() 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.fullSync()
// 初始状态作为第一步
this.beginStateUpdate()
this.endStateUpdate()
this.isChanged.value = false this.isChanged.value = false
this.pendingChanges = false
// 强制保存一次初始状态 // 强制保存一次初始状态
await this.saveToLocalstore()
console.log('[StateManager] 加载完成,共', data.items.length, '个对象') console.log('[StateManager] 加载完成,共', data.items.length, '个对象')
} finally { } finally {
@ -416,6 +418,11 @@ export default class StateManager {
this.entityManager.createOrUpdateEntity(item) this.entityManager.createOrUpdateEntity(item)
}) })
this.entityManager.endEntityUpdate() this.entityManager.endEntityUpdate()
// 初始状态作为第一步
this.beginStateUpdate()
this.endStateUpdate({ autoSave: false })
this.pendingChanges = false
} }
undoEnabled() { undoEnabled() {
@ -445,7 +452,7 @@ export default class StateManager {
/** /**
* *
*/ */
async tryLoadFromLocalstore(): Promise<boolean> { async loadFromLocalstore(): Promise<boolean> {
try { try {
this.isLoading.value = true this.isLoading.value = true
const saved: VData = await localforage.getItem(this.storeKey) const saved: VData = await localforage.getItem(this.storeKey)
@ -457,7 +464,6 @@ export default class StateManager {
this.fullSync() // 同步到视口 this.fullSync() // 同步到视口
console.log('[StateManager] 从本地存储恢复', this.vdata.items.length, '个对象') console.log('[StateManager] 从本地存储恢复', this.vdata.items.length, '个对象')
this.pendingChanges = false
return true return true
} }
@ -492,5 +498,38 @@ export default class StateManager {
delete this.vdata delete this.vdata
delete this.historySteps 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
}
}
} }

29
src/core/manager/WorldModel.ts

@ -1,11 +1,13 @@
import _ from 'lodash' import _ from 'lodash'
import { reactive, watch } from 'vue' import { reactive, watch } from 'vue'
import EventBus from '@/runtime/EventBus' import EventBus from '@/runtime/EventBus'
import localforage from 'localforage'
import StateManager from '@/core/manager/StateManager.ts'
export interface WorldModelState { export interface WorldModelState {
isOpened: boolean // 是否已打开世界模型 isOpened: boolean // 是否已打开世界模型
catalog: Catalog // 世界模型目录数据 catalog: Catalog // 世界模型目录数据
isDraft: boolean // 是否是草稿数据, 如果是草稿数据, 则不需要再从服务器加载数据
catalogCode: string // 当前楼层的目录代码 catalogCode: string // 当前楼层的目录代码
stateManagerId: string // 当前楼层的状态管理器id stateManagerId: string // 当前楼层的状态管理器id
} }
@ -22,6 +24,7 @@ export default class WorldModel {
state: WorldModelState = reactive({ state: WorldModelState = reactive({
isOpened: false, // 是否已打开世界模型 isOpened: false, // 是否已打开世界模型
catalogCode: '', catalogCode: '',
isDraft: false,
stateManagerId: '', // 当前楼层的状态管理器id stateManagerId: '', // 当前楼层的状态管理器id
catalog: [] as Catalog // 世界模型目录数据 catalog: [] as Catalog // 世界模型目录数据
}) })
@ -57,6 +60,17 @@ export default class WorldModel {
]).then(() => { ]).then(() => {
console.log('世界模型初始化完成') 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) { onCatalogCodeChanged(catalogCode: string) {
if (this.state.isDraft) {
// 草稿数据, 不需要再从服务器加载数据, 放行
EventBus.dispatch('catalogChanged', {
catalogCode: this.state.catalogCode,
stateManagerId: this.state.stateManagerId
})
return
}
if (!catalogCode) { if (!catalogCode) {
this.state.stateManagerId = '' this.state.stateManagerId = ''
EventBus.dispatch('catalogChanged', { EventBus.dispatch('catalogChanged', {
@ -112,9 +136,10 @@ export default class WorldModel {
isChanged: false, isChanged: false,
server: '', server: '',
projectId: '', projectId: '',
catalogCode: catalogCode, catalogCode: catalogCode
} }
console.log('从服务器返回数据, 一共' + vdata.items.length + '个')
return Promise.resolve(vdata) return Promise.resolve(vdata)
} }
return Promise.reject('楼层不存在, catalogCode=' + catalogCode) return Promise.reject('楼层不存在, catalogCode=' + catalogCode)

4
src/editor/Model2DEditor.vue

@ -89,6 +89,10 @@ export default defineComponent({
} }
}, },
mounted() { mounted() {
if (worldModel.state.isDraft) {
// 稿,
this.initByFloor()
}
EventBus.on('catalogChanged', (floor) => { EventBus.on('catalogChanged', (floor) => {
// , // ,
this.initByFloor() this.initByFloor()

Loading…
Cancel
Save