visionA/docs/autoflow/03-design/flow-device-usage-ux.md
jim800121chen b35b989d9d docs(design): 裝置使用流程 UX 重新設計(連接電腦→啟用裝置→載入模型→推論)
解使用者實測 4 問題:從未連線誤導、兩層狀態命名混淆(動詞不重複三層:連接
電腦/啟用裝置/載入模型/推論)、模型狀態四態、載入後推論引導。全純前端、落地
拆 3 批。待補:多電腦分組(design 進行中)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 00:27:29 +08:00

35 KiB
Raw Blame History

裝置使用流程 UX 重新設計 — 連接電腦 → 連線裝置 → 載入模型 → 推論

狀態:待 frontend 落地 · 產出Design Agent · 語言zh-TW 觸發:使用者實測後提出整條裝置使用流程的 4 個 UX 問題(狀態誤導、兩層命名混淆、模型狀態、載入後路由)。 定位:這是整條使用流程的 UX 重新設計,不是零散修 bug。統一定調三層狀態語意與命名讓使用者一眼分清「哪一層還沒好」。

本文件只出設計 + 文案 mapping不改任何 code / i18n 檔。 frontend 照本文件落地。 相關 code現況

  • visionA-frontend/src/app/devices/[id]/device-detail-client.tsx(裝置詳情頁 + 兩步式連線 + flash + 開啟工作區)
  • visionA-frontend/src/components/cloud/remote-device-badge.tsxtunnel 狀態徽章 — 問題 1 根源在此)
  • visionA-frontend/src/stores/device-store.tsremoteStatus / flashedModel / lastSeenAt / pairedAt / registeredAt / connect actions
  • visionA-frontend/src/lib/device-state.tsderiveTriState 三態運算)
  • visionA-frontend/src/lib/i18n/dictionaries/zh-Hant.ts + en.ts(文案) 延續:flow-offline-handling.md(離線降級)、flow-pairing.mdpairing-rename-mapping.md用詞體系必須一致、ADR-018serial 路由、兩步式連線)。

0. 問題總覽與設計解對照(一頁看懂)

