jim800121chen 99dea42239 feat(visionA-frontend): Phase 0 → 0.7 雲端前端(Next.js + OIDC redirect 流程)
visionA 雲端版前端 — 沿用 local-tool 既有 UI(原則 4:先抄 local-tool)+
新增雲端特有的登入 / 配對 / 設定流程,含以下整合階段:

- Phase 0:13 頁 + 30+ 元件 + 雛形 banner
  - dashboard / devices / models / workspace / clusters / settings 等頁
  - AppShell + Sidebar + Header + tokens + i18n(中英雙語 96 keys)
  - API client + 5 stores + 3 hooks
- Phase 0.6:OIDC redirect 改造
  - login 頁改為 OIDC redirect(`window.location.href = /api/auth/login`)
  - register 改說明頁、account 改唯讀(user 資料來源是 MC)
  - api client 改 cookie session(credentials: include)+ 完全清掉 localStorage
- Phase 0.7:stage 部署 + nil guard
  - getApiBaseUrl() 修:browser 環境視為 same-origin(與 login 頁一致)
  - login 頁加「已登入 → router.replace('/')」effect
  - User type email/name 改 optional(MC id_token 不一定回 email/name claim)
  - header.tsx UserMenu displayName 4 層 fallback:name → email → id → i18n
  - 雛形 banner 文案更新(已接 Innovedus 帳號中心)+ 版號 Phase 0.7

驗證:pnpm lint / test (125/125) / build 全綠

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 11:21:36 +08:00

