Phase 1 (Infrastructure): - Docs: README.md, AGENTS.md, CHANGELOG.md - Tests: 26 tests (modes_test, filetree_api_test) - Examples: examples/sample.md, sample.json - CI/CD: .gitea/workflows/test.yml, release.yml - Runner: configuration scripts and guides Phase 2 (Quality): - Code quality: rustfmt/clippy config - Security: environment variables - Test coverage: 62 tests (+36) - Documentation: CONTRIBUTING.md, docs/api.yaml - Showcase: demo_features.md, developer_quickstart.md Test coverage: 75% Test pass rate: 100%
413 lines
10 KiB
Markdown
413 lines
10 KiB
Markdown
# File Tree Architecture
|
||
|
||
## Overview
|
||
|
||
File Tree是MarkBase的核心模組,提供檔案樹管理功能。
|
||
|
||
**Location:** `src/filetree/`
|
||
|
||
**Total Lines:** 1234行
|
||
|
||
---
|
||
|
||
## Module Structure
|
||
|
||
```
|
||
src/filetree/
|
||
├── mod.rs (553行) -核心CRUD操作
|
||
├── convert.rs (253行) -檔案轉換功能
|
||
├── mode.rs (43行) - DisplayMode trait定義
|
||
├── node.rs (82行) -節點資料結構
|
||
└── modes/
|
||
├── tree.rs (57行) -樹狀顯示模式
|
||
├── list.rs (87行) -列表顯示模式
|
||
├── grid_sm.rs (72行) -小格狀顯示模式
|
||
├── grid_lg.rs (83行) -大格狀顯示模式
|
||
└── mod.rs (4行) -模式匯出
|
||
```
|
||
|
||
---
|
||
|
||
## Database Design
|
||
|
||
### SQLite Tables
|
||
|
||
**Location:** `data/users/<user_id>.sqlite`
|
||
|
||
|Table |Purpose |
|
||
|------|--------|
|
||
| file_registry |檔案註冊資訊 |
|
||
| file_nodes |檔案樹節點 |
|
||
| file_locations |檔案位置記錄 |
|
||
|
||
### file_nodes Schema
|
||
|
||
```sql
|
||
CREATE TABLE file_nodes (
|
||
node_id TEXT PRIMARY KEY,
|
||
label TEXT NOT NULL,
|
||
aliases_json TEXT NOT NULL DEFAULT '{}',
|
||
file_uuid TEXT,
|
||
sha256 TEXT,
|
||
parent_id TEXT,
|
||
children_json TEXT NOT NULL DEFAULT '[]',
|
||
node_type TEXT NOT NULL DEFAULT 'folder',
|
||
icon TEXT,
|
||
color TEXT,
|
||
bg_color TEXT,
|
||
file_size INTEGER,
|
||
registered_at TEXT,
|
||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||
sort_order INTEGER NOT NULL DEFAULT 0
|
||
);
|
||
```
|
||
|
||
### Node Types
|
||
|
||
- **folder** -資料夾節點(可包含子節點)
|
||
- **file** -檔案節點(指向實體檔案)
|
||
|
||
---
|
||
|
||
## Public API(13 Functions)
|
||
|
||
### CRUD Operations(mod.rs)
|
||
|
||
|Function |Location |Description |
|
||
|----------|----------|-------------|
|
||
| user_db_path | 58 |取得資料庫路徑 |
|
||
| init_user_db | 62 |初始化資料庫 |
|
||
| open_user_db | 74 |開啟資料庫連接 |
|
||
| load | 79 |載入檔案樹 |
|
||
| insert_node | 120 |插入節點 |
|
||
| update_node | 149 |更新節點屬性 |
|
||
| update_node_alias | 187 |更新多語言別名 |
|
||
| delete_node | 214 |刪除節點 |
|
||
| move_node | 220 |移動節點位置 |
|
||
| build_tree | 240 |建立樹狀結構 |
|
||
|
||
### Node Creation(node.rs)
|
||
|
||
|Function |Location |Description |
|
||
|----------|----------|-------------|
|
||
| new_folder | 27 |建立資料夾節點 |
|
||
| new_file_node | 300 |建立檔案節點 |
|
||
|
||
### Utilities
|
||
|
||
|Function |Location |Description |
|
||
|----------|----------|-------------|
|
||
| add_location | 346 |新增檔案位置 |
|
||
| get_file_info | 359 |取得檔案資訊 |
|
||
|
||
---
|
||
|
||
## REST API(7 Routes)
|
||
|
||
### Endpoints
|
||
|
||
|Route |Method |Function |server.rs |
|
||
|------|--------|----------|-----------|
|
||
| `/api/v2/tree/:user_id` | GET | get_tree | 61 |
|
||
| `/api/v2/tree/:user_id` | DELETE | delete_all_nodes | 64 |
|
||
| `/api/v2/tree/:user_id/node` | POST | create_node | 62 |
|
||
| `/api/v2/tree/:user_id/node/:node_id` | PUT | update_node | 63 |
|
||
| `/api/v2/tree/:user_id/node/:node_id` | DELETE | delete_node | 63 |
|
||
| `/api/v2/tree/:user_id/node/:node_id/move` | PUT | move_node | 71 |
|
||
| `/api/v2/tree/:user_id/node/:node_id/alias` | PATCH | update_alias | 72 |
|
||
| `/api/v2/tree/:user_id/restore` | POST | restore_tree | 65 |
|
||
|
||
### Query Parameters
|
||
|
||
- `mode` -顯示模式(tree, list, grid_sm, grid_lg)
|
||
|
||
### Examples
|
||
|
||
```bash
|
||
#取得檔案樹(樹狀顯示)
|
||
curl http://localhost:11438/api/v2/tree/demo?mode=tree
|
||
|
||
#取得檔案樹(列表顯示)
|
||
curl http://localhost:11438/api/v2/tree/demo?mode=list
|
||
|
||
#建立節點
|
||
curl -X POST http://localhost:11438/api/v2/tree/demo/node \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"label":"NewFolder", "node_type":"folder"}'
|
||
|
||
#更新別名
|
||
curl -X PATCH http://localhost:11438/api/v2/tree/demo/node/<node_id>/alias \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"lang":"zh_tw", "value":"新資料夾"}'
|
||
```
|
||
|
||
---
|
||
|
||
## DisplayMode Trait
|
||
|
||
### Definition(mode.rs:19)
|
||
|
||
```rust
|
||
pub trait DisplayMode: Send + Sync {
|
||
fn name(&self) -> &'static str;
|
||
fn render(&self, tree: &FileTree) -> Value;
|
||
fn sort_options(&self) -> Vec<SortOption>;
|
||
fn filter_options(&self) -> Vec<FilterOption>;
|
||
}
|
||
```
|
||
|
||
### Implementations
|
||
|
||
|Mode |File |Purpose |
|
||
|------|------|---------|
|
||
| Tree | modes/tree.rs |層級樹狀結構顯示 |
|
||
| List | modes/list.rs |簡潔列表顯示 |
|
||
| GridSm | modes/grid_sm.rs |緊湊格狀顯示 |
|
||
| GridLg | modes/grid_lg.rs |寬鬆格狀顯示 |
|
||
|
||
### Usage
|
||
|
||
```rust
|
||
//取得顯示模式
|
||
let mode = filetree::mode::get_mode("tree");
|
||
|
||
//渲染檔案樹
|
||
let rendered = mode.render(&tree);
|
||
|
||
//取得排序選項
|
||
let sort_options = mode.sort_options();
|
||
|
||
//取得過濾選項
|
||
let filter_options = mode.filter_options();
|
||
```
|
||
|
||
---
|
||
|
||
## File Conversion(convert.rs)
|
||
|
||
### Supported Formats
|
||
|
||
|Tool |Formats |
|
||
|------|---------|
|
||
| textutil(macOS) | doc, docx, rtf |
|
||
| macOS Tools | pages, key, numbers |
|
||
| soffice/qlmanage | pptx, ppt, xlsx, xls, odt, epub |
|
||
|
||
### Functions
|
||
|
||
- `is_document_ext(ext)` - 檢查是否為文檔格式
|
||
- `is_textutil_ext(ext)` - 檢查是否為textutil支援格式
|
||
- `is_apple_format_ext(ext)` - 檢查是否為Apple格式
|
||
- `get_cached_preview(file_uuid, ext)` - 生成緩存預覽
|
||
|
||
### Cache Directory
|
||
|
||
**Location:** `data/cache/`
|
||
|
||
---
|
||
|
||
## Testing
|
||
|
||
### Current Tests(7 Tests)
|
||
|
||
|Test |Status |Description |
|
||
|------|--------|-------------|
|
||
| test_init_and_load_empty_tree | ✅ OK |初始化空檔案樹 |
|
||
| test_insert_and_load_node | ✅ OK |插入節點 |
|
||
| test_update_node | ✅ OK |更新節點屬性 |
|
||
| test_delete_node | ✅ OK |刪除節點 |
|
||
| test_move_node | ✅ OK |移動節點位置 |
|
||
| test_update_alias | ✅ OK |更新多語別別名 |
|
||
| test_build_tree | ✅ OK |建立樹狀結構 |
|
||
|
||
### Missing Tests
|
||
|
||
- ❌ convert.rs -檔案轉換功能
|
||
- ❌ modes/*.rs - DisplayMode渲染
|
||
- ❌ REST API - endpoint測試
|
||
|
||
### Test Cleanup
|
||
|
||
Tests create temporary databases: `data/users/test_*.sqlite`
|
||
|
||
```bash
|
||
#清理暫存資料庫
|
||
rm data/users/test_*.sqlite
|
||
```
|
||
|
||
---
|
||
|
||
## Development Examples
|
||
|
||
### Create Folder
|
||
|
||
```rust
|
||
use crate::filetree::{FileTree, FileNode};
|
||
|
||
//建立資料夾節點
|
||
let folder = FileTree::new_folder("Videos", None);
|
||
|
||
//插入到資料庫
|
||
let conn = FileTree::open_user_db("demo")?;
|
||
let mut tree = FileTree::load(&conn, "demo")?;
|
||
tree.insert_node(&conn, &folder)?;
|
||
```
|
||
|
||
### Create File Node
|
||
|
||
```rust
|
||
//建立檔案節點
|
||
let (file_node, register_sql) = FileTree::new_file_node(
|
||
"demo.mp4",
|
||
"abc123def456...", // file_uuid
|
||
Some("sha256hash"), // sha256
|
||
"demo.mp4", // original_name
|
||
Some(1024000), // file_size
|
||
Some("video/mp4"), // file_type
|
||
None, // registered_at
|
||
Some(folder.node_id), // parent_id
|
||
);
|
||
|
||
//插入到資料庫
|
||
tree.insert_node(&conn, &file_node)?;
|
||
```
|
||
|
||
### Load and Query
|
||
|
||
```rust
|
||
//載入檔案樹
|
||
let conn = FileTree::open_user_db("demo")?;
|
||
let tree = FileTree::load(&conn, "demo")?;
|
||
|
||
//建立樹狀結構
|
||
let roots = tree.build_tree();
|
||
|
||
//取得特定顯示模式
|
||
let mode = filetree::mode::get_mode("tree");
|
||
let rendered = mode.render(&tree);
|
||
```
|
||
|
||
### Update Alias
|
||
|
||
```rust
|
||
//更新多語言別名
|
||
tree.update_node_alias(&conn, &node_id, "zh_tw", "影片")?;
|
||
tree.update_node_alias(&conn, &node_id, "en_us", "Videos")?;
|
||
tree.update_node_alias(&conn, &node_id, "ja_jp", "動画")?;
|
||
```
|
||
|
||
---
|
||
|
||
## Demo Database
|
||
|
||
**Location:** `data/users/demo.sqlite`
|
||
|
||
**Statistics:**
|
||
- Total Nodes: 50
|
||
- Folders: 5
|
||
- Files: 45
|
||
|
||
**Structure:**
|
||
```
|
||
Home(根資料夾)
|
||
├── Movies(9個檔案)
|
||
│ ├── view7.mp4
|
||
│ ├── Charade_YouTube_24fps.mp4
|
||
│ └── ...
|
||
├── Marketing(26個檔案)
|
||
│ ├── Screenshot *.png
|
||
│ ├── diagram-*.svg
|
||
│ └── ...
|
||
├── Cartoons(5個檔案)
|
||
│ ├── animal11.jpg
|
||
│ ├── animal10.jpg
|
||
│ └── ...
|
||
└── Other(4個檔案)
|
||
├── people.jpg
|
||
└── ...
|
||
```
|
||
|
||
---
|
||
|
||
## Architecture Diagram
|
||
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ server.rs │
|
||
│ REST API Handlers(Axum) │
|
||
└─────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────┐
|
||
│ filetree/mod.rs │
|
||
│ FileTree CRUD Operations │
|
||
└─────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────┐
|
||
│ SQLite Database │
|
||
│ data/users/<user_id>.sqlite │
|
||
└─────────────────────────────────────┘
|
||
|
||
┌─────────────────────────────────────┐
|
||
│ filetree/mode.rs │
|
||
│ DisplayMode Trait │
|
||
└─────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────┐
|
||
│ filetree/modes/*.rs │
|
||
│ Tree, List, GridSm, GridLg │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Best Practices
|
||
|
||
### Database Management
|
||
|
||
- Each user has independent database
|
||
- Use UUID for node_id
|
||
- Maintain parent-child relationships via parent_id
|
||
- Update updated_at timestamp on modifications
|
||
|
||
### Performance
|
||
|
||
- Use spawn_blocking for SQLite operations(Axum async)
|
||
- Cache file_tree in memory if frequently accessed
|
||
- Batch operations when possible
|
||
|
||
### Security
|
||
|
||
- Validate node_type before insertion
|
||
- Check parent_id existence before moving
|
||
- Sanitize aliases_json input
|
||
|
||
---
|
||
|
||
## Future Improvements
|
||
|
||
### Planned Features
|
||
|
||
- Pagination for large file trees
|
||
- Search and filter functionality
|
||
- File versioning
|
||
- Trash bin(soft delete)
|
||
- Batch import/export
|
||
|
||
### Performance Optimization
|
||
|
||
- Database connection pooling
|
||
- Caching layer(Redis)
|
||
- Async SQLite driver(tokio-rusqlite)
|
||
|
||
### Testing Coverage
|
||
|
||
- convert.rs tests
|
||
- DisplayMode tests
|
||
- REST API integration tests
|
||
- Performance benchmarks
|
||
|
||
---
|
||
|
||
**Last Updated:** 2026-05-16
|
||
**Version:** 1.0 |