# 使用者症狀 根因 設計解 純前端?
1 離線後顯示「離線 · 從未連線」誤導(明明連過) remote-device-badge.tsx:100-102 只看 !lastSeenAt 就顯示「從未連線」,沒用 pairedAt/registeredAt 區分「連過但離線」vs「真的沒連過」 改「從未連線」判定邏輯:優先用 lastSeenAt缺時 fallback 到 pairedAt/registeredAt 判定「連過」只有全都沒有才顯示「從未連線」§4 純前端欄位都已存在lastSeenAt 後端未穩定回傳為 §7 待確認
2 兩層都用「線」字,「在線」又要點「連線」很困惑(核心) 第 1 層 tunnelremoteStatus用「在線/離線」、第 2 層 driverconnect用「連線/斷線」,兩層命名撞、層次不明 三層語意重新定調:電腦(在線→「已連接雲端/未連上」、裝置就緒driver→「就緒/待啟用」+動作按鈕「啟用裝置/停用」、模型§2、§3 純前端(改 i18n value + badge/詳情頁呈現)
3 連線載入過模型不顯示 / 重連後未刷新 模型狀態 Card 只有「有 flashedModel/沒有」二態,離線時仍顯示 stale重連刷新 UX 不清楚 模型狀態四態呈現(已載入/未載入/離線-上次已知/載入中重連刷新引導§5 純前端
4 載入完模型要能順暢路由去推論 「開啟工作區」按鈕雖有 ring highlight但缺主動引導、埋在一排按鈕裡 載入完成 → 成功態卡片 主 CTA「前往推論」 引導文案讓下一步不用找§6 純前端

一句話總結設計主張:使用者的困惑本質是「三件不同的事都叫『連線』」。這次把三層拆成三組不會撞的詞 + 一條線性的引導流(每一步完成就明確指向下一步),讓使用者永遠知道「現在卡在哪一層、下一步該點什麼」。


1. 完整流程圖(四步線性引導)

┌─ 第 0 層(一次性,此流程外)──────────────────────────────────────────┐
│ 連接這台電腦pairing— 建立雲端帳號 ↔ 這台電腦的信任。做過就不用再做。 │
└──────────────────────────────────────────────────────────────────────┘
        │(電腦已連接,裝置出現在 /devices 列表)
        ▼
┌─ STEP 1電腦連上雲端第 1 層 tunnel / remoteStatus─────────────┐
│                                                                      │
│  ● 電腦已連接雲端online  → 進 STEP 2                              │
│  ○ 電腦未連上offline     → 離線降級:顯示「這台電腦目前未連上雲端」│
│                                 +上次連線資訊,所有裝置操作 disable   │
│  ◐ 重新連線中reconnecting→ 唯讀等待                               │
│                                                                      │
│  CTAoffline 時):引導「請在電腦上啟動 local agent」                 │
└──────────────────────────────────────────────────────────────────────┘
        │(電腦在線 online
        ▼
┌─ STEP 2裝置就緒第 2 層 driver / status connect───────────────┐
│                                                                      │
│  狀態待啟用detected/disconnected→ CTA「啟用裝置」               │
│        啟用中connecting→ loading 「首次啟用需載入韌體約1分鐘」 │
│        已就緒connected→ 進 STEP 3顯示「停用裝置」次要動作        │
│                                                                      │
│  ⚠ serial 缺 → disable  tooltip「需重新連接電腦回報序號」           │
└──────────────────────────────────────────────────────────────────────┘
        │(裝置已就緒 connected
        ▼
┌─ STEP 3載入模型flash / flashedModel─────────────────────────┐
│                                                                      │
│  未載入 → CTA「載入模型」→ 選模型 → 相容檢查 → flash → WS 進度        │
│  載入中flashing→ 進度條 +「載入中,請勿關閉」                    │
│  已載入 → 顯示模型名 +「已就緒,可開始推論」→ 進 STEP 4              │
└──────────────────────────────────────────────────────────────────────┘
        │(模型已載入 flashedModel != null
        ▼
┌─ STEP 4推論workspace──────────────────────────────────────────┐
│                                                                      │
│  成功態卡片彈出  主 CTA「前往推論 →」醒目、size lg、primary      │
│  路由 → /workspace/:id                                               │
└──────────────────────────────────────────────────────────────────────┘

進度指示(詳情頁頂部,選配但建議):在裝置詳情頁頂部放一條輕量四步進度列,讓使用者看到自己在整條流程的哪一步:

①電腦連接 ──→ ②裝置就緒 ──→ ③載入模型 ──→ ④推論
   ✓已完成      ●進行中        ○待完成       ○待完成
  • 已完成:bg-primary 實心 + CheckCircle進行中ring-2 ring-primary;待完成:bg-muted
  • 尊重 prefers-reduced-motion,狀態切換不做閃爍動畫。
  • 這條進度列是本次 UX 的核心引導元件——它把「三層各自的狀態」收攏成一條使用者能理解的線性路徑。i18n key 見 §8「Flow Stepper」。

2. 兩層狀態命名 + 視覺方案(問題 2 核心)

2.1 心智模型:為什麼會撞

系統實際有三層不同的「連接/連線」,過去第 1、2 層都用「線」字:

技術欄位 語意 頻率 對象 舊用詞(撞)
第 0 層 信任連結 pairing / pairedAt 電腦接進雲端帳號 一次 電腦 配對 → 已改「連接這台電腦」
第 1 層 tunnel remoteStatus (online/offline) 這台電腦的 local agent 有沒有連上雲端 每次 電腦host 在線 / 離線 ← 撞
第 2 層 driver status (connect/disconnect) 對這顆 USB 晶片有沒有開 driver 連線準備用 每次 裝置USB 晶片) 連線 / 斷線 ← 撞

使用者的困惑點:看到裝置「在線」(第 1 層 tunnel卻還要點「連線」第 2 層 driver才能用——兩個都是「線」使用者以為「在線」就該能用了。

2.2 命名決策:三層各給一組不撞的詞

設計原則

  1. 第 1 層講「電腦」——沿用 pairing-rename 的主詞策略(帶主詞就不會跟裝置層撞)。
  2. 第 2 層講「裝置就緒」——用「就緒 / 待啟用」描述狀態,用「啟用 / 停用」描述動作,徹底避開「線」字。
  3. 三層的動詞不重複:電腦「連接」、裝置「啟用」、模型「載入」、最後「推論」。
狀態文案(新) 動作按鈕(新) 避開的舊詞
第 1 層 tunnel 這台電腦已連上雲端 / 這台電腦未連上雲端 (無按鈕,靠 local agent 啟動) 在線 / 離線
第 2 層 driver 裝置已就緒 / 裝置待啟用 / 啟用中… 啟用裝置 / 停用 連線 / 斷線
模型 flash 模型已載入 / 尚未載入模型 載入模型

為什麼是「就緒/待啟用」不是「已連線/未連線」

  • 「就緒ready」直接對應使用者心裡的問題「這顆晶片能用了嗎」比「已連線」更貼近意圖。
  • 「啟用activate」當動作動詞跟第 1 層「連接電腦」、第 0 層「配對」全都不同字,使用者不會混。
  • 保留 flow-offline-handling.md §2 對 remoteStatus 的既有狀態機online/offline/reconnecting/error/unknown只換顯示字,不動狀態邏輯。

2.3 視覺呈現:兩層垂直堆疊、層次分明

詳情頁頂部狀態區改為兩行明確標示的層次結構(取代目前單一 RemoteDeviceBadge 混在標題下):

┌────────────────────────────────────────────────────────────┐
│  Kneron KL720                                    [停用] [載入模型] │
│  (別名/原名)                                                  │
│                                                              │
│  ┌── 第 1 層 ──────────────────────────────────────────┐    │
│  │ 💻 這台電腦   ● 已連上雲端                             │    │
│  │              office-mac · 最後心跳 2 秒前)          │    │
│  └──────────────────────────────────────────────────────┘    │
│  ┌── 第 2 層 ──────────────────────────────────────────┐    │
│  │ 🔌 裝置       ● 已就緒(可載入模型 / 推論)            │    │
│  └──────────────────────────────────────────────────────┘    │
└────────────────────────────────────────────────────────────┘

設計規格

  • 兩層各自一個 badge帶明確的層標籤💻 這台電腦 / 🔌 裝置),這是消除混淆的關鍵——使用者一眼看到「這是電腦的狀態、那是裝置的狀態」。
  • 第 1 層 badge電腦沿用 RemoteDeviceBadge 結構dot + icon + label只改 label 文案(見 §8前綴層標籤。
  • 第 2 層 badge裝置就緒新增一個 badge 呈現 driver 狀態,用 devices.status.* 收斂後的語意(見 §2.4 對照)。
  • 不只靠顏色沿用既有原則dot 色 + icon✓/○/◐)+ 文字三重編碼。
  • 色彩沿用既有 --status-* token不裸寫色碼globals.css 既有)。
  • 響應式mobile<640px兩層仍垂直堆疊、層標籤縮短為 icon+短詞tablet/desktop 同結構。

2.4 第 2 層 driver 狀態的語意收斂

現有 devices.status.* 有七值detected/connecting/connected/flashing/inferencing/error/disconnected/unknown但對使用者而言第 2 層只需知道「就緒了沒」。收斂成三個使用者可理解的態:

底層 status 第 2 層使用者語意 badge 文案 dot/icon
connected / flashing / inferencing 已就緒 裝置已就緒 🟢
connecting 啟用中 啟用中… 🟡pulse
detected / disconnected 待啟用 裝置待啟用
error 裝置錯誤 裝置錯誤 🔴
unknown 未確認 狀態未確認

註:devices.status.* 七值的原始文案保留不動其他地方如「裝置資訊」Card 的 driver 狀態明細仍可能用到);本層新增一組「就緒語意」文案(devices.readiness.*,見 §8供第 2 層 badge 使用。這是新增、不覆蓋既有 key避免波及其他引用點。


3. 兩層狀態文案 mapping跟 pairing-rename 一致)

