Files
markbase/AGENTS.md
T
Warren e3901b55d3 feat: Add UI Settings panel with config management
- Add 3 API endpoints: GET /api/v2/config, POST /api/v2/config/edit, GET /api/v2/config/validate
- Add Settings button (⚙️) to bottom bar
- Add Settings panel with CSS styling (8 classes)
- Add JavaScript functions: toggleSettings, loadSettings, editSetting, saveSetting, validateSettings, cancelEdit, toast
- Support viewing/editing/validating all config sections (server, postgresql, authentication, test, logging)
- Update AGENTS.md with UI Settings documentation

Features:
- Real-time config editing via UI
- Input validation before save
- Toast notifications for user feedback
- Responsive design matching existing UI style

Files changed:
- src/server.rs: +70 lines (API handlers)
- src/page.html: +110 lines (UI + JS)
- AGENTS.md: +40 lines (documentation)

Tested: All API endpoints verified, UI elements present in HTML
2026-05-16 20:30:39 +08:00

1055 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/<user_id>.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 <FILE> #渲染 Markdown(輸出到 stdout
cargo run -- render <FILE> -o output.html #輸出到檔案
````
##架構概覽
###核心模組
|模組 |檔案 |功能 |
|------|------|------|
| CLI入口 | `main.rs` | clap指令解析 |
| Web伺服器 | `server.rs` | Axum REST API18+路由) |
|檔案樹管理 | `filetree/mod.rs` | SQLite CRUD操作 |
| Markdown渲染 | `render.rs` | pulldown-cmark轉換 |
|音訊控制 | `audio.rs` | macOS音訊裝置管理 |
|指令隊列 | `command.rs` | WebSocket指令處理 |
###資料庫結構
-位置:`data/users/<user_id>.sqlite`
-表:`file_registry`, `file_nodes`, `file_locations`
-每個 user_id獨立資料庫
---
## File Tree核心說明(重點章節)
###架構設計
File Tree是 MarkBase的核心模組,提供檔案樹管理功能。
**核心結構:**
```rust
FileTree {
user_id: String, //用戶ID
nodes: Vec<FileNode>, //節點列表
}
````
**節點類型:**
- **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
````
###公開API13個函數)
|函數名 |功能 |檔案位置 |
|--------|------|----------|
| 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 API7個路由)
|路由 |方法 |功能 |server.rs行號 |
|------|------|------|--------------|
| `/api/v2/auth/login` | POST | 登入(返回token | 1203 |
| `/api/v2/auth/logout` | POST | 登出(需Bearer token | 1220 |
| `/api/v2/auth/verify` | GET | 验证token有效性 | 1238 |
| `/api/v2/tree/:user_id` | GET | 取得檔案樹(需認證) | 395 |
| `/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
#登入取得token
curl -X POST http://localhost:11438/api/v2/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"demo","password":"demo123"}'
#返回:{"token":"xxx","expires_at":"...","user_id":"demo"}
#使用token訪問檔案樹
curl http://localhost:11438/api/v2/tree/demo \
-H "Authorization: Bearer <TOKEN>"
```
**認證說明:**
- 所有 `/api/v2/tree/*` 和 `/api/v2/files/*` API 需要認證
- Token有效期:24小時
- 默認用戶:`demo` /密碼:`demo123`
````
---
##認證系統(Authentication
###認證方式
**Token-BasedAuthentication**
- UUID Token(簡單可靠)
- 24小時有效期
- Session管理(in-memory
**APIEndpoints**
|Endpoint |方法 |功能 |
|---------|------|------|
| `/api/v2/auth/login` | POST | 登入(返回token |
| `/api/v2/auth/logout` | POST | 登出(需Bearer token |
| `/api/v2/auth/verify` | GET | 验证token |
**使用流程:**
```
1.登入 →取得token
2.使用token訪問APIAuthorization: Bearer <token>
3.Token过期 →重新登入
```
###默認用戶
**測試用戶:**
- Username: `demo`
- Password: `demo123`
- UserID: `demo`
**密碼安全:**
- bcrypt加密(DEFAULT_COST
- 密碼不以明文儲存
###認證範例
**登入:**
```bash
curl -X POST http://localhost:11438/api/v2/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"demo","password":"demo123"}'
```
**返回:**
```json
{
"token": "b2060c13-2a2d-4d5c-82e9-985bbdadbea2",
"expires_at": "2026-05-17T09:53:51Z",
"user_id": "demo"
}
```
**使用Token訪問:**
```bash
curl http://localhost:11438/api/v2/tree/demo \
-H "Authorization: Bearer b2060c13-2a2d-4d5c-82e9-985bbdadbea2"
```
**验证Token**
```bash
curl http://localhost:11438/api/v2/auth/verify \
-H "Authorization: Bearer <TOKEN>"
```
**登出:**
```bash
curl -X POST http://localhost:11438/api/v2/auth/logout \
-H "Authorization: Bearer <TOKEN>"
```
###保護範圍
**需要認證的API**
- `/api/v2/tree/*` -檔案樹管理
- `/api/v2/files/*` -檔案操作
- `/api/v2/upload/*` -檔案上傳
- `/api/v2/render/*` -檔案渲染
**公開API(無需認證):**
- `/` -根路徑
- `/api/v2/auth/*` -認證相關
- `/version` -版本信息
- `/api/v2/modes` -顯示模式
###擴展建議
**可擴展功能:**
1. JWT認證(已添加依賴,未啟用)
2. 用戶管理APIcreate_user已實現)
3.持久化Session(目前in-memory
4. RBAC權限控制
---
### 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<SortOption>;
fn filter_options(&self) -> Vec<FilterOption>;
}
````
###檔案轉換功能(convert.rs
**支援格式轉換:**
|工具 |支援格式 |
|------|----------|
| textutilmacOS內建) | 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_aliaszh_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);
````
---
## SFTPGo同步系統(Authentication Sync
###系統架構
**同步流程:**
```
SFTPGo (PostgreSQL) → MarkBase (auth.sqlite)
users表 → sftpgo_users表
groups表 → sftpgo_groups表
users_groups_mapping表 → users_groups_mapping表
```
**同步策略:**
-啟動時同步(server.rs startup task
-每小時自動同步(tokio interval task
-手動同步API/api/v2/admin/sync
-失敗時使用緩存fallback
###數據庫結構
**auth.sqlite位置:** `data/auth.sqlite`
**表結構:**
|表名 |功能 |
|------|------|
| sftpgo_users |用戶信息(username, password_hash, status, permissions |
| sftpgo_groups |群組信息(name, description |
| users_groups_mapping |用戶-群組映射(username, group_name |
| sync_log |同步日志(sync_type, sync_time, status |
### PostgreSQL連接配置
**默認配置(pg_client.rs):**
```
host: 127.0.0.1
port: 5432
user: sftpgo
password: sftpgo_pass_2026
database: sftpgo
```
**環境變數配置(優先):**
```bash
export PG_HOST=127.0.0.1
export PG_PORT=5432
export PG_USER=sftpgo
export PG_PASSWORD=sftpgo_pass_2026
export PG_DATABASE=sftpgo
```
###同步API
**手動同步:**
```bash
curl -X POST http://localhost:11438/api/v2/admin/sync
```
**返回示例:**
```json
{
"users_synced": 3,
"groups_synced": 1,
"mappings_synced": 0,
"status": "success"
}
```
**同步狀態查詢:**
```bash
curl http://localhost:11438/api/v2/admin/sync/status
```
**返回示例:**
```json
{
"status": "ok",
"latest_sync": {
"sync_type": "full",
"sync_time": 1778927765,
"users_synced": 3,
"groups_synced": 1,
"mappings_synced": 0,
"status": "success"
}
}
```
###認證流程
**登入流程:**
```
1.客戶端發送登入請求(username, password
2.服務器從auth.sqlite查詢用戶
3.bcrypt驗證密碼
4.生成UUID token24小時有效)
5.返回token、expires_at、groups、permissions
```
**登入API**
```bash
curl -X POST http://localhost:11438/api/v2/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"demo","password":"your_password"}'
```
**返回示例:**
```json
{
"token": "8d85c37d-8cc2-4633-a838-5400bb88dc6f",
"expires_at": "2026-05-17T10:39:05Z",
"user_id": "demo",
"groups": [],
"permissions": "{\"/*\": [\"*\"]}"
}
```
###測試用戶
**SFTPGo用戶(狀態=1):**
- warren(原始密碼hash\$2a\$10\$TpGOufSlx...
- momentry(原始密碼hash\$2a\$10\$Yn/43aBY...
- demo(原始密碼hash\$2a\$10\$wCQC0wGRe...
**測試密碼:**
為測試目的,可設置統一密碼:
```bash
# 在PostgreSQL中更新密碼為demo123
psql -h 127.0.0.1 -p 5432 -U sftpgo -d sftpgo -c "
UPDATE users SET password = '\$2b\$10\$ha5wU.mOi8fHLJCfun860u2cfVopa04jwe/q82IKOwqp5uG70qsH6'
WHERE username IN ('warren', 'momentry', 'demo');
"
# 重新同步
curl -X POST http://localhost:11438/api/v2/admin/sync
#測試登入
curl -X POST http://localhost:11438/api/v2/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"warren","password":"demo123"}'
```
###同步模組
**sync.rs**
- `AuthDb` - auth.sqlite操作(get_user, get_user_groups, save_user
- `SyncResult` -同步結果統計(users_synced, groups_synced, status
- `PgUser, PgGroup, PgUserGroupMapping` - PostgreSQL數據結構
**pg_client.rs**
- `PgClient` - PostgreSQL連接客戶端
- `SftpGoSync` -同步器(fetch_users, fetch_groups, full_sync
**server.rs**
- `/api/v2/admin/sync` -手動同步endpoint
- `/api/v2/admin/sync/status` -同步狀態endpoint
- startup sync task -啟動時同步
- hourly sync task -每小時同步(tokio::spawn
###測試結果(2026-05-16
**測試時間:**18:39
**測試狀態:** ✅ 全部成功
**測試項目:**
- ✅ PostgreSQL連接成功
- ✅ 手動同步API成功(3用戶, 1群組)
- ✅ 登入測試成功(demo/momentry/warren
- ✅ Token驗證成功
- ✅ 保護API訪問成功
**密碼測試:**
使用統一密碼demo123測試,bcrypt驗證成功。
---
##測試執行
###執行測試
```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.rsAPI路由) | ❌待補 | 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 <file> #渲染 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` APItest_voice |
|文檔轉換 | textutil | convert.rsdoc/rtf轉換) |
---
## CI/CD配置(Gitea Actions
### Access Token 配置
**Token資訊:**
- **Token名稱:** OpenCode_M4Mini
- **建立日期:** 2026-05-16
- **擁有者:** warren (Warren Lo)
- **權限範圍:** repo (完整倉庫權限)
- **用途:** CI/CD部署、倉庫管理、自動化操作
**Token值:** `c5e025496ebc3c7408a971d64a33bd56aac9186c`
**使用方式:**
```bash
# API認證
curl -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
https://gitea.momentry.ddns.net/api/v1/user
# Git推送(需配置遠端)
git remote set-url origin https://oauth2:c5e025496ebc3c7408a971d64a33bd56aac9186c@gitea.momentry.ddns.net/warren/markbase.git
```
**安全提醒:**
- ⚠️ 此Token僅用於本機開發環境
- ⚠️ 請勿提交到公開倉庫
- ⚠️ 定期更換Token(建議每90天)
- ⚠️ 如需撤銷:Gitea → Settings → Applications → Access Tokens → Delete
###環境資訊
- **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 <YOUR_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 trait43行)
│ ├── 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
```
###CI/CD日志查看方式
**方法1:通過 Gitea Web UI查看(推薦)**
```
https://gitea.momentry.ddns.net/warren/markbase/actions
```
**方法2:通過 API獲取詳細日志**
**步驟:**
1. **獲取所有 Actions Runs**
```bash
curl -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
https://gitea.momentry.ddns.net/api/v1/repos/warren/markbase/actions/runs | jq '.workflow_runs[] | {id, status, conclusion}'
```
2. **獲取特定 Run的所有 Jobs**
```bash
curl -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
https://gitea.momentry.ddns.net/api/v1/repos/warren/markbase/actions/runs/<RUN_ID>/jobs | jq '.jobs[] | {id, name, status, conclusion}'
```
3. **獲取 Job詳細日志**
```bash
curl -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
https://gitea.momentry.ddns.net/api/v1/repos/warren/markbase/actions/jobs/<JOB_ID>/logs
```
**範例:查看 Run ID 6的 test job日志**
```bash
# Step 1: 獲取 jobs列表
curl -s -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
https://gitea.momentry.ddns.net/api/v1/repos/warren/markbase/actions/runs/6/jobs | jq '.jobs[] | {id, name}'
# Step 2:獲取 job 11test job)的完整日志
curl -s -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
https://gitea.momentry.ddns.net/api/v1/repos/warren/markbase/actions/jobs/11/logs
```
**日志格式:**
- 每行以時間戳開頭:`2026-05-16T08:26:07.5859940Z`
- 包含完整執行過程、命令輸出、錯誤信息
- 錯誤行通常包含 `##[error]`標記
**常見錯誤診斷:**
- `conditional binary operator expected` → bash腳本語法問題
- `Process completed with exit code 2` →腳本執行失敗
- `Unable to pull refs/heads/v3` → Git clone問題(通常可忽略)`
---
##部署狀況記錄(2026-05-16
###已完成部署
**倉庫建立:**
- ✅ warren/markbase 倉庫已建立(ID: 27
- ✅ URL: https://gitea.momentry.ddns.net/warren/markbase
- ✅ 代碼已推送(4 commits
**Runner配置:**
- ✅ Runner已註冊(ID: 2
- ✅ Runner名稱: accusys-Mac-mini-M4-2.local
- ✅ Runner標籤: macos-latest:host, macos-arm64:host
- ✅ Runner進程運行中(PID: 90905
**Actions狀態:**
- ✅ Actions已觸發並執行
- ✅ Run ID 7: 成功(test + build jobs均通過) ← 最新
- ⚠️ Run ID 1-6: 失敗(Setup Rust bash兼容性問題)
- ✅ 本地測試全部通過(62 tests)
- ✅ Clippy檢查已通過
- ✅ 格式檢查已通過
###CI問題已解決(2026-05-16
**問題根本原因:**
- GitHub Actionactions-rust-lang/setup-rust-toolchain@v1)與Gitea Runner bash環境不兼容
- 錯誤:`conditional binary operator expected`line 2
**解決方案:**
- 替換為原生rustup安裝:`curl | sh.rustup.rs`
- 在所有cargo命令前添加:`source $HOME/.cargo/env`
**結果:**
- ✅ Run ID 7: 成功(5分22秒,正常執行)
- ✅ test job: success
- ✅ build job: success
- ✅ CI/CD完全正常運行
**Commits記錄:**
- 87a3eea: 記錄CI日志獲取方式和問題診斷
- 34b6839: 替換GitHub Action為原生rustup安裝 ←修復提交
---
##部署測試經驗(2026-05-16
###核心方法論
**CI日志獲取方法:**
```bash
#1.獲取 Run列表
curl -H "Authorization: token <TOKEN>" \
<GITEA_URL>/api/v1/repos/<OWNER>/<REPO>/actions/runs
#2.獲取 Job ID
curl -H "Authorization: token <TOKEN>" \
<GITEA_URL>/api/v1/repos/<OWNER>/<REPO>/actions/runs/<RUN_ID>/jobs
#3.獲取 Job日志
curl -H "Authorization: token <TOKEN>" \
<GITEA_URL>/api/v1/repos/<OWNER>/<REPO>/actions/jobs/<JOB_ID>/logs
```
**問題診斷思路:**
```
觀察現象 →獲取日志 →定位錯誤 →分析原因 →設計方案 →實施修復 →验证結果
```
**關鍵認知:**
- GitHub Actions ≠Gitea Runner環境(不完全兼容)
- 原生工具安裝 >Action依賴(更穩定可靠)
- 環境變數載入是必要步驟(`source $HOME/.cargo/env`
**測試結果:**
-失敗→成功迭代:6次失敗 →1次成功
-執行時間對比:5秒(失敗)→5分22秒(成功)
-修復方案:原生rustup安裝替代GitHub Action
---
**最後更新:2026-05-16**
**版本:1.4(部署測試經驗版)**
---
## 配置系统
### 配置文件位置
**默认位置:** `config/markbase.toml`
**创建配置文件:**
```bash
cargo run -- config init # 创建默认配置文件
cargo run -- config init --force # 强制覆盖现有配置
```
### 配置参数说明
#### Server配置
- **host**: 服务器监听地址(默认:127.0.0.1)
- **port**: 服务器端口(默认:11438,范围:>=1024
- **log_level**: 日志级别
- **auth_db_path**: 认证数据库路径(默认:data/auth.sqlite
- **users_db_dir**: 用户数据库目录(默认:data/users)
#### PostgreSQL配置
- **host**: PostgreSQL服务器地址(默认:127.0.0.1
- **port**: PostgreSQL端口(默认:5432
- **user**: PostgreSQL用户名(默认:sftpgo
- **password**: PostgreSQL密码(默认:sftpgo_pass_2026
- **database**: PostgreSQL数据库(默认:sftpgo
- **connection_pool_size**: 连接池大小(默认:5
#### Authentication配置
- **bcrypt_cost**: bcrypt加密强度(默认:10,范围:4-31)
- **token_validity_hours**: Token有效期(默认:24小时)
- **session_storage**: Session存储方式(默认:memory
- **max_sessions_per_user**: 每用户最大Session数(默认:5)
- **default_user**: 默认用户(默认:demo
- **default_password**: 默认密码(默认:demo123
#### Test配置
- **users**: 测试用户列表(默认:["warren", "momentry", "demo"]
- **password**: 测试统一密码(默认:demo123)
- **login_test_iterations**: Login性能测试迭代次数(默认:10)
- **verify_test_iterations**: Token验证测试迭代次数(默认:100)
- **api_test_iterations**: Protected API测试迭代次数(默认:50)
- **performance_report**: 是否生成性能报告(默认:true)
- **output_format**: 输出格式(默认:markdown
#### Logging配置
- **level**: 日志级别(默认:info
- **file_path**: 日志文件路径(默认:logs/markbase.log
- **console_output**: 是否输出到控制台(默认:true)
- **structured_logging**: 是否使用结构化日志(默认:false)
### CLI Config命令
**查看配置:**
```bash
cargo run -- config show # 显示所有配置
cargo run -- config show --section server # 显示server配置
cargo run -- config show --section postgresql
cargo run -- config show --section authentication
```
**编辑配置:**
```bash
cargo run -- config edit --key server.port --value 8080
cargo run -- config edit --key postgresql.password --value new_pass
cargo run -- config edit --key authentication.token_validity_hours --value 48
```
**验证配置:**
```bash
cargo run -- config validate
```
### UI Settings面板
**访问方式:**
1. 打开浏览器访问 http://localhost:11438/
2. 点击底部栏⚙️Settings按钮
3. Settings面板将从顶部滑入
**功能:**
- **查看配置**:显示所有5个配置sectionserver, postgresql, authentication, test, logging
- **编辑配置**:点击每个参数旁的Edit按钮,修改值后Save保存
- **验证配置**:点击Validate按钮验证配置有效性
- **Toast提示**:操作成功/失败显示提示信息
**API端点:**
|端点 |方法 |功能 |
|------|------|------|
| `/api/v2/config` | GET | 获取完整配置JSON |
| `/api/v2/config/edit` | POST | 编辑配置参数 |
| `/api/v2/config/validate` | GET | 验证配置有效性 |
**编辑示例:**
```bash
# 使用API修改配置
curl -X POST "http://localhost:11438/api/v2/config/edit?key=server.port&value=8080"
# 返回:{"ok":true}
# 验证配置
curl http://localhost:11438/api/v2/config/validate
# 返回:{"ok":true}
```
### 配置优先级
默认值 → 配置文件 → 环境变量 → CLI参数
**环境变量命名:**
- Server: `MB_HOST`, `MB_PORT`, `MB_LOG_LEVEL`
- PostgreSQL: `PG_HOST`, `PG_PORT`, `PG_USER`, `PG_PASSWORD`
- Authentication: `MB_BCRYPT_COST`, `MB_TOKEN_VALIDITY_HOURS`
---
**最后更新:** 2026-05-16 20:35
**版本:** 1.6UI Settings系统版)