Feature #1422 » backend-admin-dashboard-requirements-v0.3.md
Backend Admin 營運 Dashboard 需求說明書
文件版本:v0.3 Draft
文件日期:2026-09-07
追蹤議題:Redmine #1422
適用範圍:所有 EMS Branch 案場;A17 僅為第一個資料基準與展示案例
文件狀態:需求討論快照,尚未進入 v1.0 需求鎖定與開發
配套 Mock:backend-admin-dashboard-mock-v0.3.html
本文件是目前已確認需求的完整快照,供 Product、FE、Backend、QA 與維運共同 review。Mock 內所有數字均為 UI 假資料,不代表 A17 或其他案場的即時營運結果。
1. 文件管理
1.1 版號規則
| 版號 | 用途 | 是否可直接進入開發 |
|---|---|---|
| v0.x Draft | 需求討論與 review 快照;每次保留 PDF、Markdown、HTML Mock 三份同版附件 | 否 |
| v1.0 | 所有必要需求確認後的開發基準 | 是,仍須依 Redmine SOP 通過規劃關卡 |
| v1.x | v1.0 後的需求釐清或核准變更 | 依該版變更內容判定 |
每一個 review checkpoint 都必須產出相同版號、相同日期的 PDF、Markdown 與 HTML Mock。新版本一律新增至 Redmine #1422,不覆寫、不刪除舊附件。
1.2 版本紀錄
| 版號 | 日期 | 狀態 | 內容 |
|---|---|---|---|
| v0.2 Draft | 2026-07-25 | 已封存於 #1422 | 舊版 PDF #1108、Markdown #1109、HTML #1110 |
| v0.3 Draft | 2026-09-07 | 本次 review 快照 | 納入目前所有已確認的跨案場、資料來源、WebSocket、KPI、Connector、負載、用量、帳務、狀態與驗收決策 |
1.3 本版定位
- 本版是「顯示資訊」的 Dashboard,不新增控制充電、重送命令、補帳、修改排程或調整案場設定的操作。
- 本版保留必要的即時資訊,但不追求監控中心等級的秒級正確性、斷線容錯或專用告警系統。
- 所有案場共用同一套產品規則。A17 的 Connector 數量、群組數量與歷史資料只能作為驗證尺度,不可寫死成跨案場規則。
2. 背景、目標與成功條件
2.1 背景
Backend Admin 現有 Dashboard 為空白頁。EMS 已有 Charge Point、Connector、Transaction、MeterValue、Queue、Settlement 與 Invoice 等資料,但缺少一個讓案場管理人員快速掌握營運狀況的首頁。
2.2 目標
使用者進入 Dashboard 後,應能在不執行任何控制動作的前提下快速回答:
- 案場目前是否有明顯異常或資料不可靠?
- Charge Point 與 Connector 目前大致處於什麼狀態?
- 現在充電負載多少,各群組容量與可用 slots 如何?
- 最近 30 日的充電量與使用次數如何?
- 最近一個帳期的結算流程進行到哪裡?
- 上一個完整曆月的電費是否已完整結算、金額多少?
2.3 V1 成功條件
- 有
dashboardfunction 權限的使用者可正常開啟頁面。 - 每個 Branch 在 V1 僅有一個 enabled Building 時,可由 Backend 自動解析案場,不要求 FE 傳
buildingId。 - 一般資料可於初次載入、每 5 分鐘及手動重新整理時更新。
- Connector 即時狀態與案場即時負載可由同一條 Dashboard WebSocket 更新。
- WebSocket 無法連線時,使用者看得到明確提示、最後更新時間與最後一份資料;其他 REST 區塊仍可使用。
- 1、2、12、30 個 Connector 都能在同一 UI 結構內合理顯示,頁面不因數量改變而破版。
- 390、768、1024、1440 px 寬度不產生整頁水平捲動。
- 缺資料、部分資料、錯誤與真正的零值不會被混為一談。
3. 使用者、權限與案場範圍
3.1 權限
Dashboard 沿用既有 SS3A function/API mapping,功能代碼為 dashboard。
- 預期可被授予 Dashboard 的既有角色:
administrator、power_user、association、dealer。 -
adm_user、member、hq、engineer不因角色名稱而自動取得 Dashboard 權限。 - Backend API 仍須做授權檢查;FE 隱藏選單不是安全邊界。
- 未授權時回傳或呈現 403,不顯示其他案場資料。
角色與 function 的關係應透過既有權限資料維護,不在 Dashboard 程式碼中以角色名稱硬編碼授權判斷。
3.2 Building 解析
V1 規則:一個 Branch 必須恰好有一個 enabled Building。
| 狀況 | 行為 |
|---|---|
| 恰好 1 個 enabled Building | Backend 自動解析並回傳 Dashboard 資料 |
| 0 個 enabled Building | 回傳案場設定錯誤,Dashboard 不載入資料 |
| 超過 1 個 enabled Building | 回傳案場設定錯誤,Dashboard 不自行猜測 |
FE 不傳 buildingId,也不在 V1 提供 Building 下拉選單。未來若 Branch 支援多 Building,應另開需求擴充契約。
4. 範圍
4.1 In Scope
- 案場頁首、資料更新狀態與手動重新整理。
- 需留意事項。
- 六個營運 KPI。
- 案場即時負載與三個時間範圍圖表。
- 群組容量與 slots。
- Connector 即時狀態摘要、重點卡片與完整清單 drawer。
- 最近 30 日充電用量。
- 最近一個既有結算帳期的四步驟帳務流程。
- REST API、Dashboard WebSocket、授權、資料品質、錯誤狀態與基本驗收。
4.2 Out of Scope
- 從 Dashboard 控制充電、重啟設備、改變 Connector 狀態或手動重送 OCPP command。
- 從 Dashboard 修改 Queue、priority、slot、排程或離峰設定。
- 從 Dashboard 執行補帳、重算、付款、開立發票或修正帳務。
- 新增 Operational Event SLA、處理時限、逾時升級或 on-call 規則。
- 為 Dashboard 新增專用 snapshot table、cache、排程器、監控平台、告警與 fallback polling。
- 自 Dashboard 推導「離線充電」、「待對帳」或其他會改變既有業務狀態的結論。
- 以 A17 的數量、時間或設備特性作為所有案場固定設定。
5. 頁面資訊架構
頁面由上到下固定為:
- 案場名稱、即時連線狀態、一般資料更新時間與手動重新整理。
- 需留意事項。
- 六個 KPI。
- 案場即時負載。
- 群組容量與 slots。
- Connector 即時狀態。
- 30 日充電用量。
- 帳務結算流程。
區塊可以因 Empty、Partial、Error 或權限狀態改變內容,但不可任意改變順序。Dashboard 是資訊總覽;只有明確定義的卡片或文字連結可導向既有頁面,不在首頁加入操作按鈕。
6. 資料取得架構
6.1 簡化原則
Dashboard 只使用兩條資料通道:一支 Overview REST API 與一條 Dashboard WebSocket。
| 區塊 | 初始資料 | 後續更新 | WebSocket 斷線時 |
|---|---|---|---|
| 需留意事項 | Overview REST | 每 5 分鐘或手動 refresh | 不受影響 |
| 六個 KPI | Overview REST | 每 5 分鐘或手動 refresh | 不受影響 |
| 案場即時負載 | REST 提供三段完整歷史序列;WebSocket 提供目前值與 bucket 增量 | WebSocket | 顯示斷線提示,保留最後資料,不做 fallback |
| 群組容量與 slots | Overview REST | 每 5 分鐘或手動 refresh | 不受影響 |
| Connector 即時狀態 | Overview REST 初始摘要與重點資料;WebSocket 更新 | WebSocket | 顯示斷線提示,保留最後資料,不做 fallback |
| 30 日充電用量 | Overview REST | 每 5 分鐘或手動 refresh | 不受影響 |
| 帳務結算流程 | Overview REST | 每 5 分鐘或手動 refresh | 不受影響 |
6.2 REST 生命週期
- 初次進頁呼叫一次
GET /api/dashboard/overview。 - 頁面存活期間每 5 分鐘呼叫一次。
- 使用者按下重新整理按鈕時立即呼叫一次。
- 同一時間只允許一個 Overview request;重複點擊不得製造平行請求。
- 手動重新整理只重新取得 REST 資料,不另建第二條 WebSocket。
- REST 某一來源失敗時,Backend 優先以該 section 的
dataStatus隔離,不應讓整份 response 全部失效;授權或 Building 設定錯誤除外。
6.3 WebSocket 生命週期
- 頁面載入時建立一條 Dashboard WebSocket。
- 僅處理三種 message:
DASHBOARD_LIVE_SNAPSHOTCONNECTOR_LIVE_BLOCK_UPDATEDLIVE_LOAD_UPDATED
- WebSocket 連線失敗或中斷時:
- Connector 與即時負載區塊顯示「即時連線已中斷」類提示。
- 保留最後一次成功資料與其時間,不清成 0。
- 不改用 REST 輪詢、不做自訂 exponential backoff、不做 sequence gap recovery。
- 不在背景自動重連;使用者重新載入整頁時才重新嘗試連線。
- WebSocket 斷線不影響其他 REST 區塊的顯示與五分鐘更新。
7. 共用資料契約
7.1 Overview REST
建議 endpoint:GET /api/dashboard/overview
回應至少包含:
site 案場識別、名稱、時區
generatedAt Backend 產生 response 的時間
attention 需留意事項
kpis 六個 KPI
liveLoad 三段完整圖表資料與目前值
chargeGroups 群組容量與 slots
connectorLive Connector 五狀態摘要與固定 Top 8
usage30Days 30 日用量與摘要
billingPipeline 最近既有帳期的四步驟狀態
每一個主要 section 應具有:
dataStatus COMPLETE | PARTIAL | ERROR
updatedAt 此來源最後成功更新時間
message Partial 或 Error 的可顯示原因;Complete 可為 null
0 表示已確認數值為零;null 表示無法確認、無資料或不可計算。FE 不得把 null 格式化成 0。
7.2 時間與時區
- 所有「今日」、「上月」、「最近 30 日」、「最近 7 日」以該 Building 的時區為準。
- API 時間點使用含 offset 的 ISO 8601。
- Backend 回傳 Building 時區;FE 負責依該時區顯示,不以瀏覽器所在時區重新歸日。
- 日期區間採明確的半開區間
[start, end),避免月末與午夜重複計算。
7.3 資料新鮮度
- Backend 依資料來源套用全系統預設 freshness cutoff。
- V1 不提供每案場、每 Building 的 cutoff override,也不新增 Dashboard 設定畫面。
- 每個 section 回傳自己的
updatedAt與dataStatus;FE 不自行用一個全頁時間推定所有來源都新鮮。
8. 詳細功能需求
8.1 頁首與更新狀態
- 顯示案場名稱,不把 A17 寫死在產品文案。
- 顯示一般資料最後更新時間與「每 5 分鐘更新」。
- 顯示 WebSocket 連線狀態:正常或中斷。
- 手動重新整理按鈕要有 loading、disabled 與可讀的 accessible name。
- refresh 成功時更新成功區塊;部分失敗時保留仍有效資料並顯示 section 訊息。
8.2 需留意事項
區塊名稱固定為「需留意事項」,不用 Needs Attention 作為使用者可見標題。
只允許以下五類,順序固定:
| 順序 | code | 中文名稱 | affectedCount 意義 | 導向 |
|---|---|---|---|---|
| 1 | CHARGE_POINT_OFFLINE |
Charge Point 離線 | 符合離線條件的 Charge Point 數 | /cp/list |
| 2 | CONNECTOR_FAULTED |
Connector 故障 | 符合故障條件的 Connector 數 | /connector/list |
| 3 | LIVE_LOAD_DATA_UNRELIABLE |
即時負載資料不可靠 | 目前受影響的資料來源或設備數;依 Backend 契約定義 | #load |
| 4 | QUEUE_BLOCKED |
排隊受阻 | 目前 BLOCKED 的 distinct Connector 數 |
#connectors |
| 5 | SETTLEMENT_INCOMPLETE_OR_ERROR |
帳務結算未完成或異常 | 目前帳期未完成或錯誤的結算單元數 | #billing |
顯示規則:
- 只顯示
affectedCount > 0的類別,全部顯示,不做 Top N、drawer 或獨立頁。 -
categoryCount是非零類別數,不是受影響設備總數。 - 不跨類別做 root-cause 去重;同一設備可同時影響不同類別。
-
COMPLETE且categoryCount=0顯示中性的「目前沒有需留意事項」。 -
PARTIAL顯示已確認卡片,並提示內容可能不完整。 -
ERROR時categoryCount=null,顯示暫時無法取得,不顯示 0。 - 這些卡片只提供導向,不提供修復、acknowledge 或變更狀態的功能。
8.3 六個 KPI
固定順序如下:
| 順序 | KPI | 定義 | 顯示 | 導向 |
|---|---|---|---|---|
| 1 | Charge Point 連線 | persisted OCPP connection state;分母為 enabled Charge Point | online / enabled total,並分列 offline、unknown、disabled | /cp/list |
| 2 | Connector 可服務 | enabled CP 之 Connector,且 parent CP 為 ONLINE、runtime status 在可服務 allowlist | serviceable / enabled connector total | /connector/list |
| 3 | 充電進行中 | canonical ACTIVE transaction;每個 Connector 最多計 1 個 |
{N} Sessions,輔助文案「依未結束的充電 Session 計算」 |
/connector/list |
| 4 | 等待供電 | Queue 狀態為 ELIGIBLE 的 distinct Connector |
{N} Connectors;NOT_PLUGGED 分開顯示且互斥,BLOCKED 歸需留意事項 |
/connector/list |
| 5 | 今日已完成充電量 | 與 30 日用量的今日 bucket 使用完全相同規則 | kWh | #usage |
| 6 | 上月電費 | Building 時區上一個完整曆月的 settlement cost_predict 總和 |
完整時顯示金額;不完整顯示 — 與完成數 |
#billing |
補充規則:
-
充電進行中是「未結束 Session 數」,不是實際有功功率;即使 CP offline 或 disabled,只要 canonical transaction 仍為 ACTIVE 仍計入。 - KPI 不推論 offline charging、不新增 reconciliation flag,也不重複顯示
currentPowerKw。 - 上月電費包含該月已付款與待付款的 settlement,但只有所有應計單元都完整時才顯示總額。
- 六張卡皆為 REST 資料,不使用 WebSocket 更新。
- 六張卡皆為原生可聚焦連結;整張卡的可點擊範圍與 focus ring 必須清楚。
- 版面:寬度大於等於 1240 px 為 6×1;768–1239 px 為 3×2;320–767 px 為 2×3。不隱藏、不輪播。
8.4 案場即時負載
此區塊只顯示案場「充電功率」,不顯示或推導案場契約容量、案場使用率、剩餘容量。群組契約容量只在群組區塊顯示。
固定提供三個 tab:
| tab | X 軸 | bucket | Y 軸 |
|---|---|---|---|
| 即時 | 最近 60 分鐘,由舊到新 | 1 分鐘 | 該分鐘的時間加權平均充電功率,單位 kW |
| 今日 | Building 當地日 00:00 至現在 | 15 分鐘 | 該 15 分鐘的時間加權平均充電功率,單位 kW |
| 7 日 | 含今日在內的 7 個 Building 曆日 | 1 小時 | 該小時的時間加權平均充電功率,單位 kW |
圖表規則:
- X 軸名稱為「時間」,Y 軸名稱為「充電功率(kW)」。
- REST 一次回傳三個 tab 的完整 series;切換 tab 只讀取頁面 cache,不重打 API,也不改變 WebSocket 訂閱。
- tab 選擇在五分鐘 refresh 後保留,整頁重載後回到「即時」。
- WebSocket 更新
currentPowerKw、OPEN bucket 與跨界後的 FINALIZED bucket。 -
bucketState為OPEN | FINALIZED,和dataStatus分開。 - 新鮮且已確認沒有充電時可回 0。
- 若有充電但必要功率資料超過 freshness cutoff,該 bucket 回
null且 section 為PARTIAL。 - 不做內插、不顯示猜測值、不以 coverage threshold 補值,也不提供「部分總功率」。
- 只有「目前」資料品質問題進入需留意事項;歷史缺口留在圖表中以 gap 呈現。
8.5 群組容量與 Slots
每個 Charge Group 顯示:
- 群組名稱。
- 群組目前充電功率 kW。
- 群組自己的
contractCapacitykW。 - 群組可使用與已使用 slots。
- 必要時顯示該群組資料的 Partial/Error 狀態。
不同群組的 contractCapacity 不可直接加總成案場契約容量。Dashboard 不新增群組設定或調整 slots 的操作。
8.6 Connector 即時狀態
8.6.1 五個互斥狀態桶
所有 Connector 必須恰好歸入一個狀態桶,順序固定:
| code | 中文名稱 | 核心規則 |
|---|---|---|
NEEDS_ATTENTION |
需留意 | abnormal、faulted、unknown 或 Backend 無法安全歸類的狀態 |
CHARGING |
充電進行中 | 依既有 runtime 狀態與交易事實判定 |
WAITING |
準備/排隊 | 已插槍準備或 Queue waiting 類狀態 |
AVAILABLE |
可用 | parent CP 與 Connector 均符合可服務條件 |
OTHER |
其他狀態 | 已知但不屬前四類;NOT_PLUGGED 歸此類 |
五個 count 加總必須等於 total,NEEDS_ATTENTION count 必須等於 abnormalTotal。當 total > 0 時五個摘要都顯示,包括 count 0;當 total = 0 時改顯示空狀態。
五個狀態摘要是純資訊,不可點擊、不可聚焦、不可當篩選器。使用者可點 Connector 卡片查看既有詳細頁,或按「查看全部」打開 drawer。
8.6.2 不同 Connector 數量的彈性設計
Backend 固定回傳最多 8 筆 priority items,加上 total 與 abnormalTotal。FE 依 viewport 顯示同一份 payload 的前幾筆:
| viewport | 首頁最多顯示 |
|---|---|
| Desktop | 8 |
| Tablet | 6 |
| Mobile | 4 |
- 案場只有 1 或 2 個 Connector:只顯示實際卡片,不補空白 placeholder、不把卡片無限制拉寬。
- 案場有 30 個以上 Connector:首頁仍只顯示上述重點數量,標題與按鈕顯示總數,完整清單在 drawer 內分頁。
- 重點項目由 Backend 固定 priority sort;先看 abnormal/severity,再以穩定欄位做 deterministic tie-breaker。V1 不提供使用者排序。
- 每個 item 回傳
abnormal、severity、reason;FE 不自行重算異常優先順序。
8.6.3 完整清單 Drawer
- 固定 server-side pagination,每頁 20 筆。
- 只有上一頁、下一頁;總數小於等於 20 時隱藏 pager。
- 搜尋或篩選條件改變時回到第 1 頁。
- drawer 的搜尋、篩選與當前頁只保留在本次 Dashboard page session;關閉再開保留,整頁重載或離開頁面即清除。
- 不寫入 URL、local storage 或 Backend preference。
- 不提供 user-controlled sorting;現有
/connector/list頁的排序不受影響。
8.7 30 日充電用量
- 範圍固定為含今日在內的 30 個 Building 曆日,不提供日期選擇器。
- 只計算 completed transaction。
-
energy_consumed單位由 Wh 轉為 kWh;null或負值排除並將 section 標為PARTIAL。 - Sessions 只計 completed 且
energy_consumed > 0的 transaction。 - 整筆 transaction 依
start_timestamp所屬 Building 日期歸日,不做跨日拆分。 - 平均每次充電量 = 有效 kWh / 有效 Sessions;Sessions 為 0 時回
null。 - API 固定回 30 個 buckets。已確認無資料的日期為 0;未知或無法計算為
null。 - 30 日皆為已確認 0 時,回
COMPLETE並顯示 empty 說明,不判為錯誤。 - 首次載入錯誤且無 cache 時顯示 Error;refresh 失敗但已有成功資料時保留 cache、標示 stale 與失敗時間。
- 已移除「時間使用率」,以「平均每次充電量」取代。
- 本區與「今日已完成充電量」只能使用 transaction 的
status、energy_consumed、start_timestamp。不讀 raw MeterValue、不呼叫帳務計費服務、不依 Tariff boundary 拆分。
8.8 帳務結算流程
此區塊保留 Mock 既有的四步驟流程,不新增「本月帳務摘要」或「本月預估電費」。
顯示 Backend 可取得的最新一個既有 settlement period;即使該帳期仍 pending 或 error,也顯示該帳期。完全沒有 settlement period 時顯示 empty。
固定四列:
- Connector 結算。
- 單元結算。
- 帳務覆核。
- 發票結算。
四列都是純資訊,不可點擊。區塊底部提供兩個既有頁面連結:
- 帳單:
/bill/list - 發票:
/invoice/list
帳務流程是 REST-only、read-only。上一個完整曆月的電費金額只出現在第六個 KPI,並依該 KPI 的完整性規則顯示。
9. FE 開發需求
9.1 頁面與元件
FE 至少需完成:
- Dashboard route 與 navigation entry,套用既有
dashboardfunction 可見性。 - Overview REST query、五分鐘 timer、manual refresh 與 request 去重。
- 單一 Dashboard WebSocket connection 與三種 message reducer。
- Header、Attention、KPI grid、Live Load chart、Group cards、Connector summary/cards/drawer、Usage chart、Billing pipeline。
- Loading、Empty、Partial、Error、Stale、403 與 Building config error 畫面。
- 所有既定 deep links、native links、hash focus 與 drawer keyboard interaction。
9.2 FE 不得自行推導的內容
以下必須由 Backend 回傳,FE 只負責呈現:
- Charge Point online/offline/unknown 統計。
- Connector 的五桶歸類、abnormal、severity、reason 與固定 priority sort。
- ACTIVE Session、Queue ELIGIBLE/NOT_PLUGGED/BLOCKED 計數。
- 需留意事項類別與 affectedCount。
- Usage bucket、平均每次充電量、上月電費完整性。
- Live Load 的時間加權 bucket、bucket state 與 data quality。
9.3 FE 狀態管理
- REST cache 與 WebSocket live state 分開管理。
- WebSocket message 只能更新 Connector live 與 Live Load,不得改寫 REST-only KPI。
- WebSocket 斷線保留最後資料;畫面明確標示資料時間與斷線,不把舊資料偽裝成即時。
- section refresh error 不應清除其他 section。
- tab、drawer 與 pagination 的 page-session 行為依第 8 節執行。
9.4 圖表與格式
- 圖表必須顯示 X、Y 軸名稱、單位、tooltip 時間與數值。
-
nullbucket 以 gap 表示;不得連線或補 0。 - 金額、kW、kWh、小數位與千分位由共用 formatter 統一。
- 顏色不能是唯一狀態線索;同時提供文字、icon 或 pattern。
10. Backend 開發需求
10.1 API 與授權
Backend 至少需完成:
-
GET /api/dashboard/overviewcontroller、application service 與 response DTO。 - Dashboard WebSocket endpoint 或既有 endpoint 內的 Dashboard subscription contract。
-
dashboardfunction/API mapping 與授權測試。 - 單一 enabled Building 解析及 0/多筆的明確 domain error。
- OpenAPI schema 與每個 DTO 欄位的中文說明。
10.2 Query 與聚合
Backend 負責:
- 依既有 Charge Point connection state 統計 online/offline/unknown/disabled。
- 依 parent CP 與 Connector runtime allowlist 統計可服務數。
- 以 canonical transaction 計算 ACTIVE Sessions。
- 以現有 Queue 資料計算 ELIGIBLE、NOT_PLUGGED、BLOCKED distinct Connectors。
- 產生 Attention allowlist、count 與 deep-link code。
- 產生三段 Live Load time-weighted series 與資料品質。
- 查詢 Charge Group 自身 capacity、current power 與 slots。
- 依 transaction 建立 30 日 Usage buckets。
- 查詢最近既有 settlement period 的四步驟摘要。
- 計算上一完整曆月 settlement 完整度與
cost_predict總額。 - 回傳 Connector 五桶摘要、Top 8 與 drawer 分頁查詢。
10.3 WebSocket Publisher
只需發布:
- 初次訂閱的
DASHBOARD_LIVE_SNAPSHOT。 - Connector 相關事實變動後的
CONNECTOR_LIVE_BLOCK_UPDATED。 - current power 或 bucket 變動後的
LIVE_LOAD_UPDATED。
不為 Dashboard 建立 NETWORK_HEALTH_UPDATED、CONNECTOR_OVERVIEW_UPDATED 或 KPI 專用訊息。Publisher 不負責自動修復設備狀態。
10.4 資料庫原則
- V1 先使用既有 operational tables 與既有索引可支援的 read query。
- 不預先建立 Dashboard snapshot table、materialized cache 或專用 scheduler。
- 不為 A17 寫死 Building ID、Connector 數量、Group 數量或時間門檻。
- 查詢必須限制 Building 與日期範圍,避免跨案場讀取與 unbounded scan。
- 若實測顯示瓶頸,再以 EXPLAIN 與 endpoint baseline 決定是否補索引或調整 query。
11. UI 狀態與錯誤處理
| 狀態 | 定義 | 畫面行為 |
|---|---|---|
| Loading | 尚無首次資料,request 進行中 | skeleton 或 loading,不顯示假數字 |
| Empty | request 成功且已確認沒有資料 | 中性說明;必要計數顯示 0 |
| Partial | 只有部分來源可確認 | 顯示可確認資料與「可能不完整」訊息 |
| Error | 該 section 無可用資料 | 顯示無法取得與 retry/refresh 提示,不顯示 0 |
| Stale | 曾成功,但後續 refresh 或 WebSocket 失敗 | 保留最後資料、標示最後成功時間與 stale |
| 403 | 使用者無 dashboard 權限 |
不載入營運資料,顯示無權限 |
| Building config error | enabled Building 為 0 或多筆 | 不猜測、不載入,提示管理員修正設定 |
任一 section 的資料錯誤,不應自動讓其他來源正確的 section 變成 Error。只有 auth、Branch/Building scope 無法解析等全頁前置條件才阻止整頁載入。
12. Responsive 與 Accessibility
- 測試寬度至少包含 390、768、1024、1440 px。
- 不得產生整頁水平捲動;表格或 drawer 若需要可在元件內處理。
- 鍵盤可到達所有實際可互動元素,focus ring 清楚。
- 五個 Connector 狀態摘要與帳務四列不可被放入 tab order。
- Dialog/drawer 需有正確 role、可讀標題、focus trap、Esc 關閉與關閉後 focus restoration。
- loading、斷線、error、partial 更新需有適當 live region,避免只靠視覺變色。
- 文字與背景對比、非文字元件與 focus indicator 以 WCAG 2.2 AA 基本要求為準。
- 動畫尊重
prefers-reduced-motion。
13. Performance、可靠性與安全性
13.1 Performance
本功能不設定硬性的 P95 < 1.5 秒產品 SLA。開發完成後必須做可重現 baseline:
- 對 A17 與一個代表較大量資料的尺度執行 query EXPLAIN。
- 測量 Overview endpoint 的 P50、P95。
- 記錄環境、資料列數與分布、warm-up、concurrency、sample size、計時範圍。
- 檢查 N+1、unbounded query、重複聚合與不必要 payload。
- 只有量測證明一般使用受影響時才做額外 cache、索引或聚合設計。
13.2 Reliability
- REST 五分鐘更新失敗時,保留已成功資料並標示 stale。
- WebSocket 失敗只影響兩個 live 區塊;沒有 REST fallback、自訂重連或複雜 backoff。
- 不以 Mock fixture 作為 production fallback。
- response 與 message 必須能辨識
null、0、Partial、Error 與時間。
13.3 Security與Privacy
- API 與 WebSocket 都必須做既有 session/JWT 授權與 Branch scope 驗證。
- 不接受 client 傳入任意 Building ID 來跨案場查詢。
- error message 不暴露 SQL、內部 host、token 或個資。
- Dashboard 只回營運摘要所需欄位,不擴大暴露住戶或付款個資。
14. 驗收條件
14.1 共用驗收
- 有權限且 Building 設定正確時,初次載入可見所有八個主要區段。
- 無權限回 403;0 或多 enabled Building 顯示設定錯誤。
- 五分鐘 refresh 與手動 refresh 不建立重複 request 或重複 socket。
- 一個 section Error 不清除其他成功 section。
- 0、null、Partial、Error、Stale 的畫面與文案可分辨。
- 所有日期依 Building 時區計算。
14.2 WebSocket 驗收
- 一條 socket 可更新 Connector live 與 Live Load。
- 只接受三種既定 Dashboard message。
- socket 中斷後兩區塊顯示提示、最後更新時間與最後資料。
- socket 中斷不啟動 REST fallback、不自動重連、不影響 REST-only 區塊。
- 重新載入整頁會重新嘗試建立 socket。
14.3 Connector 驗收
- 五個 count 相加等於 total,需留意 count 等於 abnormalTotal。
- total 大於 0 時五個摘要都在,且純資訊、不可點擊。
- 1、2 個 Connector 不補假卡片;30 個 Connector 不一次塞滿首頁。
- Desktop/Tablet/Mobile 最多顯示 8/6/4 筆。
- drawer 每頁 20,filter/search 回第 1 頁,page-session state 規則正確。
- Backend priority sort 穩定,同一資料重查順序一致。
14.4 圖表與數值驗收
- Live Load 三個 tab 的範圍、bucket、X/Y 軸與單位符合規格。
-
nullbucket 顯示 gap,不補 0 或內插。 - Usage 固定 30 buckets,依 start date 歸日,跨日不拆分。
- 今日已完成充電量與 Usage 今日 bucket 完全一致。
-
上月電費只有 settlement 全部完整才顯示總額;不完整時為
—。 - 帳務區只有既有四步驟,沒有本月預估電費或虛構摘要。
14.5 Responsive與A11y驗收
- 390、768、1024、1440 px 無整頁水平捲動。
- Keyboard-only 可操作 refresh、KPI links、Connector cards、drawer 與 footer links。
- 純資訊元素不誤設為 button/link,不進 tab order。
- 狀態不只依顏色傳達,screen reader 可得知 loading/error/disconnected 更新。
15. 測試與發布要求
15.1 測試範圍
進入實作後,Backend 至少涵蓋:授權、Building 解析、各 KPI/section 聚合、時區邊界、0/null/Partial/Error、Connector 分桶守恆、Usage 歸日、上月電費完整性、WebSocket message contract。
FE 至少涵蓋:初載、refresh、socket update/disconnect、responsive 數量、drawer state、deep link、chart gap、keyboard 與錯誤狀態。
E2E Catalog 分類為 Add,但目前仍在需求階段,尚不建立測試結果或宣告 Pass。正式實作時需新增 P0–P3 優先級與 execution trigger,並依專案 catalog SOP 驗證。
15.2 First Rollout
- A17 作為第一個 rollout 與資料合理性驗證案場,不代表程式限定 A17。
- 上線後執行基本 smoke test:頁面權限、REST 初載、socket 更新、主要 deep links 與錯誤狀態。
- 下一個工作日使用既有 logs、工具與 DB load 做一次檢查。
- 不要求連續 24 小時監看,也不為本功能新增專用 dashboard metrics、alerts 或 on-call 流程。
16. A17 驗證基準
以下是規格整理時的 A17 觀察基準,只用於檢查 query 與 UI 是否能處理真實尺度;不得作為固定 fixture 或跨案場 acceptance value。
| 項目 | A17 基準 |
|---|---|
| Building | BLD000000014 |
| Charge Points | 4 |
| Connectors | 12 |
| Charge Groups | B1、B2、B3,共 3 組 |
| 各 Group contract capacity | 各 99 kW;不得加總推導成案場容量 |
| 觀察區間 | 2026-08-05 至 2026-09-03 |
| Transactions | completed 78、active 1 |
| completed 正用電 | 77 筆;另 1 筆為 0 Wh,無 null/negative |
| 有效總電量 | 2,171.915 kWh |
| 有效 Sessions | 77 |
| 平均每次充電量 | 28.21 kWh/session |
| 跨日 Transactions | 10 筆,Dashboard Usage 全部依開始日歸屬 |
17. 工作拆分與 Redmine 追蹤
| Issue | 範圍 |
|---|---|
| #1422 | Parent:全案場 Dashboard 需求、文件版本、整體驗收與發佈 |
| #1423 | Connector UI/UX、不同數量、狀態摘要、卡片與 drawer |
| #1424 | Overview REST、Dashboard WebSocket、資料生命週期與效能原則 |
| #1460 | 帳務結算流程與上月電費資料 |
| #1461 | 30 日 Usage、今日用量與平均每次充電量 |
| #1462 | Live Load、圖表 buckets、群組 capacity/slots |
| #1463 | 需留意事項 allowlist、狀態與 deep links |
| #1486 | 六個 KPI 的計算、顯示與導向 |
所有 issue 在需求確認期間維持 New / 0%。只有需求 review 完成並由 Ken 明確同意進入開發後,才建立 v1.0、進入 planning gate 與實作。
18. Definition of Ready(進入開發前)
- Product 確認 v0.3 內容或後續 v0.x 修訂。
- FE 確認 layout、responsive、interaction、states 與 accessibility 可實作。
- Backend 確認現有資料可支援定義,OpenAPI/WS contract 無重大未解問題。
- QA 確認 acceptance criteria 可測。
- 所有未決項目已在 #1422 或 subtask 明確定案。
- 產出並附加同版 PDF、Markdown、HTML Mock。
- Ken 明確同意需求鎖定後,才建立 v1.0。
本文件到 v0.3 為止仍是 review Draft。任何在本文件中沒有明確定義的業務狀態、控制流程、告警 SLA、fallback 或自動修復行為,都不屬於本 Dashboard V1,不能由實作者自行補想。