frontend 照表落地。「動作」欄凡涉及第 2 層 driver 一律改「啟用/停用」;第 1 層一律帶主詞「電腦」。

3.1 第 1 層 tunnel電腦連上雲端— 改既有 remote.status.* value

i18n key 舊 zh 新 zh 舊 en 新 en 備註
remote.status.online 在線 已連上雲端 Online Connected to cloud 帶「雲端」點出這是電腦↔雲端層。搭配層標籤「這台電腦」使用
remote.status.offline 離線 未連上雲端 Offline Not connected to cloud 成套
remote.status.reconnecting 重新連線中 重新連上雲端中 Reconnecting Reconnecting to cloud 成套
remote.status.error 連線錯誤 雲端連線錯誤 Connection error Cloud connection error 成套
remote.status.unknown 未確認 未確認 Unknown Unknown 不動

⚠️ 避撞檢查:這些是第 1 層文案,必搭配層標籤「💻 這台電腦」呈現。若某些地方(如列表卡片空間小)不放層標籤,則用帶主詞版避免歧義 → 見 §3.4「列表卡片精簡版」。

3.2 第 1 層層標籤(新增 key

i18n key zh en
deviceUsage.layer.computer 這台電腦 This computer
deviceUsage.layer.device 裝置 Device

3.3 第 2 層 driver 就緒語意(新增 devices.readiness.*,不覆蓋既有 status.*

i18n key zh en 對應底層 status
devices.readiness.ready 裝置已就緒 Device ready connected/flashing/inferencing
devices.readiness.activating 啟用中… Activating… connecting
devices.readiness.notReady 裝置待啟用 Device not activated detected/disconnected
devices.readiness.error 裝置錯誤 Device error error
devices.readiness.unknown 狀態未確認 Status unknown unknown
devices.readiness.readyHint 可載入模型 / 推論 Ready to load a model / run inference

3.4 第 2 層動作按鈕 — 改既有 devices.connect.* value動詞改「啟用/停用」)

i18n key 舊 zh 新 zh 舊 en 新 en 備註
devices.connect.action 連線 啟用裝置 Connect Activate device 動作動詞改「啟用」,徹底避開「連線」撞第 1 層
devices.connect.connecting 連線中… 啟用中… Connecting… Activating… 成套
devices.connect.connectingHint 首次連線需載入韌體,約 1 分鐘,請勿關閉頁面 首次啟用需載入韌體,約 1 分鐘,請勿關閉頁面 (First connection loads firmware…) First activation loads firmware, ~1 min, keep this page open 連線→啟用
devices.connect.disconnect 斷線 停用 Disconnect Deactivate 成套次要動作、outline 樣式)
devices.connect.disconnecting 斷線中… 停用中… Disconnecting… Deactivating… 成套
devices.connect.needConnectHint 請先連線裝置才能載入模型 請先啟用裝置才能載入模型 (Activate the device first…) Activate the device before loading a model 連線→啟用
devices.connect.driverStatusLabel 連線狀態 裝置狀態 Connection status Device status 避開「連線」;這是裝置資訊 Card 的明細 label
devices.connect.toast.success 裝置已連線 裝置已就緒 Device connected Device ready 對齊就緒語意
devices.connect.toast.failed 連線失敗 啟用失敗 Connection failed Activation failed 成套
devices.connect.toast.failedDesc 請確認裝置已插上且 local agent 在線 請確認裝置已插上,且這台電腦已連上雲端 (…local agent online) Make sure the device is plugged in and this computer is connected to the cloud 「local agent 在線」→「電腦已連上雲端」對齊第 1 層用語
devices.connect.toast.timeoutDesc 連線逾時,請重試 啟用逾時,請重試 Connection timed out Activation timed out, please retry 成套
devices.connect.toast.disconnected 裝置已斷線 裝置已停用 Device disconnected Device deactivated 成套
devices.connect.toast.disconnectFailed 斷線失敗 停用失敗 Disconnect failed Deactivation failed 成套

