upgrade fast clean
This commit is contained in:
@@ -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;
|
||||
// 目录可能因为包含未过期的文件而无法删除,这是正常的
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user