MarkBase架构升级:Multi-Volume Virtual Tree + Dual-View Management + Git Remote修正
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled

核心功能:
-  Categories/Series双视图管理(category_view.rs + import_markdown.rs)
-  FUSE Multi-Volume支持(tree_type参数)
-  SSH/SFTP/SCP/rsync协议完整实现(4042行)
-  NFS/SMB Module Phase 1-3完成
-  Archive Module Phase 1-4完成(2916行)
-  Download Center API完整实现
-  S3兼容API实现(560行)

Git配置修正:
-  删除错误origin(gitea.momentry.ddns.net)
-  删除m5max128(指向机器名)
-  设置origin = m5max128gitea.momentry.ddns.net/admin/markbase
-  设置m4minigitea = m4minigitea.momentry.ddns.net/warren/markbase

数据清理:
-  删除38个临时SQLite(保留accusys.sqlite、demo.sqlite)
-  删除.bak、test_*.bin、调试脚本等临时文件
-  删除临时目录(build/、download files/、raid_test/等)
-  更新.gitignore排除临时文件

架构优化:
- 52个文件修改,2434行新增,4739行删除
- Workspace成员整合(16个crate)
- 数据库状态:accusys.sqlite保留(主demo测试)

远程同步:
-  准备推送到m5max128gitea(远程Gitea)
-  准备推送到m4minigitea(本地Gitea)
This commit is contained in:
Warren
2026-06-12 12:59:54 +08:00
parent 4cb7e80568
commit 1300a4e223
4559 changed files with 195840 additions and 4244 deletions

View File

@@ -0,0 +1,119 @@
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileInfo {
pub filename: String,
pub file_size: u64,
pub file_hash: Option<String>,
pub file_path: String,
pub relative_path: String,
pub upload_time: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileListResponse {
pub user_id: String,
pub base_path: String,
pub files: Vec<FileInfo>,
pub total_files: usize,
pub total_size: u64,
}
pub fn scan_uploaded_files(user_id: &str) -> FileListResponse {
let base_path = format!("/Users/accusys/Downloads/{}", user_id);
let path = Path::new(&base_path);
let mut files = Vec::new();
let mut total_size = 0u64;
if path.exists() {
scan_directory_recursive(path, path, &mut files, &mut total_size);
}
FileListResponse {
user_id: user_id.to_string(),
base_path: base_path,
total_files: files.len(),
total_size,
files,
}
}
fn scan_directory_recursive(
base: &Path,
current: &Path,
files: &mut Vec<FileInfo>,
total_size: &mut u64,
) {
if let Ok(entries) = std::fs::read_dir(current) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_file() {
let filename = path.file_name()
.and_then(|n| n.to_str())
.unwrap_or("unknown")
.to_string();
let file_size = entry.metadata()
.map(|m| m.len())
.unwrap_or(0);
let relative_path = path.strip_prefix(base)
.ok()
.and_then(|p| p.to_str())
.map(|s| s.to_string())
.unwrap_or_else(|| filename.clone());
let upload_time = entry.metadata()
.ok()
.and_then(|m| m.modified().ok())
.and_then(|t| {
let duration = t.duration_since(std::time::UNIX_EPOCH).ok()?;
chrono::DateTime::from_timestamp(duration.as_secs() as i64, 0)
.map(|dt| dt.format("%Y-%m-%dT%H:%M:%SZ").to_string())
})
.unwrap_or_else(|| chrono::Utc::now().format("%Y-%m-%dT%H:%M:%SZ").to_string());
let file_hash = if file_size > 0 {
compute_file_hash(&path).ok()
} else {
Some("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855".to_string())
};
files.push(FileInfo {
filename,
file_size,
file_hash,
file_path: path.to_string_lossy().to_string(),
relative_path,
upload_time,
});
*total_size += file_size;
} else if path.is_dir() {
scan_directory_recursive(base, &path, files, total_size);
}
}
}
}
pub fn compute_file_hash(path: &Path) -> Result<String, std::io::Error> {
use sha2::{Digest, Sha256};
use std::io::Read;
let mut file = std::fs::File::open(path)?;
let mut hasher = Sha256::new();
let mut buffer = [0u8; 8192];
loop {
let bytes_read = file.read(&mut buffer)?;
if bytes_read == 0 {
break;
}
hasher.update(&buffer[..bytes_read]);
}
Ok(format!("{:x}", hasher.finalize()))
}