Cursor BYOK 前端
在 apps/desktop 中已有的元件和主題系統上進行建構。保留 Tauri HTTP 邊界;前端管理功能呼叫 /__byok-api__/api,且絕不新增 IPC 業務 API。
桌面 HTTP 通訊
- 將 Rust 管理伺服器視為桌面 UI 的單一 HTTP 來源。主 WebView 和瀏覽器開啟的詳細頁面必須使用
http://127.0.0.1:<dynamic-port>/__byok-api__/;請勿從tauri://localhost載入主 UI,也請勿暴露第二個前端來源。 - 每個前端管理請求都相對於
/__byok-api__/api。請勿發現、注入、持久化或傳遞apiOrigin,也不要從固定的 port 建構管理 URL。 - 保留
/__byok-api__/命名空間專用於此邊界:/__byok-api__/api/*由 Rust 管理 API 在本機處理。- 其他
/__byok-api__/*路徑為前端文件、資產、模組和開發資源。
- 在正式環境中,透過 Rust 伺服器提供由 Tauri 的
frontendDist嵌入的前端。重複使用 Tauri 的資產解析器,而不是打包或複製第二組前端資源。 - 在開發環境中,讓 Rust 伺服器將非 API 的
/__byok-api__/*請求反向代理至 Vite。保留請求路徑和查詢字串。請勿配置 Vite 來將管理 API 請求代理回 Rust。 - 將 Vite 的 base path 配置為
/__byok-api__/,以便產生的資產、模組匯入和開發客戶端 URL 保持在保留的命名空間下。 - 將開發環境的 Vite 伺服器繫結到一個與 Rust 代理目標相容的明確迴路位址;請勿依賴
localhost解析到相同的 IP 系列。 - 使用正常的迴路 HTTP URL 和 hash 路由開啟外部詳細頁面。由於頁面和 API 是同源的,請勿添加 Tauri URL 解決方法、API 來源查詢參數或依賴 CORS 的瀏覽器流程。
- 僅將 Tauri 命令用於原生桌面功能,例如開啟終端機、系統匣整合或作業系統操作。請勿為 HTTP 業務 API 建立 IPC 鏡像。
元件邊界
- 將 Provider、Model、Call、Usage 和持久化設定狀態保留在展示元件之外。
- 讓元件接收業務快照並分發動作。允許使用本地 React 狀態來處理短暫的 UI 行為,例如焦點、開啟狀態、拖曳狀態和輸入草稿。
- 將頁面、佈局、圖表、表單和可重複使用的控制項拆分到專注的元件中。請勿在
App.tsx中收集整套功能。 - 將
App.tsx作為路由組合根節點。
頁面佈局
- 每個滿版頁面都使用
components/layout/PageLayout.tsx建構;請勿手動建立帶有網格列的頁面外殼。 - 將頁面層級的命令和控制項(例如建立、匯入、匯出、篩選、排序和檢視選項)透過
PageActions放置在共享的頁面動作區域中。僅將針對單一列表項目的操作(例如編輯和刪除)保留在該項目的行內。請勿在頁面內容中新增重複的動作列或面板標題控制項。 - 絕不在資料表格或平面資料列表上方顯示標題區域。使用頁面標題提供上下文,將欄位標籤保留在表格標題中,將頁面層級的控制項放在
PageActions中,並將表格包裝在沒有標題的Card中。在分組的父-子檢視中,用於識別父資料的層級標籤並非表格標題。 - 保持主要捲動視口為滿版高度且
position: relative;將頁面標題和動作區域絕對定位在其上方。 - 使用捲動內容的
padding-top來保留絕對標題/動作區域的空間,絕不能透過縮短或偏移捲動視口本身來實現。 - 保持選單 Card 固定,並透過內容區域的
margin-left來保留其空間;請勿將 Header、選單和內容放在流式網格中。 - 請勿使用子元素或區段內邊距來建立外部間距。在兄弟元素之間使用 flex/grid 間距,在容器邊界使用外邊距或固定偏移;捲動內容的頂部內邊距僅保留給其絕對標題/動作覆蓋層。
- 使用具有以下不變量的垂直 flex 佈局:
- Header:
flex: 0 0 auto。 - Footer:
flex: 0 0 auto。 - Content:
flex: 1 1 auto、min-height: 0和overflow: hidden。
- Header:
- 將 Header 和 Footer 保留在捲動視口之外。它們絕不能隨著內容增長或縮小。
- 僅將 macOS、Windows 和 Linux 視窗角落的安全區域變數應用於可能進入原生圓角的邊緣 chrome。
- 保持 macOS 的交通號誌燈空間和頂部固定的拖曳條區域沒有互動控制項。
- 避免使用裝飾性品牌文字和說明性副本,除非它們能幫助使用者執行動作或解讀狀態。
排版
- 使用 SCSS 編寫元件樣式,並從
src/styles/_typography.scss取得每個font-size;絕不要在 SCSS、React 樣式或圖表選項中硬編碼字型大小。 - 將
base用於一般 UI 文字和普通標題,包括標題列、面板、卡片和區段標題。不要僅僅因為元素是h1或h2就增加字型大小。 - 僅將
xs用於次要資訊。保留lg用於明確的超大顯示標題;請勿將其用於常規標題。 - 在更改比例後審計所有排版 token 的使用情況,而不僅僅是原始數值字型大小。
捲動與虛擬化
- 使用
components/layout/VirtualPage.tsx處理垂直捲動的頁面內容。 - 使用
components/virtual/VirtualList.tsx處理可能增長的資料集合和選單。 - 將
ScrollArea視為由虛擬捲動實作擁有的底層基礎元件。請勿在頁面或佈局中直接匯入ScrollArea。 - 使用全域的
scroll-shadow-top和scroll-shadow-bottom遮罩來處理捲動邊緣陰影。當捲動內容的內邊距保留了一個絕對覆蓋層時,從與其padding-top相同的 CSS 變數獲取頂部陰影距離。 - 將非列表頁面建模為一系列可衡量的頂層虛擬區段。
- 請勿使用文件捲動、原生頁面
overflow: auto或巢狀的垂直捲動容器。 - 確保虛擬視口的每個 flex/grid 祖先都具有
min-height: 0,且視口具有明確的有界高度。
路由與頁面
- 為了 Tauri 相容性,使用
HashRouter。 - 將
/保留為統計儀表板,並透過共享AppLayout中的持久選單暴露每個主要頁面。 - 為主要頁面使用頂層路由:
/、/providers、/models、/calls和/settings。 - 請勿建立獨立的 Home 和 Settings 外殼,或新增 Home 切換控制項。
- 保持路由內容與視窗 Header 和 Footer 無關。
圖表
- 透過
components/charts/EChart.tsx使用 ECharts。 - 僅註冊必要的 ECharts Core 圖表、元件和渲染器。
- 保持圖表元件為宣告式:接收領域資料並建構選項,無需擷取或持久化資料。
- 讓
ResizeObserver隨著其佈局容器調整圖表大小,並在卸載時處置實例。
驗證
從 apps/desktop 執行:
npm run check
npm run tauri:build -- --debug --no-bundle
確認 Header 和 Footer 保持固定、只有虛擬內容視口會捲動、設定導覽在最小視窗尺寸下仍可觸及,以及 macOS 控制項保持在圓角和交通號誌燈不安全區域之外。