upgrade fast clean

This commit is contained in:
Julian Freeman
2026-03-03 10:16:00 -04:00
parent b63135a0e0
commit 9fe3f606f4

View File

@@ -161,41 +161,101 @@ pub fn get_children(parent_path: String, state: &DiskState) -> Vec<FileTreeNode>
results
}
// --- 快速模式配置与逻辑 ---
#[derive(Clone)]
pub struct CleaningConfig {
pub name: String,
pub path: String,
pub filter_days: Option<u64>,
}
impl CleaningConfig {
fn new(name: &str, path: &str, filter_days: Option<u64>) -> Self {
Self { name: name.into(), path: path.into(), filter_days }
}
}
/// 获取当前所有快速清理项的配置
fn get_fast_cleaning_configs() -> Vec<CleaningConfig> {
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<ScanItem>, 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<u64>| {
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>) -> (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<CleanResult, String>
});
}
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<CleanResult, String>
})
}
fn clean_directory_contents(path: &Path) -> (u64, u32, u32) {
fn clean_directory_contents(path: &Path, filter_days: Option<u64>) -> (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;
// 目录可能因为包含未过期的文件而无法删除,这是正常的
}
}
}