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>
17 KiB
5. 使用者流程
本章節描述三個關鍵使用者流程:首次安裝 → First-Run → 日常使用。每個流程都標注對應的 User Story 與驗收標準。
5.1 首次安裝流程(對應 US-1)
┌─────────────────────────────────────────┐
│ 1. 使用者從內部 Gitea Releases 下載安裝檔 │
│ macOS → .dmg │
│ Windows → .exe(Inno 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 ready(http://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 3b(Mock 準備)
┌─────────────────────────────────────────┐
│ 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.1:Mock 模式是一鍵選項(非預設)
- AC-2.2:進入 Mock 後 ≤ 30 秒看到假推論(首次)/ ≤ 15 秒(回訪)— 第四輪 R4-7 拆兩級
- AC-2.3:Mock 模式有明確視覺標記(主視窗標題列 + 首頁徽章 + sidebar 底部狀態列)
- AC-2.4:Mock 模式不 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 到步驟 6(USB 偵測)≤ 3 秒
- 步驟 7 到步驟 9(connect 到第一幀)≤ 10 秒
5.3.2 跨會話狀態持久化
路徑說明(第三輪 Q-E1 + 第四輪 R4-5):資料目錄名統一全小寫為
visiona-local(對齊 Bundle IDcom.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 / 工作列 icon(OS 原生行為) 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)
- 已安裝 libusb(Linux:sudo 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"' - Windows:PowerShell
New-BurntToastNotification或直接用 Wails 提供的runtime.MessageDialog(如支援) - Linux:
notify-send "visionA-local" "..." - 若 shell out 失敗(工具不存在),靜默 fallback 到 app 內錯誤對話框
- macOS:
- 權限要求:macOS 首次顯示原生通知時會觸發系統通知權限請求,First-Run 需在文案裡提及「本 app 在出現嚴重錯誤時會通知你」
驗收點
- AC-7.1(新增):裝置連/斷僅以 app 內 toast 呈現,不觸發系統通知
- AC-7.2(新增):Go server 或 Python sidecar 崩潰時,使用者就算切到其他視窗也能透過系統通知得知
- AC-7.3(新增):macOS 的通知權限請求時機在 First-Run 或首次崩潰時才觸發,不在 app 啟動時無緣無故詢問