i18n key 名一律不改devices.connect.* 保留),只改 value——避開改 key 波及元件引用,比照 pairing-rename §3.1 判定。

3.5 明確「不動」清單frontend 別誤改)

  • common.connect="連接" / common.disconnect="中斷連線"(通用詞、非此流程專屬)
  • devices.status.* 七值原始文案detected/connecting/connected/…)— 保留,供裝置資訊 Card 明細用;本次新增 devices.readiness.* 平行使用,不覆蓋
  • pairing-rename 已定的所有「連接電腦」相關 key — 不動
  • pairing.step3.waiting(等待 local agent 連線)— 屬 agent↔雲端網路語意pairing-rename 已判定不動

4. 「從未連線」vs「離線」的狀態邏輯問題 1

4.1 根因

remote-device-badge.tsx:99-104 現況:

if (!showLastSeen || status === "online" || status === "unknown") return "";
if (!lastSeenAt) return t("remote.lastSeenNever");   // ← 只看 lastSeenAt缺就顯示「從未連線」
...
return formatRelativeTime(lastSeenAt, nowMs, t);

問題:lastSeenAt 缺(後端 offline 時可能沒回 last_seen_at或 DB 靜態 offline 從未寫過)就直接說「從未連線」,但裝置明明配對過、連過。使用者關掉 local agent 後看到「從未連線」=明顯錯誤。

