jim800121chen c54f16fca0 Initial commit: visionA monorepo with local-tool subproject
local-tool/: visionA-local desktop app
- M1: Wails shell + Go server + Next.js UI + Mock mode (macOS dmg ready)
- M2: i18n (zh-TW/en) + Settings 4-tab refactor
- M3: Embedded Python 3.12 runtime (python-build-standalone) + KneronPLUS wheels
- M4: Windows Inno Setup script (build on Windows runner)
- M5: Linux AppImage script + udev rule (build on Linux runner)
- M6: ffmpeg (GPL, pending legal review) + yt-dlp bundled
- Lifecycle: watchServer health check, fatal native dialog,
            Wails IPC raise endpoint, stale process cleanup

.autoflow/: full PRD / Design Spec / Architecture / Testing docs
            (4 rounds tri-party discussion + cross review)
.github/workflows/: macOS / Windows / Linux build CI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:10:38 +08:00

296 lines
17 KiB
Markdown
Raw 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.

# 5. 使用者流程
本章節描述三個關鍵使用者流程:**首次安裝 → First-Run → 日常使用**。每個流程都標注對應的 User Story 與驗收標準。
## 5.1 首次安裝流程(對應 US-1
```
┌─────────────────────────────────────────┐
│ 1. 使用者從內部 Gitea Releases 下載安裝檔 │
│ macOS → .dmg │
│ Windows → .exeInno Setup
│ Ubuntu → .AppImage │
└────────────┬────────────────────────────┘
┌─────────────────────────────────────────┐
│ 2. 雙擊安裝檔 │
│ macOS: .dmg mount → 拖拉到 Applications │
│ 首次開啟跳 Gatekeeper 警告 │
│ → 右鍵 → 開啟(安裝頁文件說明) │
│ Win: .exe 安裝精靈Inno Setup 預設流程) │
│ SmartScreen 警告 → 仍要執行 │
│ Linux: 給 .AppImage chmod +x → 雙擊 │
└────────────┬────────────────────────────┘
┌─────────────────────────────────────────┐
│ 3. Wails 殼啟動 → 偵測是否首次執行 │
│ 首次:開啟安裝精靈(沿用原 installer UI
│ 後續:跳過,直接進主畫面 │
└────────────┬────────────────────────────┘
┌─────────────────────────────────────────┐
│ 4. 安裝精靈執行以下步驟(有進度條): │
│ a. 解壓 payload 到應用資料目錄 │
│ (mac: ~/Library/Application Support/ │
│ visiona-local/Win/Linux 依慣例) │
│ b. 建立 Python venv優先用內嵌 Python
│ c. pip install --no-index wheels/ │
numpy / opencv / pyusb / KneronPLUS
│ d. 解壓 ffmpeg binary │
│ e. 解壓預置 .nef 模型 │
│ f. 平台特定步驟: │
│ - Win: 裝 WinUSB driver跳 UAC
│ - Linux: 寫入 udev rules跳 sudo
│ - Mac: ad-hoc codesign dylib │
│ g. 啟動 edge-ai-server 子行程 │
│ h. 等待 server readyhttp://127.0.0.1:3721
└────────────┬────────────────────────────┘
┌─────────────────────────────────────────┐
│ 5. 進入 First-Run 歡迎流程(見 5.2
└─────────────────────────────────────────┘
```
**關鍵驗收點:**
- 第 4 步 a-h 全部自動化,使用者無需任何 CLI 操作
- 若 Python fallback 失敗(系統無 Python明確告知使用者到哪下載
- 若 Windows 拒絕 UAC提供「手動安裝 driver」的指引
- 整個流程目標 ≤ 3 分鐘 / **上限 ≤ 5 分鐘**(一般硬體 + SSD— 第四輪 R4-4 決策
## 5.2 First-Run 歡迎流程(對應 US-2
```
┌─────────────────────────────────────────┐
│ Step 1 — 歡迎畫面 │
│ ┌─────────────────────────────────────┐ │
│ │ [visionA-local Logo沿用 EAP] │ │
│ │ │ │
│ │ 「邊緣 AI 推論,裝起來就能跑」 │ │
│ │ │ │
│ │ [開始使用] [稍後再說] │ │
│ └─────────────────────────────────────┘ │
└────────────┬────────────────────────────┘
│(點擊「開始使用」)
┌─────────────────────────────────────────┐
│ Step 2 — 執行模式選擇 │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ 🟢 真實硬體 │ │ 🟡 Mock 模式 │ │
│ │ │ │(先看看) │ │
│ │ 需要 Kneron │ │ 無需硬體 │ │
│ │ KL720/KL730 │ │ 假裝置 + 假推論│ │
│ │ USB 裝置 │ │ │ │
│ │ │ │ │ │
│ │ [選擇] │ │ [選擇] │ │
│ └──────────────┘ └──────────────┘ │
│ │
│ 預設:真實硬體(依據 Q8
└────────────┬────────────────────────────┘
├─── 選真實硬體 ───▶ Step 3a硬體偵測
└─── 選 Mock ──────▶ Step 3bMock 準備)
┌─────────────────────────────────────────┐
│ Step 3a — 硬體偵測(真實模式) │
│ 「請插上 Kneron 裝置…」 │
│ [自動掃描 USB持續 10 秒] │
│ ├ 成功:顯示偵測到的裝置卡片 │
│ │ [前往 Workspace] │
│ └ 失敗:顯示排錯清單 │
│ 1. 確認 USB 已插好 │
│ 2. 試試 USB 3.0 埠 │
│ 3. 重插一次 │
│ 4. 檢查驅動是否安裝 │
│ [重試] [切換 Mock 模式] │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ Step 3b — Mock 模式準備 │
│ 「已進入 Mock 模式,您將看到 3 個假裝置」 │
│ [進入 Dashboard] │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 完成 → 進入 Dashboard │
│ 右上角顯示目前模式(真實 / Mock
│ 主視窗標題列 + sidebar 底部狀態列同步顯示模式│
└─────────────────────────────────────────┘
```
**關鍵驗收點:**
- AC-2.1Mock 模式是一鍵選項(非預設)
- AC-2.2:進入 Mock 後 ≤ 30 秒看到假推論(首次)/ ≤ 15 秒(回訪)— 第四輪 R4-7 拆兩級
- AC-2.3Mock 模式有明確視覺標記(主視窗標題列 + 首頁徽章 + sidebar 底部狀態列)
- AC-2.4Mock 模式**不 spawn Python sidecar**,純前端 state + Go server對應 nonfunctional §6.1 的 Mock idle RAM ≤ 600MB 預算)
- 三步都可「稍後再說」跳過,直接進 Dashboard
## 5.3 日常使用流程
### 5.3.1 典型使用會話FAE 在客戶現場)
```
1. 使用者從 app 目錄或桌面捷徑開啟 visionA-local
2. Wails 殼啟動 → 跳過 First-Run已完成
3. 啟動 edge-ai-server 子行程(< 2 秒)
4. 主視窗開啟 → Dashboard
5. 使用者插上 Kneron USB
6. Devices 頁自動顯示新裝置WebSocket push
7. 使用者點「Connect」→ 進入 Workspace
8. 選 webcam + 選模型 → 點 Start
9. 看到 MJPEG 串流 + 推論 overlay
10. demo 完畢 → 點 Stop → 關閉主視窗 → 程式退出Q7 傳統式)
```
**關鍵驗收點:**
- 步驟 3 到步驟 9 整段 ≤ 30 秒
- 步驟 5 到步驟 6USB 偵測)≤ 3 秒
- 步驟 7 到步驟 9connect 到第一幀)≤ 10 秒
### 5.3.2 跨會話狀態持久化
> **路徑說明(第三輪 Q-E1 + 第四輪 R4-5**:資料目錄名統一全小寫為 `visiona-local`(對齊 Bundle ID `com.innovedus.visiona-local` 與 Linux 檔案系統慣例。macOS 採 OS 慣例路徑 `~/Library/Application Support/visiona-local/`Windows 預期為 `%APPDATA%\visiona-local\`Linux 預期為 `~/.local/share/visiona-local/` 或 `$XDG_DATA_HOME/visiona-local/`。以下以 `<APPDATA>` 表示該目錄。
| 狀態 | 儲存位置 | 是否跨會話保留 |
|------|---------|----------------|
| 上次選的模型 | `<APPDATA>/config.json` | ✅ 是 |
| 上次選的 webcam | `<APPDATA>/config.json` | ✅ 是 |
| 上次的模式(真實 / Mock | `<APPDATA>/config.json` | ✅ 是 |
| 上傳的自訂模型 | `<APPDATA>/models/` | ✅ 是 |
| 推論歷史 / 日誌 | `<APPDATA>/logs/` | ✅ 是(滾動保留) |
| 語言偏好 | `<APPDATA>/config.json` | ✅ 是 |
| 深色模式 | N/A | 跟隨系統,無覆寫 |
### 5.3.3 快速操作流程(原 Tray 流程 — 已砍)
> **第三輪 Q-A 決策**:系統列 tray 已砍掉。原本透過 tray 提供的快速操作顯示主視窗、Server 狀態、快速動作、模式切換、結束)改由以下方式提供:
>
> | 原 Tray 項目 | 新的入口 |
> |-------------|---------|
> | 顯示主視窗 | 桌面 / Dock / 工作列 iconOS 原生行為) |
> | Server 狀態 | Dashboard 的 Server 狀態卡片 + sidebar 底部狀態列 |
> | 快速動作(新增裝置 / 上傳模型 / 開啟工作區)| 原生 menu bar`File → New Device / Upload Model / Open Workspace` |
> | 模式切換(真實 / Mock| Settings 一般分頁;或 Dashboard 右上角的模式指示器 |
> | 關於 | 原生 menu bar`Help → About` |
> | 結束⌘Q| 原生 menu bar + OS 標準快捷鍵 |
>
> Q7 已決定「關閉視窗 = 結束程式」,搭配 tray 被砍,整體生命週期就是「打開 = 跑、關閉 = 結束」的傳統桌面 app 模式。
## 5.4 錯誤處理流程
### 5.4.1 Port 3721 被占用
```
Server 啟動失敗 → 顯示錯誤對話框:
「連接埠 3721 已被其他程式占用。
請關閉占用該埠的程式,或在 Settings 中變更 server 埠號。」
[設定埠號] [結束]
```
### 5.4.2 Python venv 建立失敗
```
First-Run 步驟 4b 失敗 → 顯示錯誤對話框:
「無法建立 Python 執行環境。
可能原因:
- 系統 Python 版本不符(需要 3.10+
- 磁碟空間不足(需要 ~500MB
- 權限不足
[檢視日誌] [重試] [結束]」
```
### 5.4.3 KneronPLUS wheel 安裝失敗
```
First-Run 步驟 4c 失敗 → 顯示錯誤對話框:
「KneronPLUS SDK 安裝失敗。
請確認:
- 已允許 UAC 提權Windows
- 已安裝 libusbLinuxsudo apt install libusb-1.0-0
[檢視日誌] [重試] [結束]」
```
### 5.4.4 Mac Gatekeeper 警告
```
首次開啟 → Mac 跳出「無法開啟,因為來自未識別的開發者」
→ First-Run 歡迎頁提供說明:
「第一次開啟時,請在 Finder 中對 visionA-local 按右鍵,
選擇『開啟』,然後確認警告。
這是因為 visionA-local 未購買 Apple notarization。」
```
### 5.4.5 Windows SmartScreen 警告
```
首次下載執行 → SmartScreen 跳出警告
→ 發佈說明頁提供引導:
「點選『更多資訊』→『仍要執行』。
這是因為 visionA-local 未購買 Windows 程式碼簽章。」
```
## 5.5 Single-instance 行為與第二次雙擊 UX第四輪補
**背景**visionA-local 以 single-instance 模式運作(單一程式實例),避免多個 Wails 殼搶 Go server 的 127.0.0.1:3721 port。實作細節請參考 Architect 的 `04-architecture/lifecycle.md`single-instance lock 章節)。
**PRD 層級要求的 UX 行為**
| 情境 | 預期行為 | 驗收點 |
|------|---------|--------|
| 第一次雙擊 icon無已開啟的 visionA-local | 正常啟動,走 First-Run 或直達 Dashboard | 與 5.1 / 5.2 流程一致 |
| **第二次雙擊 icon已有 visionA-local 在前景)** | **把既有視窗帶到前景 + focus****不開第二個視窗**、**不顯示錯誤** | 無閃爍、無崩潰 |
| **第二次雙擊 icon已有 visionA-local 但視窗最小化 / 隱藏)** | **把既有視窗還原並帶到前景 + focus** | 使用者不會以為「怎麼沒反應」 |
| **第二次雙擊 icon已有 visionA-local 但 Go server 已 crash** | 第二個實例偵測到 lock 殘留但 server 不在,清理 lock 後正常啟動 | 不該無限卡住 |
**快捷鍵相關**
- 原生 menu bar `File → 重啟 Server` 的快捷鍵為 **⌘Shift+R**macOS/ **Ctrl+Shift+R**Win/Linux— 第四輪 R4-6 決策:從原 `⌘R` 改為 `⌘Shift+R`,避免與瀏覽器 reload 的肌肉記憶衝突
- 原本規畫的 `⌘Shift+W` 取消⌘W / ⌘4 已可關閉視窗)— 第四輪 R4-6 決策
- 其餘快捷鍵維持:`⌘Q` 結束、`⌘W` 關閉視窗(= 結束Q7 傳統式)、`⌘,` 開 Settings、`⌘1-⌘4` 切換主導航
**第二次雙擊的具體 Design 規格待 Design Agent 在 `03-design/spec/` 補齊**動畫時間、focus ring 表現、Dock icon bounce 等細節。PRD 層級只定義行為意圖,不定義視覺細節。
## 5.6 OS 通知策略(第四輪 R4-8 決策)
visionA-local 採**分層通知策略**,不是所有事件都走原生 OS 通知,避免噪音與跨平台一致性問題。
| 事件 | 通知管道 | 理由 |
|------|---------|------|
| 裝置連線成功USB 插入 + connect OK | **App 內 toast**右下角auto-dismiss 3 秒)| 使用者 app 已在前景OS 通知是多餘噪音;跨平台一致 |
| 裝置斷線USB 拔出 / connect 失敗) | **App 內 toast**右下角auto-dismiss 5 秒 + 錯誤色)| 同上 |
| 模型上傳完成 | **App 內 toast** | 同上 |
| 推論開始 / 停止 | **狀態列更新 + 無 toast**(過於頻繁,改用持續性狀態指示) | 避免噪音 |
| First-Run 步驟完成 | **步驟條更新 + 無 toast** | First-Run 本身就是向導,不需額外通知 |
| **Server 崩潰**Go server 意外退出)| **shell out 原生 OS 通知**`osascript` on macOS / PowerShell `New-BurntToastNotification` 或 WinRT on Windows / `notify-send` on Linux+ app 內錯誤對話框 | 重大錯誤,使用者可能切到其他視窗,必須確保看到 |
| **Python sidecar 崩潰**(推論 backend 掛了)| **shell out 原生 OS 通知** + app 內錯誤對話框 | 同上 |
| **致命錯誤**(無法啟動、依賴缺失)| **app 啟動對話框**blocking | 無 app 可用,必須擋住使用者 |
### 實作要求
- **App 內 toast** 沿用原 edge-ai-platform 的 `sonner` 或 shadcn toast 元件
- **原生 OS 通知** 採 shell out 策略(不引入 go-toast 等第三方 binding避免增加依賴與打包複雜度
- macOS`osascript -e 'display notification "..." with title "visionA-local"'`
- WindowsPowerShell `New-BurntToastNotification` 或直接用 Wails 提供的 `runtime.MessageDialog`(如支援)
- Linux`notify-send "visionA-local" "..."`
- 若 shell out 失敗(工具不存在),靜默 fallback 到 app 內錯誤對話框
- **權限要求**macOS 首次顯示原生通知時會觸發系統通知權限請求First-Run 需在文案裡提及「本 app 在出現嚴重錯誤時會通知你」
### 驗收點
- AC-7.1(新增):裝置連/斷僅以 app 內 toast 呈現,不觸發系統通知
- AC-7.2新增Go server 或 Python sidecar 崩潰時,使用者就算切到其他視窗也能透過系統通知得知
- AC-7.3新增macOS 的通知權限請求時機在 First-Run 或首次崩潰時才觸發,不在 app 啟動時無緣無故詢問