依 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)。
722 lines
37 KiB
Markdown
722 lines
37 KiB
Markdown
# visionA Agent — UI 設計規格
|
||
|
||
| 項目 | 內容 |
|
||
|------|------|
|
||
| 專案代號 | visionA Agent(`visiona-agent`) |
|
||
| 文件版本 | v0.1 |
|
||
| 最後更新 | 2026-04-22 |
|
||
| 狀態 | Design Agent 產出(M 級任務,不走三方聯合討論) |
|
||
| 定位 | visionA 雲端版的 local agent / tunnel bridge |
|
||
| 技術堆疊 | Wails v2 + React + TypeScript + Tailwind 4 + shadcn/ui(與 visionA-frontend 完全相同)|
|
||
| Bundle ID | `com.innovedus.visiona-agent`(獨立於 local-tool 的 `com.innovedus.visiona-local`)|
|
||
|
||
> **本規格從 visionA-frontend 的 Design System 延伸**。Design Tokens、元件、字型、Dark Mode 全部沿用,確保同一使用者在雲端 Web 與桌面 Agent 之間切換「能一眼認出是同家人」。
|
||
|
||
---
|
||
|
||
## 1. 設計概述
|
||
|
||
### 1.1 產品定位
|
||
|
||
visionA Agent 是**純橋樑**:它只做一件事 — 讓使用者桌機上的 Kneron 裝置「出現在雲端」。所有裝置管理、模型管理、推論操作都在 visionA 雲端 Web UI。Agent 本身**沒有**裝置面板、沒有攝影機預覽、沒有推論視窗。
|
||
|
||
它是一個「**開了就忘掉它**」的工具:使用者配對完之後,Agent 只要維持連線、不出問題就好。
|
||
|
||
### 1.2 與 visionA-frontend 的對應關係
|
||
|
||
| 使用者流程 | visionA-frontend(Web)| visionA Agent(桌面) |
|
||
|-----------|---------------------|--------------------|
|
||
| 取得 Pairing Token | `/devices/pair` Step 1 | — |
|
||
| 下載並啟動 Agent | `/devices/pair` Step 2(指引)| **Agent 安裝後首次啟動** |
|
||
| 輸入 Token 配對 | — | **配對頁** |
|
||
| 確認連線建立 | `/devices/pair` Step 3 | **狀態頁**(雙端同時顯示)|
|
||
| 後續使用裝置 | `/devices`、`/workspace/*` | 持續維持連線,無需互動 |
|
||
|
||
**設計職責切分**:Web 負責「拿到 token」+「看到裝置」;Agent 負責「用 token 連上」+「顯示連線狀態」。
|
||
|
||
### 1.3 設計原則
|
||
|
||
1. **極簡優先** — 一個 utility 不是一個 product。不做 onboarding tour、不做裝飾性插圖、不做動畫秀。
|
||
2. **誠實呈現狀態** — online / offline / reconnecting / error 必須清楚區分,不只靠顏色(搭配 icon + 文字)。
|
||
3. **與雲端視覺一致** — Design Tokens 100% 沿用,使用者看到會立刻聯想「這是 visionA 那家」。
|
||
4. **跨平台** — 不做任何倚賴特定 OS 的互動(不做 traffic light 自訂、不做 system tray、不做 Win11 Mica)。
|
||
5. **鍵盤友善** — 所有操作 Tab 可達,符合 WCAG 2.1 AA。
|
||
6. **Dark Mode 跟隨 OS** — 不提供手動切換,不需要多餘開關。
|
||
|
||
### 1.4 範圍內 vs 範圍外
|
||
|
||
| 範圍內 | 範圍外 |
|
||
|--------|--------|
|
||
| 連線狀態頁、配對頁、設定頁 | 裝置管理 / 模型管理 / 推論操作 UI |
|
||
| 全域 Header + Tab 導航 | System Tray / Menu Bar 圖示 |
|
||
| 開機自啟、Log 匯出、Relay URL 設定 | Onboarding Tour / Tutorial |
|
||
| 繁中 + English(跟 OS 語言,無 UI switcher) | i18n 切換 UI、多語言 admin |
|
||
| Dark Mode 跟隨系統 | 手動 Dark Mode toggle |
|
||
|
||
---
|
||
|
||
## 2. Design Tokens(沿用 visionA-frontend)
|
||
|
||
完整沿用 `.autoflow/03-design/design-tokens.md`。實作時 **直接複製 visionA-frontend 的 `globals.css`**,不動一行。
|
||
|
||
### 2.1 Agent 會用到的 token 清單
|
||
|
||
| 用途 | Token / class |
|
||
|------|---------------|
|
||
| 視窗背景 | `--background` → `bg-background` |
|
||
| 主要文字 | `--foreground` → `text-foreground` |
|
||
| 次要文字 | `--muted-foreground` → `text-muted-foreground` |
|
||
| 卡片 / 區塊 | `--card` + `border` + `shadow-sm` + `rounded-xl` |
|
||
| 主按鈕 | `--primary` + `--primary-foreground` |
|
||
| 次要按鈕 | `--secondary` / outline variant |
|
||
| 危險按鈕(重置 / 斷線)| `--destructive` |
|
||
| Input 邊框 | `--input`,focus `--ring/50` |
|
||
| Tab bar 背景 | `--sidebar`(沿用) |
|
||
| Focus ring | `--ring`(`ring-[3px]`)|
|
||
|
||
### 2.2 連線狀態色(沿用雲端版既有約定)
|
||
|
||
與 `flow-offline-handling.md` 第 2 節的狀態模型對齊:
|
||
|
||
| 狀態 | 顏色(light / dark)| Icon(Lucide)|
|
||
|------|---------------------|---------------|
|
||
| online | `bg-green-500` | `CheckCircle2` |
|
||
| offline | `bg-gray-400` + `dark:bg-gray-600` | `PowerOff` |
|
||
| reconnecting | `bg-yellow-400` + `animate-pulse` | `RefreshCw`(旋轉) |
|
||
| notPaired | `bg-gray-400` | `Unlink` |
|
||
| error | `bg-red-500` | `AlertTriangle` |
|
||
|
||
**無障礙**:每個狀態**必須同時有**「圓點顏色 + Icon + 文字標籤」,不只靠顏色。
|
||
|
||
### 2.3 字型
|
||
|
||
- UI 文字:`font-sans`(Geist Sans,沿用)
|
||
- Token 顯示、Log、Relay URL:`font-mono`(Geist Mono)
|
||
|
||
---
|
||
|
||
## 3. 全域元件 — Header / Tab 導航
|
||
|
||
### 3.1 版型
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────┐
|
||
│ [Logo] visionA Agent 狀態 · 配對 · 設定 🟢 在線 │ ← h-14
|
||
├──────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ [ 當前分頁內容 ] │
|
||
│ │
|
||
└──────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 3.2 規格
|
||
|
||
- **高度**:`h-14`(56px),與 visionA-frontend Header 一致
|
||
- **背景**:`bg-sidebar` + `border-b border-sidebar-border`
|
||
- **左側**:Logo + 產品名「visionA Agent」(`text-sm font-semibold`)
|
||
- **中央(或左側緊接)**:三個 Tab
|
||
- 「狀態」(Status)— 預設
|
||
- 「配對」(Pair)
|
||
- 「設定」(Settings)
|
||
- 使用 shadcn `Tabs` 風格;active tab `bg-primary text-primary-foreground rounded-md`,其餘 `hover:bg-accent`
|
||
- **右上角**:`ConnectionStatusBadge`(小型 `RemoteDeviceBadge` 的簡化版)
|
||
- 圓點 + 文字(例:`🟢 在線` / `⚪ 離線` / `🟡 重連中` / `🔗 未配對`)
|
||
- 點擊可切回「狀態」tab
|
||
|
||
### 3.3 互動
|
||
|
||
- Tab 切換:`Ctrl/Cmd+1/2/3` 鍵盤快捷鍵
|
||
- Badge 永遠即時反映連線狀態(從 backend event 推送)
|
||
- **沒有**雲端版的 `PrototypeBanner`、**沒有** Sidebar(視窗太小、功能太少)
|
||
|
||
### 3.4 視窗規格(Wails 設定)
|
||
|
||
| 項目 | 值 | 說明 |
|
||
|------|---|------|
|
||
| 初始大小 | **720 × 560** | 比 800×600 稍收斂,足夠不壅擠 |
|
||
| 最小大小 | 640 × 480 | 強制最小,避免壞掉 |
|
||
| 最大大小 | 不限 | 使用者想放大就放大(但內容有 `max-w-2xl` 收斂) |
|
||
| Title | `visionA Agent` | OS title bar |
|
||
| Resizable | Yes | 使用者可調整 |
|
||
| 關閉行為 | **退出 process** | 不隱藏到 tray(已決策) |
|
||
| Icon | visionA 品牌 logo(3 平台各別規格) | — |
|
||
|
||
---
|
||
|
||
## 4. 頁面 1 — 連線狀態頁(首頁 / 預設 Tab)
|
||
|
||
### 4.1 版型(已配對 + 在線)
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────┐
|
||
│ │
|
||
│ ╭────────────────────╮ │
|
||
│ │ ✓ 已連線 │ │
|
||
│ │ 🟢 │ │
|
||
│ ╰────────────────────╯ │
|
||
│ │
|
||
│ ┌────────────────────────────────────────────────────────────┐ │
|
||
│ │ 帳號 jim@innovedus.com │ │
|
||
│ │ Relay wss://relay.visionA.cloud │ │
|
||
│ │ 連線開始 2026-04-22 14:30(已連線 2 小時 15 分) │ │
|
||
│ │ Session vAs_a1b2c3d4 ··· e7f8 │ │
|
||
│ │ │ │
|
||
│ │ [ 斷開連線 ] [ 重新配對 ] │ │
|
||
│ └────────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ 最近連線紀錄 [ 查看完整 Log ] │
|
||
│ ┌────────────────────────────────────────────────────────────┐ │
|
||
│ │ 14:30 ✓ 已連線 │ │
|
||
│ │ 14:29 ⟳ 連線中... │ │
|
||
│ │ 14:28 ▲ 程式啟動 │ │
|
||
│ │ ...(最多 10 筆) │ │
|
||
│ └────────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
└──────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 4.2 主要元件
|
||
|
||
#### (A) StatusHero — 大狀態指示器
|
||
|
||
- **大小**:直徑 80px 的圓,置中
|
||
- **內容**:
|
||
- 頂層:狀態 Icon(Lucide,`h-8 w-8`)
|
||
- 底層:圓點 + 狀態文字(`text-xl font-semibold`)
|
||
- **狀態變體**(對應 2.2 狀態色):
|
||
- online:綠圓 + `CheckCircle2` + 「已連線」
|
||
- offline:灰圓 + `PowerOff` + 「離線」
|
||
- reconnecting:黃圓 pulse + `RefreshCw` 旋轉 + 「重新連線中...」+ 次行 `text-xs text-muted-foreground`「第 {n}/5 次嘗試」
|
||
- notPaired:灰圓 + `Unlink` + 「尚未配對」+ 次行按鈕「立即配對 →」切到配對頁
|
||
- error:紅圓 + `AlertTriangle` + 「連線錯誤」+ 次行 `text-xs text-red-600`「{errorMessage}」
|
||
|
||
#### (B) InfoCard — 連線資訊卡
|
||
|
||
- shadcn `Card`,`p-6 space-y-3`
|
||
- **欄位**(每行 `grid grid-cols-[120px_1fr]`,左欄 `text-muted-foreground text-sm`,右欄 `text-sm font-mono`):
|
||
|
||
| 欄位 | 內容 | 未配對 / 離線時 |
|
||
|------|------|---------------|
|
||
| 帳號 | `jim@innovedus.com` | `—`(未配對)/ 快取顯示(離線) |
|
||
| Relay | `wss://relay.visionA.cloud` | 顯示當前設定值 |
|
||
| 連線開始 | `2026-04-22 14:30(已連線 2 小時 15 分)` | 未配對 `—`;離線顯示上次連線時間 + 「已離線 {duration}」|
|
||
| Session | `vAs_a1b2c3d4 ··· e7f8`(遮蔽中段)| 未配對 `—`;離線保留顯示(以 `text-muted-foreground` 淡化) |
|
||
|
||
- **Session Token 遮蔽規則**:顯示 `前綴(vAs_) + 前 8 hex + " ··· " + 後 4 hex`(共約 20 字元可見)。完整 token 永遠不顯示、不可複製、不寫進 log。
|
||
|
||
#### (C) 主要按鈕
|
||
|
||
於 InfoCard 下方,排成一列:
|
||
|
||
| 狀態 | 主按鈕 | 次按鈕 |
|
||
|------|--------|--------|
|
||
| online | `[ 斷開連線 ]`(`variant=outline`)| `[ 重新配對 ]`(ghost 配 `AlertDialog`) |
|
||
| offline | `[ 立即重試 ]`(`variant=default`)| `[ 重新配對 ]` |
|
||
| reconnecting | `[ 取消並手動重連 ]`(outline,重連中停用自動策略一次)| `[ 重新配對 ]` |
|
||
| notPaired | `[ 前往配對 → ]`(default,切 tab)| — |
|
||
| error | `[ 重試 ]`(default)+ `[ 查看 log ]`(ghost)| `[ 重新配對 ]` |
|
||
|
||
- 「斷開連線」→ `AlertDialog`「確定要斷開嗎?斷開後遠端將無法使用此裝置。Session Token 不會被撤銷,下次可直接重連。」
|
||
- 「重新配對」→ `AlertDialog`「確定要重新配對?目前的 Session 會立即失效,需重新取得 Pairing Token。」確認後切配對頁並清除本地 Session Token。
|
||
|
||
#### (D) RecentLog — 最近連線紀錄
|
||
|
||
- shadcn `Card`,標題 + 右上角「查看完整 Log」連結(切到設定頁 → Log 區塊)
|
||
- 每筆紀錄:`時間(HH:mm) · Icon · 事件文字`
|
||
- `✓ 已連線` / `⟳ 連線中...(嘗試 {n}/5)` / `✗ 連線失敗:{reason}` / `▲ 程式啟動` / `◼ 程式關閉` / `⚙ 設定已更新`
|
||
- 最多顯示 10 筆,`text-xs font-mono`,超過出現「查看完整 Log」連結
|
||
- **只顯示使用者應該看得懂的事件**;debug 級別的細節進 log 檔不上 UI
|
||
|
||
### 4.3 空狀態(尚未配對)
|
||
|
||
未配對時,StatusHero 顯示 notPaired 狀態,InfoCard 欄位皆為 `—`,RecentLog 顯示:
|
||
|
||
```
|
||
┌─────────────────────────────────┐
|
||
│ 🔗 │
|
||
│ │
|
||
│ 尚未配對裝置 │
|
||
│ │
|
||
│ 去雲端 Web 產生 Pairing Token, │
|
||
│ 在「配對」分頁貼上即可開始 │
|
||
│ │
|
||
│ [ 前往配對 → ] │
|
||
└─────────────────────────────────┘
|
||
```
|
||
|
||
### 4.4 錯誤狀態
|
||
|
||
- 連線錯誤:StatusHero 顯示 error,InfoCard 最下方紅色 banner(`bg-red-50 dark:bg-red-950/30 border-red-300`)顯示 `errorMessage`(例:「Pairing Token 已撤銷,請重新配對」「Relay URL 不可達」)
|
||
- 錯誤分類(對應 `flow-offline-handling.md` 第 1 節的 A/B/C 失效點):
|
||
- **本機斷網**(A):「你的網路似乎離線了,請檢查 Wi-Fi / 有線連線」
|
||
- **雲端不可達**(B):「無法連上 visionA 雲端服務,正在重試...」
|
||
- **認證失敗**:「Session Token 已失效,請重新配對」
|
||
- **未知錯誤**:「連線錯誤,請[查看 log]{連結}」
|
||
|
||
### 4.5 互動行為
|
||
|
||
| 操作 | 行為 |
|
||
|------|------|
|
||
| 進入頁面 | 自動從 backend 取當前狀態(透過 Wails runtime event) |
|
||
| 狀態變化 | backend 推送事件 → 前端即時更新 StatusHero + Badge + InfoCard |
|
||
| 點「斷開連線」| AlertDialog 確認 → call backend `Disconnect()` → 狀態變 offline |
|
||
| 點「重新連線」| call backend `Reconnect()` → 狀態變 reconnecting |
|
||
| 點「查看完整 Log」| 切到設定頁,自動 scroll 到 Log 區塊 |
|
||
| 視窗 resize | 內容以 `max-w-2xl mx-auto` 置中,大螢幕不會過寬 |
|
||
|
||
### 4.6 驗收條件
|
||
|
||
- [ ] 五種狀態(online / offline / reconnecting / notPaired / error)視覺各異且符合 2.2 色表
|
||
- [ ] Session Token 永遠只顯示遮蔽版
|
||
- [ ] 離線時「連線開始」欄位顯示「已離線 {duration}」並使用 `text-muted-foreground`
|
||
- [ ] 「斷開連線」「重新配對」都有 `AlertDialog` 確認
|
||
- [ ] 最近 Log 最多 10 筆,時間格式 `HH:mm`
|
||
- [ ] Dark Mode 下所有顏色對比達 4.5:1
|
||
- [ ] 完整鍵盤導航(Tab / Enter / Space / Esc)
|
||
|
||
---
|
||
|
||
## 5. 頁面 2 — 配對頁
|
||
|
||
### 5.1 版型
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────┐
|
||
│ │
|
||
│ 配對到 visionA 雲端 │
|
||
│ 貼上 Pairing Token,讓你的裝置出現在雲端 Web │
|
||
│ │
|
||
│ ┌────────────────────────────────────────────────────────────┐ │
|
||
│ │ Pairing Token │ │
|
||
│ │ ┌────────────────────────────────────────────────────────┐│ │
|
||
│ │ │ vAc_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8 ││ │
|
||
│ │ └────────────────────────────────────────────────────────┘│ │
|
||
│ │ ✓ 格式正確(36 字元) │ │
|
||
│ │ │ │
|
||
│ │ 還沒有 token?[ 到雲端網頁產生 ↗ ] │ │
|
||
│ │ │ │
|
||
│ │ [ 取消 ] [ 配對 ] │ │
|
||
│ └────────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ 💡 Token 15 分鐘內有效,一次性使用。Agent 會自動換取長期 Session,│ │
|
||
│ 你不需要記住或重複貼上。 │ │
|
||
│ │
|
||
└──────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.2 元件規格
|
||
|
||
#### (A) 標題區
|
||
|
||
- `h1`:「配對到 visionA 雲端」(`text-2xl font-semibold`)
|
||
- `description`:「貼上 Pairing Token,讓你的裝置出現在雲端 Web」(`text-sm text-muted-foreground`)
|
||
|
||
#### (B) Token 輸入卡
|
||
|
||
- shadcn `Card`,`p-6 space-y-4`,`max-w-xl mx-auto`
|
||
- `Label`:「Pairing Token」
|
||
- shadcn `Input`:
|
||
- `font-mono text-sm`(等寬)
|
||
- `placeholder="貼上 vAc_... 格式的 token"`
|
||
- 自動 `spellcheck={false}`、`autocapitalize="none"`、`autocomplete="off"`
|
||
- **貼上時自動清除所有空格與換行**(雲端網頁顯示可能有空格分隔,如 `vAc_a1b2c3d4 e5f6a7b8 ...`)
|
||
- **焦點**進入自動全選(方便覆蓋貼上)
|
||
- **即時格式驗證**(在 input 下方顯示 hint line):
|
||
- 空:`text-muted-foreground`「請貼上 token」
|
||
- 格式不對:`text-red-600`「格式不正確 — token 應為 `vAc_` 開頭 + 32 字元 hex」+ `AlertCircle` icon
|
||
- 格式正確:`text-green-600`「✓ 格式正確(36 字元)」+ `CheckCircle2` icon
|
||
- 邊框狀態:預設 `border-input` / 錯誤 `border-destructive` + `ring-destructive/20` / 正確 `border-green-500`
|
||
|
||
#### (C) 輔助連結
|
||
|
||
- 「還沒有 token?[ 到雲端網頁產生 ↗ ]」
|
||
- 點擊 → `wails.BrowserOpenURL("https://visionA.cloud/devices/pair")`
|
||
- **Phase 0 雛形**:URL 寫死 placeholder,正式上線再改為環境變數驅動
|
||
|
||
#### (D) 按鈕列(右對齊)
|
||
|
||
- 「取消」(`variant=ghost`)→ 切回狀態頁
|
||
- 「配對」(`variant=default`):格式不正確時 disabled
|
||
- 配對中:按鈕變「`⟳ 正在配對...`」(`aria-busy=true`),其餘 input / cancel disabled
|
||
|
||
#### (E) 底部提示
|
||
|
||
`Alert` 元件(`variant=default`,`bg-blue-50 dark:bg-blue-950/30 border-blue-300`):
|
||
|
||
> 💡 Token 15 分鐘內有效,一次性使用。Agent 會自動換取長期 Session,你不需要記住或重複貼上。
|
||
|
||
### 5.3 配對流程狀態
|
||
|
||
| 階段 | UI |
|
||
|------|---|
|
||
| 閒置 | 如 5.1 所示,按鈕依格式驗證 enable / disable |
|
||
| 驗證中(貼上後)| 即時驗證格式,100ms debounce,無 loading(純 client-side 正規表達式) |
|
||
| 配對中 | 按鈕變 spinner「正在連線到雲端...」,其餘 disabled。backend 呼叫 WS `/tunnel/connect?token=vAc_...` |
|
||
| 成功 | Toast `✓ 配對成功` → 0.5s 後自動切回「狀態」tab → StatusHero 顯示 online |
|
||
| 失敗 | 停留在本頁,Input 下方紅色 `Alert` 顯示錯誤訊息(見 5.4),按鈕恢復為「重試」+「取消」|
|
||
|
||
### 5.4 錯誤訊息對照
|
||
|
||
| 後端錯誤代碼 | 顯示訊息 | 建議動作 |
|
||
|-------------|---------|---------|
|
||
| `token_expired` | 「此 Token 已過期(15 分鐘有效)」 | 「回雲端網頁重新產生 →」 |
|
||
| `token_used` | 「此 Token 已被其他裝置使用」 | 「回雲端網頁重新產生 →」 |
|
||
| `token_invalid` | 「Token 無效或格式錯誤」 | 「請檢查是否複製完整」 |
|
||
| `token_revoked` | 「此 Token 已被撤銷」 | 「回雲端網頁重新產生 →」 |
|
||
| `network_error` | 「無法連上雲端服務,請檢查網路」 | 「重試」 |
|
||
| `relay_unreachable` | 「Relay `{url}` 無法連線,請確認設定」 | 「前往設定 →」|
|
||
| `unknown` | 「配對失敗,請查看 log」 | 「查看 log」 |
|
||
|
||
### 5.5 互動行為
|
||
|
||
| 操作 | 行為 |
|
||
|------|------|
|
||
| Focus Input | 全選現有內容 |
|
||
| 貼上 token | trim + 去空白 + 去換行;立即格式驗證 |
|
||
| 輸入中 | 100ms debounce 後顯示驗證結果 |
|
||
| Enter 鍵 | 若格式正確則觸發「配對」;否則無動作 |
|
||
| Esc 鍵 | 觸發「取消」(切回狀態頁,清空 input) |
|
||
| 配對成功 | Toast + auto navigate,不留在本頁 |
|
||
| 配對失敗 | Input 保留原值(方便使用者修改),顯示錯誤,按鈕變「重試」|
|
||
|
||
### 5.6 i18n key
|
||
|
||
```
|
||
pair.title → 配對到 visionA 雲端
|
||
pair.description → 貼上 Pairing Token,讓你的裝置出現在雲端 Web
|
||
pair.tokenLabel → Pairing Token
|
||
pair.tokenPlaceholder → 貼上 vAc_... 格式的 token
|
||
pair.hint.empty → 請貼上 token
|
||
pair.hint.invalid → 格式不正確 — token 應為 vAc_ 開頭 + 32 字元 hex
|
||
pair.hint.valid → 格式正確(36 字元)
|
||
pair.noToken → 還沒有 token?
|
||
pair.openCloud → 到雲端網頁產生
|
||
pair.cancel → 取消
|
||
pair.submit → 配對
|
||
pair.submitting → 正在配對...
|
||
pair.bottomHint → Token 15 分鐘內有效,一次性使用。Agent 會自動換取長期 Session,你不需要記住或重複貼上。
|
||
pair.toast.success → 配對成功
|
||
pair.error.expired → 此 Token 已過期(15 分鐘有效)
|
||
pair.error.used → 此 Token 已被其他裝置使用
|
||
pair.error.invalid → Token 無效或格式錯誤
|
||
pair.error.revoked → 此 Token 已被撤銷
|
||
pair.error.network → 無法連上雲端服務,請檢查網路
|
||
pair.error.relayUnreachable → Relay {url} 無法連線,請確認設定
|
||
pair.error.unknown → 配對失敗,請查看 log
|
||
pair.error.regenerate → 回雲端網頁重新產生
|
||
pair.error.goSettings → 前往設定
|
||
pair.error.viewLog → 查看 log
|
||
pair.error.retry → 重試
|
||
```
|
||
|
||
### 5.7 驗收條件
|
||
|
||
- [ ] 貼上含空格 / 換行的 token 自動清乾淨
|
||
- [ ] 格式驗證正規表達式:`/^vAc_[a-f0-9]{32}$/i`(大小寫不敏感)
|
||
- [ ] 格式不正確時按鈕 disabled
|
||
- [ ] 配對中所有 input + 按鈕 disabled,僅保留「取消」
|
||
- [ ] 成功後切回狀態頁,並更新全域狀態
|
||
- [ ] 所有錯誤訊息都能明確告訴使用者「下一步該做什麼」
|
||
- [ ] 支援完整鍵盤操作(Enter 送出、Esc 取消)
|
||
|
||
---
|
||
|
||
## 6. 頁面 3 — 設定頁
|
||
|
||
### 6.1 版型
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────┐
|
||
│ 設定 │
|
||
│ │
|
||
│ ── 連線 ───────────────────────────────────────────────────── │
|
||
│ Relay URL [ wss://relay.visionA.cloud ] [ 測試連線 ]│
|
||
│ 當前設定將於下次連線時生效 │
|
||
│ │
|
||
│ ── 行為 ───────────────────────────────────────────────────── │
|
||
│ ☐ 開機自動啟動 visionA Agent │
|
||
│ │
|
||
│ 重連策略 ◉ 自動重試(指數退避,最多 5 次) │
|
||
│ ○ 手動重連 │
|
||
│ │
|
||
│ ── Log ───────────────────────────────────────────────────── │
|
||
│ Log 等級 [ Info ▼ ](Debug / Info / Warn / Error) │
|
||
│ Log 位置 ~/Library/Application Support/visionA Agent/logs/ │
|
||
│ [ 開啟資料夾 ] [ 匯出 Log... ] │
|
||
│ │
|
||
│ ── 關於 ───────────────────────────────────────────────────── │
|
||
│ 版本 visionA Agent 0.1.0 │
|
||
│ [ 檢查更新 ] [ 開啟文件 ↗ ] [ GitHub ↗ ] │
|
||
│ │
|
||
│ 危險區域 [ 重置所有設定 ] │
|
||
│ │
|
||
└──────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 6.2 區塊規格
|
||
|
||
容器:`max-w-2xl mx-auto p-6 space-y-8`。每個區塊:`space-y-3`,區塊間用 `Separator`。
|
||
|
||
#### 6.2.1 連線
|
||
|
||
- **Relay URL**:
|
||
- `Label` + `Input`(`font-mono text-sm`)+ `Button "測試連線"`(`variant=outline size=sm`)
|
||
- 預設值:`wss://relay.visionA.cloud`
|
||
- 驗證:必須以 `wss://` 或 `ws://` 開頭
|
||
- 變更不會立即套用;下方 `text-xs text-muted-foreground` 顯示「當前設定將於下次連線時生效」
|
||
- 若與當前連線值不同:顯示橙色 badge `未套用`
|
||
- **測試連線**按鈕:
|
||
- 點擊後嘗試 WebSocket handshake(不帶 token,只測 reachability)
|
||
- Loading:spinner
|
||
- 成功:`Toast ✓ Relay 可達({latency}ms)`
|
||
- 失敗:`Toast ✗ 無法連上 {url}:{reason}`
|
||
|
||
#### 6.2.2 行為
|
||
|
||
- **開機自動啟動**:
|
||
- shadcn `Checkbox` + `Label`
|
||
- 預設**關閉**(已決策)
|
||
- 勾選後立即套用(backend 寫入對應 OS 啟動項;macOS Login Items / Windows Registry Run / Linux `.desktop` autostart)
|
||
- 變更時 toast:「✓ 已啟用開機自啟動」/ 「已關閉開機自啟動」
|
||
|
||
- **重連策略**:
|
||
- shadcn `RadioGroup`
|
||
- `自動重試` — 預設;指數退避(1s → 2s → 4s → 8s → 16s),最多 5 次失敗後停止並轉為手動
|
||
- `手動重連` — 連線中斷後不自動重試,使用者需在狀態頁點「立即重試」
|
||
|
||
#### 6.2.3 Log
|
||
|
||
- **Log 等級**:shadcn `Select`,選項 `Debug / Info / Warn / Error`,預設 `Info`
|
||
- 變更立即生效
|
||
- **Log 位置**:唯讀顯示 OS 對應路徑(`font-mono text-xs`)
|
||
- macOS:`~/Library/Application Support/visionA Agent/logs/`
|
||
- Windows:`%APPDATA%\visionA Agent\logs\`
|
||
- Linux:`~/.config/visionA-agent/logs/`
|
||
- 「開啟資料夾」按鈕:call backend 開檔案總管到該路徑
|
||
- **匯出 Log**按鈕:
|
||
- 點擊 → OS save dialog(Wails runtime `SaveFileDialog`)
|
||
- 預設檔名:`visionA-agent-log-YYYYMMDD-HHmmss.zip`
|
||
- 內容:壓縮最近 7 天的 log 檔
|
||
- 匯出中:按鈕 loading;完成 toast「✓ 已匯出到 {path}」
|
||
|
||
#### 6.2.4 關於
|
||
|
||
- **版本**:`visionA Agent {version}`(從 `runtime.Environment` 取)
|
||
- **檢查更新**按鈕:
|
||
- Phase 0 stub:call backend `CheckForUpdates()`,雛形直接回 `up-to-date`
|
||
- Toast:`✓ 已是最新版本` / `有新版本可用:v0.2.0 [ 開啟下載頁 ]`
|
||
- **開啟文件**:`BrowserOpenURL("https://docs.visionA.cloud/agent")`
|
||
- **GitHub**:`BrowserOpenURL("https://github.com/innovedus/visionA-agent")`
|
||
|
||
#### 6.2.5 危險區域
|
||
|
||
- 小標:`危險區域`(`text-sm font-medium text-destructive`)
|
||
- **重置所有設定**按鈕:
|
||
- `variant=destructive size=sm`
|
||
- 點擊 → shadcn `AlertDialog`
|
||
- 標題:「確定要重置所有設定嗎?」
|
||
- 內文:「這將清除:Relay URL、開機自啟、Log 等級、**以及已配對的 Session Token**。你將需要重新配對才能使用。此操作無法復原。」
|
||
- 按鈕:`取消` / `確定重置`(destructive)
|
||
- 確認後:backend 清除 config + session token → toast「已重置所有設定」→ 切到配對頁顯示 notPaired
|
||
|
||
### 6.3 i18n key
|
||
|
||
```
|
||
settings.title → 設定
|
||
settings.connection → 連線
|
||
settings.relayUrl → Relay URL
|
||
settings.relayUrl.hint → 當前設定將於下次連線時生效
|
||
settings.relayUrl.unapplied → 未套用
|
||
settings.testConnection → 測試連線
|
||
settings.testConnection.success → Relay 可達({latency}ms)
|
||
settings.testConnection.failed → 無法連上 {url}:{reason}
|
||
|
||
settings.behavior → 行為
|
||
settings.autoStart → 開機自動啟動 visionA Agent
|
||
settings.autoStart.enabled → 已啟用開機自啟動
|
||
settings.autoStart.disabled → 已關閉開機自啟動
|
||
settings.reconnectStrategy → 重連策略
|
||
settings.reconnectStrategy.auto → 自動重試(指數退避,最多 5 次)
|
||
settings.reconnectStrategy.manual → 手動重連
|
||
|
||
settings.log → Log
|
||
settings.logLevel → Log 等級
|
||
settings.logLocation → Log 位置
|
||
settings.openFolder → 開啟資料夾
|
||
settings.exportLog → 匯出 Log...
|
||
settings.exportLog.success → 已匯出到 {path}
|
||
|
||
settings.about → 關於
|
||
settings.version → 版本
|
||
settings.checkUpdate → 檢查更新
|
||
settings.checkUpdate.upToDate → 已是最新版本
|
||
settings.checkUpdate.available → 有新版本可用:{version}
|
||
settings.openDocs → 開啟文件
|
||
settings.github → GitHub
|
||
|
||
settings.dangerZone → 危險區域
|
||
settings.reset → 重置所有設定
|
||
settings.reset.confirm.title → 確定要重置所有設定嗎?
|
||
settings.reset.confirm.description → 這將清除:Relay URL、開機自啟、Log 等級、以及已配對的 Session Token。你將需要重新配對才能使用。此操作無法復原。
|
||
settings.reset.confirm.cancel → 取消
|
||
settings.reset.confirm.ok → 確定重置
|
||
settings.reset.done → 已重置所有設定
|
||
```
|
||
|
||
### 6.4 驗收條件
|
||
|
||
- [ ] Relay URL 驗證 `ws(s)://` 前綴
|
||
- [ ] 變更 Relay URL 不立即套用,顯示「未套用」badge
|
||
- [ ] 「測試連線」真正發 WS handshake(不是假 loading)
|
||
- [ ] 開機自啟 checkbox 在三平台都能正確寫入 OS 啟動項
|
||
- [ ] Log 位置顯示 OS 對應路徑,可開啟資料夾
|
||
- [ ] 匯出 Log 檔名格式正確、可正常解壓
|
||
- [ ] 重置設定會清 Session Token 並切回配對頁
|
||
|
||
---
|
||
|
||
## 7. 跨平台適配
|
||
|
||
### 7.1 macOS
|
||
|
||
| 項目 | 處理 |
|
||
|------|------|
|
||
| 視窗 chrome | **Wails 預設**(標準紅黃綠按鈕),不自訂 traffic light 位置 |
|
||
| 選單列 | Wails 預設 Menu(App / Edit / Window / Help),不加自訂項 |
|
||
| 檔案對話框 | `runtime.SaveFileDialog` / `OpenDirectoryDialog` |
|
||
| 啟動項 | `~/Library/LaunchAgents/com.innovedus.visiona-agent.plist` |
|
||
| Log 路徑 | `~/Library/Application Support/visionA Agent/logs/` |
|
||
| 打包 | DMG(參考 local-tool 已有的 `create-dmg` 流程)|
|
||
|
||
### 7.2 Windows
|
||
|
||
| 項目 | 處理 |
|
||
|------|------|
|
||
| 視窗 chrome | 標準 title bar(Windows 11 Mica 可選但**不強制**) |
|
||
| 檔案對話框 | `runtime.SaveFileDialog`(Wails 內建用 Win32 API) |
|
||
| 啟動項 | Registry `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` |
|
||
| Log 路徑 | `%APPDATA%\visionA Agent\logs\` |
|
||
| 打包 | NSIS installer(`.exe`)|
|
||
|
||
### 7.3 Linux
|
||
|
||
| 項目 | 處理 |
|
||
|------|------|
|
||
| 視窗 chrome | 依 DE(GNOME / KDE / XFCE)走預設 |
|
||
| 檔案對話框 | GTK / Qt(Wails 依系統偵測) |
|
||
| 啟動項 | `~/.config/autostart/visiona-agent.desktop` |
|
||
| Log 路徑 | `~/.config/visionA-agent/logs/`(XDG 規範)|
|
||
| 打包 | AppImage |
|
||
|
||
### 7.4 共通原則
|
||
|
||
- **不用** hover-only 操作(觸控筆電也要能用 — 所有資訊 hover 才顯示的 tooltip,都必須 focus 也顯示)
|
||
- **不用** OS 特殊動畫 API(避免 Linux 裝了 compositor 死機)
|
||
- **不用** 特殊字型(全跟 Geist,Wails 會 bundle)
|
||
- **檔案路徑**顯示時一律 `font-mono text-xs`,避免字型不同導致錯位
|
||
|
||
---
|
||
|
||
## 8. Dark Mode
|
||
|
||
- 跟隨 OS:macOS `appearance` / Windows `apps use dark theme` / Linux `color-scheme` media query
|
||
- 實作方式:沿用 visionA-frontend 的 `ThemeSync` 元件(react hook + `matchMedia`)
|
||
- **不提供**手動切換 UI
|
||
- 所有顏色用 CSS 變數(Design Tokens),自動跟 `.dark` class 切換
|
||
- 圖示(Lucide SVG)用 `currentColor`,自動跟文字色
|
||
- **logo 圖片**需要 light / dark 兩版(logo-light.svg / logo-dark.svg)
|
||
|
||
---
|
||
|
||
## 9. 無障礙基準(WCAG 2.1 AA)
|
||
|
||
- **色彩對比**:一般文字 ≥ 4.5:1;大文字 ≥ 3:1;UI 元件 ≥ 3:1
|
||
- **不只靠顏色**:所有狀態搭配 icon + 文字
|
||
- **鍵盤導航**:
|
||
- Tab 依視覺順序移動
|
||
- `Ctrl/Cmd+1/2/3` 切 Tab
|
||
- `Enter` 送出表單
|
||
- `Esc` 關閉 Dialog / 取消操作
|
||
- Focus ring 永遠可見(`ring-[3px] ring-ring`)
|
||
- **ARIA**:
|
||
- Tab 用 `role="tab"` / `role="tabpanel"` / `aria-selected`
|
||
- StatusHero 用 `role="status" aria-live="polite"`
|
||
- Toast 用 Sonner 預設 `aria-live="assertive"`
|
||
- AlertDialog 用 shadcn 內建焦點陷阱
|
||
- **螢幕閱讀器**:
|
||
- Session Token 遮蔽版:`aria-label="Session token, ending in e7f8"`(不念完整字串)
|
||
- 圖示裝飾:`aria-hidden="true"`
|
||
- **Reduce motion**:支援 `prefers-reduced-motion`,停用 pulse / spinner 旋轉
|
||
|
||
---
|
||
|
||
## 10. i18n 字典 keys 預估
|
||
|
||
| 分類 | keys 數 |
|
||
|------|--------|
|
||
| 全域(nav / header / common)| ~15 |
|
||
| 狀態頁(status)| ~25 |
|
||
| 配對頁(pair)| ~30 |
|
||
| 設定頁(settings)| ~40 |
|
||
| 錯誤訊息(errors)| ~15 |
|
||
| Toast | ~10 |
|
||
| **總計** | **~135 keys** |
|
||
|
||
兩語言(繁中 + English)共約 270 條翻譯。文件位置建議:
|
||
|
||
```
|
||
visiona-agent/frontend/src/lib/i18n/
|
||
├── zh-TW.ts
|
||
└── en.ts
|
||
```
|
||
|
||
偵測優先序:OS locale → 預設 `en`(若非 `zh-*` 均 fallback en)。
|
||
|
||
---
|
||
|
||
## 11. 需使用者裁決的設計決定
|
||
|
||
以下三點為設計過程中稍有不確定、建議使用者快速裁決的點(不影響動工,可先照 Design 建議實作):
|
||
|
||
| # | 問題 | Design 建議 | 備選 |
|
||
|---|------|-----------|------|
|
||
| 1 | 視窗大小是否允許使用者記住上次大小? | **記住**(Wails 預設行為) | 每次固定 720×560 |
|
||
| 2 | 配對成功後的轉場 | **0.5 秒後自動切回狀態頁**(有 toast 確認) | 停留原地,顯示大 ✓ 後讓使用者手動點繼續 |
|
||
| 3 | 「檢查更新」按鈕在 Phase 0 雛形的行為 | **stub:直接回 up-to-date** | 直接隱藏按鈕,Phase 1 再開 |
|
||
|
||
---
|
||
|
||
## 12. 交付檔案
|
||
|
||
| 檔案 | 狀態 |
|
||
|------|------|
|
||
| `.autoflow/03-design/visiona-agent-spec.md`(本檔)| ✅ 完成 |
|
||
|
||
**不產出**:
|
||
- wireframe 子檔(本檔內已含 ASCII wireframe,小規模 utility 無需再拆)
|
||
- 高保真 prototype(雛形階段無必要)
|
||
- 獨立 design-tokens(完全沿用 visionA-frontend 既有檔案)
|
||
|
||
---
|
||
|
||
## 13. 給 Architect / Frontend Agent 的提醒
|
||
|
||
### 13.1 給 Architect
|
||
|
||
- Agent 與 remote-proxy 的通訊契約(WS upgrade、session token 持久化、reconnect 指數退避)請對齊 `04-architecture/security.md` 的 Pairing / Session 兩階段協定
|
||
- 前端(Wails runtime 呼叫 Go backend)建議定義清楚的 API:`Connect(token) / Disconnect() / Reconnect() / GetStatus() / TestRelay(url) / ExportLog() / ResetAll()`
|
||
- 狀態同步:backend 用 Wails `EventsEmit("connection:status", payload)` 推送,前端 `EventsOn` 監聽
|
||
|
||
### 13.2 給 Frontend(未來撰寫 Agent 前端的工程師)
|
||
|
||
- **直接複製** `visionA-frontend/src/app/globals.css` 到 Agent 專案,**不動一行**
|
||
- **直接複製** shadcn 基礎元件(Button / Card / Dialog / Input / Tabs / Checkbox / RadioGroup / Select / AlertDialog / Alert / Sonner)
|
||
- **不引入** Next.js(Agent 是純 SPA);用 Vite + React Router(或不用 router,三個 tab 用 state 切換)
|
||
- i18n 沿用 visionA-frontend 的 `src/lib/i18n` 模式(自訂 hook + TS 字典)
|
||
- 所有 backend 呼叫走 Wails runtime bindings,不碰 HTTP
|
||
- Dark Mode sync:沿用 `ThemeSync` 元件
|
||
|
||
---
|
||
|
||
**本規格結束。共 3 頁面 + 1 全域導航 + 3 平台適配 + 135 i18n keys,符合「極簡 utility」定位。**
|