4.2 設計解:三層 fallback 判定「連過沒」

離線裝置的次要文字,依以下優先序決定:

若 status === online 或 unknown        → 不顯示次要文字(沿用既有)
否則offline / reconnecting / error
  1. 有 lastSeenAt                     → 「最後心跳 {相對時間}」(最準)
  2. 無 lastSeenAt但有 pairedAt      → 「上次連線:{pairedAt 日期}」(退而求其次:連接過就不是「從未」)
  3. 無 lastSeenAt但有 registeredAt  → 「上次連線:{registeredAt 日期}」(同上,已註冊=用過)
  4. 三者皆無                          → 「從未連線」(真的沒連過,才顯示這句)

判定「連過」的訊號lastSeenAt || pairedAt || registeredAt 任一存在 → 這台裝置曾經連上過,不可顯示「從未連線」。

4.3 文案 mapping問題 1

i18n key 舊 zh 新 zh 舊 en 新 en 備註
remote.lastSeenNever 從未連線 尚未連線過 Never connected Never connected 只在「真的沒連過」時顯示;文案微調更中性
remote.lastSeen 最後心跳 {time} 最後心跳 {time} Last seen {time} Last seen {time} 有 lastSeenAt 時用;不動
remote.lastConnectedAt(新) 上次連線:{time} 上次連線:{time} Last connected {time} Last connected {time} 缺 lastSeenAt 但有 pairedAt/registeredAt 時用fallback

4.4 呈現範例

情境 lastSeenAt pairedAt 顯示
連過、剛關 agent 2 分鐘前 未連上雲端 · 最後心跳 2 分鐘前
連過、後端沒回 lastSeenAt 2026-07-01 未連上雲端 · 上次連線2026-07-01
真的沒連過剛配對、agent 從沒起來) ✗(極少見) 未連上雲端 · 尚未連線過

