代码优化
This commit is contained in:
parent
aefba7c565
commit
557970fd87
317
web/src/views/testdata/fileSynchronization/index.vue
vendored
317
web/src/views/testdata/fileSynchronization/index.vue
vendored
@ -189,7 +189,7 @@ function diffMiss() {
|
|||||||
function diffColor() {
|
function diffColor() {
|
||||||
// 1. 使用Map优化查找性能
|
// 1. 使用Map优化查找性能
|
||||||
const createMap = (arr: any[]) => new Map(arr.map(item => [item.id, item]));
|
const createMap = (arr: any[]) => new Map(arr.map(item => [item.id, item]));
|
||||||
|
|
||||||
const localMap = createMap(localOnlyFiles.value);
|
const localMap = createMap(localOnlyFiles.value);
|
||||||
const md5Map = createMap(md5MismatchedFiles.value);
|
const md5Map = createMap(md5MismatchedFiles.value);
|
||||||
const minioMap = createMap(minioOnlyFiles.value);
|
const minioMap = createMap(minioOnlyFiles.value);
|
||||||
@ -197,7 +197,7 @@ function diffColor() {
|
|||||||
// 2. 单次遍历优化
|
// 2. 单次遍历优化
|
||||||
const processTree = (tree: any[], location: 'local' | 'minio') => {
|
const processTree = (tree: any[], location: 'local' | 'minio') => {
|
||||||
const stack = [...tree];
|
const stack = [...tree];
|
||||||
|
|
||||||
while (stack.length) {
|
while (stack.length) {
|
||||||
const node = stack.pop();
|
const node = stack.pop();
|
||||||
if (!node) continue;
|
if (!node) continue;
|
||||||
@ -272,37 +272,45 @@ function gettreedata() {
|
|||||||
}
|
}
|
||||||
function handleNodeClick(data: any, node: any) {
|
function handleNodeClick(data: any, node: any) {
|
||||||
pathid.value = data.nodeId
|
pathid.value = data.nodeId
|
||||||
|
localOnlyFiles.value.length = 0
|
||||||
|
md5MismatchedFiles.value.length = 0
|
||||||
|
minioOnlyFiles.value.length = 0
|
||||||
getlocaltree()
|
getlocaltree()
|
||||||
getminiotree()
|
getminiotree()
|
||||||
}
|
}
|
||||||
//工作空间树点击
|
//工作空间树点击
|
||||||
const handleCheckChange = (
|
const handleCheckChange = (
|
||||||
data: any,
|
data: any,
|
||||||
checked: boolean,
|
checked: boolean,
|
||||||
indeterminate: boolean
|
indeterminate: boolean
|
||||||
) => {
|
) => {
|
||||||
// 使用Map优化查找性能
|
// 使用Map优化查找性能
|
||||||
const nodeMap = new Map(workall.value.map(item => [item.id, item]));
|
const nodeMap = new Map(workall.value.map(item => [item.id, item]));
|
||||||
|
|
||||||
// 当完全选中时添加节点
|
// 当完全选中时添加节点
|
||||||
if (checked && !indeterminate) {
|
if (checked && !indeterminate) {
|
||||||
if (!nodeMap.has(data.id)) {
|
if (!nodeMap.has(data.id)) {
|
||||||
workall.value = [...workall.value, data];
|
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(() => {
|
const updateCompare = debounce(() => {
|
||||||
comparearr.value = getclickdata(workall.value);
|
const compareNodes = getclickdata(workall.value);
|
||||||
// 同步备份空间的选中状态
|
|
||||||
beifentree.value?.setCheckedNodes(comparearr.value, false);
|
|
||||||
}, 50);
|
|
||||||
|
|
||||||
updateCompare();
|
// 转换节点格式
|
||||||
|
const checkedKeys = compareNodes
|
||||||
|
.map(node => node.id)
|
||||||
|
nextTick(() => {
|
||||||
|
beifentree.value?.setCheckedKeys(checkedKeys, false);
|
||||||
|
});
|
||||||
|
}, 50);
|
||||||
|
|
||||||
|
updateCompare();
|
||||||
};
|
};
|
||||||
//递归整理点击参数
|
//递归整理点击参数
|
||||||
function getclickdata(nodes: any[]): any[] {
|
function getclickdata(nodes: any[]): any[] {
|
||||||
@ -310,7 +318,7 @@ function getclickdata(nodes: any[]): any[] {
|
|||||||
const excludeIds = new Set<string>();
|
const excludeIds = new Set<string>();
|
||||||
// 使用栈结构进行迭代处理
|
// 使用栈结构进行迭代处理
|
||||||
const stack = [...nodes];
|
const stack = [...nodes];
|
||||||
|
|
||||||
// 第一阶段:收集所有需要排除的子节点 ID
|
// 第一阶段:收集所有需要排除的子节点 ID
|
||||||
while (stack.length > 0) {
|
while (stack.length > 0) {
|
||||||
const node = stack.pop();
|
const node = stack.pop();
|
||||||
@ -339,83 +347,118 @@ function getclickdata(nodes: any[]): any[] {
|
|||||||
}
|
}
|
||||||
//获取本地树
|
//获取本地树
|
||||||
function getlocaltree() {
|
function getlocaltree() {
|
||||||
|
if (!projectId.value || !pathid.value) return;
|
||||||
if(projectId.value && pathid.value){
|
|
||||||
worktree.value = true
|
worktree.value = true;
|
||||||
listLocalTree({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => {
|
listLocalTree({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => {
|
||||||
workdata.value = res.data.localTrees
|
const CHUNK_SIZE = 500; // 每批处理500个节点
|
||||||
if (workdata.value.length > 0) {
|
const rawData = res.data.localTrees;
|
||||||
assignment(workdata.value, 'local')
|
|
||||||
}
|
// 使用requestAnimationFrame分批次处理
|
||||||
worktree.value = false
|
const processChunk = (index = 0) => {
|
||||||
diffColor()
|
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)
|
const worktree1 = ref(false)
|
||||||
//获取minio树
|
//获取minio树
|
||||||
function getminiotree() {
|
function getminiotree() {
|
||||||
if(projectId.value && pathid.value){
|
if (!projectId.value || !pathid.value) return;
|
||||||
worktree1.value = true
|
|
||||||
listBackupTree({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => {
|
worktree1.value = true;
|
||||||
backupsdata.value = res.data.minioTrees
|
listBackupTree({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => {
|
||||||
if (backupsdata.value.length > 0) {
|
const CHUNK_SIZE = 500;
|
||||||
assignment(backupsdata.value, 'minio')
|
const rawData = res.data.minioTrees;
|
||||||
}
|
|
||||||
worktree1.value = false
|
const processChunk = (index = 0) => {
|
||||||
diffColor()
|
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') {
|
function assignment(data: any[], difference: 'local' | 'minio') {
|
||||||
// 使用栈结构替代递归,防止栈溢出
|
const queue = [...data]; // 使用队列代替栈
|
||||||
const stack: any[] = [...data];
|
while (queue.length > 0) {
|
||||||
while (stack.length > 0) {
|
const node = queue.shift();
|
||||||
const node = stack.pop();
|
|
||||||
if (!node) continue;
|
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) {
|
if (node.children?.length) {
|
||||||
stack.push(...[...node.children].reverse());
|
queue.push(...node.children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//备份空间
|
//备份空间
|
||||||
const beifentree = ref()
|
const beifentree = ref()
|
||||||
const backupsChange = (
|
const backupsChange = (
|
||||||
data: any,
|
data: any,
|
||||||
checked: boolean,
|
checked: boolean,
|
||||||
indeterminate: boolean
|
indeterminate: boolean
|
||||||
) => {
|
) => {
|
||||||
// 使用临时变量避免多次访问响应式对象
|
// 使用临时变量避免多次访问响应式对象
|
||||||
const currentWorkall = [...workall.value];
|
const currentWorkall = [...workall.value];
|
||||||
|
|
||||||
// 使用Map优化查找性能
|
// 使用Map优化查找性能
|
||||||
const nodeMap = new Map(currentWorkall.map(item => [item.id, item]));
|
const nodeMap = new Map(currentWorkall.map(item => [item.id, item]));
|
||||||
|
|
||||||
// 当完全选中时添加节点(防止重复添加)
|
// 当完全选中时添加节点(防止重复添加)
|
||||||
if (checked && !indeterminate) {
|
if (checked && !indeterminate) {
|
||||||
if (!nodeMap.has(data.id)) {
|
if (!nodeMap.has(data.id)) {
|
||||||
workall.value = [...currentWorkall, data];
|
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) => {
|
const handleRightClick = (event: Event, data: any, node: any) => {
|
||||||
@ -929,68 +972,68 @@ const tabs = ref(1)
|
|||||||
<div class="tree_left">
|
<div class="tree_left">
|
||||||
<div class="tree_title">工作空间:</div>
|
<div class="tree_title">工作空间:</div>
|
||||||
<div class="tree_content">
|
<div class="tree_content">
|
||||||
<el-scrollbar height="73vh">
|
<!-- <el-scrollbar height="73vh"> -->
|
||||||
<el-tree ref="workref" style="max-width: 600px" :props="props" :data="workdata"
|
<el-tree-v2 ref="workref" style="max-width: 600px" :props="props" :data="workdata" :height="700"
|
||||||
@node-click="workclick" @node-contextmenu="handleRightClick" default-expand-all
|
@node-click="workclick" @node-contextmenu="handleRightClick" default-expand-all
|
||||||
:expand-on-click-node="false" show-checkbox node-key="id" v-loading="worktree"
|
:expand-on-click-node="false" show-checkbox node-key="id" v-loading="worktree"
|
||||||
@check-change="handleCheckChange">
|
@check-change="handleCheckChange">
|
||||||
<template #default="{ data }">
|
<template #default="{ data }">
|
||||||
<span
|
<span
|
||||||
:class="data.station == '0' ? 'custom-tree-node' : (data.station == '1' ? 'custom-tree-node1' : (data.station == '2' ? 'custom-tree-node2' : 'custom-tree-node3'))">
|
:class="data.station == '0' ? 'custom-tree-node' : (data.station == '1' ? 'custom-tree-node1' : (data.station == '2' ? 'custom-tree-node2' : 'custom-tree-node3'))">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
{{ data.fileName }}({{ data.isFile == 'FOLDER' ? data.children.length :
|
{{ data.fileName }}({{ data.isFile == 'FOLDER' ? data.children.length :
|
||||||
data.fileSize + 'MB' }})
|
data.fileSize + 'MB' }})
|
||||||
<span v-if="data.station != '0'">({{ data.station == '1' ? '新增' :
|
<span v-if="data.station != '0'">({{ data.station == '1' ? '新增' :
|
||||||
(data.station
|
(data.station
|
||||||
== '2' ? '已变更' : '已删除') }})</span>
|
== '2' ? '已变更' : '已删除') }})</span>
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</span>
|
||||||
</el-tree>
|
</template>
|
||||||
<div v-show="contextMenuVisible" class="context-menu" :style="{
|
</el-tree-v2>
|
||||||
left: `${contextMenuPosition.x}px`,
|
<div v-show="contextMenuVisible" class="context-menu" :style="{
|
||||||
top: `${contextMenuPosition.y}px`
|
left: `${contextMenuPosition.x}px`,
|
||||||
}">
|
top: `${contextMenuPosition.y}px`
|
||||||
<div class="menu-item" @click="handleMenuClick('backups', 'local')">备份</div>
|
}">
|
||||||
<div class="menu-item" @click="handleMenuClick('delete', 'local')">删除</div>
|
<div class="menu-item" @click="handleMenuClick('backups', 'local')">备份</div>
|
||||||
<div v-if="currentNode && currentNode.isFile == 'FILE'" class="menu-item"
|
<div class="menu-item" @click="handleMenuClick('delete', 'local')">删除</div>
|
||||||
@click="handleMenuClick('preview', 'local')">预览</div>
|
<div v-if="currentNode && currentNode.isFile == 'FILE'" class="menu-item"
|
||||||
</div>
|
@click="handleMenuClick('preview', 'local')">预览</div>
|
||||||
</el-scrollbar>
|
</div>
|
||||||
|
<!-- </el-scrollbar> -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tree_left">
|
<div class="tree_left">
|
||||||
<div class="tree_title">备份空间:</div>
|
<div class="tree_title">备份空间:</div>
|
||||||
<div class="tree_content">
|
<div class="tree_content">
|
||||||
<el-scrollbar height="73vh">
|
<!-- <el-scrollbar height="73vh"> -->
|
||||||
<el-tree ref="beifentree" style="max-width: 600px" :props="props" :data="backupsdata"
|
<el-tree-v2 ref="beifentree" style="max-width: 600px" :props="props" :data="backupsdata"
|
||||||
default-expand-all @node-click="workclick" @node-contextmenu="handleRightClick"
|
:height="700" default-expand-all @node-click="workclick"
|
||||||
:expand-on-click-node="false" show-checkbox node-key="id" v-loading="worktree1"
|
@node-contextmenu="handleRightClick" :expand-on-click-node="false" show-checkbox
|
||||||
@check-change="backupsChange">
|
node-key="id" v-loading="worktree1" @check-change="backupsChange">
|
||||||
<template #default="{ data }">
|
<template #default="{ data }">
|
||||||
<span
|
<span
|
||||||
:class="data.station == '0' ? 'custom-tree-node' : (data.station == '1' ? 'custom-tree-node1' : (data.station == '2' ? 'custom-tree-node2' : 'custom-tree-node3'))">
|
:class="data.station == '0' ? 'custom-tree-node' : (data.station == '1' ? 'custom-tree-node1' : (data.station == '2' ? 'custom-tree-node2' : 'custom-tree-node3'))">
|
||||||
<!-- data.children.length -->
|
<!-- data.children.length -->
|
||||||
<span class="text">{{ data.fileName }}({{ data.isFile == 'FOLDER' ?
|
<span class="text">{{ data.fileName }}({{ data.isFile == 'FOLDER' ?
|
||||||
data.children.length :
|
data.children.length :
|
||||||
data.fileSize + 'MB' }})</span>
|
data.fileSize + 'MB' }})</span>
|
||||||
<span v-if="data.station != '0'">({{ data.station == '1' ? '新增' :
|
<span v-if="data.station != '0'">({{ data.station == '1' ? '新增' :
|
||||||
(data.station
|
(data.station
|
||||||
== '2' ? '已变更' : '已删除') }})</span>
|
== '2' ? '已变更' : '已删除') }})</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-tree>
|
</el-tree-v2>
|
||||||
<div v-show="contextMenuVisible2" class="context-menu" :style="{
|
<div v-show="contextMenuVisible2" class="context-menu" :style="{
|
||||||
left: `${contextMenuPosition.x}px`,
|
left: `${contextMenuPosition.x}px`,
|
||||||
top: `${contextMenuPosition.y}px`
|
top: `${contextMenuPosition.y}px`
|
||||||
}">
|
}">
|
||||||
<div class="menu-item" @click="handleMenuClick('restore', 'minio')">恢复</div>
|
<div class="menu-item" @click="handleMenuClick('restore', 'minio')">恢复</div>
|
||||||
<div class="menu-item" @click="handleMenuClick('delete', 'minio')">删除</div>
|
<div class="menu-item" @click="handleMenuClick('delete', 'minio')">删除</div>
|
||||||
<div v-if="currentNode && currentNode.isFile == 'FILE'" class="menu-item"
|
<div v-if="currentNode && currentNode.isFile == 'FILE'" class="menu-item"
|
||||||
@click="handleMenuClick('preview', 'minio')">预览</div>
|
@click="handleMenuClick('preview', 'minio')">预览</div>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
<!-- </el-scrollbar> -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user