Browse Source

状态管理器

master
修宁 7 months ago
parent
commit
55fec47908
  1. 203
      src/designer/StateManager.ts

203
src/designer/StateManager.ts

@ -89,6 +89,12 @@ export default class StateManager {
*/
private lastSnapshot: Map<string, VDataItem> = new Map()
// 自动保存相关
private autoSaveInterval: number | null = null
private autoSaveIntervalMs = 5000 // 5秒自动保存
private pendingChanges = false // 是否有待保存的更改
private lastAutoSaveTime = 0 // 上次自动保存时间
/**
* @param id , key
* @param viewport ,
@ -99,7 +105,10 @@ export default class StateManager {
this.viewport = markRaw(viewport)
this.historyBufferSize = bufferSize
// 初始化固定大小的历史缓冲区
this.historySteps = new Array(this.maxHistorySteps)
this.historySteps = new Array(this.maxHistorySteps).fill(null)
// 启动自动保存定时器
this.startAutoSave()
}
/**
@ -108,7 +117,7 @@ export default class StateManager {
beginUserWrite() {
// 创建当前状态快照(非深拷贝)
this.lastSnapshot = new Map(
this.vdata.items.map(item => [item.id, item])
this.vdata.items.map(item => [item.id, _.cloneDeep(item)])
)
this.changeTracker = { added: [], removed: [], updated: [] }
}
@ -121,6 +130,7 @@ export default class StateManager {
this.saveStep()
this.syncDataState()
this.isChanged.value = true
this.pendingChanges = true // 标记有需要保存的更改
}
@ -178,7 +188,7 @@ export default class StateManager {
}
this.historyIndex = nextIndex
this.saveToLocalstore()
this.pendingChanges = true // 标记有需要保存的更改
}
@ -232,18 +242,34 @@ export default class StateManager {
*/
async load(items: VDataItem[]) {
this.isLoading.value = true
this.historySteps = new Array(this.maxHistorySteps).fill(null)
this.historyIndex = -1
try {
// 停止自动保存,避免在加载过程中触发
this.stopAutoSave()
// 直接替换数组引用(避免响应式开销)
this.vdata.items = items
this.fullSync() // 同步到视口
// 初始状态作为第一步
this.beginUserWrite()
this.endUserWrite()
this.isChanged.value = false
this.pendingChanges = false
// 强制保存一次初始状态
await this.saveToLocalstore()
this.pendingChanges = false
console.log('[StateManager] 加载完成,共 ', items.length, '个对象')
} finally {
this.isLoading.value = false
// 重新启动自动保存
this.startAutoSave()
}
}
@ -255,6 +281,20 @@ export default class StateManager {
}
/**
*
*/
async forceSave() {
try {
await this.saveToLocalstore()
this.pendingChanges = false
return true
} catch (error) {
console.error('[StateManager] 强制保存失败:', error)
return false
}
}
/**
*
*/
undo() {
@ -266,6 +306,7 @@ export default class StateManager {
this.applyReverseDiff(step.diff)
this.historyIndex = (this.historyIndex - 1 + this.maxHistorySteps) % this.maxHistorySteps
this.isChanged.value = true
this.pendingChanges = true
this.syncDataState()
}
@ -281,6 +322,7 @@ export default class StateManager {
this.applyDiff(step.diff)
this.isChanged.value = true
this.pendingChanges = true
this.syncDataState()
}
@ -306,6 +348,8 @@ export default class StateManager {
updateMap.has(item.id) ? updateMap.get(item.id)! : item
)
}
this.lastSnapshot = new Map(this.vdata.items.map(item => [item.id, _.cloneDeep(item)]))
}
/**
@ -340,47 +384,158 @@ export default class StateManager {
restoreMap.has(item.id) ? restoreMap.get(item.id)! : item
)
}
this.lastSnapshot = new Map(this.vdata.items.map(item => [item.id, _.cloneDeep(item)]))
}
/**
* ()
*/
async saveToLocalstore() {
// 只保存变化部分和关键元数据
const saveData = {
diff: this.changeTracker,
timestamp: Date.now(),
itemsCount: this.vdata.items.length
}
// /**
// * 保存到本地存储(防止数据丢失)
// */
// async saveToLocalstore() {
// // 只保存变化部分和关键元数据
// const saveData = {
// diff: this.changeTracker,
// timestamp: Date.now(),
// itemsCount: this.vdata.items.length
// }
//
// await localforage.setItem(`scene-tmp-${this.id}`, saveData)
// }
//
// /**
// * 从本地存储加载数据
// */
// async loadFromLocalstore() {
// try {
// this.isLoading.value = true
// const saved: any = await localforage.getItem(`scene-tmp-${this.id}`)
// if (saved && saved.diff) {
// this.applyDiff(saved.diff)
// this.isChanged.value = true
// this.pendingChanges = true
// console.log('[StateManager] 从本地存储恢复 ', saved.itemsCount, '个对象')
// }
//
// } catch (error) {
// console.error('[StateManager] 从本地存储加载失败:', error)
//
// } finally {
// this.isLoading.value = false
// }
// }
await localforage.setItem(`scene-tmp-${this.id}`, saveData)
async saveToLocalstore() {
await localforage.setItem(`scene-tmp-${this.id}`, this.vdata)
}
/**
*
*/
async loadFromLocalstore() {
const saved: any = await localforage.getItem(`scene-tmp-${this.id}`)
if (saved && saved.diff) {
this.applyDiff(saved.diff)
this.isChanged.value = true
try {
this.isLoading.value = true
const saved: VData = await localforage.getItem(`scene-tmp-${this.id}`)
if (saved) {
this.vdata.items = saved.items || []
this.isChanged.value = saved.isChanged || false
this.pendingChanges = true
this.fullSync() // 同步到视口
console.log('[StateManager] 从本地存储恢复', this.vdata.items.length, '个对象')
}
} catch (error) {
console.error('[StateManager] 从本地存储加载失败:', error)
} finally {
this.isLoading.value = false
}
}
private fullSync() {
this.viewport.beginSync()
this.vdata.items.forEach(item => {
this.viewport.syncOnAppend(item)
})
this.viewport.endSync()
}
undoEnabled() {
return this.historyIndex >= 0 && this.historySteps[this.historyIndex] !== undefined
return this.historyIndex >= 0 && this.historySteps[this.historyIndex]
}
redoEnabled() {
const nextIndex = (this.historyIndex + 1) % this.maxHistorySteps
return this.historySteps[nextIndex] !== undefined
return !!this.historySteps[nextIndex]
}
/**
*
*/
async removeLocalstore() {
await localforage.removeItem(`scene-tmp-${this.id}`)
try {
await localforage.removeItem(`scene-tmp-${this.id}`)
console.log('[StateManager] 本地存储已清除')
} catch (error) {
console.error('[StateManager] 清除本地存储失败:', error)
}
}
/**
*
*/
startAutoSave() {
if (this.autoSaveInterval) return
this.autoSaveInterval = window.setInterval(() => {
this.autoSaveIfNeeded()
}, this.autoSaveIntervalMs)
}
/**
*
*/
stopAutoSave() {
if (this.autoSaveInterval) {
clearInterval(this.autoSaveInterval)
this.autoSaveInterval = null
}
}
/**
*
*/
private async autoSaveIfNeeded() {
// 没有变化或正在加载时跳过
if (!this.pendingChanges || this.isLoading.value) return
try {
await this.saveToLocalstore()
this.pendingChanges = false
this.lastAutoSaveTime = Date.now()
console.debug(`[StateManager] 自动保存成功 at ${new Date().toLocaleTimeString()}`)
} catch (error) {
console.error('[StateManager] 自动保存失败:', error)
}
}
/**
*
*/
destroy() {
this.stopAutoSave()
this.removeLocalstore().catch(console.error)
// 清理引用
this.viewport = null as any
this.vdata.items = []
this.historySteps = []
}
/**
*
*/
getAutoSaveStatus() {
return {
enabled: this.autoSaveInterval !== null,
interval: this.autoSaveIntervalMs,
lastSaveTime: this.lastAutoSaveTime,
pendingChanges: this.pendingChanges
}
}
}

Loading…
Cancel
Save