依 autoflow-agent workspace v2 設計把 PRD / 設計 / 架構 / 交付類 共享文件從個人層 .autoflow/(ignored)搬到 docs/autoflow/(進 git), 讓團隊可共享產品與架構文件,個人層只留 progress / review / testing 等 per-branch 筆記。 - 02-prd/ 21 個檔(PRD、features、market-analysis 等) - 03-design/ 18 個檔(design-spec、wireframes、flows 等) - 04-architecture/ 31 個檔(TDD、design-doc、ADR×14、API 規格等) - 07-delivery/ 3 個檔(project-summary、phase-0.6-handover、stage-deployment-setup) 合計 73 檔。原檔已從 .autoflow/ 移除(migration 工具執行 git mv, 但因 .autoflow/ 在 .gitignore 中、git 將此操作視為新增、無 rename history)。
20 KiB
元件庫清單與規格 — visionA Cloud
本元件庫 100% 沿用
local-tool/frontend/src/components/,Frontend Agent 實作時直接搬(或整併到 monorepo shared package)。本文件整理既有元件清單與用途,並定義雲端版新增的 4 個元件。
1. 元件分類總覽
| 類別 | 數量 | 來源 | 狀態 |
|---|---|---|---|
| 基礎 UI(Shadcn 風) | 22 | src/components/ui/ |
沿用 |
| Layout | 4 | src/components/layout/ |
沿用(Sidebar 需擴充) |
| Dashboard | 3 | src/components/dashboard/ |
沿用 |
| Devices | 8 | src/components/devices/ |
沿用(需擴充遠端狀態) |
| Models | 6 | src/components/models/ |
沿用 |
| Inference | 5 | src/components/inference/ |
沿用 |
| Camera | 多個 | src/components/camera/ |
沿用 |
| 特殊 | 7 | 根目錄 | 沿用(部分可能棄用) |
| 雲端版新增 | 4 | src/components/cloud/(建議) |
本次新增 |
2. 基礎 UI 元件(沿用 Shadcn 風)
來源:local-tool/frontend/src/components/ui/
| 元件 | 檔案 | 用途 |
|---|---|---|
Button |
button.tsx |
6 variants(default / destructive / outline / secondary / ghost / link),8 sizes(xs / sm / default / lg / icon*3) |
Card |
card.tsx |
資訊容器(含 Header / Title / Description / Content / Footer / Action 子元件) |
Dialog |
dialog.tsx |
Modal 對話框(Radix Dialog 封裝) |
AlertDialog |
alert-dialog.tsx |
確認危險操作的專用 Dialog(無法 ESC 關閉) |
Tabs |
tabs.tsx |
分頁切換(Radix Tabs 封裝) |
Input |
input.tsx |
單行文字輸入框,h-9 |
Select |
select.tsx |
下拉選單(Radix Select 封裝) |
Badge |
badge.tsx |
標籤徽章,6 variants |
Slider |
slider.tsx |
滑桿(Radix Slider 封裝,用於 confidence threshold) |
Progress |
progress.tsx |
進度條(Radix Progress) |
Checkbox |
checkbox.tsx |
多選框(Radix Checkbox) |
Label |
label.tsx |
表單標籤(Radix Label) |
Separator |
separator.tsx |
分隔線 |
ScrollArea |
scroll-area.tsx |
自訂滾動條(Radix ScrollArea) |
Sonner |
sonner.tsx |
Toast 通知(Sonner 封裝) |
EmptyState |
empty-state.tsx |
空狀態頁面(Icon + Title + Description + Action) |
狀態覆蓋(所有互動元件都需具備):
- Default / Hover / Active / Focus-visible / Disabled / Loading
- Focus-visible 使用 shadcn 預設
ring-[3px](符合 WCAG AA) - Disabled 統一
disabled:pointer-events-none disabled:opacity-50
3. Layout 元件(沿用 + 擴充)
來源:local-tool/frontend/src/components/layout/
| 元件 | 檔案 | 用途 | 雲端版變更 |
|---|---|---|---|
Header |
header.tsx |
頂部列:平台標題 + HelpButton + ConnectionStatus | 平台標題改「visionA Cloud」;ConnectionStatus 語義變更(見下) |
Sidebar |
sidebar.tsx |
左側導航:Dashboard / Models / Devices / Workspace / Settings | 新增:底部 UserMenu;新增:/clusters 導航項 |
ConnectionStatus |
connection-status.tsx |
伺服器連線狀態徽章(綠 / 紅點) | 語義變更:local-tool 指「本機 server」,Cloud 指「雲端 API Server」 |
HelpButton |
help-button.tsx |
開啟引導(driver.js tour) | Phase 0 保留,Phase 1 重寫內容為雲端版 |
3.1 Sidebar 變更規格(雲端版)
┌────────────────────────┐
│ [Logo] visionA Cloud │ ← h-14,border-b
├────────────────────────┤
│ ▸ Dashboard │
│ ▸ Models │
│ ▸ Devices │
│ ▸ Clusters (new) │ ← 新增
│ ▸ Workspace │
│ ▸ Settings │
│ │
│ (flex-1) │
│ │
├────────────────────────┤
│ [avatar] username ▾ │ ← 新增 UserMenu(點開展示 Account / Sign out)
├────────────────────────┤
│ v0.1.0 │
└────────────────────────┘
導航項目(繁中 / English):
| i18n key | 繁中 | English | icon |
|---|---|---|---|
nav.dashboard |
儀表板 | Dashboard | LayoutDashboard |
nav.modelLibrary |
模型庫 | Models | Boxes |
nav.devices |
裝置 | Devices | Cable |
nav.clusters |
叢集 | Clusters | Network |
nav.workspace |
工作區 | Workspace | Play |
nav.settings |
設定 | Settings | Settings |
改動說明:local-tool 目前用
{ icon: 'H' }這種單字母佔位(見sidebar.tsx:13-18),設計上不理想。Design Review 列為 Minor。雲端版建議改用 Lucide Icon,與產品視覺語言一致。
3.2 ConnectionStatus 語義變更
原 local-tool 的 ConnectionStatus 檢查 fetch('/system/health'),顯示「伺服器已連線」。
雲端版需要區分兩層連線:
| 層級 | 顯示位置 | 含義 | 綠 / 紅 / 黃 |
|---|---|---|---|
| 雲端 API | Header 右側(現有位置) | 前端能不能打雲端 API Server | 綠:OK / 紅:API 不可達 |
| 遠端 Agent | 個別裝置卡片 / 詳情頁 | 該使用者的 local agent 有沒有連上雲端 | 綠:在線 / 灰:離線 / 黃:連線中 |
Cloud 版 ConnectionStatus 行為:
- 綠點 + 「已連線」→ 可以正常使用
- 紅點 + 「連線失敗,重試中」→ 整個服務不可用,顯示全域
NetworkErrorBanner - 不再顯示 local-tool 的「伺服器未連線」— 雲端 API 應該永遠可達,失敗應觸發明顯警告
4. Dashboard 元件(沿用)
來源:local-tool/frontend/src/components/dashboard/
| 元件 | 用途 | 雲端版變更 |
|---|---|---|
StatCard |
統計卡片(標題 + 數字 + icon) | 無 |
ActivityTimeline |
近期活動時間軸 | 無(但資料來源從 local store 改為雲端事件) |
ConnectedDevicesList |
已連線裝置列表(Dashboard 上的) | 小改動:裝置項目要顯示「最後心跳 X 秒前」 |
5. Devices 元件(沿用 + 擴充)
來源:local-tool/frontend/src/components/devices/
| 元件 | 用途 | 雲端版變更 |
|---|---|---|
DeviceList |
裝置卡片網格 | 無 |
DeviceCard |
單一裝置卡片(名稱、狀態、類型、韌體、已燒錄模型、操作按鈕) | 擴充:右上角新增 RemoteDeviceBadge(見第 10 節) |
DeviceStatus / DeviceStatusBadge |
狀態點 + 文字徽章 | 新增狀態:offline(遠端掉線)、reconnecting(重連中) |
DeviceHealthCard |
健康狀態(運行時間、韌體版本、最後活動) | 擴充:新增「Pairing Token」、「最後心跳」欄位 |
DeviceConnectionLog |
連線歷史紀錄 | 無(但雲端版 log 應包含 tunnel 事件) |
DeviceSettingsCard |
裝置別名、備註 | 無 |
FlashDialog |
燒錄模型對話框 | 無(行為透過 tunnel 傳到 local agent) |
FlashProgress |
燒錄進度 | 無(WebSocket 透過雲端中繼) |
5.1 DeviceStatusBadge 擴充
新增狀態(雲端版):
| 狀態 | 顏色 | i18n key | 文字(繁中) |
|---|---|---|---|
offline |
bg-gray-400 |
devices.status.offline |
離線 |
reconnecting |
bg-yellow-400 animate-pulse |
devices.status.reconnecting |
重新連線中 |
既有的
detected/disconnected狀態在雲端版可能用不到(使用者不會直接「scan」遠端裝置)。雛形不刪除,但 UI 上會以 Pairing 流程取代 scan。
6. Models 元件(沿用,無變更)
來源:local-tool/frontend/src/components/models/
ModelCard/ModelGrid/ModelFilters/ModelDetail/ModelUploadDialog/ModelComparisonDialog
雲端版行為差異:上傳 .nef 檔案走雲端儲存(S3-compat),但 UI 不變。
7. Inference 元件(沿用,無變更)
來源:local-tool/frontend/src/components/inference/
InferencePanel/PerformanceMetrics/ClassificationResult/VideoProgress/ConfidenceSlider
雲端版行為差異:推論結果透過 WebSocket 從 local agent → 雲端 → 瀏覽器。UI 不變。
8. Camera 元件(沿用,無變更)
來源:local-tool/frontend/src/components/camera/
CameraInferenceView/CameraControls/SourceSelector/BatchImageThumbnails等
雲端版注意:
- Camera stream 仍然走 local agent(硬體存取)
- MJPEG stream 透過 tunnel 從 local agent → 雲端 → 瀏覽器顯示
- Image / Video 上傳:Phase 0 仍走 local agent 處理;Phase 1+ 考慮直上雲端
9. 特殊元件(部分調整)
來源:local-tool/frontend/src/components/
| 元件 | 用途 | 雲端版變更 |
|---|---|---|
OnboardingDialog |
首次訪問引導 Dialog | Phase 0 暫時保留;Phase 1 重寫(現版本假設「插 USB Dongle」,雲端不適用) |
GuidedTour |
driver.js 步驟引導 | Phase 0 暫時保留;Phase 1 重寫為 Cloud Tour |
ServerStatusDashboard |
後端 Go runtime 狀態 | Phase 0 可移除 or 隱藏(使用者看不到雲端 runtime);留供 Phase 1 重新定位 |
ServerLogViewer |
伺服器即時日誌 | 同上 |
LangSync |
語言狀態同步 | 無變更 |
ThemeSync |
主題跟隨系統 | 無變更 |
StoreHydration |
Zustand store hydration | 無變更 |
10. 雲端版新增元件
建議路徑:visionA-frontend/src/components/cloud/
10.1 UserMenu
用途:Sidebar 底部的使用者選單,雲端版必備。
視覺:
┌──────────────────────────┐
│ [avatar] jim@example.com ▾ │ ← trigger
└──────────────────────────┘
↓ click
┌──────────────────────────┐
│ 帳號設定 (Account) │
│ 語言切換 (Language) │
│ ─────────────── │
│ 登出 (Sign out) │
└──────────────────────────┘
規格:
- 基底元件:Radix DropdownMenu(shadcn 封裝)
- Trigger:Button variant=ghost,size=default
- Avatar:40px 圓形(
rounded-full),顯示使用者 Email 首字母 or GravatarURL - 下拉位置:
side="top" align="start"(展開往上) - 項目圖示:Lucide
UserCog/Globe/LogOut
i18n key:
account.menu.accountSettingsaccount.menu.languageaccount.menu.signOut
雛形簡化:Phase 0 signOut 直接跳回 /login(不接 API);account.menu.accountSettings 跳 /account stub 頁。
無障礙:
- Trigger 可 Tab 聚焦、Enter / Space 展開
- 下拉內容鍵盤可 Arrow 導航
aria-label= 使用者 Email
10.2 PairingTokenCard
用途:/devices/pair 頁面的主要卡片,展示 Pairing Token 並提供複製功能。
視覺:
┌────────────────────────────────────────────────┐
│ 🔗 Pairing Token │
│ │
│ 使用這組 token 讓你的 local agent 連上雲端 │
│ ─────────────────────────────────────── │
│ │
│ ┌────────────────────────────────────────┐ │
│ │ vAc_a1b2c3d4e5f6a7b8 │ │
│ │ c9d0e1f2a3b4c5d6e7f8 │ │
│ │ (vAc_ + 32 hex,視覺切兩行; │ │
│ │ 複製為完整 36 字元無空格) │ │
│ └────────────────────────────────────────┘ │
│ │
│ [📋 複製] [🔄 重新產生] │
│ │
│ ⏱ 剩餘 14:52 ──────────────── │
│ (進度條 bg-primary → amber(≤10:00) │
│ → red(≤3:00);過期轉灰 disabled) │
│ 📅 產生時間:14:30 │
└────────────────────────────────────────────────┘
規格:
- 基底:
Card+ CardHeader + CardContent + CardFooter - Token 格式:
vAc_+ 32 字元 hex(總長 36),TTL 15 分鐘,一次性使用 - Token 顯示區:
bg-muted font-mono text-xl tracking-wider p-4 rounded-md select-all- 視覺切兩行(第 1 行
vAc_+ 16 hex,第 2 行 16 hex);Mobile 降為text-lg - 複製到剪貼簿永遠是完整 36 字元無空格無換行
- 過期狀態:
text-muted-foreground line-through
- 視覺切兩行(第 1 行
- 複製按鈕:
variant=default+ LucideCopyicon;按下後暫態改為「已複製 ✓」2 秒,伴隨 toast;過期時 disabled - 重新產生:
variant=outline+ LucideRefreshCw;點擊後 AlertDialog 確認「重新產生會讓舊 token 失效,新 token 有效期 15 分鐘」 - 倒數計時器(15 分鐘 TTL 必備):
- 格式
mm:ss,1 秒更新一次 - 進度條
h-1.5 w-full,初始bg-primary,≤ 10:00 →bg-amber-500,≤ 3:00 →bg-red-500且卡片加ring-1 ring-red-300 - ≤ 0:30 發一次 Toast「Token 即將過期」
- 0:00 自動切過期狀態;主 CTA 變「重新產生 token」
- 格式
互動:
- 按複製:
navigator.clipboard.writeText(token)+showSuccess(t('pairing.copied')) - 按重新產生:開 AlertDialog,確認後呼叫 API → 更新 token + 重置計時
i18n key:
pairing.tokenTitlepairing.tokenDescriptionpairing.copy/pairing.copied/pairing.regeneratepairing.expiresIn/pairing.generatedAtpairing.regenerateConfirm/pairing.regenerateWarning
無障礙:
- Token 區塊:
aria-label="Pairing token",role="text" - 複製按鈕:Enter / Space 可觸發
- 重新產生:AlertDialog 的焦點陷阱(shadcn 內建)
10.3 RemoteDeviceBadge
用途:在雲端場景下顯示單一遠端裝置的連線狀態,取代 / 擴充既有 DeviceStatusBadge。
視覺變體:
🟢 在線 ← bg-green-500 + 文字
🟡 重新連線中 (pulse) ← bg-yellow-400 animate-pulse
⚪ 離線・最後心跳 2 分鐘前 ← bg-gray-400 + 文字 + 次要文字(timestamp)
🔴 錯誤・無法建立 tunnel ← bg-red-500 + 文字 + tooltip 顯示錯誤詳情
規格:
- 基底:
div.flex.items-center.gap-2 - 狀態點:
h-2.5 w-2.5 rounded-full(沿用DeviceStatusBadge樣式) - 狀態文字:
text-sm - 次要資訊(最後心跳):
text-xs text-muted-foreground pulse狀態:animate-pulseclass
Props:
interface RemoteDeviceBadgeProps {
status: 'online' | 'offline' | 'reconnecting' | 'error';
lastSeenAt?: string; // ISO 8601 timestamp
errorMessage?: string; // tooltip 顯示
size?: 'sm' | 'md'; // 預設 md
}
使用情境:
/devices裝置卡片右上角(取代DeviceStatusBadge)/devices/[id]裝置詳情頁的大型狀態顯示(size=md)- Dashboard
ConnectedDevicesList的每個項目右側 /workspace/[deviceId]頂部(裝置掉線時要能即時看到)
i18n key(新增):
remote.status.online→ 在線remote.status.offline→ 離線remote.status.reconnecting→ 重新連線中remote.status.error→ 連線錯誤remote.lastSeen→ 最後心跳 {time}remote.lastSeenNever→ 從未連線
無障礙:
- 角色:
role="status"+aria-live="polite"(狀態改變時通知 SR) - 不只靠顏色:圓點 + 文字雙保險
- 錯誤狀態提供
aria-describedby指向 tooltip 的完整訊息
時間格式化(建議用 date-fns 或輕量 util):
- < 60 秒 → 「剛剛」
- < 60 分 → 「X 分鐘前」
- < 24 時 → 「X 小時前」
- ≥ 24 時 → 絕對時間「04/20 14:30」
10.4 NetworkErrorBanner
用途:全域警告橫幅,當雲端 API 不可達時顯示於 Header 下方。
視覺:
┌────────────────────────────────────────────────────────┐
│ ⚠ 連線中斷 — 無法連上雲端服務。正在重試... [立即重試] │
└────────────────────────────────────────────────────────┘
規格:
- 背景:
bg-amber-50 dark:bg-amber-950/30 - 邊框:
border-b border-amber-300 dark:border-amber-700 - 文字:
text-amber-800 dark:text-amber-200 text-sm - 圖示:Lucide
AlertTriangle,text-amber-600 - 位置:Header 下方 sticky(
sticky top-14 z-40) - 右側按鈕:
Button variant=outline size=sm
狀態變化:
- API 正常 → 不顯示
- API 失敗 > 3 次連續 → 顯示 banner
- API 恢復 → banner 切換為「已恢復連線」短暫顯示 3 秒後消失
i18n key:
network.disconnected.title→ 連線中斷network.disconnected.description→ 無法連上雲端服務。正在重試...network.disconnected.retryButton→ 立即重試network.restored→ 已恢復連線 ✓
無障礙:
role="alert"+aria-live="assertive"(重要警告)- 重試按鈕:
aria-label="重試連線"
11. 元件狀態覆蓋檢查表(給 Frontend QA 與 Design QA)
每個互動元件都應有以下狀態:
| 狀態 | 所有按鈕 / Input | 卡片列表 | 頁面 | 資料載入 |
|---|---|---|---|---|
| Default | ✅ | ✅ | ✅ | — |
| Hover | ✅ | ✅(整個卡片) | — | — |
| Active / Pressed | ✅ | — | — | — |
| Focus-visible | ✅ | ✅ | — | — |
| Disabled | ✅ | — | — | — |
| Loading | ✅(Loader2 icon) | ✅(skeleton) | ✅(skeleton) | ✅(skeleton) |
| Empty | — | ✅(EmptyState) | ✅(EmptyState) | — |
| Error | — | ✅(error banner) | ✅(error page) | ✅(retry) |
| Success | ✅(toast) | — | — | — |
12. UX Writing 規範(簡版,完整版見 Flow 子檔)
產品語調:
- 對象是開發者,可用技術術語(如「Pairing Token」、「tunnel」、「session」)但不濫用
- 錯誤訊息要說清楚發生什麼事 + 使用者能做什麼
- 避免過度客氣(不需要「請」「您」滿天飛)
- 繁中台灣用語(不用「鏈接」用「連結」;不用「您」頻繁出現)
常用文案(整合到 i18n):
| 場景 | 繁中 | English |
|---|---|---|
| 載入中 | 載入中... | Loading... |
| 儲存成功 | 已儲存 | Saved |
| 儲存失敗 | 儲存失敗,請重試 | Save failed, please retry |
| 刪除確認 | 確定要刪除「{name}」嗎?此操作無法復原。 | Delete "{name}"? This cannot be undone. |
| 空列表 | 還沒有任何紀錄 | Nothing here yet |
| API 錯誤 | 連線失敗,請檢查網路或稍後再試 | Connection failed, check network or try later |
| 權限不足 | 沒有權限進行此操作 | No permission for this action |
| Session 過期 | 登入已過期,請重新登入 | Session expired, please sign in |
13. 實作建議(給 Frontend Agent)
- Monorepo 結構:若
visionA-frontend與local-tool之後都在同 repo,可抽出packages/ui/、packages/i18n/共用,避免重複。Phase 0 不需要,直接複製即可。 - 新元件檔案放
src/components/cloud/,命名清晰,不要與既有元件混放。 - 測試:新增的元件(
UserMenu、PairingTokenCard、RemoteDeviceBadge、NetworkErrorBanner)都要有對應 Vitest 測試。 - Storybook / Playground:Phase 0 不要求;Phase 1 考慮引入 Storybook。