upgrade fast clean
This commit is contained in:
@@ -161,41 +161,101 @@ pub fn get_children(parent_path: String, state: &DiskState) -> Vec<FileTreeNode>
|
|||||||
results
|
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)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct ScanItem { pub name: String, pub path: String, pub size: u64, pub count: u32 }
|
pub struct ScanItem { pub name: String, pub path: String, pub size: u64, pub count: u32 }
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct FastScanResult { pub items: Vec<ScanItem>, pub total_size: String, pub total_count: u32 }
|
pub struct FastScanResult { pub items: Vec<ScanItem>, pub total_size: String, pub total_count: u32 }
|
||||||
|
|
||||||
pub async fn run_fast_scan() -> FastScanResult {
|
pub async fn run_fast_scan() -> FastScanResult {
|
||||||
|
let configs = get_fast_cleaning_configs();
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
let mut total_bytes = 0;
|
let mut total_bytes = 0;
|
||||||
let mut total_count = 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);
|
for config in configs {
|
||||||
items.push(ScanItem { name: name.into(), path: path.into(), size, count });
|
let (size, count) = get_dir_stats(Path::new(&config.path), config.filter_days);
|
||||||
total_bytes += size; total_count += count;
|
items.push(ScanItem {
|
||||||
};
|
name: config.name,
|
||||||
if let Ok(t) = std::env::var("TEMP") { add_item("用户临时文件", &t, None); }
|
path: config.path,
|
||||||
add_item("系统临时文件", "C:\\Windows\\Temp", None);
|
size,
|
||||||
add_item("Windows 更新残留", "C:\\Windows\\SoftwareDistribution\\Download", Some(10));
|
count
|
||||||
add_item("传递优化缓存", "C:\\Windows\\ServiceProfiles\\NetworkService\\AppData\\Local\\Microsoft\\Windows\\DeliveryOptimization", None);
|
});
|
||||||
FastScanResult { items, total_size: format_size(total_bytes), total_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) {
|
fn get_dir_stats(path: &Path, filter_days: Option<u64>) -> (u64, u32) {
|
||||||
if !path.exists() { return (0, 0); }
|
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 now = SystemTime::now();
|
||||||
let dur = filter_days.map(|d| Duration::from_secs(d * 24 * 3600));
|
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()) {
|
for entry in walkdir::WalkDir::new(path).into_iter().filter_map(|e| e.ok()) {
|
||||||
if entry.file_type().is_file() {
|
if entry.file_type().is_file() {
|
||||||
let mut ok = true;
|
let mut ok = true;
|
||||||
if let (Some(d), Ok(m)) = (dur, entry.metadata()) {
|
if let (Some(d), Ok(m)) = (dur, entry.metadata()) {
|
||||||
if let Ok(mod_t) = m.modified() {
|
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)
|
(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 success_count = 0;
|
||||||
let mut fail_count = 0;
|
let mut fail_count = 0;
|
||||||
let mut total_freed: u64 = 0;
|
let mut total_freed: u64 = 0;
|
||||||
|
|
||||||
let mut target_paths = Vec::new();
|
for config in configs {
|
||||||
if let Ok(t) = std::env::var("TEMP") { target_paths.push(t); }
|
let path = Path::new(&config.path);
|
||||||
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);
|
|
||||||
if path.exists() {
|
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;
|
total_freed += freed;
|
||||||
success_count += s;
|
success_count += s;
|
||||||
fail_count += f;
|
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 freed = 0;
|
||||||
let mut success = 0;
|
let mut success = 0;
|
||||||
let mut fail = 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) {
|
if let Ok(entries) = fs::read_dir(path) {
|
||||||
for entry in entries.filter_map(|e| e.ok()) {
|
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 metadata = entry.metadata();
|
||||||
let size = metadata.as_ref().map(|m| m.len()).unwrap_or(0);
|
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 entry_path.is_file() {
|
||||||
if fs::remove_file(&entry_path).is_ok() {
|
if fs::remove_file(&entry_path).is_ok() {
|
||||||
freed += size;
|
freed += size;
|
||||||
@@ -264,15 +330,15 @@ fn clean_directory_contents(path: &Path) -> (u64, u32, u32) {
|
|||||||
}
|
}
|
||||||
} else if entry_path.is_dir() {
|
} 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;
|
freed += f;
|
||||||
success += s;
|
success += s;
|
||||||
fail += fl;
|
fail += fl;
|
||||||
// 尝试删除已清空的目录
|
// 尝试删除已清空的目录 (如果它本身不是根清理目录且已过期)
|
||||||
if fs::remove_dir(&entry_path).is_ok() {
|
if fs::remove_dir(&entry_path).is_ok() {
|
||||||
success += 1;
|
success += 1;
|
||||||
} else {
|
} else {
|
||||||
fail += 1;
|
// 目录可能因为包含未过期的文件而无法删除,这是正常的
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user