feat: MarkBase initial version
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%
This commit is contained in:
753
docs/api.yaml
Normal file
753
docs/api.yaml
Normal file
@@ -0,0 +1,753 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: MarkBase API
|
||||
description: Momentry Display Engine - Markdown渲染與檔案樹管理系統
|
||||
version: 0.1.0
|
||||
contact:
|
||||
name: MarkBase Team
|
||||
|
||||
servers:
|
||||
- url: http://localhost:11438
|
||||
description: 本地開發伺服器
|
||||
- url: https://gitea.momentry.ddns.net
|
||||
description: 生產伺服器
|
||||
|
||||
tags:
|
||||
- name: Display
|
||||
description: 內容顯示與渲染
|
||||
- name: File Tree
|
||||
description: 檔案樹管理
|
||||
- name: Files
|
||||
description: 檔案操作
|
||||
- name: System
|
||||
description: 系統狀態與控制
|
||||
- name: Audio
|
||||
description: macOS音訊控制
|
||||
|
||||
paths:
|
||||
# Display相關路由
|
||||
/:
|
||||
get:
|
||||
tags: [Display]
|
||||
summary: 主頁顯示
|
||||
description: 返回當前顯示的HTML內容
|
||||
responses:
|
||||
'200':
|
||||
description: HTML內容
|
||||
content:
|
||||
text/html:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/display:
|
||||
post:
|
||||
tags: [Display]
|
||||
summary: 更新顯示內容
|
||||
description: 根據內容類型更新顯示內容
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [md, markdown, json, url, video, image, html]
|
||||
description: 內容類型
|
||||
data:
|
||||
type: string
|
||||
description: 內容資料
|
||||
file:
|
||||
type: string
|
||||
description:檔案路徑
|
||||
url:
|
||||
type: string
|
||||
description: URL地址
|
||||
html:
|
||||
type: string
|
||||
description: HTML內容
|
||||
step_id:
|
||||
type: string
|
||||
step_num:
|
||||
type: integer
|
||||
step_total:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: 更新成功
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
|
||||
/version:
|
||||
get:
|
||||
tags: [System]
|
||||
summary: 取得版本號
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
v:
|
||||
type: integer
|
||||
|
||||
/status:
|
||||
get:
|
||||
tags: [System]
|
||||
summary: 取得狀態
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
paused:
|
||||
type: boolean
|
||||
step:
|
||||
type: integer
|
||||
total:
|
||||
type: integer
|
||||
id:
|
||||
type: string
|
||||
label:
|
||||
type: string
|
||||
voice:
|
||||
type: string
|
||||
|
||||
/body:
|
||||
get:
|
||||
tags: [Display]
|
||||
summary: 取得內容body
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
text/html:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/labels:
|
||||
get:
|
||||
tags: [System]
|
||||
summary: 取得標籤列表
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
post:
|
||||
tags: [System]
|
||||
summary:更新標籤列表
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
|
||||
# Audio相關路由
|
||||
/devices:
|
||||
get:
|
||||
tags: [Audio]
|
||||
summary: 取得音訊裝置
|
||||
description: 列出所有音訊輸入/輸出裝置(macOS)
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
output:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
input:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
current_out:
|
||||
type: string
|
||||
current_in:
|
||||
type: string
|
||||
|
||||
/volume:
|
||||
get:
|
||||
tags: [Audio]
|
||||
summary: 取得音量
|
||||
description: 取得當前音量級別(macOS)
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
level:
|
||||
type: integer
|
||||
|
||||
# Command相關路由
|
||||
/command:
|
||||
get:
|
||||
tags: [System]
|
||||
summary: 取得指令隊列
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
cmd:
|
||||
type: string
|
||||
val:
|
||||
type: string
|
||||
post:
|
||||
tags: [System]
|
||||
summary: 提交指令
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
cmd:
|
||||
type: string
|
||||
val:
|
||||
type: string
|
||||
out:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
|
||||
# File Tree相關路由
|
||||
/api/v2/tree/{user_id}:
|
||||
get:
|
||||
tags: [File Tree]
|
||||
summary: 取得檔案樹
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: mode
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum: [tree, list, grid_sm, grid_lg]
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
mode:
|
||||
type: string
|
||||
nodes:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/FileNode'
|
||||
delete:
|
||||
tags: [File Tree]
|
||||
summary: 刪除所有節點
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
deleted:
|
||||
type: integer
|
||||
|
||||
/api/v2/tree/{user_id}/node:
|
||||
post:
|
||||
tags: [File Tree]
|
||||
summary: 建立節點
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CreateNodeRequest'
|
||||
responses:
|
||||
'201':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
node_id:
|
||||
type: string
|
||||
|
||||
/api/v2/tree/{user_id}/node/{node_id}:
|
||||
put:
|
||||
tags: [File Tree]
|
||||
summary: 更新節點
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
required: true
|
||||
- name: node_id
|
||||
in: path
|
||||
required: true
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UpdateNodeRequest'
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
delete:
|
||||
tags: [File Tree]
|
||||
summary: 刪除節點
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
required: true
|
||||
- name: node_id
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
|
||||
/api/v2/tree/{user_id}/node/{node_id}/move:
|
||||
put:
|
||||
tags: [File Tree]
|
||||
summary: 移動節點
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
required: true
|
||||
- name: node_id
|
||||
in: path
|
||||
required: true
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
parent_id:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
|
||||
/api/v2/tree/{user_id}/node/{node_id}/alias:
|
||||
patch:
|
||||
tags: [File Tree]
|
||||
summary: 更新別名
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
required: true
|
||||
- name: node_id
|
||||
in: path
|
||||
required: true
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
lang:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
|
||||
/api/v2/tree/{user_id}/restore:
|
||||
post:
|
||||
tags: [File Tree]
|
||||
summary: 從外部API恢復檔案樹
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
deleted:
|
||||
type: integer
|
||||
imported:
|
||||
type: integer
|
||||
|
||||
/api/v2/modes:
|
||||
get:
|
||||
tags: [File Tree]
|
||||
summary: 取得顯示模式列表
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
modes:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/DisplayMode'
|
||||
|
||||
# Files相關路由
|
||||
/api/v2/dupes/{user_id}:
|
||||
get:
|
||||
tags: [Files]
|
||||
summary: 取得重複檔案
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
|
||||
/api/v2/unregister/{file_uuid}:
|
||||
post:
|
||||
tags: [Files]
|
||||
summary: 取消註冊檔案
|
||||
parameters:
|
||||
- name: file_uuid
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
|
||||
/api/v2/upload/{user_id}:
|
||||
post:
|
||||
tags: [Files]
|
||||
summary: 上傳檔案
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
required: true
|
||||
requestBody:
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
type: string
|
||||
format: binary
|
||||
responses:
|
||||
'201':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
filename:
|
||||
type: string
|
||||
file_uuid:
|
||||
type: string
|
||||
sha256:
|
||||
type: string
|
||||
size:
|
||||
type: integer
|
||||
|
||||
/api/v2/render/{file_uuid}:
|
||||
get:
|
||||
tags: [Files]
|
||||
summary: 渲染檔案
|
||||
parameters:
|
||||
- name: file_uuid
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
text/html:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/api/v2/render/{file_uuid}/body:
|
||||
get:
|
||||
tags: [Files]
|
||||
summary: 取得檔案渲染內容
|
||||
parameters:
|
||||
- name: file_uuid
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
text/html:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/api/v2/files/{file_uuid}/info:
|
||||
get:
|
||||
tags: [Files]
|
||||
summary: 取得檔案資訊
|
||||
parameters:
|
||||
- name: file_uuid
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FileInfo'
|
||||
|
||||
/api/v2/files/{file_uuid}/probe:
|
||||
get:
|
||||
tags: [Files]
|
||||
summary: 取得檔案探測資訊
|
||||
parameters:
|
||||
- name: file_uuid
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
|
||||
/api/v2/files/{file_uuid}/stream:
|
||||
get:
|
||||
tags: [Files]
|
||||
summary: 串流檔案
|
||||
parameters:
|
||||
- name: file_uuid
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/octet-stream:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
|
||||
/api/v2/files/{file_uuid}/locations:
|
||||
post:
|
||||
tags: [Files]
|
||||
summary: 新增檔案位置
|
||||
parameters:
|
||||
- name: file_uuid
|
||||
in: path
|
||||
required: true
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
location:
|
||||
type: string
|
||||
label:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
|
||||
components:
|
||||
schemas:
|
||||
FileNode:
|
||||
type: object
|
||||
properties:
|
||||
node_id:
|
||||
type: string
|
||||
label:
|
||||
type: string
|
||||
aliases:
|
||||
type: object
|
||||
file_uuid:
|
||||
type: string
|
||||
sha256:
|
||||
type: string
|
||||
parent_id:
|
||||
type: string
|
||||
node_type:
|
||||
type: string
|
||||
enum: [folder, file]
|
||||
icon:
|
||||
type: string
|
||||
color:
|
||||
type: string
|
||||
bg_color:
|
||||
type: string
|
||||
file_size:
|
||||
type: integer
|
||||
registered_at:
|
||||
type: string
|
||||
children:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
CreateNodeRequest:
|
||||
type: object
|
||||
required: [label]
|
||||
properties:
|
||||
label:
|
||||
type: string
|
||||
node_type:
|
||||
type: string
|
||||
enum: [folder, file]
|
||||
parent_id:
|
||||
type: string
|
||||
file_uuid:
|
||||
type: string
|
||||
sha256:
|
||||
type: string
|
||||
file_size:
|
||||
type: integer
|
||||
file_type:
|
||||
type: string
|
||||
|
||||
UpdateNodeRequest:
|
||||
type: object
|
||||
properties:
|
||||
label:
|
||||
type: string
|
||||
icon:
|
||||
type: string
|
||||
color:
|
||||
type: string
|
||||
bg_color:
|
||||
type: string
|
||||
|
||||
DisplayMode:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
sort_options:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/SortOption'
|
||||
filter_options:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/FilterOption'
|
||||
|
||||
SortOption:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
label:
|
||||
type: string
|
||||
|
||||
FilterOption:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
label:
|
||||
type: string
|
||||
|
||||
FileInfo:
|
||||
type: object
|
||||
properties:
|
||||
file_uuid:
|
||||
type: string
|
||||
original_name:
|
||||
type: string
|
||||
file_size:
|
||||
type: integer
|
||||
file_type:
|
||||
type: string
|
||||
registered_at:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
413
docs/filetree.md
Normal file
413
docs/filetree.md
Normal file
@@ -0,0 +1,413 @@
|
||||
# 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
|
||||
300
docs/gitea_runner_setup.md
Normal file
300
docs/gitea_runner_setup.md
Normal file
@@ -0,0 +1,300 @@
|
||||
# Gitea Actions Runner配置指南
|
||||
|
||||
##環境資訊
|
||||
|
||||
- **Gitea Server**: https://gitea.momentry.ddns.net
|
||||
- **Gitea版本**: 1.25.3(支援 Actions)
|
||||
- **Runner位置**:本機Mac
|
||||
- **目標**:實機測試 macOS音訊功能
|
||||
|
||||
---
|
||||
|
||||
##配置步驟
|
||||
|
||||
### 1. 取得 Runner Token
|
||||
|
||||
1.登入 Gitea: https://gitea.momentry.ddns.net
|
||||
2.進入 **Settings → Actions → Runners**
|
||||
3.建立新 Runner,複製 Token
|
||||
|
||||
**Token格式範例:**
|
||||
```
|
||||
A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.下載並安裝 Runner
|
||||
|
||||
**macOS ARM版本:**
|
||||
|
||||
```bash
|
||||
#下載 act_runner(Gitea官方Runner)
|
||||
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
|
||||
|
||||
#驗證安裝
|
||||
act_runner --version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.註冊 Runner
|
||||
|
||||
**連接遠端 Gitea:**
|
||||
|
||||
```bash
|
||||
#註冊 Runner(使用步驟1取得的Token)
|
||||
act_runner register --instance https://gitea.momentry.ddns.net --token <YOUR_TOKEN>
|
||||
|
||||
#交互式配置
|
||||
#會提示輸入 Runner名稱、標籤等資訊
|
||||
```
|
||||
|
||||
**建議配置:**
|
||||
- Runner名稱:`macos-runner`
|
||||
- Labels:`macos-latest`
|
||||
- Runner group:default
|
||||
|
||||
---
|
||||
|
||||
### 4.啟動 Runner
|
||||
|
||||
**前景執行(測試用):**
|
||||
|
||||
```bash
|
||||
act_runner daemon
|
||||
```
|
||||
|
||||
**背景服務(macOS launchd):**
|
||||
|
||||
建立服務配置檔案:
|
||||
|
||||
```xml
|
||||
<!-- ~/Library/LaunchAgents/com.gitea.runner.plist -->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.gitea.runner</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/local/bin/act_runner</string>
|
||||
<string>daemon</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/gitea-runner.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/gitea-runner.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
**載入服務:**
|
||||
|
||||
```bash
|
||||
#載入服務
|
||||
launchctl load ~/Library/LaunchAgents/com.gitea.runner.plist
|
||||
|
||||
#驗證服務狀態
|
||||
launchctl list | grep gitea
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.驗證 Runner狀態
|
||||
|
||||
**在 Gitea網頁驗證:**
|
||||
|
||||
1.登入 Gitea
|
||||
2. Settings → Actions → Runners
|
||||
3.確認 Runner已連接(狀態為 green)
|
||||
|
||||
**在本機驗證:**
|
||||
|
||||
```bash
|
||||
#檢查 Runner狀態
|
||||
act_runner list
|
||||
|
||||
#檢查 Runner日誌
|
||||
tail -f /tmp/gitea-runner.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
##必要環境配置
|
||||
|
||||
### Rust Toolchain
|
||||
|
||||
```bash
|
||||
#確認 Rust環境
|
||||
rustc --version
|
||||
cargo --version
|
||||
|
||||
#若未安裝
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
```
|
||||
|
||||
### SwitchAudioSource(音訊測試)
|
||||
|
||||
```bash
|
||||
#安裝
|
||||
brew install switchaudio-source
|
||||
|
||||
#驗證
|
||||
SwitchAudioSource -a
|
||||
```
|
||||
|
||||
###其他工具
|
||||
|
||||
```bash
|
||||
#確認 clippy
|
||||
cargo clippy --version
|
||||
|
||||
#確認 rustfmt
|
||||
cargo fmt -- --version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow觸發測試
|
||||
|
||||
###觸發方式
|
||||
|
||||
**Push觸發:**
|
||||
|
||||
```bash
|
||||
git push origin main
|
||||
```
|
||||
|
||||
**PR觸發:**
|
||||
|
||||
```bash
|
||||
git checkout -b feature/test
|
||||
git push origin feature/test
|
||||
#在 Gitea建立 Pull Request
|
||||
```
|
||||
|
||||
**查看執行結果:**
|
||||
|
||||
1.進入專案頁面
|
||||
2. Actions →查看workflow執行狀態
|
||||
|
||||
---
|
||||
|
||||
##常見問題
|
||||
|
||||
### Runner無法連接 Gitea
|
||||
|
||||
**檢查網路連接:**
|
||||
|
||||
```bash
|
||||
curl -I https://gitea.momentry.ddns.net
|
||||
```
|
||||
|
||||
**確認 Token正確:**
|
||||
|
||||
```bash
|
||||
act_runner list
|
||||
```
|
||||
|
||||
### Workflow執行失敗
|
||||
|
||||
**檢查日誌:**
|
||||
|
||||
```bash
|
||||
tail -f /tmp/gitea-runner.log
|
||||
```
|
||||
|
||||
**常見錯誤:**
|
||||
|
||||
- Rust未安裝 →安裝 Rust toolchain
|
||||
- SwitchAudioSource未安裝 → brew install
|
||||
- clippy警告 →修復代碼
|
||||
|
||||
---
|
||||
|
||||
## Runner維護
|
||||
|
||||
###更新 Runner
|
||||
|
||||
```bash
|
||||
#停止服務
|
||||
launchctl unload ~/Library/LaunchAgents/com.gitea.runner.plist
|
||||
|
||||
#下載新版本
|
||||
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
|
||||
|
||||
#重新啟動
|
||||
launchctl load ~/Library/LaunchAgents/com.gitea.runner.plist
|
||||
```
|
||||
|
||||
###清理緩存
|
||||
|
||||
```bash
|
||||
#清理 cargo緩存
|
||||
cargo clean
|
||||
|
||||
#清理測試暫存檔
|
||||
rm -f data/users/test_*.sqlite
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
##進階配置
|
||||
|
||||
###多 Runner支援
|
||||
|
||||
若有多台機器,可配置多個 Runner:
|
||||
|
||||
```bash
|
||||
#第二台機器註冊
|
||||
act_runner register --instance https://gitea.momentry.ddns.net --token <TOKEN2>
|
||||
```
|
||||
|
||||
**使用不同 labels區分:**
|
||||
|
||||
- macos-runner-1: `macos-latest`
|
||||
- macos-runner-2: `macos-14`
|
||||
- linux-runner: `ubuntu-latest`
|
||||
|
||||
---
|
||||
|
||||
##安全性考量
|
||||
|
||||
### Token管理
|
||||
|
||||
- Token應妥善保存,避免暴露
|
||||
-定期更新 Token
|
||||
- 使用環境變數配置
|
||||
|
||||
###網路安全
|
||||
|
||||
- Gitea使用 HTTPS(已配置)
|
||||
- Runner使用 Token認證
|
||||
-僅連接信任的 Gitea server
|
||||
|
||||
---
|
||||
|
||||
##叢考資源
|
||||
|
||||
- [Gitea Actions官方文檔](https://docs.gitea.com/usage/actions/overview)
|
||||
- [act_runner GitHub](https://gitea.com/gitea/act_runner)
|
||||
- [GitHub Actions兼容性](https://docs.gitea.com/usage/actions/comparison)
|
||||
|
||||
---
|
||||
|
||||
**最後更新:2026-05-16**
|
||||
106
docs/runner_usage.md
Normal file
106
docs/runner_usage.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Gitea Runner使用指南(快速版)
|
||||
|
||||
## Runner已配置完成!
|
||||
|
||||
**Runner資訊:**
|
||||
-版本:v1.0.3
|
||||
- 名稱:accusys-Mac-mini-M4-2.local
|
||||
- ID:1
|
||||
-地址:https://gitea.momentry.ddns.net
|
||||
|
||||
---
|
||||
|
||||
## 啟動 Runner
|
||||
|
||||
### 方式A:前景執行(測試用)
|
||||
|
||||
```bash
|
||||
cd /Users/accusys/markbase
|
||||
./scripts/start_runner.sh
|
||||
```
|
||||
|
||||
或直接執行:
|
||||
|
||||
```bash
|
||||
cd /Users/accusys/markbase
|
||||
~/.local/bin/gitea-runner daemon
|
||||
```
|
||||
|
||||
### 方式B:背景服務(macOS launchd)
|
||||
|
||||
```bash
|
||||
#配置為系統服務
|
||||
./scripts/setup_launchd.sh
|
||||
|
||||
#管理命令
|
||||
launchctl load ~/Library/LaunchAgents/com.gitea.runner.plist #啟動
|
||||
launchctl unload ~/Library/LaunchAgents/com.gitea.runner.plist #停止
|
||||
launchctl list | grep gitea #狀態
|
||||
tail -f /tmp/gitea-runner.log #日誌
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
##驗證 Runner狀態
|
||||
|
||||
```bash
|
||||
./scripts/verify_runner.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
##支持的Labels
|
||||
|
||||
- `macos-latest:host` -本機Mac執行(bare-metal)
|
||||
- `macos-arm64:host` -本機Mac執行(bare-metal)
|
||||
- `ubuntu-latest:docker` - Docker容器執行
|
||||
|
||||
---
|
||||
|
||||
##觸發Workflow測試
|
||||
|
||||
### Push觸發
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "test workflow"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### 在Gitea查看結果
|
||||
|
||||
1.登入:https://gitea.momentry.ddns.net
|
||||
2.進入專案 → Actions →查看workflow執行狀態
|
||||
|
||||
---
|
||||
|
||||
##常見問題
|
||||
|
||||
**Q: Runner無法連接Gitea?**
|
||||
```bash
|
||||
curl -I https://gitea.momentry.ddns.net
|
||||
```
|
||||
|
||||
**Q: Workflow執行失敗?**
|
||||
```bash
|
||||
tail -f /tmp/gitea-runner.log
|
||||
tail -f /tmp/gitea-runner.err
|
||||
```
|
||||
|
||||
**Q: macOS功能測試失敗?**
|
||||
-確認SwitchAudioSource已安裝:`brew install switchaudio-source`
|
||||
-確認使用`runs-on: macos-latest`(bare-metal執行)
|
||||
|
||||
---
|
||||
|
||||
##Runner配置檔案
|
||||
|
||||
**位置:** `/Users/accusys/markbase/.runner`
|
||||
|
||||
**重要:**
|
||||
-不要手動刪除.runner檔案(會導致Runner重新註冊)
|
||||
- Runner token與註冊token不同(已自動生成)
|
||||
|
||||
---
|
||||
|
||||
**最後更新:2026-05-16**
|
||||
Reference in New Issue
Block a user