From 507b049ab1be59fc95986e8424e0d611a6b52d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E7=94=9F=E6=9D=82=E7=89=A9=E6=88=BF?= <88823709+TC999@users.noreply.github.com> Date: Sun, 8 Dec 2024 21:47:46 +0800 Subject: [PATCH] bak --- src/move_module.rs | 234 +++++++++++++++++++++++++++++---------------- src/ui.rs | 12 ++- 2 files changed, 160 insertions(+), 86 deletions(-) diff --git a/src/move_module.rs b/src/move_module.rs index 679b565..3c40d25 100644 --- a/src/move_module.rs +++ b/src/move_module.rs @@ -1,105 +1,173 @@ -// move_module.rs use eframe::egui; -use std::fs::{self, File}; -use std::io::{self, Read, Write}; +use std::fs; use std::path::{Path, PathBuf}; -use std::process::Command; +use std::sync::mpsc::{Sender, Receiver}; +use std::thread; +use std::sync::mpsc; -pub struct MoveOperation { - pub source_folder: PathBuf, - pub target_folder: PathBuf, +pub struct MoveModule { + pub show_window: bool, + pub folder_name: String, + pub selected_path: Option, + pub progress: f32, // 复制进度 + pub status_message: Option, // 操作状态 } -impl MoveOperation { - pub fn new(source_folder: PathBuf) -> Self { - MoveOperation { - source_folder, - target_folder: PathBuf::new(), +impl Default for MoveModule { + fn default() -> Self { + Self { + show_window: false, + folder_name: String::new(), + selected_path: None, + progress: 0.0, + status_message: None, } } +} - pub fn choose_target_folder(&mut self, ctx: &egui::Context) -> bool { - let mut target_folder = String::new(); - egui::SidePanel::left("move_folder").show(ctx, |ui| { - ui.label("选择目标文件夹"); - if ui.button("浏览").clicked() { - let mut file_browser = egui::FileDialog::new("select_folder", "选择文件夹") - .action(egui::FileDialogAction::Open); - file_browser.show(ctx); - if let Some(path) = file_browser.selected_path() { - target_folder = path.to_str().unwrap().to_string(); - } - } - ui.text_edit_singleline(&mut target_folder); - }); - if !target_folder.is_empty() { - self.target_folder = PathBuf::from(target_folder); - true - } else { - false - } - } +impl MoveModule { + pub fn show_move_window(&mut self, ctx: &egui::Context) { + if self.show_window { + egui::Window::new("移动文件夹") + .resizable(false) + .collapsible(false) + .show(ctx, |ui| { + ui.label(format!("需要移动的文件夹: {}", self.folder_name)); + + if let Some(path) = &self.selected_path { + ui.horizontal(|ui| { + ui.label("目标路径:"); + ui.text_edit_singleline(&mut path.display().to_string()); + }); + } else { + if ui.button("选择目标路径").clicked() { + // TODO: 调用路径选择对话框,获取用户选择的目标路径 + self.selected_path = Some(PathBuf::from("C:/YourSelectedPath")); + } + } - pub fn confirm_and_move(&self, ctx: &egui::Context) -> bool { - egui::Dialog::new("confirm_move") - .default_width(400.0) - .show(ctx, |ui| { - ui.label(format!("您正在将 {} 移动至 {}", self.source_folder.display(), self.target_folder.display())); - ui.label("这可能导致UWP程序异常!"); - if ui.button("确定").clicked() { - ui.close_modal(true); - } - ui.button("取消"); - }) - } + if let Some(message) = &self.status_message { + ui.label(message); + } - pub fn perform_move(&self) -> Result<(), String> { - // 复制文件夹内容到目标路径 - self.copy_folder(&self.source_folder, &self.target_folder)?; - // 校验哈希值 - if !self.check_hash(&self.source_folder, &self.target_folder) { - return Err("哈希校验失败".to_string()); + if ui.button("确定").clicked() { + if let Some(target_path) = &self.selected_path { + if let Err(err) = self.move_folder_with_progress(&self.folder_name, target_path) { + self.status_message = Some(format!("错误: {}", err)); + } + } + } + + if ui.button("取消").clicked() { + self.show_window = false; + } + }); } - // 删除原文件夹 - self.remove_dir_all(&self.source_folder)?; - // 创建符号链接 - self.create_symbolic_link(&self.source_folder, &self.target_folder)?; - Ok(()) } - fn copy_folder(&self, source: &Path, target: &Path) -> Result<(), String> { - fs::create_dir_all(&target)?; - for entry in fs::read_dir(source).map_err(|e| e.to_string())? { - let entry = entry.map_err(|e| e.to_string())?; - let target_path = target.join(entry.file_name()); - if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) { - self.copy_folder(&entry.path(), &target_path)?; - } else { - let mut src_file = File::open(entry.path()).map_err(|e| e.to_string())?; - let mut dest_file = File::create(&target_path).map_err(|e| e.to_string())?; - io::copy(&mut src_file, &mut dest_file).map_err(|e| e.to_string())?; + fn move_folder_with_progress(&mut self, source: &str, target: &Path) -> Result<(), String> { + let source_path = Path::new(source); + if !source_path.exists() { + return Err(format!("源文件夹 {} 不存在", source)); + } + + let (tx, rx) = mpsc::channel(); + self.status_message = Some("正在移动文件夹...".to_string()); + + let target_path = target.to_path_buf(); + let source_path = source_path.to_path_buf(); + + thread::spawn(move || { + if let Err(err) = fs::create_dir_all(&target_path) { + tx.send(Err(format!("无法创建目标目录: {}", err))).unwrap(); + return; + } + + if let Err(err) = copy_dir_with_progress(&source_path, &target_path, &tx) { + tx.send(Err(format!("复制失败: {}", err))).unwrap(); + return; + } + + // 校验哈希值 + // TODO: 哈希校验逻辑 + + // 删除原文件夹 + if let Err(err) = fs::remove_dir_all(&source_path) { + tx.send(Err(format!("删除源目录失败: {}", err))).unwrap(); + return; + } + + // 创建符号链接 + let output = std::process::Command::new("cmd") + .args(["/C", "mklink", "/D", source_path.to_str().unwrap(), target_path.to_str().unwrap()]) + .output(); + + match output { + Ok(output) if output.status.success() => { + tx.send(Ok(format!( + "为 {} <<===>> {} 创建的符号链接", + source_path.display(), + target_path.display() + ))) + .unwrap(); + } + Ok(output) => { + tx.send(Err(format!( + "创建符号链接失败: {}", + String::from_utf8_lossy(&output.stderr) + ))) + .unwrap(); + } + Err(err) => { + tx.send(Err(format!("符号链接命令执行失败: {}", err))).unwrap(); + } + } + }); + + for msg in rx { + match msg { + Ok(status) => { + self.status_message = Some(status); + self.progress = 1.0; // 完成 + } + Err(err) => { + self.status_message = Some(err); + break; + } } } + Ok(()) } +} - fn check_hash(&self, source: &Path, target: &Path) -> bool { - // 这里需要实现哈希校验逻辑,为了简化,我们假设总是返回true - true - } +fn copy_dir_with_progress( + source: &Path, + target: &Path, + tx: &Sender>, +) -> Result<(), String> { + let entries = fs::read_dir(source).map_err(|err| format!("无法读取目录: {}", err))?; + let total_entries = entries.count() as f32; + let mut copied_entries = 0; - fn remove_dir_all(&self, path: &Path) -> Result<(), String> { - fs::remove_dir_all(path).map_err(|e| e.to_string()) - } + for entry in fs::read_dir(source).map_err(|err| format!("无法读取目录: {}", err))? { + let entry = entry.map_err(|err| format!("无法读取条目: {}", err))?; + let file_type = entry.file_type().map_err(|err| format!("无法获取文件类型: {}", err))?; + + let src_path = entry.path(); + let dest_path = target.join(entry.file_name()); - fn create_symbolic_link(&self, source: &Path, target: &Path) -> Result<(), String> { - let output = Command::new("cmd") - .args(&["/C", "mklink", "/D", source.to_str().unwrap(), target.to_str().unwrap()]) - .output() - .map_err(|e| e.to_string())?; - if !output.status.success() { - return Err(String::from_utf8_lossy(&output.stderr).to_string()); + if file_type.is_dir() { + fs::create_dir_all(&dest_path).map_err(|err| format!("无法创建目录: {}", err))?; + copy_dir_with_progress(&src_path, &dest_path, tx)?; + } else { + fs::copy(&src_path, &dest_path).map_err(|err| format!("无法复制文件: {}", err))?; } - Ok(()) + + copied_entries += 1.0; + let progress = copied_entries / total_entries; + tx.send(Ok(())).unwrap(); // 更新进度 } -} \ No newline at end of file + + Ok(()) +} diff --git a/src/ui.rs b/src/ui.rs index a0a7490..84673e6 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -5,11 +5,11 @@ use crate::scanner; use crate::utils; use crate::logger; // 导入 logger 模块 use crate::ignore; -use crate::move_module; use crate::open; use eframe::egui::{self, Grid, ScrollArea}; use std::sync::mpsc::{Sender, Receiver}; use std::collections::HashSet; +use crate::move_module; pub struct AppDataCleaner { // 定义数据类型 is_scanning: bool, @@ -24,6 +24,7 @@ pub struct AppDataCleaner { // 定义数据类型 //current_folder_type: String, // 新增字段 previous_logging_state: bool, // 记录上一次日志启用状态 ignored_folders: HashSet, // 忽略文件夹集合 + move_module: Option, } impl Default for AppDataCleaner { // 定义变量默认值 @@ -81,7 +82,7 @@ impl AppDataCleaner { Ok(_) => { logger::log_info(&format!("成功移动文件夹 '{}' 到 '{}'", folder, move_op.target_folder)); } - Err(err) => { + Err(err.to_string()) => { logger::log_error(&err); } } @@ -206,7 +207,12 @@ impl eframe::App for AppDataCleaner { self.confirm_delete = Some((folder.clone(), false)); } if ui.button("移动").clicked() { - + let move_module = move_module::MoveModule { + show_window: true, + folder_name: folder.clone(), + ..Default::default() + }; + self.move_module = Some(move_module); } if ui.button("忽略").clicked() { self.ignored_folders.insert(folder.clone());