Skip to content

Instantly share code, notes, and snippets.

@qoli
Created July 24, 2025 22:07
Show Gist options
  • Save qoli/4b67584a77ddfef6034f52ce75340e39 to your computer and use it in GitHub Desktop.
Save qoli/4b67584a77ddfef6034f52ce75340e39 to your computer and use it in GitHub Desktop.
# Notion 同步功能增強計劃 (V2.1)
本文檔根據最新需求進行重構,旨在設計一個以 App 為中心、具備雙向同步能力的 Notion 數據庫管理系統。V2.1 版本整合了關於文件上傳 API 的詳細技術研究。
## 1. 核心設計思想
系統將不再依賴用戶已有的數據庫,而是轉變為由 Trackly App 主動創建和管理一個專用的 Notion 數據庫。系統的核心是引入「主/次數據庫」和「雙向同步引擎」的概念。
- **App 管理的數據庫**:App 將在用戶授權後,於指定的父頁面下,創建一個結構標準化的數據庫,並保存其 ID。
- **主/次數據庫**:用戶可以在設置中指定「本地數據 (CoreData)」或「Notion」為權威數據源(主數據庫)。另一個則為次要數據庫。
- **雙向同步引擎**:負責處理本地與 Notion 之間的數據同步,包括記錄的創建、更新和刪除,確保次要數據庫為主數據庫的精確鏡像。
---
## 2. 預設數據庫結構
App 將創建包含以下屬性(Properties)的 Notion 數據庫:
- **描述 (Name)**: `title` - 記錄的主要標題。
- **分類 (Category)**: `rich_text` - 記錄的分類。
- **金額 (Amount)**: `number` - 記錄的金額。
- **日期 (Date)**: `date` - 記錄發生的日期。
- **Timestamp**: `rich_text` - 來自 `record.timestamp.timeIntervalSince1970` 的字符串,作為跨平台的唯一標識符 (Unique ID),用於匹配記錄。
- **位置 (Location)**: `rich_text` - 記錄的地理位置名稱。
以下內容將作為頁面內容(Page Content / Blocks)添加:
- **圖片 (Images)**: `image` block - 記錄的圖片。
- **LLM Response**: `code` block - LLM 的分析結果,使用代碼塊以保持格式。
---
## 3. 功能實現路線圖
### 階段一:數據庫生命週期管理
此階段的目標是讓 App 能夠在 Notion 中創建和管理自己的數據庫。
1. **UI - 擴展現有設置頁面**
- 在現有的 `NotionSyncView.swift` 視圖中進行擴展。
- 利用其已有的 API Token 輸入功能。
- 在視圖中新增一個區域,用於引導用戶選擇一個「父頁面」來存放 Trackly 數據庫,並提供一個「創建/關聯數據庫」的按鈕。
2. **Service - 創建數據庫**
- 實現 `createDedicatedDatabase(parentPageId:)` 方法。
- 該方法根據上述「預設數據庫結構」調用 `notion.databaseCreate` API。
- 成功後,將返回的 `databaseId` 安全地存儲在本地(如 `UserDefaults` 或 Keychain)。
3. **Service - 清空數據庫**
- 實現 `clearAllDatabaseRecords()` 方法。
- 該方法會查詢指定 `databaseId` 下的所有頁面,並分批將它們歸檔(Archive),以實現清空效果。
### 階段二:雙向同步引擎的構建
此階段是實現數據雙向流動的核心。
1. **Service - 批量上傳 (Push)**
- 實現 `syncToNotion()` 方法。
- 遍歷本地所有 `RecordEntity`,對每一條記錄:
- 使用 `timestamp` 在 Notion 中查詢是否存在。
- **不存在則創建**:創建新頁面,填充屬性,並將 LLM Response 作為內容塊添加。如果記錄包含圖片,則執行下述「圖片上傳與附加」流程。
- **存在則更新**:更新頁面屬性和內容塊。
2. **專項任務:圖片上傳與附加**
- **技術路徑**:經確認,`NotionSwift` SDK 不支持文件上傳 API,因此本功能需要手動實現 HTTP 請求。
- **步驟 1: 創建文件上傳請求**:向 `https://api.notion.com/v1/file_uploads` 發起 `POST` 請求,獲取 `upload_url` 和 `id`。
- **步驟 2: 上傳文件內容**:使用獲取的 `upload_url`,以 `multipart/form-data` 格式 `POST` 圖片數據。
- **步驟 3: 附加到頁面**:文件上傳成功後,獲取其引用 ID,在創建或更新頁面內容時,將其作為 `image` 類型的 block 附加。
- **注意事項**:需要處理 API 的速率限制、文件大小限制(免費版 5MiB)以及上傳後一小時內必須附加的時效性問題。
3. **Service - 批量下載 (Pull)**
- 實現 `syncFromNotion()` 方法。
- 查詢 Notion 數據庫中的所有頁面。
- 對於每個頁面,使用 `timestamp` 在本地 CoreData 中查找:
- **不存在則創建**:創建新的 `RecordEntity`。
- **存在則更新**:更新本地記錄。(需注意避免覆蓋用戶在本地的修改,需要引入版本控制或時間戳比較)
4. **App 體驗**
- 在 App 啟動時,自動調用同步方法。
- 在 UI 中提供手動觸發同步的按鈕,並顯示同步進度或結果。
### 階段三:主/次數據庫與刪除同步
此階段實現最複雜的同步邏輯。
1. **UI - 主數據庫選擇**
- 在設置頁面中提供一個開關或選項,讓用戶選擇「本地」或「Notion」作為主數據庫。
2. **Service - 實現刪除同步**
- 在 `syncToNotion()` 和 `syncFromNotion()` 的流程中加入刪除邏輯。
- **同步邏輯**:
- **獲取兩端鍵集合**:分別獲取本地所有記錄的 `timestamp` 集合 `localKeys` 和 Notion 中所有頁面的 `timestamp` 集合 `remoteKeys`。
- **計算差異**:
- 如果「本地」是主庫:需要從 Notion 刪除的記錄 = `remoteKeys` - `localKeys`。
- 如果「Notion」是主庫:需要從本地刪除的記錄 = `localKeys` - `remoteKeys`。
- **執行刪除**:根據計算出的差異集,在次要數據庫中執行刪除操作。
### 可視化同步流程
```mermaid
graph TD
subgraph "用戶操作"
U1[啟動 App]
U2[手動觸發同步]
U3[在設置頁選擇主數據庫]
end
subgraph "同步引擎 (Sync Engine)"
S1{主數據庫是?}
S2[本地 (CoreData)]
S3[遠程 (Notion)]
S4[執行 Push 同步]
S5[執行 Pull 同步]
end
U1 & U2 --> S1;
U3 --> S1;
S1 -- 本地為主 --> S4;
S1 -- Notion為主 --> S5;
subgraph "Push 同步 (本地 -> Notion)"
P1[讀取本地所有記錄]
P2[讀取 Notion 所有記錄]
P3[對比數據, 執行增/改/圖片上傳]
P4[對比數據, 執行刪除]
end
subgraph "Pull 同步 (Notion -> 本地)"
L1[讀取 Notion 所有記錄]
L2[讀取本地所有記錄]
L3[對比數據, 執行增/改]
L4[對比數據, 執行刪除]
end
S4 --> P1 --> P2 --> P3 --> P4;
S5 --> L1 --> L2 --> L3 --> L4;
```
---
## 4. 開發注意事項
- **API 調用限制**:Notion API 有速率限制,批量操作時需要考慮加入延遲,避免請求過於頻繁。
- **數據一致性**:雙向同步非常容易出錯,需要設計完善的日誌和回滾機制。
- **用戶體驗**:同步過程可能是耗時的,必須在後台執行,並向用戶提供清晰的進度反饋。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment