From 5f0f52d4ef5b3302dc7376ee3ea7566772cb8cba Mon Sep 17 00:00:00 2001 From: yyy <2605810609@qq.com> Date: Thu, 10 Jul 2025 18:18:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/deepClone.ts | 76 +++++++++++++++++++++++ src/views/mapPage/realTimeMap/editMap.vue | 51 +++++++++------ 2 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 src/utils/deepClone.ts diff --git a/src/utils/deepClone.ts b/src/utils/deepClone.ts new file mode 100644 index 00000000..8164ca93 --- /dev/null +++ b/src/utils/deepClone.ts @@ -0,0 +1,76 @@ +/** + * 深度克隆工具函数 + * 优先使用 structuredClone API,降级到 JSON 方法 + */ + +// 检查是否支持 structuredClone +const isStructuredCloneSupported = typeof structuredClone === 'function' + +/** + * 深度克隆对象 + * @param obj 要克隆的对象 + * @returns 克隆后的对象 + */ +export function deepClone(obj: T): T { + if (obj === null || obj === undefined) { + return obj + } + + // 基本类型直接返回 + if (typeof obj !== 'object') { + return obj + } + + // 日期对象特殊处理 + if (obj instanceof Date) { + return new Date(obj.getTime()) as T + } + + // 数组对象特殊处理 + if (Array.isArray(obj)) { + return obj.map((item) => deepClone(item)) as T + } + + // 优先使用 structuredClone + if (isStructuredCloneSupported) { + try { + return structuredClone(obj) + } catch (error) { + console.warn('structuredClone failed, falling back to JSON method:', error) + } + } + + // 降级到 JSON 方法 + try { + return JSON.parse(JSON.stringify(obj)) + } catch (error) { + console.error('Deep clone failed:', error) + // 如果都失败了,返回浅拷贝 + return { ...obj } as T + } +} + +/** + * 专门用于克隆地图数据的优化函数 + * 针对 allMapPointInfo 和 mapRouteList 数据结构优化 + */ +export function cloneMapData(data: T): T { + if (!data) return data + + // 对于地图数据,使用 structuredClone 性能最佳 + if (isStructuredCloneSupported) { + try { + return structuredClone(data) + } catch (error) { + console.warn('structuredClone failed for map data:', error) + } + } + + // 降级到 JSON 方法 + try { + return JSON.parse(JSON.stringify(data)) + } catch (error) { + console.error('Map data clone failed:', error) + return { ...data } as T + } +} diff --git a/src/views/mapPage/realTimeMap/editMap.vue b/src/views/mapPage/realTimeMap/editMap.vue index fef6b371..98804138 100644 --- a/src/views/mapPage/realTimeMap/editMap.vue +++ b/src/views/mapPage/realTimeMap/editMap.vue @@ -1084,6 +1084,7 @@ import GenerateStraightLinesDialog from './components-tool/GenerateStraightLines import BatchEditNodePropertiesDialog from './components-tool/BatchEditNodePropertiesDialog.vue' import BatchEditRoutePropertiesDialog from './components-tool/BatchEditRoutePropertiesDialog.vue' import mapScaleTool from './components-tool/map-scale-tool.vue' +import { deepClone, cloneMapData } from '@/utils/deepClone' import * as MapApi from '@/api/map/map' import cursorCollection from './cursorCollection' @@ -1325,7 +1326,7 @@ const activatedHandle = (item, index) => { if (toolbarSwitchType.value === 'editNode' && item.type !== 7) { let list = state.allMapPointInfo.filter((item) => item.type === 3) removeEventListener() //移除监听 - editNodePropertiesRef.value.open(JSON.parse(JSON.stringify(item)), list) + editNodePropertiesRef.value.open(deepClone(item), list) } } @@ -1338,11 +1339,25 @@ const addEditHistory = () => { if (state.currentIndex < state.allHistoryList.length - 1) { state.allHistoryList.splice(state.currentIndex + 1) } + + // 添加新的历史记录 state.allHistoryList.push({ - allMapPointInfo: JSON.parse(JSON.stringify(state.allMapPointInfo)), - mapRouteList: JSON.parse(JSON.stringify(state.mapRouteList)) + allMapPointInfo: cloneMapData(state.allMapPointInfo), + mapRouteList: cloneMapData(state.mapRouteList) }) - state.currentIndex = state.allHistoryList.length - 1 + + // 限制历史记录数量为50个,保留最新的记录 + const MAX_HISTORY_COUNT = 50 + if (state.allHistoryList.length > MAX_HISTORY_COUNT) { + // 删除最旧的记录,保留最新的50个 + const deleteCount = state.allHistoryList.length - MAX_HISTORY_COUNT + state.allHistoryList.splice(0, deleteCount) + // 调整当前索引 + state.currentIndex = Math.max(0, state.currentIndex - deleteCount) + } else { + state.currentIndex = state.allHistoryList.length - 1 + } + interfaceRefreshed.value = true } @@ -1353,12 +1368,12 @@ const backPreviousStep = () => { state.allMapPointInfo.splice( 0, state.allMapPointInfo.length, - ...JSON.parse(JSON.stringify(state.allHistoryList[state.currentIndex]?.allMapPointInfo)) + ...cloneMapData(state.allHistoryList[state.currentIndex]?.allMapPointInfo) ) state.mapRouteList.splice( 0, state.mapRouteList.length, - ...JSON.parse(JSON.stringify(state.allHistoryList[state.currentIndex]?.mapRouteList)) + ...cloneMapData(state.allHistoryList[state.currentIndex]?.mapRouteList) ) } else { message.warning('没了老铁') @@ -1371,12 +1386,12 @@ const backNextStep = () => { state.allMapPointInfo.splice( 0, state.allMapPointInfo.length, - ...JSON.parse(JSON.stringify(state.allHistoryList[state.currentIndex]?.allMapPointInfo)) + ...cloneMapData(state.allHistoryList[state.currentIndex]?.allMapPointInfo) ) state.mapRouteList.splice( 0, state.mapRouteList.length, - ...JSON.parse(JSON.stringify(state.allHistoryList[state.currentIndex]?.mapRouteList)) + ...cloneMapData(state.allHistoryList[state.currentIndex]?.mapRouteList) ) } else { message.warning('没了老铁') @@ -2405,7 +2420,7 @@ const replicationNode = () => { } //粘贴 const pasteNode = () => { - let copyObj = JSON.parse(JSON.stringify(state.copyMapItem)) + let copyObj = deepClone(state.copyMapItem) // 检查节点是否已存在 const isDuplicate = state.allMapPointInfo.some( @@ -3174,7 +3189,7 @@ const BatchEditNodePropertiesSucceeded = (data) => { //批量路线编辑成功 const BatchEditRoutePropertiesSucceeded = (data) => { - let newRoutes = JSON.parse(JSON.stringify(state.drawSelectionRouteList)) + let newRoutes = deepClone(state.drawSelectionRouteList) const routeIdSet = new Set(newRoutes.map((route) => route.id)) state.mapRouteList.forEach((route) => { if (routeIdSet.has(route.id)) { @@ -3219,8 +3234,8 @@ const BatchEditRoutePropertiesSucceeded = (data) => { //批量复制 const submitBatchCopyingFormSuccess = async (form) => { - let newPoints = JSON.parse(JSON.stringify(state.drawSelectionPointList)) - let newRoutes = JSON.parse(JSON.stringify(state.drawSelectionRouteList)) + let newPoints = deepClone(state.drawSelectionPointList) + let newRoutes = deepClone(state.drawSelectionRouteList) // 创建节点ID映射 const nodeIdMap = new Map() @@ -3758,8 +3773,8 @@ const handleChooseRoute = async (item, index, type, e) => { state.mapRouteList.push(positionMapLineTwo) state.mapRouteList.splice(index, 1) state.allHistoryList[0] = { - allMapPointInfo: JSON.parse(JSON.stringify(state.allMapPointInfo)), - mapRouteList: JSON.parse(JSON.stringify(state.mapRouteList)) + allMapPointInfo: cloneMapData(state.allMapPointInfo), + mapRouteList: cloneMapData(state.mapRouteList) } state.currentIndex = 0 message.success('添加成功') @@ -3778,7 +3793,7 @@ const handleChooseRoute = async (item, index, type, e) => { if (toolbarSwitchType.value === 'editRoute') { removeEventListener() //移除监听 - editMapRouteDialogRef.value.open(JSON.parse(JSON.stringify(item))) + editMapRouteDialogRef.value.open(deepClone(item)) } } } @@ -4121,8 +4136,8 @@ const getAllMapRoute = async () => { state.mapRouteList = await MapApi.getPositionMapLineByPositionMapId(imgBgObj.positionMapId) state.allHistoryList = [] state.allHistoryList[0] = { - allMapPointInfo: JSON.parse(JSON.stringify(state.allMapPointInfo)), - mapRouteList: JSON.parse(JSON.stringify(state.mapRouteList)) + allMapPointInfo: cloneMapData(state.allMapPointInfo), + mapRouteList: cloneMapData(state.mapRouteList) } } //获取设备类型 @@ -4675,7 +4690,7 @@ const hideCurveContextMenu = () => { state.curveContextMenu.currentIndex = -1 } -// 曲线删除(仅UI,逻辑留空) +// 曲线删除 const deleteCurveRoute = () => { if (state.currentDragTarget.index !== null) { state.mapRouteList.splice(state.currentDragTarget.index, 1)