diff --git a/tauri-app/src-tauri/src/lib.rs b/tauri-app/src-tauri/src/lib.rs index 40099c0..0b86571 100644 --- a/tauri-app/src-tauri/src/lib.rs +++ b/tauri-app/src-tauri/src/lib.rs @@ -46,6 +46,71 @@ pub struct ApiResponse { pub data: Option, } +// ============================================================ +// 视频缓存清理 +// ============================================================ + +/// 清理 video_cache 目录 +/// +/// 策略: +/// 1. 删除超过 30 天未修改的文件 +/// 2. 总容量超过 500MB 时,按修改时间删最旧文件直到 300MB +fn clean_video_cache(app_data_dir: &std::path::Path) { + let cache_dir = app_data_dir.join("video_cache"); + if !cache_dir.exists() { + return; + } + + let max_age = std::time::Duration::from_secs(30 * 24 * 60 * 60); + let max_total_size: u64 = 500 * 1024 * 1024; + let target_size: u64 = 300 * 1024 * 1024; + let now = std::time::SystemTime::now(); + + let mut entries: Vec<(std::path::PathBuf, std::time::SystemTime, u64)> = Vec::new(); + let mut total_size: u64 = 0; + + let read_dir = match std::fs::read_dir(&cache_dir) { + Ok(d) => d, + Err(e) => { + eprintln!("[cache] 无法读取缓存目录: {}", e); + return; + } + }; + + for entry in read_dir.flatten() { + let Ok(metadata) = entry.metadata() else { continue }; + if !metadata.is_file() { continue; } + let mtime = metadata.modified().unwrap_or(now); + let size = metadata.len(); + total_size += size; + entries.push((entry.path(), mtime, size)); + } + + // 1. 删除超过 30 天的文件 + let mut deleted_size: u64 = 0; + for (path, mtime, size) in &entries { + if now.duration_since(*mtime).unwrap_or_default() > max_age { + if std::fs::remove_file(path).is_ok() { + deleted_size += size; + } + } + } + + // 2. 容量超限,删最旧的 + let remaining_size = total_size.saturating_sub(deleted_size); + if remaining_size > max_total_size { + let mut sorted = entries; + sorted.sort_by_key(|(_, mtime, _)| *mtime); + let mut to_free = remaining_size.saturating_sub(target_size); + for (path, _, size) in sorted { + if to_free == 0 { break; } + if path.exists() && std::fs::remove_file(&path).is_ok() { + to_free = to_free.saturating_sub(size); + } + } + } +} + // ============================================================ // 应用入口 // ============================================================ @@ -69,7 +134,9 @@ pub fn run() { .setup(|app| { // 初始化应用数据目录(所有业务数据的根目录) if let Ok(app_data_dir) = app.path().app_local_data_dir() { - crate::storage::init_app_data_dir(app_data_dir); + crate::storage::init_app_data_dir(app_data_dir.clone()); + // 后台清理过期视频缓存,不阻塞首屏 + std::thread::spawn(move || clean_video_cache(&app_data_dir)); } // 窗口初始 visible=false,setup 阶段先显示窗口