This commit is contained in:
yyy 2025-07-10 18:18:13 +08:00
parent d131ecece5
commit 5f0f52d4ef
2 changed files with 109 additions and 18 deletions

76
src/utils/deepClone.ts Normal file
View File

@ -0,0 +1,76 @@
/**
*
* 使 structuredClone API JSON
*/
// 检查是否支持 structuredClone
const isStructuredCloneSupported = typeof structuredClone === 'function'
/**
*
* @param obj
* @returns
*/
export function deepClone<T>(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<T>(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
}
}

View File

@ -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)