diff --git a/web/src/views/testdata/datamanagement/index.vue b/web/src/views/testdata/datamanagement/index.vue index e9cf0ce..9d88c64 100644 --- a/web/src/views/testdata/datamanagement/index.vue +++ b/web/src/views/testdata/datamanagement/index.vue @@ -209,6 +209,7 @@ function delSubItem(row: any) { } ) .then(() => { + loading.value = true deleteTsNodesById({ id: row.nodeId }).then((res: any) => { if (res.code == 0) { gettreedata() @@ -408,6 +409,7 @@ function delfile(row: any) { } ) .then(() => { + loading.value = true deleteTsFilesById({ id: row.id, type: 'local' }).then((res: any) => { if (res.code == 0) { getdata() @@ -443,6 +445,7 @@ function delprojectArr() { } ) .then(() => { + loading.value = true deleteTsFilesByIds({ ids: ids.join(','), type: 'local' }).then((res: any) => { if (res.code == 0) { ElMessage({ @@ -1185,6 +1188,8 @@ async function submitzip(formEl: any) { if (!formEl) return await formEl.validate((valid: any, fields: any) => { if (valid) { + loading.value = true + zipfiles.value = false if (zipzheng.value == true) { let idsarr = [] tableIdarr.value.forEach((item: any) => { @@ -1192,7 +1197,6 @@ async function submitzip(formEl: any) { }) zipObj.value.ids = idsarr.join(',') zipObj.value.parentId = zipParentid.value - // gettreedata() getdata() zipfiles.value = false zipObj.value.compressedPath = '/' + pathid.value + zipObj.value.compressedPath @@ -1206,12 +1210,10 @@ async function submitzip(formEl: any) { }) } else { - // loading.value = true + Decompression({ id: jiezip.value.id, parentId: zipParentid.value, decompressionPath: '/' + pathid.value + zipObj.value.compressedPath }).then((res: any) => { if (res.code == 0) { ElMessage.success('解压成功') - // // gettreedata() - // pathclick({ id: '' }, -1) getdata() zipfiles.value = false tableIdarr.value.length = 0 diff --git a/web/src/views/testdata/fileSynchronization/index.vue b/web/src/views/testdata/fileSynchronization/index.vue index 5a72be8..6b395f9 100644 --- a/web/src/views/testdata/fileSynchronization/index.vue +++ b/web/src/views/testdata/fileSynchronization/index.vue @@ -16,18 +16,14 @@ import Page from '@/components/Pagination/page.vue'; import textEdit from '@/components/textEditing/index.vue' import txtexl from '@/components/textEditing/txtexl.vue' // 文件预览相关 -import useFileUpload from "@/components/file/file/useFileUpload"; -import useHeaderStorageList from "@/components/header/useHeaderStorageList"; import useFileData from "@/components/file/file/useFileData"; import Viewfile from '@/views/component/Viewfile.vue' import useFilePreview from "@/components/file/file/useFilePreview"; -import MarkdownViewerAsyncLoading from "@/components/file/preview/MarkdownViewerAsyncLoading.vue"; import VideoPlayerAsyncLoading from "@/components/file/preview/VideoPlayerAsyncLoading.vue"; import TextViewerAsyncLoading from "@/components/file/preview/TextViewerAsyncLoading.vue"; import MarkdownViewerDialogAsyncLoading from "@/components/file/preview/MarkdownViewerDialogAsyncLoading.vue"; const { dialogVideoVisible, dialogTextVisible, dialogPdfVisible, dialogOfficeVisible, dialog3dVisible } = useFilePreview(); -const { clearALlFinishedUploadFile } = useFileUpload(); -const { currentStorageKey } = useHeaderStorageList(); + const { openRow } = useFileData(); //左侧树的选择框 @@ -281,38 +277,72 @@ function handleNodeClick(data: any, node: any) { } //工作空间树点击 const handleCheckChange = ( - data: any, - checked: boolean, - indeterminate: boolean + data: any, + checked: boolean, + indeterminate: boolean ) => { - console.log(data) - // debugger - if (checked === true && indeterminate === false) { - workall.value.push(data) - } else { - workall.value = workall.value.filter(item => item.id !== data.id); + // 使用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]; } - comparearr.value = getclickdata(workall.value) - beifentree.value!.setCheckedNodes(comparearr.value, false) -} + } + // 当取消选中时移除节点 + 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); + + updateCompare(); +}; //递归整理点击参数 -function getclickdata(data: any) { - data.forEach((item: any) => { - if (item.isFile == "FOLDER") { - item.children.forEach((child: any) => { - data = data.filter((items: any) => items.id !== child.id); - if (child.children.length > 0) { - getclickdata(child.children) - } - }) +function getclickdata(nodes: any[]): any[] { + // 使用 Set 存储需要排除的节点 ID + const excludeIds = new Set(); + // 使用栈结构进行迭代处理 + const stack = [...nodes]; + + // 第一阶段:收集所有需要排除的子节点 ID + while (stack.length > 0) { + const node = stack.pop(); + if (node.isFile === "FOLDER" && node.children) { + // 将子节点加入待处理队列 + stack.push(...node.children); + // 收集所有子节点 ID + node.children.forEach((child: any) => { + excludeIds.add(child.id); + }); } + } + + // 第二阶段:过滤原始数据 + return nodes.filter(node => { + // 保留非排除项,且如果是文件夹则清空其子节点 + if (!excludeIds.has(node.id)) { + // 创建新对象避免污染原始数据 + return { + ...node, + children: node.isFile === "FOLDER" ? [] : node.children + }; + } + return false; }); - return data } //获取本地树 function getlocaltree() { - worktree.value = true - listLocalTree({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => { + + 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') @@ -320,12 +350,14 @@ function getlocaltree() { worktree.value = false diffColor() }) + } } const worktree1 = ref(false) //获取minio树 function getminiotree() { - worktree1.value = true - listBackupTree({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => { + 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') @@ -333,33 +365,58 @@ function getminiotree() { worktree1.value = false diffColor() }) + } } //数据递归赋值 -function assignment(data: any, difference: any) { - data.forEach((item: any) => { - item.location = difference - item.station = '0' //0相同1新增2变更3删除 - if (item.children.length > 0) { - assignment(item.children, difference) +function assignment(data: any[], difference: 'local' | 'minio') { + // 使用栈结构替代递归,防止栈溢出 + const stack: any[] = [...data]; + while (stack.length > 0) { + const node = stack.pop(); + if (!node) continue; + // 添加类型断言确保操作安全 + node.location = difference; + node.station = '0'; // 0: 相同, 1: 新增, 2: 变更, 3: 删除 + + // 反向压栈保持原有顺序 + if (node.children?.length) { + stack.push(...[...node.children].reverse()); } - }) + } } //备份空间 const beifentree = ref() const backupsChange = ( - data: any, - checked: boolean, - indeterminate: boolean + data: any, + checked: boolean, + indeterminate: boolean ) => { - if (checked == true && indeterminate == false) { - workall.value.push(data) - } else { - workall.value = workall.value.filter(item => item.id !== data.id); + // 使用临时变量避免多次访问响应式对象 + 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); + } - comparearr.value = getclickdata(workall.value) - workref.value!.setCheckedNodes(comparearr.value, false) -} + // 使用防抖优化批量操作 + const updateCompare = debounce(() => { + comparearr.value = getclickdata(workall.value); + // 同步工作空间选中状态 + workref.value?.setCheckedNodes(comparearr.value, false); + }, 50); + + updateCompare(); +}; //右键菜单 const handleRightClick = (event: Event, data: any, node: any) => { if (data.station != '0') { @@ -489,11 +546,13 @@ function tableBeifen(row: any) { size: row.fileSize, type: row.isFile }] + loading1.value = true + loading2.value = true uploadToBackup({ parameterLists: params }).then((res: any) => { if (res.code == '0') { ElMessage.success("上传成功") - localOnlyFiles.value = localOnlyFiles.value.filter((item: any) => item.id !== row.id) - md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== row.id) + diffSure() + diffChange() } }) }) @@ -520,13 +579,13 @@ function moretableBeifen() { beifenArr3.push({ path: '/' + pathid.value + items.workPath, name: items.fileName, size: items.fileSize, type: items.isFile }) // items.path = '/' + pathid.value + items.path }) + loading1.value = true + loading2.value = true uploadToBackup({ parameterLists: beifenArr3 }).then((res: any) => { if (res.code == '0') { + diffSure() + diffChange() ElMessage.success("上传成功") - beifenArr.value.forEach((items: any) => { - localOnlyFiles.value = localOnlyFiles.value.filter((item: any) => item.id !== items.id) - md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== items.id) - }) } }) @@ -551,11 +610,13 @@ function tablerestore(row: any) { size: row.fileSize, type: row.isFile }] + loading3.value = true + loading2.value = true downloadToLocal({ parameterLists: params }).then((res: any) => { if (res.code == '0') { ElMessage.success("恢复成功") - minioOnlyFiles.value = minioOnlyFiles.value.filter((item: any) => item.id !== row.id) - md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== row.id) + diffChange() + diffMiss() } }) }) @@ -581,13 +642,13 @@ function moretablerestore() { restoreArr2.forEach((items: any) => { restoreArr3.push({ path: '/' + pathid.value + items.backupPath, name: items.fileName, size: items.fileSize, type: items.isFile }) }) + loading2.value = true + loading3.value = true downloadToLocal({ parameterLists: restoreArr3 }).then((res: any) => { if (res.code == '0') { ElMessage.success("恢复成功") - restoreArr.value.forEach((items: any) => { - minioOnlyFiles.value = minioOnlyFiles.value.filter((item: any) => item.id !== items.id) - md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== items.id) - }) + diffChange() + diffMiss() } }) @@ -608,12 +669,11 @@ function delhuifu() { restoreArr.value.forEach((item: any) => { ids.value.push(item.id) }) + loading3.value = true deleteTsFilesByIds({ ids: ids.value.join(','), type: 'minio' }).then((res: any) => { if (res.code == '0') { ElMessage.success("删除成功") - restoreArr.value.forEach((items: any) => { - minioOnlyFiles.value = minioOnlyFiles.value.filter((item: any) => item.id !== items.id) - }) + diffMiss() } }) @@ -641,6 +701,8 @@ function bfclick(type: any) { } ) .then(() => { + loading1.value = true + loading2.value = true if (type == 'bf') { let beifenArr3 = [] let beifenArr2 = JSON.parse(JSON.stringify(changeclick.value)) @@ -650,9 +712,7 @@ function bfclick(type: any) { uploadToBackup({ parameterLists: beifenArr3 }).then((res: any) => { if (res.code == '0') { ElMessage.success("上传成功") - changeclick.value.forEach((items: any) => { - md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== items.id) - }) + diffChange() } }) } else { @@ -664,9 +724,7 @@ function bfclick(type: any) { downloadToLocal({ parameterLists: restoreArr3 }).then((res: any) => { if (res.code == '0') { ElMessage.success("恢复成功") - changeclick.value.forEach((items: any) => { - md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== items.id) - }) + diffChange() } }) }