SCRUM-43 後台數據監控與管理實作分析
JIRA: SCRUM-43
Parent: SCRUM-14 (後台-數值管理頁、操作紀錄)
難度: ⭐⭐⭐⭐ (大型)
預估工作量: 5-7 天
主要工作: 前端 writeahead-admin-web + 後端 writeahead-main-api
功能概述
後台數據監控頁面,提供即時數據讓管理者確認平台狀況。包含時間篩選、10+ 核心指標、4 種時間序列圖表。
一、功能需求拆解
1.1 時間篩選模組
| 元件 | 說明 |
|---|---|
| 快速切換按鈕 | 全部 / 1日 / 1月 / 1年 / 自定義 (5 個) |
| 自訂日期選擇器 | 起始日期 + 結束日期 (點擊「自定義」時顯示) |
| 清除按鈕 | 重置篩選條件 |
| 篩選按鈕 | 送出查詢 |
1.2 核心數據指標 (10 項)
| # | 指標名稱 | 類型 | 計算方式 |
|---|---|---|---|
| 1 | 活躍人數 | 直接查詢 | 期間內有登入的帳號數 (DISTINCT) |
| 2 | 做題總數 | 直接查詢 | 期間內全體做題累計 |
| 3 | 平均做題數 | 計算值 | 做題總數 ÷ 活躍人數 |
| 4 | 平均得分 | 計算值 | 總得分 ÷ 做題總數 |
| 5 | 平均解題時間 | 計算值 | 總做題時間 ÷ 做題總數 |
| 6 | 題目平均使用數 | 計算值 | 總批改數 ÷ 題庫總題數 |
| 7 | 題目最大使用數 | 統計值 | 使用次數最多的題目 (顯示題號+次數) |
| 8 | 題目最小使用數 | 統計值 | 使用次數最少的題目 (顯示題號+次數) |
| 9 | 新增未批改總數 | 直接查詢 | 期間內建立但未批改的題目數 |
| 10 | 平均未批改數 | 計算值 | 總未批改數 ÷ 活躍人數 |
1.3 資料圖表 (4 種)
| 圖表 | X 軸 | Y 軸 | 預設 |
|---|---|---|---|
| 活躍人數表 | 日期 | 人數 | ✅ |
| 做題總數表 | 日期 | 題數 | |
| 做題數表 | 日期 | 題數 | |
| 未批改總數表 | 日期 | 未批改數 |
切換方式: 下拉選單
二、技術架構
2.1 前端 (writeahead-admin-web)
app/pages/statistics/
└── index.vue # 主頁面
app/components/statistics/
├── time-filter.vue # 時間篩選元件
├── core-metrics.vue # 核心指標卡片群組
├── metric-card.vue # 單一指標卡片
├── chart-selector.vue # 圖表選擇器
└── time-series-chart.vue # 時間序列折線圖
app/composables/
├── useStatistics.ts # 統計頁面邏輯
└── useStatisticsApi.ts # API 呼叫封裝
2.2 後端 (writeahead-main-api)
已存在:
├── app/Controllers/Admin/StatisticsController.php
└── app/Models/Admin/StatisticsModel.php
需新增/擴展:
├── POST /admin/statistics/getStatistics # 核心指標 (擴展)
└── POST /admin/statistics/getChartData # 圖表數據 (新增)
2.3 資料來源表
| 資料 | 來源表 |
|---|---|
| 活躍人數 | logs_user_logins |
| 做題/批改 | answer |
| 題庫 | question |
三、實作 Checklist
Phase 1: 後端 API (依賴: SCRUM-67, SCRUM-68)
核心指標 API 擴展
- 確認現有
POST /admin/statistics/getStatistics回傳格式 - 擴展
StatisticsModel::getActiveUsersCount()支援時間範圍 - 擴展
StatisticsModel::getTotalAnswersCount()支援時間範圍 - 新增
StatisticsModel::getAverageScore()- 平均得分 - 新增
StatisticsModel::getAverageSolvingTime()- 平均解題時間 - 新增
StatisticsModel::getQuestionUsageStats()- 題目使用統計- 平均使用數
- 最大使用數 (含題號)
- 最小使用數 (含題號)
- 新增
StatisticsModel::getUnreviewedStats()- 未批改統計- 總未批改數
- 平均未批改數
- 處理除以零情況 (
NULLIF或max(divisor, 1)) - 單元測試:
tests/StatisticsModelTest.php
圖表數據 API
- 新增 Controller 方法
StatisticsController::getChartData() - 新增 Model 方法
StatisticsModel::getTimeSeriesData($type, $start, $end) - 支援 4 種圖表類型:
-
active_users- 活躍人數 -
total_answers- 做題總數 -
answer_count- 做題數 -
unreviewed- 未批改總數
-
- 日期填充 (無資料日期補 0)
- 資料點限制 (建議 ≤ 365 點)
效能優化
- 確認索引存在:
-
idx_answer_created_reviewonanswer(created_at, is_review) -
idx_answer_user_emailonanswer(user_email) -
idx_logs_user_logins_createdonlogs_user_logins(created_at)
-
- (選用) 快取熱門查詢 (Redis, TTL 5-15 分鐘)
Phase 2: 前端頁面
環境準備
- 安裝圖表庫:
npm install echarts vue-echarts - 設定 ECharts SSR 處理 (nuxt.config 或 plugin)
路由與頁面
- 建立
app/pages/statistics/index.vue - 設定 layout:
definePageMeta({ layout: 'default' }) - 加入側邊欄選單項目 (若尚未存在)
時間篩選元件 (time-filter.vue)
- 快速切換按鈕群組 (全部/1日/1月/1年/自定義)
- 自訂日期 DatePicker x2 (起/迄)
- 日期選擇器僅在「自定義」時顯示
- 清除按鈕功能
- 篩選按鈕 emit 事件
- 預設值: 全部 (或月,依效能考量)
核心指標卡片 (core-metrics.vue + metric-card.vue)
- 10 個指標卡片佈局 (Grid 或 Flex)
- 單一卡片元件:
- 指標名稱
- 數值顯示
- 載入狀態 (skeleton)
- 特殊格式化 (時間顯示為 mm:ss、得分小數一位)
- 「題目最大/最小使用數」顯示題號
- 空值處理 (顯示
-或N/A)
圖表區域 (chart-selector.vue + time-series-chart.vue)
- 圖表類型下拉選單 (預設: 活躍人數表)
- ECharts 折線圖元件
- X 軸: 日期
- Y 軸: 數值
- Tooltip
- 響應式寬高
-
<ClientOnly>包裹圖表 (SSR 兼容) - 載入狀態處理
- 空資料提示
Composables
-
useStatisticsApi.ts:-
fetchCoreMetrics(params)- 核心指標 -
fetchChartData(type, params)- 圖表數據
-
-
useStatistics.ts:- 狀態管理 (loading, error, data)
- 篩選條件響應式
- 圖表類型切換
Phase 3: 整合測試
- 時間篩選正確過濾資料
- 全部範圍查詢效能測試 (>10 秒需優化)
- 圖表切換不重複請求 (前端快取)
- 響應式佈局 (桌面/平板)
- 錯誤處理與使用者提示
四、API 規格草案
4.1 核心指標 API
Request: POST /admin/statistics/getStatistics
{
"start_date": "2026-01-01",
"end_date": "2026-02-06"
}Response:
{
"success": true,
"data": {
"active_users": 150,
"total_answers": 1200,
"avg_answers_per_user": 8.0,
"avg_score": 78.5,
"avg_solving_time": 1800,
"question_avg_usage": 2.3,
"question_max_usage": { "question_id": 15, "count": 78 },
"question_min_usage": { "question_id": 3, "count": 2 },
"total_unreviewed": 45,
"avg_unreviewed_per_user": 0.3
}
}4.2 圖表數據 API
Request: POST /admin/statistics/getChartData
{
"type": "active_users",
"start_date": "2026-01-01",
"end_date": "2026-02-06"
}Response:
{
"success": true,
"data": {
"labels": ["2026-01-01", "2026-01-02", "..."],
"values": [12, 15, "..."]
}
}五、風險與注意事項
| 風險 | 緩解措施 |
|---|---|
| 大時間範圍查詢慢 | 預設「月」範圍、加索引、快取 |
| 除以零錯誤 | SQL 使用 NULLIF、前端顯示 N/A |
| 圖表 SSR 錯誤 | <ClientOnly> 包裹 |
| 日期無資料 | 後端填充或前端處理 |
六、依賴關係
SCRUM-67 (核心數據抽取) ──┐
├──→ SCRUM-43 (本任務)
SCRUM-68 (圖表數據抽取) ──┘
建議順序: 先完成 SCRUM-67 + 68 後端 API,再進行 SCRUM-43 前端整合。
相關筆記
- WriteAhead Sprint 4 工程分析報告 - Sprint 總覽
- SCRUM-36 前台數據頁實作分析 - 前台數據頁 (類似功能)
- SCRUM-67 核心數據抽取實作分析 - 核心數據抽取深度分析
- SCRUM-68 圖表數據抽取實作分析 - 圖表數據抽取詳細 checklist
更新紀錄
| 日期 | 更新內容 |
|---|---|
| 2026-02-06 | 初始分析,建立 checklist |