多數情境會落在前兩列。第三列pairedAt 也沒有)在正常流程幾乎不會發生(配對成功必寫 pairedAt保留只為極端防呆。

4.5 是否需要後端配合

  • 主要:純前端pairedAtregisteredAtlastSeenAt 三欄在 Device 型別都已存在device-store.ts:98-100, 108前端改 badge 判定邏輯即可。
  • 待確認§7:後端 offline 時是否穩定回傳 last_seen_at?若後端能在裝置每次上線時寫入 last_seen_at則情境二會落回情境一最準即使後端沒回,本設計的 pairedAt fallback 也已能避免「從未連線」誤導——後端修不修都不阻擋本次落地,只是 last_seen_at 有回會更精準。

5. 模型狀態呈現(問題 3

5.1 現況

模型狀態 Carddevice-detail-client.tsx:443-466只有二態flashedModel 有值 → 顯示模型名 + 「已就緒,可開始推論」;沒值 → 「尚未燒錄任何模型」。缺離線態、載入中態、以及重連刷新引導。

5.2 四態設計

條件 呈現 icon
已載入 flashedModel != null 且 online 模型名font-medium+ 「已就緒,可開始推論」+ CTA「前往推論」 ✓ 綠
未載入 flashedModel == null 且裝置已就緒 「尚未載入模型」+ 提示「載入模型後即可開始推論」+ 引導看上方「載入模型」按鈕 ○ 灰
載入中 status === "flashing" 進度條WS 推送)+ 「模型載入中,請勿關閉頁面」 ◐ pulse
離線 · 上次已知 offline 且有 cache 的 flashedModel 模型名 + 標註「資料截至上次連線」(淡化 opacity-75+ 「裝置重新連上後會自動刷新」 + 時間戳

5.3 重連刷新邏輯 UX

  • 重連後刷新:裝置從 offline → online或 driver 重新啟用)時,詳情頁應重新 fetchDevice(id) 拉最新 flashedModel現況 connect 成功後已呼叫 fetchDevicedisconnect 亦同)。
  • 重連=清空舊模型狀態使用者提到「重連後應刷新為未載入」——driver 停用再啟用(或 agent 重連)後,若晶片已無 flash 的模型,fetchDevice 會拿回 flashedModel: null → 自動回到「未載入」態。不需前端額外清空邏輯,只要確保重連後有 fetchDevice現況已有
  • 離線時不主動 polling(沿用 flow-offline-handling §12顯示 cache 並標「資料截至上次連線」,避免顯示過時資料卻讓使用者以為是即時。

5.4 文案 mapping問題 3

i18n key zh en 備註
devices.detail.readyForInference 已就緒,可開始推論 Ready for inference 不動
devices.detail.noModelFlashed 尚未載入模型 No model loaded 「燒錄」→「載入」對齊 flash 已改用「載入」;補一句引導見下
devices.detail.noModelHint(新) 載入模型後即可開始推論。點上方「載入模型」開始。 Load a model to start inference. Use "Load model" above. 未載入態引導
devices.detail.modelFlashing(新) 模型載入中,請勿關閉頁面 Loading model, keep this page open 載入中態
devices.detail.modelStaleHint(新) 資料截至上次連線,裝置重新連上後會自動刷新 As of last connection; refreshes when the device reconnects 離線 cache 態

6. 載入後 → 推論的引導(問題 4

6.1 現況

flash 完成後 fetchDeviceflashedModel 有值 → 「開啟工作區」按鈕出現device-detail-client.tsx:287已有 ring-primary/40 ring-2 highlight。但按鈕跟「停用/載入模型/移除」擠在同一排,使用者反映「原本樣式不明顯要自己找」。

6.2 設計解flash 完成後彈成功態 + 主 CTA

flash 完成的當下FlashDialog 關閉、fetchDevice 回來 flashedModel 有值),做兩件事:

  1. 模型狀態 Card 切換為「已載入」成功態Card 內直接放主 CTA
    ┌── 模型狀態 ──────────────────────────┐
    │ ✓ 模型已載入yolov5s_640.nef         │
    │   已就緒,可開始推論                    │
    │                                        │
    │   [ 前往推論 → ]  ← 主 CTAsize lg    │
    └────────────────────────────────────────┘
    
  2. 一次性 toast:「模型載入成功,可以開始推論了」+ toast action「前往推論」點了直接 router.push

為什麼不自動跳轉沿用現況決策device-detail-client.tsx:282-286 註解)——自動 push 會誤導、使用者可能還想載別的模型或檢查。維持手動導航但把入口做到不用找:模型 Card 內的主 CTA + toast action 雙入口。

