From 557970fd878487e7af0ec2b5a28244e79000bfe2 Mon Sep 17 00:00:00 2001 From: wangxk Date: Wed, 9 Apr 2025 14:56:26 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../testdata/fileSynchronization/index.vue | 317 ++++++++++-------- 1 file changed, 180 insertions(+), 137 deletions(-) diff --git a/web/src/views/testdata/fileSynchronization/index.vue b/web/src/views/testdata/fileSynchronization/index.vue index 6b395f9..538bff1 100644 --- a/web/src/views/testdata/fileSynchronization/index.vue +++ b/web/src/views/testdata/fileSynchronization/index.vue @@ -189,7 +189,7 @@ function diffMiss() { function diffColor() { // 1. 使用Map优化查找性能 const createMap = (arr: any[]) => new Map(arr.map(item => [item.id, item])); - + const localMap = createMap(localOnlyFiles.value); const md5Map = createMap(md5MismatchedFiles.value); const minioMap = createMap(minioOnlyFiles.value); @@ -197,7 +197,7 @@ function diffColor() { // 2. 单次遍历优化 const processTree = (tree: any[], location: 'local' | 'minio') => { const stack = [...tree]; - + while (stack.length) { const node = stack.pop(); if (!node) continue; @@ -272,37 +272,45 @@ function gettreedata() { } function handleNodeClick(data: any, node: any) { pathid.value = data.nodeId + localOnlyFiles.value.length = 0 + md5MismatchedFiles.value.length = 0 + minioOnlyFiles.value.length = 0 getlocaltree() getminiotree() } //工作空间树点击 const handleCheckChange = ( - data: any, - checked: boolean, - indeterminate: boolean + data: any, + checked: boolean, + indeterminate: boolean ) => { - // 使用Map优化查找性能 - const nodeMap = new Map(workall.value.map(item => [item.id, item])); - - // 当完全选中时添加节点 - if (checked && !indeterminate) { - if (!nodeMap.has(data.id)) { - workall.value = [...workall.value, data]; + // 使用Map优化查找性能 + const nodeMap = new Map(workall.value.map(item => [item.id, item])); + + // 当完全选中时添加节点 + if (checked && !indeterminate) { + if (!nodeMap.has(data.id)) { + workall.value = [...workall.value, data]; + } + } + // 当取消选中时移除节点 + else { + workall.value = workall.value.filter(item => item.id !== data.id); } - } - // 当取消选中时移除节点 - else { - workall.value = workall.value.filter(item => item.id !== data.id); - } - // 使用防抖优化批量操作 - const updateCompare = debounce(() => { - comparearr.value = getclickdata(workall.value); - // 同步备份空间的选中状态 - beifentree.value?.setCheckedNodes(comparearr.value, false); - }, 50); + // 使用防抖优化批量操作 + const updateCompare = debounce(() => { + const compareNodes = getclickdata(workall.value); - updateCompare(); + // 转换节点格式 + const checkedKeys = compareNodes + .map(node => node.id) + nextTick(() => { + beifentree.value?.setCheckedKeys(checkedKeys, false); + }); + }, 50); + + updateCompare(); }; //递归整理点击参数 function getclickdata(nodes: any[]): any[] { @@ -310,7 +318,7 @@ function getclickdata(nodes: any[]): any[] { const excludeIds = new Set(); // 使用栈结构进行迭代处理 const stack = [...nodes]; - + // 第一阶段:收集所有需要排除的子节点 ID while (stack.length > 0) { const node = stack.pop(); @@ -339,83 +347,118 @@ function getclickdata(nodes: any[]): any[] { } //获取本地树 function getlocaltree() { - - if(projectId.value && pathid.value){ - worktree.value = true - listLocalTree({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => { - workdata.value = res.data.localTrees - if (workdata.value.length > 0) { - assignment(workdata.value, 'local') - } - worktree.value = false - diffColor() - }) - } + if (!projectId.value || !pathid.value) return; + + worktree.value = true; + listLocalTree({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => { + const CHUNK_SIZE = 500; // 每批处理500个节点 + const rawData = res.data.localTrees; + + // 使用requestAnimationFrame分批次处理 + const processChunk = (index = 0) => { + const chunk = rawData.slice(index, index + CHUNK_SIZE); + if (chunk.length > 0) { + assignment(chunk, 'local'); + workdata.value.push(...chunk); // 分批追加数据 + requestAnimationFrame(() => processChunk(index + CHUNK_SIZE)); + } else { + worktree.value = false; + diffColor(); + } + }; + + workdata.value = []; // 清空旧数据 + processChunk(); + }); } const worktree1 = ref(false) //获取minio树 function getminiotree() { - if(projectId.value && pathid.value){ - worktree1.value = true - listBackupTree({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => { - backupsdata.value = res.data.minioTrees - if (backupsdata.value.length > 0) { - assignment(backupsdata.value, 'minio') - } - worktree1.value = false - diffColor() - }) - } + if (!projectId.value || !pathid.value) return; + + worktree1.value = true; + listBackupTree({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => { + const CHUNK_SIZE = 500; + const rawData = res.data.minioTrees; + + const processChunk = (index = 0) => { + const chunk = rawData.slice(index, index + CHUNK_SIZE); + if (chunk.length > 0) { + assignment(chunk, 'minio'); + backupsdata.value.push(...chunk); + requestAnimationFrame(() => processChunk(index + CHUNK_SIZE)); + } else { + worktree1.value = false; + diffColor(); + } + }; + + backupsdata.value = []; + processChunk(); + }); } //数据递归赋值 function assignment(data: any[], difference: 'local' | 'minio') { - // 使用栈结构替代递归,防止栈溢出 - const stack: any[] = [...data]; - while (stack.length > 0) { - const node = stack.pop(); + const queue = [...data]; // 使用队列代替栈 + while (queue.length > 0) { + const node = queue.shift(); if (!node) continue; - // 添加类型断言确保操作安全 - node.location = difference; - node.station = '0'; // 0: 相同, 1: 新增, 2: 变更, 3: 删除 - // 反向压栈保持原有顺序 + // 使用Object.defineProperty避免Vue响应式转换 + Object.defineProperty(node, 'location', { + value: difference, + writable: true, + enumerable: true + }); + + Object.defineProperty(node, 'station', { + value: '0', + writable: true, + enumerable: true + }); + if (node.children?.length) { - stack.push(...[...node.children].reverse()); + queue.push(...node.children); } } } //备份空间 const beifentree = ref() const backupsChange = ( - data: any, - checked: boolean, - indeterminate: boolean + data: any, + checked: boolean, + indeterminate: boolean ) => { - // 使用临时变量避免多次访问响应式对象 - const currentWorkall = [...workall.value]; - - // 使用Map优化查找性能 - const nodeMap = new Map(currentWorkall.map(item => [item.id, item])); - - // 当完全选中时添加节点(防止重复添加) - if (checked && !indeterminate) { - if (!nodeMap.has(data.id)) { - workall.value = [...currentWorkall, data]; + // 使用临时变量避免多次访问响应式对象 + const currentWorkall = [...workall.value]; + + // 使用Map优化查找性能 + const nodeMap = new Map(currentWorkall.map(item => [item.id, item])); + + // 当完全选中时添加节点(防止重复添加) + if (checked && !indeterminate) { + if (!nodeMap.has(data.id)) { + workall.value = [...currentWorkall, data]; + } + } + // 当取消选中时精确移除节点 + else { + workall.value = currentWorkall.filter(item => item.id !== data.id); } - } - // 当取消选中时精确移除节点 - else { - workall.value = currentWorkall.filter(item => item.id !== data.id); - } - // 使用防抖优化批量操作 - const updateCompare = debounce(() => { - comparearr.value = getclickdata(workall.value); - // 同步工作空间选中状态 - workref.value?.setCheckedNodes(comparearr.value, false); - }, 50); + // 使用防抖优化批量操作 - updateCompare(); + const updateCompare = debounce(() => { + const compareNodes = getclickdata(workall.value); + + // 转换节点格式 + const checkedKeys = compareNodes + .map(node => node.id) + nextTick(() => { + workref.value?.setCheckedKeys(checkedKeys, false); + }); + }, 50); + updateCompare(); }; //右键菜单 const handleRightClick = (event: Event, data: any, node: any) => { @@ -929,68 +972,68 @@ const tabs = ref(1)
工作空间:
- - - + +
+ + + +
+
备份空间:
- - - - -
- - - -
-
+ + + + +
+ + + +
+