# MarkBase開發指南 ##專案概述 **MarkBase - Momentry Display Engine** Rust Axum Web伺服器,提供 Markdown渲染與檔案樹管理功能。 -技術棧:Rust 1.92+, Axum 0.7, SQLite, pulldown-cmark -目標平台:macOS(含音訊控制功能) -資料庫:Per-user SQLite in `data/users/.sqlite` ##核心指令 ```bash #建構與測試 cargo build #建構專案 cargo test #域行所有測試 cargo test test_insert #執行特定測試 cargo clippy #代碼品質檢查 #執行伺服器 cargo run -- display #啟動顯示伺服器(預設 port 11438) cargo run -- display -p8080 #自訂 port cargo run -- display README.md #顯示指定 Markdown檔案 #渲染工具 cargo run -- render #渲染 Markdown(輸出到 stdout) cargo run -- render -o output.html #輸出到檔案 ```` ##架構概覽 ###核心模組 |模組 |檔案 |功能 | |------|------|------| | CLI入口 | `main.rs` | clap指令解析 | | Web伺服器 | `server.rs` | Axum REST API(18+路由) | |檔案樹管理 | `filetree/mod.rs` | SQLite CRUD操作 | | Markdown渲染 | `render.rs` | pulldown-cmark轉換 | |音訊控制 | `audio.rs` | macOS音訊裝置管理 | |指令隊列 | `command.rs` | WebSocket指令處理 | ###資料庫結構 -位置:`data/users/.sqlite` -表:`file_registry`, `file_nodes`, `file_locations` -每個 user_id獨立資料庫 --- ## File Tree核心說明(重點章節) ###架構設計 File Tree是 MarkBase的核心模組,提供檔案樹管理功能。 **核心結構:** ```rust FileTree { user_id: String, //用戶ID nodes: Vec, //節點列表 } ```` **節點類型:** - **Folder** -資料夾節點(可包含子節點) - **File** -檔案節點(指向實體檔案) ###資料庫設計 **SQLite表結構:** |表名 |功能 | |------|------| | file_registry |檔案註冊資訊 | | file_nodes |檔案樹節點 | | file_locations |檔案位置記錄 | **節點欄位:** ``` node_id, label, aliases_json, file_uuid, sha256, parent_id, children_json, node_type, icon, color, bg_color, file_size, registered_at, created_at, updated_at, sort_order ```` ###公開API(13個函數) |函數名 |功能 |檔案位置 | |--------|------|----------| | user_db_path | 取得DB路徑 | mod.rs:58 | | init_user_db | 初始化DB | mod.rs:62 | | open_user_db | 開啟DB | mod.rs:74 | | load | 載入檔案樹 | mod.rs:79 | | insert_node | 插入節點 | mod.rs:112 | | update_node | 更新節點 | mod.rs:149 | | update_node_alias | 更新別名 | mod.rs:187 | | delete_node | 刪除節點 | mod.rs:214 | | move_node | 移動節點 | mod.rs:220 | | build_tree | 建立樹狀結構 | mod.rs:240 | | new_folder | 建立資料夾節點 | node.rs:27 | | new_file_node | 建立檔案節點 | node.rs:300 | | add_location | 新增檔案位置 | mod.rs:346 | ### REST API(7個路由) |路由 |方法 |功能 |server.rs行號 | |------|------|------|--------------| | `/api/v2/tree/:user_id` | GET | 取得檔案樹 | 61 | | `/api/v2/tree/:user_id` | DELETE | 刪除所有節點 | 64 | | `/api/v2/tree/:user_id/node` | POST | 建立節點 | 62 | | `/api/v2/tree/:user_id/node/:node_id` | PUT | 更新節點 | 63 | | `/api/v2/tree/:user_id/node/:node_id` | DELETE | 刪除節點 | 63 | | `/api/v2/tree/:user_id/node/:node_id/move` | PUT | 移動節點 | 71 | | `/api/v2/tree/:user_id/node/:node_id/alias` | PATCH | 更新別名 | 72 | | `/api/v2/tree/:user_id/restore` | POST | 從外部API恢復 | 65 | **Query參數:** - `mode` -顯示模式 **使用範例:** ```bash curl http://localhost:11438/api/v2/tree/demo?mode=tree curl http://localhost:11438/api/v2/tree/demo?mode=list ```` ### DisplayMode(顯示模式) **顯示模式選項:** |模式 |檔案 |用途 | |------|------|------| | tree | `modes/tree.rs` |樹狀顯示 | | list | `modes/list.rs` |列表顯示 | | grid_sm | `modes/grid_sm.rs` |小格狀顯示 | | grid_lg | `modes/grid_lg.rs` |大格狀顯示 | **DisplayMode trait定義(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; fn filter_options(&self) -> Vec; } ```` ###檔案轉換功能(convert.rs) **支援格式轉換:** |工具 |支援格式 | |------|----------| | textutil(macOS內建) | doc, docx, rtf | | macOS工具 | pages, key, numbers | | soffice/qlmanage | pptx, ppt, xlsx, xls, odt, epub | **核心函數:** - `is_doc_ext(ext)` - 檢查是否為文檔格式 - `get_cached_preview(file, ext)` - 生成緩存預覽 **緩存目錄:** `data/cache/` ###測試覆蓋現況 **已測試(7個):** - ✅ init_and_load_empty_tree - ✅ insert_and_load_node - ✅ update_node - ✅ delete_node - ✅ move_node - ✅ update_alias(zh_tw等多語言別名) - ✅ build_tree(樹狀結構) **待補測試:** - ❌ convert.rs - 檔案轉換功能 - ❌ modes/*.rs - DisplayMode渲染 - ❌ API路由 - REST endpoint測試 ###開發範例 **新增節點範例:** ```rust //建立資料夾 let folder = FileTree::new_folder("Videos", None); tree.insert_node(&conn, &folder)?; //建立檔案節點 let (file_node, register_sql) = FileTree::new_file_node( "demo.mp4", "abc123def456...", Some("sha256hash"), "demo.mp4", Some(1024000), Some("video/mp4"), None, Some(folder.node_id), ); tree.insert_node(&conn, &file_node)?; ```` **查詢範例:** ```rust //載入檔案樹 let tree = FileTree::load(&conn, &user_id)?; //建立樹狀結構(parent-child關係) let roots = tree.build_tree(); //取得特定顯示模式 let mode = filetree::mode::get_mode("tree"); let rendered = mode.render(&tree); ```` --- ##測試執行 ###執行測試 ```bash cargo test #域行所有測試 cargo test test_insert #執行特定測試 cargo test -- --nocapture #顯示詳細輸出 rm data/users/test_*.sqlite #清理暫存資料庫 ```` ###測試現況 |模組 |狀態 |說明 | |------|------|------| | filetree/mod.rs | ✅已測試 | 7個 CRUD測試 | | filetree/convert.rs | ❌待補 | 檔案轉換測試 | | filetree/modes/*.rs | ❌待補 | DisplayMode測試 | | server.rs(API路由) | ❌待補 | API handler測試 | | render.rs | ❌待補 | Markdown渲染測試 | | audio.rs | ❌待補 | macOS音訊功能測試 | ###測試清理 測試會產生暫存資料庫:`data/users/test_*.sqlite` 階段性任務結束後應手動清除: ```bash rm data/users/test_*.sqlite ```` --- ##展示執行 ###啟動伺服器 ```bash cargo run -- display #啟動(自動開啟瀏覽器) cargo run -- render #渲染 Markdown檔案 ```` ###Demo資料 - `data/users/demo.sqlite` - 50節點範例資料 - 5個 Folder節點 - 45個 File節點 - `data/cache/` -範例檔案 - 29ffd4c12ef6481da6bee7ae4c36a89f.jpg - 2c62f90aacc542a9bcfa0c65b63be02a.txt ###Demo資料庫結構 ``` Home(根資料夾) ├── Movies(子資料夾,包含影片檔案) ├── Marketing(子資料夾,包含行銷素材) ├── Cartoons(子資料夾,包含動畫檔案) └── Other(子資料夾,包含其他檔案) ```` --- ## macOS環境需求 ###必要工具 - **SwitchAudioSource** -音訊裝置切換CLI ```bash brew install switchaudio-source SwitchAudioSource -a #列出所有音訊裝置 ```` ### macOS限定功能 |功能 |依賴 |說明 | |------|------|------| |音訊裝置切換 | SwitchAudioSource | `/devices` API | |音量控制 | osascript | `/volume` API | |語音測試 | say命令 | `/command` API(test_voice) | |文檔轉換 | textutil | convert.rs(doc/rtf轉換) | --- ## CI/CD配置(Gitea Actions) ###環境資訊 - **Gitea Server**: https://gitea.momentry.ddns.net - **Gitea版本**: 1.25.3(支援 Actions) - **Runner**: 本機Mac(實機測試) - **Workflow**: `.gitea/workflows/*.yml` ### Runner配置步驟 **1. 取得 Runner Token** - 登入 Gitea: https://gitea.momentry.ddns.net - Settings → Actions → Runners →建立新 Runner **2. 下載並安裝 Runner** ```bash # macOS ARM版本 wget https://dl.gitea.com/act_runner/latest/act_runner-darwin-arm64 chmod +x act_runner-darwin-arm64 sudo mv act_runner-darwin-arm64 /usr/local/bin/act_runner ```` **3. 註冊 Runner** ```bash act_runner register --instance https://gitea.momentry.ddns.net --token ```` **4.啟動 Runner** ```bash act_runner daemon ```` ###Workflow範例 ```yaml # .gitea/workflows/test.yml name: Test on: [push, pull_request] jobs: test: runs-on: macos-latest steps: - uses: actions/checkout@v3 - name: Setup Rust uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Install SwitchAudioSource run: brew install switchaudio-source - name: Run tests run: cargo test --all - name: Run clippy run: cargo clippy --all-targets --all-features -- -D warnings - name: Check formatting run: cargo fmt -- --check - name: Clean test databases run: rm -f data/users/test_*.sqlite ```` --- ##開發環境設定 ###開發環境API Key `server.rs:192`包含開發環境 API key: ```rust let api_key = "muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69"; let api_url = "http://localhost:3002/api/v1/files"; ```` 用途:`restore_tree`功能從外部 API恢復檔案樹。 **改進建議:** -應改用環境變數配置 - 建立 `.env.example`範例 ###環境變數配置(待實作) ```bash # .env(未來配置) RESTORE_API_KEY=muser_your_api_key_here RESTORE_API_URL=http://localhost:3002 SERVER_PORT=11438 DB_DIR=data/users ```` --- ##代碼風格 ###Rust標準工具 ```bash cargo fmt #代碼格式化 cargo clippy #代碼品質檢查 ```` **現有clippy警告:** - server.rs:609 -未使用變數 `state` - server.rs:1020 -未使用變數 `pg_url` --- ##專案結構 ``` markbase/ ├── src/ │ ├── main.rs # CLI入口 │ ├── lib.rs #模組宣告 │ ├── server.rs # Web伺服器(18+路由) │ ├── render.rs # Markdown渲染 │ ├── audio.rs # macOS音訊 │ ├── command.rs #指令隊列 │ ├── page.html # HTML模板 │ └── filetree/ │ ├── mod.rs #檔案樹核心(553行) │ ├── convert.rs #檔案轉換(253行) │ ├── mode.rs # DisplayMode trait(43行) │ ├── node.rs #節點定義(82行) │ └── modes/ │ ├── tree.rs #樹狀模式(57行) │ ├── list.rs #列表模式(87行) │ ├── grid_sm.rs #小格狀模式(72行) │ ├── grid_lg.rs #大格狀模式(83行) │ └── mod.rs #模式匯出(4行) ├── data/ │ ├── users/ # SQLite資料庫 │ │ ├── demo.sqlite # Demo資料(50節點) │ │ └── test_*.sqlite #測試暫存(已清理) │ └── cache/ #檔案緩存 │ ├── *.jpg #圖片緩存 │ └── *.txt #文本緩存 ├── tests/ #整合測試(待建立) ├── examples/ #範例檔案(待建立) ├── .gitea/ │ └ workflows/ │ ├── test.yml #測試workflow(待建立) │ ├── build.yml #建構workflow(待建立) │ └── release.yml #發布workflow(待建立) ├── Cargo.toml # Rust配置 ├── Cargo.lock #依賴鎖定 └── AGENTS.md # 本文件 ```` --- ##常見問題 ###測試暫存檔清理 ```bash rm data/users/test_*.sqlite ```` ###音訊功能無效 確認 `SwitchAudioSource`已安裝: ```bash brew install switchaudio-source SwitchAudioSource -a #列出音訊裝置 ```` ###File Tree API測試 ```bash curl http://localhost:11438/api/v2/tree/demo curl http://localhost:11438/api/v2/tree/demo?mode=tree ```` ###CI/CD Runner連接失敗 確認 Runner已配置並啟動: ```bash act_runner list #查看 Runner狀態 act_runner daemon #啟動 Runner ```` --- **最後更新:2026-05-16** **版本:1.0(file tree優先版)**