6.3 主 CTA 規格

  • 位置優先序:模型狀態 Card 內(最貼近「模型剛載入好」的語境)> 頂部按鈕排(保留現況的 ring highlight 版作為次要入口)。
  • 樣式:size="lg" + primary 填色 + ArrowRight 圖示 + ring-primary/40 ring-2 ring-offset-2(沿用現況 highlight
  • 文案:主 CTA 用「前往推論」(比「開啟工作區」更直指使用者意圖——工作區=推論的地方)。保留 devices.openWorkspace 作為別處引用;新增 devices.goToInference
  • 離線 / serial 缺:沿用現況 disable + tooltip 分支device-detail-client.tsx:299-322

6.4 文案 mapping問題 4

i18n key zh en 備註
devices.openWorkspace 開啟工作區 Open workspace 保留(別處引用)
devices.goToInference(新) 前往推論 Go to inference flash 完成後主 CTA
devices.flash.readyToast(新) 模型載入成功,可以開始推論了 Model loaded — ready for inference 成功 toast
devices.flash.readyToastAction(新) 前往推論 Go to inference toast action

7. 各狀態的空 / 載入 / 錯誤 / 離線降級(統整)

沿用 flow-offline-handling.md §5 的降級策略,補齊本流程各步驟的四態。

7.1 詳情頁整體

情境 呈現
載入中fetchDevice 中) Skeleton現況已有device-detail-client.tsx:123-134
404 / 找不到 現況占位(:137-155→ 建議補明確「找不到此裝置」空狀態 + 返回列表 CTA
第 1 層 offline 頂部離線 banner現況 :188-204+ 第 2 層 badge 顯示「狀態未確認」+ 啟用/載入/推論全 disable + tooltip「這台電腦未連上雲端」
第 1 層 online、第 2 層待啟用 顯示「啟用裝置」CTA載入模型/推論 disable + tooltip「請先啟用裝置」
serial 缺 啟用/載入/推論 disable + tooltip「此裝置尚未回報序號需在 local agent 重新連接電腦一次」(沿用 devices.serial.missingHint,該文案 pairing-rename 已改「重新連接」)
啟用失敗 toast「啟用失敗」+ desc「請確認裝置已插上且這台電腦已連上雲端」
flash 失敗 toast「模型載入失敗」現況 devices.flash.flashFailed+ 保留在未載入態,可重試

7.2 離線 banner 文案調整

i18n key 舊 zh 新 zh 備註
devices.detail.offlineBanner.title 此裝置目前離線 這台電腦目前未連上雲端 校正語意離線的是電腦tunnel非單一裝置對齊第 1 層用語
devices.detail.offlineBanner.description 部分操作無法使用,待 local agent 重新連線後自動恢復 部分操作無法使用,待這台電腦重新連上雲端後自動恢復 對齊

⚠️ 注意offlineBanner 目前語意是「裝置離線」,但根因是第 1 層 tunnel電腦離線——local agent 一關該電腦上所有裝置都離線flow-offline-handling §1 失效點 C。改文案點出是「電腦」層級避免使用者以為只是這一顆晶片壞。


8. 完整新增 / 修改 i18n key 清單frontend 落地總表)

zh 與 en 同步。修改既有 value 的已列在 §3/§4/§5/§6/§7此處彙整新增 keyfrontend 一次補齊。

8.1 新增 key

i18n key zh en
deviceUsage.layer.computer 這台電腦 This computer
deviceUsage.layer.device 裝置 Device
deviceUsage.stepper.pairing 電腦連接 Computer
deviceUsage.stepper.activate 裝置就緒 Device ready
deviceUsage.stepper.loadModel 載入模型 Load model
deviceUsage.stepper.inference 推論 Inference
devices.readiness.ready 裝置已就緒 Device ready
devices.readiness.activating 啟用中… Activating…
devices.readiness.notReady 裝置待啟用 Device not activated
devices.readiness.error 裝置錯誤 Device error
devices.readiness.unknown 狀態未確認 Status unknown
devices.readiness.readyHint 可載入模型 / 推論 Ready to load a model / run inference
remote.lastConnectedAt 上次連線:{time} Last connected {time}
devices.detail.noModelHint 載入模型後即可開始推論。點上方「載入模型」開始。 Load a model to start inference. Use "Load model" above.
devices.detail.modelFlashing 模型載入中,請勿關閉頁面 Loading model, keep this page open
devices.detail.modelStaleHint 資料截至上次連線,裝置重新連上後會自動刷新 As of last connection; refreshes when the device reconnects
devices.goToInference 前往推論 Go to inference
devices.flash.readyToast 模型載入成功,可以開始推論了 Model loaded — ready for inference
devices.flash.readyToastAction 前往推論 Go to inference

