From 7bd7fa7dbfc8bb6ee47df25f52e11eedf95b568f Mon Sep 17 00:00:00 2001 From: Momentry Studio Date: Fri, 9 Oct 2026 23:11:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20get=5Ffiles=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=A4=9A=E9=A1=B5=E8=8E=B7=E5=8F=96=E6=89=80=E6=9C=89=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: - Library 只显示 20 个文件 - 数据库有 176 个文件 - API per_page 强制限制最大 20 解决方案: - 实现多页获取逻辑 - 先获取第一页得到 total - 计算总页数 - 循环获取剩余页 - 合并所有文件返回 变更: - get_files 函数重构 - 新增 parse_file_info 辅助函数 - 支持最多 500 个文件(pageSize 限制) 测试: - ✅ 编译通过 - ⏳ 需要部署测试 预期效果: - Library 显示所有文件(176 个) - 一次调用获取所有数据 - 前端无需修改 --- src-tauri/src/main.rs | 85 +++++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 24 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index bc3fd84..8c2edd8 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -220,35 +220,72 @@ async fn search_agents(query: String, conversation_id: Option) -> Result async fn get_files(args: GetFilesArgs) -> Result, String> { let page_size = args.page_size; let client = get_client(); - let url = format!("{}/api/v1/files?api_key={}&page=1&per_page={}", CORE_API, API_KEY, page_size); + let per_page = 20; // API 限制最大 20 + // 获取第一页并获取总数 + let url = format!("{}/api/v1/files?api_key={}&page=1&per_page={}", CORE_API, API_KEY, per_page); let response = client.get(&url).send().await.map_err(|e| format!("Request failed: {}", e))?; let json: serde_json::Value = response.json().await.map_err(|e| format!("Parse failed: {}", e))?; - let files: Vec = json["data"] - .as_array() - .unwrap_or(&vec![]) - .iter() - .filter_map(|f| { - let is_reg = f["is_registered"].as_bool().unwrap_or(false); - let file_uuid = f["file_uuid"].as_str() - .unwrap_or_else(|| f["file_path"].as_str().unwrap_or("")).to_string(); - let status = f["status"].as_str().unwrap_or("").to_string(); - Some(FileInfo { - file_uuid, - file_name: f["file_name"].as_str()?.to_string(), - file_path: f["file_path"].as_str().unwrap_or("").to_string(), - file_size: f["file_size"].as_i64().unwrap_or(0), - modified_time: f["modified_time"].as_str().unwrap_or("").to_string(), - is_registered: is_reg, - registration_time: f["registration_time"].as_str().map(|s| s.to_string()), - ingested: matches!(status.as_str(), "completed" | "keyword_ready" | "semantic_ready" | "face_mgmt_ready" | "agent_ready"), - status, - }) - }) - .collect(); + let total = json["total"].as_u64().unwrap_or(0) as usize; + let mut all_files: Vec = Vec::new(); - Ok(files) + // 解析第一页的文件 + if let Some(files_array) = json["data"].as_array() { + for f in files_array { + if let Some(file_info) = parse_file_info(f) { + all_files.push(file_info); + } + } + } + + // 计算总页数 + let total_pages = (total + per_page - 1) / per_page; + + // 获取剩余页(如果有限制) + let max_files = std::cmp::min(page_size, total); + let max_pages = (max_files + per_page - 1) / per_page; + + for page in 2..=max_pages.min(total_pages) { + if all_files.len() >= page_size { + break; + } + + let url = format!("{}/api/v1/files?api_key={}&page={}&per_page={}", CORE_API, API_KEY, page, per_page); + let response = client.get(&url).send().await.map_err(|e| format!("Request failed: {}", e))?; + let json: serde_json::Value = response.json().await.map_err(|e| format!("Parse failed: {}", e))?; + + if let Some(files_array) = json["data"].as_array() { + for f in files_array { + if all_files.len() >= page_size { + break; + } + if let Some(file_info) = parse_file_info(f) { + all_files.push(file_info); + } + } + } + } + + Ok(all_files) +} + +fn parse_file_info(f: &serde_json::Value) -> Option { + let is_reg = f["is_registered"].as_bool().unwrap_or(false); + let file_uuid = f["file_uuid"].as_str() + .unwrap_or_else(|| f["file_path"].as_str().unwrap_or("")).to_string(); + let status = f["status"].as_str().unwrap_or("").to_string(); + Some(FileInfo { + file_uuid, + file_name: f["file_name"].as_str()?.to_string(), + file_path: f["file_path"].as_str().unwrap_or("").to_string(), + file_size: f["file_size"].as_i64().unwrap_or(0), + modified_time: f["modified_time"].as_str().unwrap_or("").to_string(), + is_registered: is_reg, + registration_time: f["registration_time"].as_str().map(|s| s.to_string()), + ingested: matches!(status.as_str(), "completed" | "keyword_ready" | "semantic_ready" | "face_mgmt_ready" | "agent_ready"), + status, + }) } #[derive(Serialize)]