diff --git a/docs/PRD-Integrated.md b/docs/PRD-Integrated.md index 33ef3cf..45d2ccc 100644 --- a/docs/PRD-Integrated.md +++ b/docs/PRD-Integrated.md @@ -1087,17 +1087,19 @@ Kneron Dongle Arduino 開發板 非 Kneron 晶片 ### B4.5 已實作的額外功能 -> 以下功能為 MVP 開發過程中額外實作,超出原始 PRD 範圍。共 9 項功能。 +> 以下功能為 MVP 開發過程中額外實作,超出原始 PRD 範圍。共 11 項功能。 #### F5 — 多來源推論輸入 | 項目 | 規格 | |------|------| | **概述** | 除了攝影機之外,支援上傳圖片和影片作為推論輸入來源 | -| **輸入來源** | 攝影機(即時)、圖片上傳(JPG/PNG)、影片上傳(MP4/AVI/MOV)、影片 URL(直接連結、YouTube、RTSP) | +| **輸入來源** | 攝影機(即時)、圖片上傳(JPG/PNG,支援單張與多張批次)、影片上傳(MP4/AVI/MOV)、影片 URL(直接連結、YouTube、RTSP) | | **圖片推論** | 上傳圖片至後端,送入裝置 NPU 推論後回傳結果 | +| **批次圖片推論** | 上傳多張圖片(最多 50 張),後端逐張送入 NPU 推論,結果透過 WebSocket 即時串流回前端;前端提供縮圖列表、進度條、點擊切換瀏覽各張結果 | | **影片推論** | 上傳影片或提供 URL,後端逐幀擷取送入裝置推論,結果透過 WebSocket 即時串流 | | **YouTube 支援** | 透過 yt-dlp 解析 YouTube URL 取得直接影片連結,再進行影片推論 | +| **拖放上傳** | 圖片 tab 支援 drag & drop 拖放上傳,拖入時顯示高亮邊框提示 | | **UI 設計** | Tab 式切換(攝影機 / 圖片 / 影片),影片 tab 內再切換上傳檔案或貼上 URL | #### F6 — 多語系支援(i18n) @@ -1107,7 +1109,7 @@ Kneron Dongle Arduino 開發板 非 Kneron 晶片 | **概述** | 完整的前端多語系支援,支援英文與繁體中文切換 | | **支援語言** | English (en)、繁體中文 (zh-TW) | | **實作方式** | 自訂 TypeScript i18n 系統,不依賴外部框架(無 next-intl / react-i18next) | -| **翻譯字典** | 約 120+ 翻譯 key,按功能分區(common, nav, dashboard, devices, models, camera, inference, settings, errors) | +| **翻譯字典** | 約 130+ 翻譯 key,按功能分區(common, nav, dashboard, devices, models, camera, inference, settings, errors) | | **型別安全** | `TranslationKey` 型別由 `Paths` 遞迴產生,提供所有 key 的自動完成,缺 key 時 TypeScript 報錯 | | **切換方式** | Settings 頁面語言下拉選單,切換後即時生效(無需重新整理) | | **持久化** | 語言設定透過 Zustand persist 儲存至 localStorage | @@ -1177,6 +1179,26 @@ Kneron Dongle Arduino 開發板 非 Kneron 晶片 | **健康狀態** | 狀態、韌體版本、運行時間、最後活動時間 | | **連線歷史** | 按時間排列的連線/斷線事件紀錄 | +#### F14 — 批次圖片推論 + +| 項目 | 規格 | +|------|------| +| **概述** | 支援一次上傳多張圖片進行批次推論,適用於工業檢測等需要大量圖片驗證的場景 | +| **上傳方式** | 檔案選擇器多選、拖放上傳(drag & drop),上限 50 張 | +| **處理方式** | 後端逐張送入 NPU 推論(硬體限制),結果透過 WebSocket 即時串流回前端 | +| **進度顯示** | 進度條顯示已處理 / 總數,縮圖列表標示完成(✓)/處理中(⏳)/待處理(編號) | +| **結果瀏覽** | 水平捲動縮圖列表,點擊切換檢視不同圖片的推論結果(BBox overlay + 分類結果) | +| **UI 設計** | 批次模式下自動隱藏手動推論按鈕,inference panel 顯示批次進度卡片 | + +#### F15 — 攝影機自動偵測 + +| 項目 | 規格 | +|------|------| +| **概述** | 進入 workspace 時自動偵測系統是否有可用攝影機,無攝影機時自動停用攝影機功能 | +| **偵測方式** | 後端透過 ffmpeg 偵測系統攝影機(macOS: AVFoundation, Windows: DirectShow) | +| **無攝影機行為** | Camera tab 自動 disabled、預設切換至 Image tab、顯示「未偵測到攝影機」提示訊息 | +| **有攝影機行為** | 維持原有攝影機推論功能不變 | + --- ## B5. 功能路線圖(Post-MVP) diff --git a/docs/TDD.md b/docs/TDD.md index bf8f493..273caab 100644 --- a/docs/TDD.md +++ b/docs/TDD.md @@ -1439,6 +1439,8 @@ MVP 階段不使用資料庫,使用檔案系統: |---------|---------|-----| | `SourceSelector` (Tab: camera/image/video) | `camera/manager` | `POST /api/camera/start` | | Image upload button | `api/handlers/media_handler` | `POST /api/media/upload/image` | +| Batch image upload (多選 + drag & drop) | `api/handlers/camera_handler` | `POST /api/media/upload/batch-images` | +| Batch image frame viewer | `camera/multi_image_source` | `GET /api/media/batch-images/:index` | | Video upload button | `api/handlers/media_handler` | `POST /api/media/upload/video` | | URL input + submit | `api/handlers/media_handler` | `POST /api/media/url` | @@ -1458,7 +1460,7 @@ URL 輸入 → 後端分類 URL 類型: ``` src/lib/i18n/ ├── types.ts # TranslationDict 介面 + Paths 遞迴型別 -├── en.ts # 英文字典(~120 keys) +├── en.ts # 英文字典(~130+ keys) ├── zh-TW.ts # 繁體中文字典 └── index.ts # useTranslation() hook + getTranslation() helper ``` @@ -1518,6 +1520,71 @@ src/lib/i18n/ **Settings Store:** `settings-store.ts` 管理 `theme` ('light' | 'dark') 和 `language` ('en' | 'zh-TW'),persist 至 localStorage。 +#### 8.5.8 自訂模型上傳(F11) + +| 前端元件 | 後端模組 | API | +|---------|---------|-----| +| `ModelUploadDialog` | `api/handlers/model_handler` | `POST /api/models/upload` | +| 表單驗證(檔案、名稱、任務類型、標籤) | 模型元資訊存檔 | `DELETE /api/models/:id` | + +**上傳流程:** 前端 FormData(.nef + 元資訊)→ 後端儲存檔案 + 建立模型紀錄 → 回傳模型 ID → 前端更新模型庫。 + +#### 8.5.9 裝置健康狀態與連線歷史(F13) + +| 前端元件 | 資料來源 | 說明 | +|---------|---------|------| +| `DeviceHealthCard` | `device-store` | 狀態、韌體版本、運行時間(useEffect + setInterval 更新) | +| `DeviceConnectionLog` | `device-preferences-store` | 連線/斷線事件紀錄,含時間戳記 | + +**Hydration 安全:** 運行時間使用 `useState(0)` + `useEffect` 避免 `Date.now()` 造成 SSR 不匹配;時間格式化使用 `suppressHydrationWarning`。 + +#### 8.5.10 批次圖片推論(F14) + +| 前端元件 | 後端模組 | API | +|---------|---------|-----| +| `BatchImageThumbnails` | `camera/multi_image_source.go` | `POST /api/media/upload/batch-images` | +| `SourceSelector`(多選 + drag & drop) | `api/handlers/camera_handler` | `GET /api/media/batch-images/:index` | +| `InferencePanel`(批次進度卡片) | `camera/pipeline.go`(SourceBatchImage 分支) | WebSocket 推論結果串流 | + +**資料流:** + +``` +前端多選/拖放圖片 → FormData POST 至後端 +→ 後端建立 MultiImageSource → Pipeline 逐張 ReadFrame +→ NPU 推論 → InferenceResult 加入 imageIndex/totalImages/filename +→ WebSocket 即時回傳 → 前端 addBatchResult → 更新進度 + 縮圖狀態 +→ 使用者點擊縮圖 → 切換 batchSelectedIndex → 顯示對應圖片 + BBox overlay +``` + +**前端 Store 擴展:** +- `camera-store`:新增 `batchImages`, `batchSelectedIndex`, `batchProcessedCount`, `uploadBatchImages()` +- `inference-store`:新增 `batchResults: Record`, `addBatchResult()` +- `use-inference-stream`:判斷 `imageIndex !== undefined` 走批次處理邏輯 + +**型別擴展:** +- `SourceType` 新增 `'batch_image'` +- `BatchImageInfo`:`{ index, filename, width, height }` +- `InferenceResult` 新增 `imageIndex?`, `totalImages?`, `filename?` + +#### 8.5.11 攝影機自動偵測(F15) + +| 前端元件 | 後端模組 | API | +|---------|---------|-----| +| `workspace-client.tsx`(fetchCameras) | `camera/manager.go` | `GET /api/camera/list` | +| `SourceSelector`(cameraDisabled 邏輯) | `camera/ffmpeg_detect.go` | — | + +**偵測流程:** + +``` +workspace 載入 → fetchCameras() → GET /api/camera/list +→ 後端 Manager.ListCameras(): + ├── mockMode=true → 回傳 mock camera + └── mockMode=false → ffmpeg 偵測真實攝影機 → 回傳列表或空陣列 +→ 前端 cameras.length === 0 → useEffect 切換至 Image tab + disable Camera tab +``` + +**Hydration 安全:** 使用 `useHydrated()` hook 確保 `disabled` 屬性在 SSR 時為 `false`(與 `Tabs value="camera"` 一致),hydration 完成後才根據 cameras 列表設定 disabled 狀態。 + --- ## 9. 開發環境與工具鏈