feat: get_files 支持多页获取所有文件

问题:
- Library 只显示 20 个文件
- 数据库有 176 个文件
- API per_page 强制限制最大 20

解决方案:
- 实现多页获取逻辑
- 先获取第一页得到 total
- 计算总页数
- 循环获取剩余页
- 合并所有文件返回

变更:
- get_files 函数重构
- 新增 parse_file_info 辅助函数
- 支持最多 500 个文件(pageSize 限制)

测试:
- ✅ 编译通过
- ⏳ 需要部署测试

预期效果:
- Library 显示所有文件(176 个)
- 一次调用获取所有数据
- 前端无需修改
This commit is contained in:
2026-10-09 23:11:30 +08:00
parent 670ef45c32
commit 7bd7fa7dbf

View File

@@ -220,35 +220,72 @@ async fn search_agents(query: String, conversation_id: Option<String>) -> Result
async fn get_files(args: GetFilesArgs) -> Result<Vec<FileInfo>, String> { async fn get_files(args: GetFilesArgs) -> Result<Vec<FileInfo>, String> {
let page_size = args.page_size; let page_size = args.page_size;
let client = get_client(); 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 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 json: serde_json::Value = response.json().await.map_err(|e| format!("Parse failed: {}", e))?;
let files: Vec<FileInfo> = json["data"] let total = json["total"].as_u64().unwrap_or(0) as usize;
.as_array() let mut all_files: Vec<FileInfo> = Vec::new();
.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();
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<FileInfo> {
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)] #[derive(Serialize)]