From 717b7237a2a099162bf575ec8e1790ed1123a6e7 Mon Sep 17 00:00:00 2001 From: shay7sev Date: Sat, 28 Feb 2026 16:31:50 +0800 Subject: [PATCH] fix(store): fix structuredClone --- components/label/store.ts | 54 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/components/label/store.ts b/components/label/store.ts index aba4aa4..c4aefe0 100644 --- a/components/label/store.ts +++ b/components/label/store.ts @@ -145,6 +145,56 @@ const initialLabelState = { }, } +const deepCloneFallback = (value: T, cache = new WeakMap()): T => { + if (value === null || typeof value !== "object") return value + if (cache.has(value as object)) return cache.get(value as object) + + if (value instanceof Date) return new Date(value.getTime()) as T + if (value instanceof Map) { + const clonedMap = new Map() + cache.set(value as object, clonedMap) + value.forEach((mapValue, mapKey) => { + clonedMap.set( + deepCloneFallback(mapKey, cache), + deepCloneFallback(mapValue, cache) + ) + }) + return clonedMap as T + } + if (value instanceof Set) { + const clonedSet = new Set() + cache.set(value as object, clonedSet) + value.forEach((setValue) => { + clonedSet.add(deepCloneFallback(setValue, cache)) + }) + return clonedSet as T + } + if (Array.isArray(value)) { + const clonedArr: any[] = [] + cache.set(value as object, clonedArr) + value.forEach((item, index) => { + clonedArr[index] = deepCloneFallback(item, cache) + }) + return clonedArr as T + } + + const clonedObj: Record = {} + cache.set(value as object, clonedObj) + Object.keys(value as object).forEach((key) => { + clonedObj[key] = deepCloneFallback((value as any)[key], cache) + }) + return clonedObj as T +} + +const safeClone = (value: T): T => { + try { + return structuredClone(value) + } catch (error) { + console.warn("structuredClone failed, fallback to deep clone", error) + return deepCloneFallback(value) + } +} + export const initialDetail = { comment: [], create_timestamp: 0, @@ -301,8 +351,8 @@ export const useLabelStore = create( labelData.get(imageId)?.set(operationId, [path]) } console.log("绘制时", labelData) - useLabelStore.getState().pushStateStack(structuredClone(labelData)) - return { ...state, label: structuredClone(labelData) } + useLabelStore.getState().pushStateStack(safeClone(labelData)) + return { ...state, label: safeClone(labelData) } }), // 删除path