diff --git a/src-tauri/src/cleaner.rs b/src-tauri/src/cleaner.rs index d6501cd..f8ebda3 100644 --- a/src-tauri/src/cleaner.rs +++ b/src-tauri/src/cleaner.rs @@ -161,41 +161,101 @@ pub fn get_children(parent_path: String, state: &DiskState) -> Vec results } +// --- 快速模式配置与逻辑 --- + +#[derive(Clone)] +pub struct CleaningConfig { + pub name: String, + pub path: String, + pub filter_days: Option, +} + +impl CleaningConfig { + fn new(name: &str, path: &str, filter_days: Option) -> Self { + Self { name: name.into(), path: path.into(), filter_days } + } +} + +/// 获取当前所有快速清理项的配置 +fn get_fast_cleaning_configs() -> Vec { + let mut configs = Vec::new(); + + // 1. 用户临时文件 + if let Ok(t) = std::env::var("TEMP") { + configs.push(CleaningConfig::new("用户临时文件", &t, None)); + } + + // 2. 系统临时文件 + configs.push(CleaningConfig::new("系统临时文件", "C:\\Windows\\Temp", None)); + + // 3. Windows 更新残留 (通常建议清理 10 天前的) + configs.push(CleaningConfig::new("Windows 更新残留", "C:\\Windows\\SoftwareDistribution\\Download", Some(10))); + + // 4. 传递优化缓存 + // configs.push(CleaningConfig::new( + // "传递优化缓存", + // "C:\\Windows\\ServiceProfiles\\NetworkService\\AppData\\Local\\Microsoft\\Windows\\DeliveryOptimization", + // None + // )); + + // 以后要添加新目录,只需在此处追加一行: + // configs.push(CleaningConfig::new("新目录名称", "C:\\路径", None)); + + configs +} + #[derive(Serialize, Clone)] pub struct ScanItem { pub name: String, pub path: String, pub size: u64, pub count: u32 } + #[derive(Serialize)] pub struct FastScanResult { pub items: Vec, pub total_size: String, pub total_count: u32 } pub async fn run_fast_scan() -> FastScanResult { + let configs = get_fast_cleaning_configs(); let mut items = Vec::new(); let mut total_bytes = 0; let mut total_count = 0; - let mut add_item = |name: &str, path: &str, filter: Option| { - let (size, count) = get_dir_stats(Path::new(path), filter); - items.push(ScanItem { name: name.into(), path: path.into(), size, count }); - total_bytes += size; total_count += count; - }; - if let Ok(t) = std::env::var("TEMP") { add_item("用户临时文件", &t, None); } - add_item("系统临时文件", "C:\\Windows\\Temp", None); - add_item("Windows 更新残留", "C:\\Windows\\SoftwareDistribution\\Download", Some(10)); - add_item("传递优化缓存", "C:\\Windows\\ServiceProfiles\\NetworkService\\AppData\\Local\\Microsoft\\Windows\\DeliveryOptimization", None); - FastScanResult { items, total_size: format_size(total_bytes), total_count } + + for config in configs { + let (size, count) = get_dir_stats(Path::new(&config.path), config.filter_days); + items.push(ScanItem { + name: config.name, + path: config.path, + size, + count + }); + total_bytes += size; + total_count += count; + } + + FastScanResult { + items, + total_size: format_size(total_bytes), + total_count + } } fn get_dir_stats(path: &Path, filter_days: Option) -> (u64, u32) { if !path.exists() { return (0, 0); } - let mut size = 0; let mut count = 0; + let mut size = 0; + let mut count = 0; let now = SystemTime::now(); let dur = filter_days.map(|d| Duration::from_secs(d * 24 * 3600)); + for entry in walkdir::WalkDir::new(path).into_iter().filter_map(|e| e.ok()) { if entry.file_type().is_file() { let mut ok = true; if let (Some(d), Ok(m)) = (dur, entry.metadata()) { if let Ok(mod_t) = m.modified() { - if let Ok(el) = now.duration_since(mod_t) { if el < d { ok = false; } } + if let Ok(el) = now.duration_since(mod_t) { + if el < d { ok = false; } + } } } - if ok { size += entry.metadata().map(|m| m.len()).unwrap_or(0); count += 1; } + if ok { + size += entry.metadata().map(|m| m.len()).unwrap_or(0); + count += 1; + } } } (size, count) @@ -217,20 +277,15 @@ pub async fn run_fast_clean(is_simulation: bool) -> Result }); } + let configs = get_fast_cleaning_configs(); let mut success_count = 0; let mut fail_count = 0; let mut total_freed: u64 = 0; - let mut target_paths = Vec::new(); - if let Ok(t) = std::env::var("TEMP") { target_paths.push(t); } - target_paths.push("C:\\Windows\\Temp".into()); - target_paths.push("C:\\Windows\\SoftwareDistribution\\Download".into()); - target_paths.push("C:\\Windows\\ServiceProfiles\\NetworkService\\AppData\\Local\\Microsoft\\Windows\\DeliveryOptimization".into()); - - for path_str in target_paths { - let path = Path::new(&path_str); + for config in configs { + let path = Path::new(&config.path); if path.exists() { - let (freed, s, f) = clean_directory_contents(path); + let (freed, s, f) = clean_directory_contents(path, config.filter_days); total_freed += freed; success_count += s; fail_count += f; @@ -244,10 +299,12 @@ pub async fn run_fast_clean(is_simulation: bool) -> Result }) } -fn clean_directory_contents(path: &Path) -> (u64, u32, u32) { +fn clean_directory_contents(path: &Path, filter_days: Option) -> (u64, u32, u32) { let mut freed = 0; let mut success = 0; let mut fail = 0; + let now = SystemTime::now(); + let dur = filter_days.map(|d| Duration::from_secs(d * 24 * 3600)); if let Ok(entries) = fs::read_dir(path) { for entry in entries.filter_map(|e| e.ok()) { @@ -255,6 +312,15 @@ fn clean_directory_contents(path: &Path) -> (u64, u32, u32) { let metadata = entry.metadata(); let size = metadata.as_ref().map(|m| m.len()).unwrap_or(0); + // 检查过滤逻辑 (如果设置了天数) + if let (Some(d), Ok(m)) = (dur, &metadata) { + if let Ok(mod_t) = m.modified() { + if let Ok(el) = now.duration_since(mod_t) { + if el < d { continue; } + } + } + } + if entry_path.is_file() { if fs::remove_file(&entry_path).is_ok() { freed += size; @@ -264,15 +330,15 @@ fn clean_directory_contents(path: &Path) -> (u64, u32, u32) { } } else if entry_path.is_dir() { // 递归清理子目录 - let (f, s, fl) = clean_directory_contents(&entry_path); + let (f, s, fl) = clean_directory_contents(&entry_path, filter_days); freed += f; success += s; fail += fl; - // 尝试删除已清空的目录 + // 尝试删除已清空的目录 (如果它本身不是根清理目录且已过期) if fs::remove_dir(&entry_path).is_ok() { success += 1; } else { - fail += 1; + // 目录可能因为包含未过期的文件而无法删除,这是正常的 } } }