235 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# visionA Cloud Frontend
> visionA Cloud 前端 Web 應用Next.js 16 + React 19 + Tailwind 4
>
> 目的:將 `local-tool/` 的使用體驗延伸到雲端,讓使用者透過瀏覽器操作由 local agent 連入的邊緣裝置Kneron KL520/KL720 等)。
> 🚧 **Phase 0 雛形** — 任何功能皆以 UI 走通為目標不做真實身分驗證、OAuth、WebSocket 即時推送、MJPEG 串流。完整功能清單見下方「雛形範圍與限制」。
>
> 規劃中的正式版請見 [`.autoflow/02-prd/PRD.md`](../.autoflow/02-prd/PRD.md),架構決策見 [`.autoflow/04-architecture/design-doc.md`](../.autoflow/04-architecture/design-doc.md)。
---
## 技術堆疊
| 層級 | 技術 | 版本 |
|------|------|------|
| 框架 | Next.jsApp Router | 16.1.6 |
| UI 函式庫 | React / React DOM | 19.2.3 |
| 語言 | TypeScript | ^5 |
| 樣式 | Tailwind CSS`@tailwindcss/postcss`| ^4 |
| 元件 primitive | Radix UI | ^1.4.3 |
| 元件規範 | shadcn `new-york` style`components.json` | — |
| 圖示 | lucide-react | ^0.575.0 |
| 狀態管理 | Zustand | ^5.0.11 |
| 主題 | next-themes | ^0.4.6 |
| Toast | sonner | ^2.0.7 |
| Class 工具 | clsx + tailwind-merge + class-variance-authority | — |
| 測試 | Vitest + @testing-library/react + jsdom | ^4 / ^16 / ^28 |
| Lint | ESLint + eslint-config-next | ^9 / 16.1.6 |
版本與 [`local-tool/frontend/`](../local-tool/frontend/) 對齊,確保「雲端版 / 離線版同一套前端」的架構決策可執行。
---
## 前置需求
- Node.js **≥ 20**
- pnpm **≥ 10**
- **依賴:** 需同時運行 [`visionA-backend`](../visionA-backend/README.md)Go。前端所有 API 呼叫會指向 `NEXT_PUBLIC_API_BASE`,後端未啟動時功能會顯示錯誤但 UI 仍可瀏覽(多數頁面對 501 / 連線錯誤已做 graceful fallback
---
## 快速啟動
```bash
# 1. 安裝依賴
cd visionA-frontend
pnpm install
# 2. 設定環境變數
cp .env.local.example .env.local
# 檢查 NEXT_PUBLIC_API_BASE 是否指到正確後端位址
# 3. 啟動後端(另一個 terminal
cd ../visionA-backend
make run # 或參考 visionA-backend/README.md
# 4. 啟動前端
cd ../visionA-frontend
pnpm dev # http://localhost:3000
```
進入後**任何 email + 任何密碼**都可登入Phase 0 的 StaticAuthProvider
### 可用腳本
| 指令 | 說明 |
|------|------|
| `pnpm dev` | 開發模式Turbopack / HMR |
| `pnpm build` | 產線打包(`output: "standalone"`,便於 Docker 部署) |
| `pnpm start` | 啟動 production build |
| `pnpm lint` | 執行 ESLint |
| `pnpm test` | 執行 Vitest一次性 |
| `pnpm test:watch` | 執行 Vitestwatch mode |
---
## 專案結構
```
visionA-frontend/
├── src/
│ ├── app/ # Next.js App Router 路由
│ │ ├── layout.tsx # Root layoutTheme / Locale / AppShell
│ │ ├── page.tsx # / Dashboard
│ │ ├── login/ # /login
│ │ ├── register/ # /registerPhase 0 Coming Soon
│ │ ├── account/ # /account 帳號設定 stub
│ │ ├── devices/ # /devices, /devices/[id], /devices/pair
│ │ ├── models/ # /models, /models/[id]
│ │ ├── workspace/ # /workspace, /workspace/[deviceId]
│ │ ├── clusters/ # /clustersPhase 0 預告頁)
│ │ └── settings/ # /settings
│ ├── components/
│ │ ├── ui/ # Shadcn primitiveButton / Card / Input ...
│ │ ├── layout/ # Sidebar / Header / PrototypeBanner / AppShell
│ │ ├── dashboard/ # StatCard / ActivityTimeline / ConnectedDevicesList
│ │ ├── devices/ # DeviceCard 相關
│ │ ├── models/ # ModelCard / ModelUploadDialog
│ │ ├── cloud/ # RemoteDeviceBadge
│ │ └── pairing/ # PairingTokenCard / PairingCountdown
│ ├── hooks/ # useFetch / useWebsocket / useTunnelStatus
│ ├── lib/
│ │ ├── api.ts # 統一 API clientenvelope / 401 / 501 / timeout
│ │ ├── utils.ts # cn() 等
│ │ └── i18n/ # zh-Hant / en 字典 + Context
│ ├── stores/ # Zustand storesauth / session / device / model / activity / pairing
│ ├── tests/ # Vitest setup
│ └── types/ # 共用型別api / user / pairing ...
├── public/ # 靜態資源
├── components.json # Shadcn CLI 設定
├── next.config.ts # output: standalone
├── tsconfig.json # @/* → ./src/*
└── package.json
```
---
## 主要頁面清單
| 路徑 | Phase 0 狀態 | 說明 |
|------|-------------|------|
| `/login` | ✅ 可用 | 任意帳密皆通過StaticAuth |
| `/register` | ⚠️ Coming Soon | 引導回 /loginPhase 1 才實作 |
| `/` Dashboard | ✅ 可用 | StatCard × 4、近期活動、快速操作無裝置時顯示空狀態引導 /devices/pair |
| `/devices` | ✅ 可用 | 裝置列表RemoteDeviceBadge 顯示遠端連線狀態 |
| `/devices/[id]` | ✅ 可用 | 裝置詳細、離線 banner |
| `/devices/pair` | ✅ 可用(核心) | 三步配對流程:產生 Pairing Token → 15 分鐘倒數 → 輪詢 3 分鐘 |
| `/models` | ✅ 可用 | 模型列表 + 上傳 DialogXHR 進度) |
| `/models/[id]` | ✅ 可用 | 模型詳細、部署到裝置 |
| `/workspace` | ✅ 可用 | 選擇線上裝置 |
| `/workspace/[deviceId]` | ⚠️ Camera placeholder | 推論 Start/Stop 可按MJPEG stream Phase 1 接上 |
| `/clusters` | ⚠️ Phase 1 預告 | POC 有完整實作,雛形後端是 stub |
| `/account` | ✅ 可用 stub | 顯示使用者 + 登出;其他操作是 toast 提醒 |
| `/settings` | ✅ 可用 | 語言 / 主題 / API 端點切換 |
---
## 環境變數
| 變數 | 說明 | 預設值 | 必要 |
|------|------|--------|------|
| `NEXT_PUBLIC_API_BASE` | 雲端 API Server 位址(無尾斜線) | `http://localhost:3721` | 是 |
| `NEXT_PUBLIC_WS_BASE` | WebSocket 位址;留空則從 API 推導 | 從 API base 推導 | 否 |
所有 runtime 變數都以 `NEXT_PUBLIC_` 開頭Next.js 要求前端可讀),**不要放真正機密的值**——這類值應走後端。
---
## Phase 0 雛形範圍與限制
### ✅ 可做到的
- 完整 UI 骨架Sidebar / Header / 全域雛形 Banner / Sonner toast
- i18nzh-Hant / en可即時切換key 集合兩語系強制同步
- Light / Dark / System 主題切換
- 裝置 / 模型 / 活動 三個 store 的 CRUD UI對齊 api-spec
- **Pairing 流程**:產 token → 視覺切兩行顯示(複製永遠是完整 36 字元)→ 15 分鐘倒數3 色階段)→ 輪詢連線狀態 → 成功 toast + 跳轉
- 離線降級:`RemoteDeviceBadge` + 頁面離線 Banner + Workspace 遮罩
- 模型上傳XHR progress + presigned URL 直送 storage
### ❌ Phase 0 刻意不做Phase 1 接手)
- **任何帳密可登入** — 後端 `StaticAuthProvider``demo-user`;重啟後端後前端 localStorage 的 token 雖然還在,但伺服器上沒有任何 session 資料
- **OAuth / 2FA / 密碼重設** — 全部 Phase 1
- **註冊功能** — 顯示 Coming Soon 頁面
- **重啟後端 → 裝置 / 模型資料消失** — 後端目前是 InMemoryRepository
- **WebSocket 即時推送** — 事件 / 推論結果 / 配對狀態的 WS endpoint 目前回 501前端改用 3 秒輪詢pairing 頁)
- **Camera / MJPEG 串流** — `/workspace/[deviceId]` 的 Camera tab 顯示 placeholderImage / Video / Batch tabs disabled
- **Cluster CRUD** — `/clusters` 顯示 Phase 1 預告頁
- **Account CRUD** — 變更個人資料 / 刪除帳號都是 toast stub
- **真實 SHA-256 checksum** — 模型上傳用 `placeholder:{size}:{nameLen}`(詳見 `model-upload-dialog.tsx` §placeholderChecksum
前端安全債詳見 [`.autoflow/04-architecture/security.md`](../.autoflow/04-architecture/security.md) §14localStorage token / WS querystring / CSP / CSRF 等 6 項,每項有 Phase 1 計畫)。
---
## 效能預算Phase 1 開始嚴格執行)
| 資源 | 預算 |
|------|------|
| JavaScript首次載入壓縮後 | < 200 KB |
| CSS壓縮後 | < 50 KB |
| 首次載入總大小 | < 500 KB |
| Core Web Vitals | LCP < 2.5sINP < 200msCLS < 0.1 |
雛形Phase 0階段僅確保 `pnpm build` 成功CI 中加入 bundle 檢查由 DevOps 任務處理
---
## 無障礙規範
目標 **WCAG 2.2 AA**詳見 [`.autoflow/03-design/design-spec.md`](../.autoflow/03-design/design-spec.md) §8
- 色彩對比一般文字 4.5:1大文字 3:1
- 鍵盤可操作所有核心流程Tab / Enter / Escape
- Focus ring 可見shadcn 預設 `ring-2 ring-ring`
- 語意化 HTML`<nav>``<main>``<aside>``<header>`
- 動態內容 `aria-live`
- Pairing token 顯示`role="text"` + 完整 token `aria-label`避免 SR 一字一念
- Status card成功 / 失敗用 `role="status"` / `role="alert"` + `aria-live`
---
## 測試
- **策略**Unit ~60% / Integration ~25% / Visual ~10% / E2E ~5%E2E 交給 Testing Agent
- **工具**Vitest + React Testing Library + jsdom
- **當前**15 個測試檔94 test 全綠
- **強制一致**`i18n.test.ts` zh-Hant / en 兩份字典 key 集合完全一致且無空字串
```bash
pnpm test # 一次跑完
pnpm test:watch # watch mode
```
---
## 部署
- `next.config.ts` 已設 `output: "standalone"`方便未來 Docker
- Dockerfile / docker-compose / Helm chart DevOps Agent 規劃Phase 1
---
## 相關文件
- PRD[`.autoflow/02-prd/PRD.md`](../.autoflow/02-prd/PRD.md)
- 設計規格索引[`.autoflow/03-design/design-spec.md`](../.autoflow/03-design/design-spec.md)
- Design Tokens[`.autoflow/03-design/design-tokens.md`](../.autoflow/03-design/design-tokens.md)
- Pairing 流程[`.autoflow/03-design/flows/flow-pairing.md`](../.autoflow/03-design/flows/flow-pairing.md)
- Auth 流程[`.autoflow/03-design/flows/flow-auth.md`](../.autoflow/03-design/flows/flow-auth.md)
- TDD §10 前端章節[`.autoflow/04-architecture/TDD.md`](../.autoflow/04-architecture/TDD.md)
- API Spec[`.autoflow/04-architecture/api/api-spec.md`](../.autoflow/04-architecture/api/api-spec.md)
- 前端安全債[`.autoflow/04-architecture/security.md`](../.autoflow/04-architecture/security.md) §14
- 整體進度[`.autoflow/progress.md`](../.autoflow/progress.md)