SCRUM-49 後台操作紀錄實作分析
JIRA: SCRUM-49 Parent: SCRUM-14 (後台-數值管理頁) 難度: ⭐⭐ (低) 預估工作量: 1-2 天 特點: 後端已完成,僅需前端實作
功能需求摘要
篩選條件
| 篩選項 | 類型 | 說明 |
|---|---|---|
| 使用者名稱 | 文字輸入 | LIKE 模糊搜尋 |
| 文字輸入 | LIKE 模糊搜尋 | |
| 角色 | 下拉選單 (多選) | 支援 array / 逗號分隔 |
| 操作類型 | 下拉選單 | 檢視/新增/編輯/刪除/登入/登出 |
| 模組名稱 | 下拉選單 | 各功能模組 |
| 操作內容 | 文字輸入 | LIKE 模糊搜尋 |
| 日期區間 | 日期選擇器 | start_date / end_date (YYYY-MM-DD) |
列表欄位
| 欄位 | API Key | 說明 |
|---|---|---|
| 角色 | role_name | 來自 admin_roles JOIN |
| 使用者名稱 | username | 來自 admin_users JOIN |
| 操作帳號 (Email) | email | 來自 admin_users JOIN |
| IP | ip | 操作者 IP 位址 |
| 操作類型 | action | 檢視/新增/編輯/刪除/登入/登出 |
| 模組名稱 | module | 如:系統管理、題目管理 |
| 功能名稱 | feature | 如:帳號管理、角色管理 |
| 操作內容 | content | 長文本,需 ellipsis + Tooltip |
| 日期時間 | created_at | 格式:YYYY-MM-DD HH:mm:ss |
唯讀列表:無新增/編輯/刪除操作
後端 API 分析 (已完成)
POST /admin/activityLog/list
路由權限: permission:activity_log,view
請求參數:
{
"username": "admin",
"email": "admin@",
"role_id": [1, 2],
"action": "編輯",
"module": "系統管理",
"feature": "帳號管理",
"content": "編輯帳號",
"start_date": "2026-01-01",
"end_date": "2026-02-06",
"page": 1,
"per_page": 10
}回傳格式:
{
"code": 200,
"data": [
{
"id": 1,
"admin_id": 1,
"ip": "127.0.0.1",
"module": "系統管理",
"feature": "帳號管理",
"action": "編輯",
"content": "編輯帳號管理:ID: 5",
"method": "POST",
"path": "/admin/admin_user/update",
"created_at": "2026-01-15 10:30:25",
"username": "admin",
"email": "admin@example.com",
"role_name": "超級管理員"
}
],
"page": 1,
"per_page": 10,
"total": 150,
"pages": 15
}資料庫 JOIN:
admin_user_activity_logs (主表)
LEFT JOIN admin_users (取 username, email)
LEFT JOIN admin_user_roles → admin_roles (取 role_name)
後端關鍵檔案
/home/matt/Github/writeahead-main-api/
├── app/Controllers/Admin/ActivityLogController.php # 控制器 (已完成)
├── app/Models/Admin/ActivityLogModel.php # 模型 (已完成)
└── app/Services/ActivityLogService.php # 日誌記錄服務 (已完成)
前端可複用資源
組件模式 (來自帳號管理頁)
| 組件 | 用途 |
|---|---|
CommonFilterCard | 篩選卡片容器 (查詢/清除按鈕) |
CommonFilterInput | 文字輸入篩選 (v-model + enter 觸發) |
CommonFilterSelect | 下拉選單篩選 (支援 multiple) |
CommonBaseTableCard | 通用表格卡片 (分頁/日期格式化) |
commonBreadcrumb | 麵包屑導覽 |
Composable 模式
| Composable | 用途 |
|---|---|
usePagination | 分頁狀態管理 (已存在,可直接複用) |
useTableColumns | 欄位定義工廠 (createColumn, createDateColumn) |
useAccountList | 列表 composable 範本 (filters + useFetch + pagination) |
實作 Checklist
1. 建立 Composable
-
建立 useActivityLogApi.ts
- 檔案:
app/composables/useActivityLogApi.ts - 方法:
fetchActivityLogs(params)→ POST/admin/activityLog/list - 使用
useFetch+ Bearer token 認證
- 檔案:
-
建立 useActivityLogList.ts
- 檔案:
app/composables/useActivityLogList.ts - 參考
useAccountList.ts模式 - 管理 filters 狀態 (username, email, role_id, action, module, content, start_date, end_date)
- 整合
usePagination分頁 - 提供
applyFilters()/resetFilters()/updatePagination()
- 檔案:
2. 建立常數
- 新增操作類型選項
- 檔案:
constants/activityLog.ts - 操作類型:
[檢視, 新增, 編輯, 刪除, 登入, 登出] - 模組名稱: 從現有 codebase 蒐集 (系統管理、題目管理 等)
- 檔案:
3. 建立篩選組件
- 建立 filter.vue
- 檔案:
app/components/system/log/filter.vue - 使用
CommonFilterCard包裹 - 篩選欄位:
CommonFilterInput: 使用者名稱、EMAIL、操作內容CommonFilterSelect: 角色 (多選)、操作類型、模組名稱a-range-picker或兩個a-date-picker: 日期區間
- 綁定
@apply→applyFilters、@reset→resetFilters
- 檔案:
4. 建立表格組件
-
建立 table.vue
- 檔案:
app/components/system/log/table.vue - 使用
CommonBaseTableCard - 不需要 create/edit/delete 按鈕 (唯讀)
- 欄位定義 (使用
useTableColumns):
欄位 key 寬度 對齊 特殊處理 角色 role_name 120 center - 使用者名稱 username 120 center - Email email 180 left - IP ip 130 center - 操作類型 action 100 center a-tag 顏色區分 模組 module 120 center - 功能 feature 120 center - 內容 content 200 left ellipsis + a-tooltip 時間 created_at 180 center dateColumns 自動格式化 - 操作類型建議顏色:
- 檢視: blue、新增: green、編輯: orange、刪除: red、登入: cyan、登出: default
- 檔案:
-
處理長文本 content 欄位
- 使用
a-typography-text的 ellipsis 或自訂 CSS - hover 時用
a-tooltip顯示完整內容
- 使用
5. 建立頁面
- 建立 logs 頁面
- 檔案:
app/pages/system/logs/index.vue - 結構:
<commonBreadcrumb :items="[{ label: '系統管理' }, { label: '操作紀錄' }]" /> <SystemLogFilter /> <SystemLogTable style="margin-top: 20px;" /> definePageMeta設定:- middleware:
['auth-guard', 'permission-guard'] - permissions:
['activity_log:view']
- middleware:
onMounted: 呼叫applyFilters()載入初始資料
- 檔案:
6. 加入導覽選單
- 更新 useMenuItems.ts
- 在
system選單下新增:{ key: 'system-logs', label: '操作紀錄', icon: () => h(DatabaseOutlined), link: '/system/logs', requiredPermission: 'activity_log:view' }
- 在
7. 測試驗證
- 頁面載入正確顯示資料
- 各篩選條件正確運作 (文字模糊搜尋、下拉選單、日期區間)
- 分頁切換正確
- 長文本 content 欄位 ellipsis + tooltip 正常
- 操作類型 tag 顏色正確
- 無權限時頁面正確攔截
- 選單項目正確顯示
關鍵決策
日期區間實作方式
| 方案 | 優點 | 缺點 |
|---|---|---|
| a-range-picker | 一個組件搞定,UX 好 | 需確認 CommonFilterCard 排版 |
| 兩個 a-date-picker | 與既有 pattern 一致 | 佔用兩個欄位 |
建議: 使用 a-range-picker,設定 format="YYYY-MM-DD" 即可
模組/功能選項來源
| 方案 | 說明 |
|---|---|
| 硬編碼常數 | 從 codebase 蒐集已知模組名稱 |
| 動態 API 取得 | 後端新增 endpoint 回傳 distinct module/feature |
建議: 先用硬編碼常數,日後有需要再加 API
關鍵檔案路徑
前端 (待建立)
/home/matt/Github/writeahead-admin-web/
├── app/pages/system/logs/index.vue # 頁面
├── app/components/system/log/
│ ├── filter.vue # 篩選組件
│ └── table.vue # 表格組件
├── app/composables/
│ ├── useActivityLogList.ts # 列表邏輯
│ └── useActivityLogApi.ts # API 呼叫
└── constants/activityLog.ts # 常數定義
後端 (已完成)
/home/matt/Github/writeahead-main-api/
├── app/Controllers/Admin/ActivityLogController.php
├── app/Models/Admin/ActivityLogModel.php
└── app/Services/ActivityLogService.php
參考檔案 (複用 pattern)
/home/matt/Github/writeahead-admin-web/
├── app/pages/system/accounts/index.vue # 頁面模式參考
├── app/components/system/account/filter.vue # 篩選組件參考
├── app/components/system/account/table.vue # 表格組件參考
├── app/composables/useAccountList.ts # composable 參考
├── app/components/common/filter-card.vue # 通用篩選卡片
├── app/components/common/filter-input.vue # 通用輸入篩選
├── app/components/common/filter-select.vue # 通用下拉篩選
└── app/components/common/base-table-card.vue # 通用表格卡片
風險與注意事項
- 日期區間選擇器: admin-web 是否已有
a-range-picker使用案例?需確認 Ant Design Vue 版本支援 - 模組/功能清單: 需從 codebase 蒐集完整的 module/feature 列表作為下拉選項
- 權限 key: 前端 permission guard 的 key 格式需與後端
activity_log:view對齊 - 大量資料: 操作紀錄會持續增長,確認
per_page預設值與分頁效能
相關筆記
- WriteAhead Sprint 4 工程分析報告
- SCRUM-36 前台數據頁實作分析
- SCRUM-43 後台數據監控與管理實作分析
更新紀錄
| 日期 | 更新內容 |
|---|---|
| 2026-02-06 | 初始分析:後端 API 完整解析 + 前端 checklist 建立 |