8.2 修改既有 value彙整詳見對應章節

  • remote.status.online/offline/reconnecting/error§3.1
  • remote.lastSeenNever§4.3
  • devices.connect.action/connecting/connectingHint/disconnect/disconnecting/needConnectHint/driverStatusLabel/toast.*§3.4
  • devices.detail.noModelFlashed§5.4
  • devices.detail.offlineBanner.title/description§7.2

9. 無障礙(沿用既有 + 本次補充)

  • 兩層 badge 各自 role="status" + aria-live="polite",狀態變更宣告(現況 RemoteDeviceBadge 已有,第 2 層新 badge 比照)。
  • 層標籤(「這台電腦」/「裝置」)不只用 icon——搭配文字SR 可讀。
  • Flow Stepperrole="list" + 每步 role="listitem" + 當前步 aria-current="step"(比照 flow-pairing §10
  • 三態(就緒/待啟用/錯誤不只靠顏色dot + icon✓/○/◐/⚠)+ 文字三重編碼。
  • flash 完成 toastaria-live="polite";主 CTA 可 Tab 聚焦、Enter 觸發。
  • 重連倒數 / pulse 動畫尊重 prefers-reduced-motion

10. 落地後驗證frontend / Design QA 自檢)

  1. 兩層不打架:詳情頁同時出現「💻 這台電腦 已連上雲端」與「🔌 裝置 待啟用」時,使用者能分清兩層、知道要點「啟用裝置」。
  2. 「從未連線」修正:關掉 local agent 後,連過的裝置顯示「未連上雲端 · 最後心跳 X」或「上次連線X」不再顯示「從未連線/尚未連線過」。
  3. grep 檢查:第 2 層動作按鈕文案不再出現「連線/斷線」(改「啟用/停用」);第 1 層文案帶「雲端」或搭配「這台電腦」層標籤。
  4. 模型四態:離線時模型 Card 顯示 cache + 「資料截至上次連線」;重連後 fetchDevice 刷新為最新(含未載入)。
  5. 載入後引導flash 完成 → 模型 Card 內出現「前往推論」主 CTA + toast action不用在按鈕排裡找。
  6. 三斷點截圖mobile(≤375)/tablet(768)/desktop(≥1280) 兩層 badge + 進度列佈局正常。
  7. 對比度:兩層 badge 文字 + 層標籤 WCAG AA4.5:1
  8. 離線降級:第 1 層 offline 時,啟用/載入/推論全 disable + tooltip 指出是「電腦未連上雲端」。

11. 給 Orchestrator / frontend 的落地摘要

全部純前端(改 i18n value + badge 呈現 + 詳情頁佈局 + 模型 Card 四態 + flash 完成引導)。底層欄位(remoteStatus/status/flashedModel/lastSeenAt/pairedAt/registeredAt)都已存在,無需改 store 型別。

唯一後端待確認(不阻擋落地)offline 時後端是否穩定回傳 last_seen_at§7。有回 → 「最後心跳 X」最精準沒回 → 本設計已用 pairedAt fallback 避免「從未連線」誤導。建議 Orchestrator 順帶問後端 / architect裝置每次上線時是否有寫 last_seen_at。

落地建議拆批frontend 增量)

  • 批 1問題 1最小、解使用者最痛remote-device-badge.tsx 的「從未連線」fallback 邏輯 + remote.lastSeenNever 文案 + 新增 remote.lastConnectedAt
  • 批 2問題 2 核心):兩層命名 i18n value 全改 + 詳情頁兩層 badge 呈現 + 層標籤 + 第 2 層就緒 badge。
  • 批 3問題 3+4模型 Card 四態 + flash 完成主 CTA + toast action + Flow Stepper 進度列。