Backend: - LOW-002: Add Query validation with max page size limits (100) - LOW-003: Replace magic strings with TaskStatus.is_done flag - LOW-004: Add 'creation' trigger type validation - Add action_executor.py with UpdateFieldAction and AutoAssignAction Frontend: - LOW-005: Replace TypeScript 'any' with 'unknown' + type guards - LOW-006: Add ConfirmModal component with A11Y support - LOW-007: Add ToastContext for user feedback notifications - LOW-009: Add Skeleton components (17 loading states replaced) - LOW-010: Setup Vitest with 21 tests for ConfirmModal and Skeleton Components updated: - App.tsx, ProtectedRoute.tsx, Spaces.tsx, Projects.tsx, Tasks.tsx - ProjectSettings.tsx, AuditPage.tsx, WorkloadPage.tsx, ProjectHealthPage.tsx - Comments.tsx, AttachmentList.tsx, TriggerList.tsx, TaskDetailModal.tsx - NotificationBell.tsx, BlockerDialog.tsx, CalendarView.tsx, WorkloadUserDetail.tsx 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
784 lines
32 KiB
Markdown
784 lines
32 KiB
Markdown
# PROJECT CONTROL - Issue Tracking
|
||
|
||
> 審核日期: 2026-01-04
|
||
> 更新日期: 2026-01-06
|
||
> 整體完成度: 100% (核心功能及 A11Y 全部完成)
|
||
> 已修復問題: 32 (CRIT-001~003, HIGH-001~008, MED-001~012, NEW-001~002, A11Y-001~006)
|
||
|
||
---
|
||
|
||
## 目錄
|
||
|
||
- [嚴重問題 (Critical)](#嚴重問題-critical)
|
||
- [高優先問題 (High)](#高優先問題-high)
|
||
- [中優先問題 (Medium)](#中優先問題-medium)
|
||
- [低優先問題 (Low)](#低優先問題-low)
|
||
- [未實作功能 (Missing Features)](#未實作功能-missing-features)
|
||
- [可訪問性問題 (Accessibility)](#可訪問性問題-accessibility)
|
||
- [程式碼品質建議 (Code Quality)](#程式碼品質建議-code-quality)
|
||
|
||
---
|
||
|
||
## 嚴重問題 (Critical)
|
||
|
||
### CRIT-001: JWT 密鑰硬編碼
|
||
|
||
- **類型**: 安全漏洞
|
||
- **模組**: Backend - Authentication
|
||
- **檔案**: `backend/app/core/config.py:28`
|
||
- **問題描述**: JWT secret key 有硬編碼的預設值 `"your-secret-key-change-in-production"`,若部署時未設定環境變數,所有 JWT token 都可被偽造。
|
||
- **影響**: 完全繞過認證系統
|
||
- **建議修復**:
|
||
```python
|
||
JWT_SECRET_KEY: str = "" # 移除預設值
|
||
|
||
def __init__(self, **kwargs):
|
||
super().__init__(**kwargs)
|
||
if not self.JWT_SECRET_KEY or self.JWT_SECRET_KEY == "your-secret-key-change-in-production":
|
||
raise ValueError("JWT_SECRET_KEY must be set in environment")
|
||
```
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 使用 pydantic @field_validator 驗證 JWT_SECRET_KEY,拒絕空值和佔位符值
|
||
|
||
---
|
||
|
||
### CRIT-002: 登入嘗試未記錄稽核日誌
|
||
|
||
- **類型**: 安全漏洞
|
||
- **模組**: Backend - Authentication / Audit
|
||
- **檔案**: `backend/app/api/auth/router.py`
|
||
- **問題描述**: Spec 要求記錄失敗的登入嘗試,但 auth router 未呼叫 AuditService.log_event() 記錄登入成功/失敗。
|
||
- **影響**: 無法偵測暴力破解攻擊,稽核追蹤不完整
|
||
- **建議修復**:
|
||
```python
|
||
# 登入成功時
|
||
AuditService.log_event(
|
||
db=db,
|
||
event_type="user.login",
|
||
resource_type="user",
|
||
action=AuditAction.LOGIN,
|
||
user_id=user.id,
|
||
...
|
||
)
|
||
|
||
# 登入失敗時
|
||
AuditService.log_event(
|
||
db=db,
|
||
event_type="user.login_failed",
|
||
...
|
||
)
|
||
```
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 在 login endpoint 添加 AuditService.log_event() 呼叫,記錄成功/失敗的登入嘗試,包含 IP 和 User-Agent
|
||
|
||
---
|
||
|
||
### CRIT-003: 前端 API 路徑重複導致請求失敗
|
||
|
||
- **類型**: Bug
|
||
- **模組**: Frontend - Core
|
||
- **檔案**:
|
||
- `frontend/src/pages/Spaces.tsx:29, 43`
|
||
- `frontend/src/pages/Projects.tsx:44-45, 61`
|
||
- `frontend/src/pages/Tasks.tsx:54-56, 73, 86`
|
||
- **問題描述**: API 呼叫使用 `/api/spaces` 但 axios baseURL 已設為 `/api`,導致實際請求路徑變成 `/api/api/spaces`。
|
||
- **影響**: Spaces、Projects、Tasks 頁面所有 API 呼叫都會失敗
|
||
- **建議修復**:
|
||
```typescript
|
||
// 錯誤:
|
||
const response = await api.get('/api/spaces')
|
||
// 正確:
|
||
const response = await api.get('/spaces')
|
||
```
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 移除 Spaces.tsx, Projects.tsx, Tasks.tsx, attachments.ts 中所有 API 路徑的 `/api` 前綴
|
||
|
||
---
|
||
|
||
## 高優先問題 (High)
|
||
|
||
### HIGH-001: 專案刪除使用硬刪除
|
||
|
||
- **類型**: 資料完整性
|
||
- **模組**: Backend - Projects
|
||
- **檔案**: `backend/app/api/projects/router.py:268-307`
|
||
- **問題描述**: 專案刪除使用 `db.delete(project)` 硬刪除,但 Audit Trail spec 要求所有刪除操作使用軟刪除。
|
||
- **影響**: 資料遺失,稽核日誌無法參照已刪除專案
|
||
- **建議修復**: 為 Project model 新增 `is_deleted`, `deleted_at`, `deleted_by` 欄位,實作軟刪除
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 使用現有 is_active 欄位實作軟刪除,delete_project 設定 is_active=False 而非 db.delete()
|
||
|
||
---
|
||
|
||
### HIGH-002: Redis Session Token 類型比對問題
|
||
|
||
- **類型**: Bug
|
||
- **模組**: Backend - Authentication
|
||
- **檔案**: `backend/app/middleware/auth.py:43-50`
|
||
- **問題描述**: Redis `get()` 在某些配置下回傳 bytes,與字串 token 比對可能失敗。
|
||
- **影響**: 使用者可能意外被登出
|
||
- **建議修復**:
|
||
```python
|
||
stored_token = redis_client.get(f"session:{user_id}")
|
||
if stored_token is None:
|
||
raise HTTPException(...)
|
||
if isinstance(stored_token, bytes):
|
||
stored_token = stored_token.decode('utf-8')
|
||
if stored_token != token:
|
||
raise HTTPException(...)
|
||
```
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 在 middleware/auth.py 添加 bytes 類型檢查和 decode 處理
|
||
|
||
---
|
||
|
||
### HIGH-003: 無 Rate Limiting 實作
|
||
|
||
- **類型**: 安全漏洞
|
||
- **模組**: Backend - API
|
||
- **檔案**: 多個 API endpoints
|
||
- **問題描述**: Spec 提及 rate limiting,但未實作任何速率限制中介軟體。
|
||
- **影響**: API 易受暴力破解和 DoS 攻擊
|
||
- **建議修復**:
|
||
```python
|
||
from slowapi import Limiter
|
||
from slowapi.util import get_remote_address
|
||
|
||
limiter = Limiter(key_func=get_remote_address)
|
||
|
||
@router.post("/login")
|
||
@limiter.limit("5/minute")
|
||
async def login(...):
|
||
```
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 使用 slowapi 實作 rate limiting,login endpoint 限制 5 req/min,測試環境使用 memory storage
|
||
|
||
---
|
||
|
||
### HIGH-004: 附件 API 缺少權限檢查
|
||
|
||
- **類型**: 安全漏洞
|
||
- **模組**: Backend - Attachments
|
||
- **檔案**: `backend/app/api/attachments/router.py`
|
||
- **問題描述**: 附件 endpoints 只檢查任務是否存在,未驗證當前使用者是否有權存取該任務的專案。`check_task_access` 函數存在但未被呼叫。
|
||
- **影響**: 使用者可上傳/下載不應有權存取的任務附件
|
||
- **建議修復**: 在每個 endpoint 加入 `check_task_access(current_user, task, task.project)` 呼叫
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 新增 get_task_with_access_check 和 get_attachment_with_access_check 輔助函數,所有 endpoints 都使用這些函數進行權限驗證
|
||
|
||
---
|
||
|
||
### HIGH-005: 任務視角僅有列表視角
|
||
|
||
- **類型**: 功能缺失
|
||
- **模組**: Frontend - Task Management
|
||
- **檔案**: `frontend/src/pages/Tasks.tsx`
|
||
- **問題描述**: Spec 要求 4 種視角 (Kanban, Gantt, List, Calendar),目前僅實作列表視角。
|
||
- **影響**: 無法滿足不同工作流程需求
|
||
- **建議修復**: 優先實作看板 (Kanban) 視角,支援拖拉變更狀態
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 新增 KanbanBoard.tsx 元件,支援 HTML5 drag-and-drop 變更狀態,Tasks.tsx 新增 List/Kanban 切換按鈕,偏好設定儲存於 localStorage
|
||
|
||
---
|
||
|
||
### HIGH-006: 資源管理模組前端 UI 未開發
|
||
|
||
- **類型**: 功能缺失
|
||
- **模組**: Frontend - Resource Management
|
||
- **檔案**: -
|
||
- **問題描述**: 整個資源管理模組前端未開發,包括負載熱圖、容量規劃、專案健康看板。
|
||
- **影響**: 主管無法視覺化查看團隊工作負載
|
||
- **建議修復**: 開發 WorkloadHeatmap 元件和相關頁面
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 新增 WorkloadPage.tsx、WorkloadHeatmap.tsx、WorkloadUserDetail.tsx 元件,完整實作負載熱圖視覺化功能
|
||
|
||
---
|
||
|
||
### HIGH-007: 協作/附件/觸發器元件未整合
|
||
|
||
- **類型**: 功能缺失
|
||
- **模組**: Frontend - Integration
|
||
- **檔案**:
|
||
- `frontend/src/components/Comments.tsx` - 未使用
|
||
- `frontend/src/components/TaskAttachments.tsx` - 未使用
|
||
- `frontend/src/components/TriggerList.tsx` - 未使用
|
||
- `frontend/src/components/TriggerForm.tsx` - 未使用
|
||
- **問題描述**: 多個元件已開發但未整合進任何頁面或路由。
|
||
- **影響**: 使用者無法使用留言、附件管理、觸發器設定功能
|
||
- **建議修復**:
|
||
1. 建立任務詳情頁面/Modal,整合 Comments 和 Attachments
|
||
2. 新增 /automation 路由整合 TriggerList/TriggerForm
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 新增 TaskDetailModal.tsx 元件,整合 Comments 和 TaskAttachments,點擊任務卡片/列表項目即可開啟詳細視窗
|
||
|
||
---
|
||
|
||
### HIGH-008: 任務指派 UI 缺失
|
||
|
||
- **類型**: 功能缺失
|
||
- **模組**: Frontend - Task Management
|
||
- **檔案**: `frontend/src/pages/Tasks.tsx`
|
||
- **問題描述**: 建立/編輯任務時無法選擇指派者 (assignee),無法設定時間估算。
|
||
- **影響**: 核心任務管理功能不完整
|
||
- **建議修復**: 在任務建立 Modal 新增指派者下拉選單和時間估算欄位
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 新增 UserSelect.tsx 元件提供使用者搜尋下拉選單,Tasks.tsx 建立任務 Modal 新增指派者、到期日、時間估算欄位,TaskDetailModal 支援編輯這些欄位
|
||
|
||
---
|
||
|
||
## 中優先問題 (Medium)
|
||
|
||
### MED-001: 附件 Router 重複 Commit
|
||
|
||
- **類型**: 效能問題
|
||
- **模組**: Backend - Attachments
|
||
- **檔案**: `backend/app/api/attachments/router.py:118-133, 178-192`
|
||
- **問題描述**: 同一請求中多次 `db.commit()`,效率低且可能導致部分交易狀態。
|
||
- **建議修復**: 移除重複 commit,使用單一交易
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 移除 attachments/router.py 中 4 處重複的 db.commit() 呼叫
|
||
|
||
---
|
||
|
||
### MED-002: 負載熱圖 N+1 查詢
|
||
|
||
- **類型**: 效能問題
|
||
- **模組**: Backend - Resource Management
|
||
- **檔案**: `backend/app/services/workload_service.py:169-210`
|
||
- **問題描述**: 計算多使用者負載時,對每個使用者分別查詢任務。
|
||
- **影響**: 使用者數量增加時資料庫效能下降
|
||
- **建議修復**: 批次查詢所有使用者的任務,在記憶體中分組
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 重構為批次查詢所有使用者的任務,使用 defaultdict 在記憶體中分組
|
||
|
||
---
|
||
|
||
### MED-003: datetime.utcnow() 已棄用
|
||
|
||
- **類型**: 棄用警告
|
||
- **模組**: Backend - Security
|
||
- **檔案**: `backend/app/core/security.py:21-25`
|
||
- **問題描述**: 使用 `datetime.utcnow()` 在 Python 3.12+ 已棄用。
|
||
- **建議修復**:
|
||
```python
|
||
from datetime import datetime, timezone
|
||
expire = datetime.now(timezone.utc) + timedelta(...)
|
||
```
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 將所有 datetime.utcnow() 改為 datetime.now(timezone.utc).replace(tzinfo=None) 以保持與 SQLite 相容性
|
||
|
||
---
|
||
|
||
### MED-004: 錯誤回應格式不一致
|
||
|
||
- **類型**: API 一致性
|
||
- **模組**: Backend - API
|
||
- **檔案**: 多個 endpoints
|
||
- **問題描述**: 部分 endpoints 回傳 `{"message": "..."}` 而其他回傳 `{"detail": "..."}`。FastAPI 慣例是 `detail`。
|
||
- **影響**: 前端必須處理不一致的回應格式
|
||
- **建議修復**: 統一使用 `{"detail": "..."}` 格式
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 統一 attachments/router.py 和 auth/router.py 的回應格式為 {"detail": "..."}
|
||
|
||
---
|
||
|
||
### MED-005: 阻礙狀態自動設定可能衝突
|
||
|
||
- **類型**: 邏輯問題
|
||
- **模組**: Backend - Tasks
|
||
- **檔案**: `backend/app/api/tasks/router.py:506-511`
|
||
- **問題描述**: 狀態變更時自動設定 `blocker_flag = False` 可能與 Blocker 表中未解除的阻礙記錄衝突。
|
||
- **建議修復**: 根據 Blocker 表實際記錄設定 flag,而非僅依據狀態名稱
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 修改狀態變更邏輯,檢查 Blocker 表中是否有未解決的阻礙記錄來決定 blocker_flag
|
||
|
||
---
|
||
|
||
### MED-006: 專案健康看板未實作
|
||
|
||
- **類型**: 功能缺失
|
||
- **模組**: Backend + Frontend - Resource Management
|
||
- **檔案**: -
|
||
- **問題描述**: `pjctrl_project_health` 表和相關 API 未實作。
|
||
- **影響**: 主管無法一覽所有專案狀態
|
||
- **建議修復**: 實作後端 API 和前端健康看板元件
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 實作 HealthService、health router、ProjectHealthPage 前端元件
|
||
|
||
---
|
||
|
||
### MED-007: 容量更新 API 缺失
|
||
|
||
- **類型**: 功能缺失
|
||
- **模組**: Backend - Resource Management
|
||
- **檔案**: -
|
||
- **問題描述**: 使用者容量 (capacity) 儲存在資料庫,但無更新 API。
|
||
- **建議修復**: 新增 `PUT /api/users/{id}/capacity` endpoint
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 新增 PUT /api/users/{user_id}/capacity endpoint,支援權限檢查、稽核日誌、快取失效
|
||
|
||
---
|
||
|
||
### MED-008: 排程觸發器未完整實作
|
||
|
||
- **類型**: 功能缺失
|
||
- **模組**: Backend - Automation
|
||
- **檔案**: `backend/app/api/triggers/router.py`
|
||
- **問題描述**: 觸發器類型驗證僅支援 `field_change` 和 `schedule`,但 schedule 類型的執行邏輯未完成。
|
||
- **影響**: 無法使用時間條件觸發器
|
||
- **建議修復**: 實作排程觸發器的 cron 解析和執行邏輯
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 實作 TriggerSchedulerService,支援 cron 表達式解析、截止日期提醒、排程任務整合
|
||
|
||
---
|
||
|
||
### MED-009: 浮水印功能未實作
|
||
|
||
- **類型**: 功能缺失
|
||
- **模組**: Backend - Document Management
|
||
- **檔案**: `backend/app/api/attachments/router.py`
|
||
- **問題描述**: Spec 要求下載時自動加上使用者浮水印,但未實作 Pillow/PyPDF2 處理邏輯。
|
||
- **影響**: 無法追蹤檔案洩漏來源
|
||
- **建議修復**: 實作圖片和 PDF 浮水印處理函數
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 實作 WatermarkService,支援圖片和 PDF 浮水印,整合至下載流程
|
||
|
||
---
|
||
|
||
### MED-010: useEffect 依賴缺失
|
||
|
||
- **類型**: Bug
|
||
- **模組**: Frontend - Multiple Components
|
||
- **檔案**:
|
||
- `frontend/src/components/TriggerList.tsx:27-29`
|
||
- `frontend/src/components/ResourceHistory.tsx:15-17`
|
||
- **問題描述**: `fetchTriggers` 和 `loadHistory` 函數在 useEffect 中呼叫但未列為依賴。
|
||
- **影響**: 可能導致閉包過期 (stale closure),ESLint 警告
|
||
- **建議修復**: 使用 useCallback 包裝函數並加入依賴陣列
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 使用 useCallback 包裝 fetchTriggers 和 loadHistory 函數,並加入正確的依賴陣列
|
||
|
||
---
|
||
|
||
### MED-011: DOM 操作在元件外執行
|
||
|
||
- **類型**: 反模式
|
||
- **模組**: Frontend - Attachments
|
||
- **檔案**: `frontend/src/components/AttachmentUpload.tsx:185-192`
|
||
- **問題描述**: 在元件模組頂層建立並附加 style 元素,違反 React 生命週期管理。
|
||
- **影響**: 潛在記憶體洩漏,每次 import 都會執行
|
||
- **建議修復**: 將樣式移至 CSS 檔案或使用 useEffect 管理
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 將 style 元素注入邏輯移至 useEffect,並在清理時移除樣式元素
|
||
|
||
---
|
||
|
||
### MED-012: PDF 匯出未實作
|
||
|
||
- **類型**: 功能缺失
|
||
- **模組**: Frontend - Audit Trail
|
||
- **檔案**: `frontend/src/pages/AuditPage.tsx`
|
||
- **問題描述**: Spec 提及 CSV/PDF 匯出,目前僅實作 CSV。
|
||
- **建議修復**: 新增 PDF 匯出選項
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復方式**: 新增 Export PDF 按鈕,使用瀏覽器 window.print() 功能匯出 PDF
|
||
|
||
---
|
||
|
||
## 低優先問題 (Low)
|
||
|
||
### LOW-001: 缺少完整類型提示
|
||
|
||
- **類型**: 程式碼品質
|
||
- **模組**: Backend - Services
|
||
- **檔案**: 多個 service 檔案
|
||
- **問題描述**: 部分函數缺少完整類型提示。
|
||
- **狀態**: [ ] 待改善
|
||
|
||
---
|
||
|
||
### LOW-002: 分頁無最大限制
|
||
|
||
- **類型**: 效能問題
|
||
- **模組**: Backend - API
|
||
- **檔案**: 多個 list endpoints
|
||
- **問題描述**: 雖有分頁實作,但部分 endpoints 無最大 page size 限制。
|
||
- **狀態**: [x] 已修復 (Query validation with max limits)
|
||
|
||
---
|
||
|
||
### LOW-003: 狀態名稱使用魔術字串
|
||
|
||
- **類型**: 程式碼品質
|
||
- **模組**: Backend - Reports
|
||
- **檔案**: `backend/app/services/report_service.py:84-92`
|
||
- **問題描述**: 使用硬編碼字串比對狀態名稱 `["done", "completed", "完成"]`。
|
||
- **建議修復**: 統一使用 TaskStatus model 的 is_done flag
|
||
- **狀態**: [x] 已修復 (使用 TaskStatus.is_done flag)
|
||
|
||
---
|
||
|
||
### LOW-004: 觸發器類型驗證不完整
|
||
|
||
- **類型**: 驗證不足
|
||
- **模組**: Backend - Automation
|
||
- **檔案**: `backend/app/api/triggers/router.py:62-66`
|
||
- **問題描述**: 觸發器類型僅驗證 "field_change" 和 "schedule",但 spec 提及 "creation" 類型。
|
||
- **狀態**: [x] 已修復 (新增 "creation" 類型驗證)
|
||
|
||
---
|
||
|
||
### LOW-005: 使用 any 類型
|
||
|
||
- **類型**: TypeScript 類型安全
|
||
- **模組**: Frontend - Login
|
||
- **檔案**: `frontend/src/pages/Login.tsx:21`
|
||
- **問題描述**: `catch (err: any)` 失去類型安全。
|
||
- **建議修復**: 使用 `catch (err: unknown)` 並進行類型守衛
|
||
- **狀態**: [x] 已修復 (使用 unknown + type guard)
|
||
|
||
---
|
||
|
||
### LOW-006: 使用原生 confirm()/alert()
|
||
|
||
- **類型**: UX 一致性
|
||
- **模組**: Frontend - Multiple
|
||
- **檔案**:
|
||
- `frontend/src/components/Comments.tsx:74`
|
||
- `frontend/src/components/AttachmentList.tsx:40`
|
||
- `frontend/src/components/TriggerList.tsx:41`
|
||
- `frontend/src/components/WeeklyReportPreview.tsx:171`
|
||
- **問題描述**: 使用原生對話框,非無障礙且 UX 不一致。
|
||
- **建議修復**: 建立可重用的確認 Modal 元件
|
||
- **狀態**: [x] 已修復 (ConfirmModal 元件 + A11Y 支援)
|
||
|
||
---
|
||
|
||
### LOW-007: 錯誤處理無使用者回饋
|
||
|
||
- **類型**: UX 問題
|
||
- **模組**: Frontend - Spaces
|
||
- **檔案**: `frontend/src/pages/Spaces.tsx:31-32`
|
||
- **問題描述**: 錯誤僅記錄至 console,無向使用者顯示。
|
||
- **建議修復**: 新增 toast 通知系統
|
||
- **狀態**: [x] 已修復 (ToastContext + 整合至 Spaces/Projects/ProjectSettings 等頁面)
|
||
|
||
---
|
||
|
||
### LOW-008: 樣式方法不一致
|
||
|
||
- **類型**: 程式碼一致性
|
||
- **模組**: Frontend - Styling
|
||
- **檔案**: 多個元件
|
||
- **問題描述**: 混合使用 inline styles 物件 (Dashboard.tsx) 和類似 Tailwind 的 class 字串 (Comments.tsx)。
|
||
- **建議修復**: 統一使用 CSS Modules 或 styled-components
|
||
- **狀態**: [ ] 待改善
|
||
|
||
---
|
||
|
||
### LOW-009: 缺少載入骨架
|
||
|
||
- **類型**: UX 問題
|
||
- **模組**: Frontend - Multiple
|
||
- **問題描述**: 所有載入狀態顯示純文字 "Loading...",造成版面跳動。
|
||
- **建議修復**: 新增骨架元件 (skeleton components)
|
||
- **狀態**: [x] 已修復 (Skeleton 元件系列 + 全站整合)
|
||
- **已整合頁面**: App.tsx, ProtectedRoute.tsx, Spaces.tsx, Projects.tsx, Tasks.tsx, ProjectSettings.tsx, AuditPage.tsx, WorkloadPage.tsx, ProjectHealthPage.tsx
|
||
- **已整合元件**: Comments.tsx, AttachmentList.tsx, TriggerList.tsx, TaskDetailModal.tsx, NotificationBell.tsx, BlockerDialog.tsx, CalendarView.tsx, WorkloadUserDetail.tsx
|
||
|
||
---
|
||
|
||
### LOW-010: 缺少前端測試
|
||
|
||
- **類型**: 測試覆蓋
|
||
- **模組**: Frontend
|
||
- **問題描述**: 未發現任何測試檔案。
|
||
- **建議修復**: 新增 Vitest/Jest 單元測試
|
||
- **狀態**: [x] 已修復 (Vitest + 21 測試)
|
||
|
||
---
|
||
|
||
## 未實作功能 (Missing Features)
|
||
|
||
| ID | 模組 | 功能 | 後端 | 前端 | 優先級 | 狀態 |
|
||
|----|------|------|:----:|:----:|--------|------|
|
||
| FEAT-001 | Task Management | 自定義欄位 (Custom Fields) | 有 | 有 | 高 | ✅ 已完成 (2026-01-05) |
|
||
| FEAT-002 | Task Management | 看板視角 (Kanban View) | 有 | 有 | 高 | ✅ 已完成 (KanbanBoard.tsx) |
|
||
| FEAT-003 | Task Management | 甘特圖視角 (Gantt View) | 有 | 有 | 中 | ✅ 已完成 (2026-01-05) |
|
||
| FEAT-004 | Task Management | 行事曆視角 (Calendar View) | 有 | 有 | 中 | ✅ 已完成 (2026-01-05) |
|
||
| FEAT-005 | Task Management | 子任務建立 UI | 有 | 有 | 中 | ✅ 已完成 (2026-01-06) |
|
||
| FEAT-006 | Task Management | 拖拉變更狀態 | 有 | 有 | 中 | ✅ 已完成 (KanbanBoard drag-drop) |
|
||
| FEAT-007 | Resource Management | 負載熱圖 UI | 有 | 有 | 高 | ✅ 已完成 (WorkloadPage.tsx) |
|
||
| FEAT-008 | Resource Management | 專案健康看板 | 有 | 有 | 中 | ✅ 已完成 (ProjectHealthPage.tsx) |
|
||
| FEAT-009 | Resource Management | 容量更新 API | 有 | N/A | 低 | ✅ 已完成 (PUT /api/users/{id}/capacity) |
|
||
| FEAT-010 | Document Management | AES-256 加密存儲 | 有 | N/A | 高 | ✅ 已完成 (2026-01-05) |
|
||
| FEAT-011 | Document Management | 動態浮水印 | 有 | N/A | 中 | ✅ 已完成 (watermark_service.py) |
|
||
| FEAT-012 | Document Management | 版本還原 UI | 有 | 有 | 低 | ✅ 已完成 (2026-01-06) |
|
||
| FEAT-013 | Automation | 排程觸發器執行 | 有 | N/A | 中 | ✅ 已完成 (trigger_scheduler.py) |
|
||
| FEAT-014 | Automation | 更新欄位動作 | 有 | N/A | 低 | ✅ 已完成 (2026-01-06) |
|
||
| FEAT-015 | Automation | 自動指派動作 | 有 | N/A | 低 | ✅ 已完成 (2026-01-06) |
|
||
| FEAT-016 | Audit Trail | 稽核完整性驗證 UI | 有 | 有 | 低 | ✅ 已完成 (2026-01-06) |
|
||
|
||
---
|
||
|
||
## 可訪問性問題 (Accessibility)
|
||
|
||
### A11Y-001: 表單缺少 Label
|
||
|
||
- **檔案**: `frontend/src/pages/Spaces.tsx:95-101`
|
||
- **問題**: Modal 中的 input 欄位缺少關聯的 `<label>` 元素。
|
||
- **WCAG**: 1.3.1 Info and Relationships
|
||
- **狀態**: [x] 已修復 (2026-01-06)
|
||
- **修復方式**: 新增 visuallyHidden label 元素關聯 input 欄位,同時修復 Tasks.tsx, Projects.tsx
|
||
|
||
---
|
||
|
||
### A11Y-002: 非語義化按鈕
|
||
|
||
- **檔案**: `frontend/src/components/ResourceHistory.tsx:46`
|
||
- **問題**: 可點擊的 div 缺少 button role 或鍵盤處理。
|
||
- **WCAG**: 4.1.2 Name, Role, Value
|
||
- **狀態**: [x] 已修復 (2026-01-06)
|
||
- **修復方式**: 新增 `role="button"`, `tabIndex={0}`, `onKeyDown` 處理 Enter/Space 鍵, `aria-expanded`, `aria-label`
|
||
|
||
---
|
||
|
||
### A11Y-003: 圖示按鈕缺少 aria-label
|
||
|
||
- **檔案**: `frontend/src/pages/AuditPage.tsx:16`
|
||
- **問題**: 關閉按鈕 (x) 缺少 aria-label。
|
||
- **WCAG**: 4.1.2 Name, Role, Value
|
||
- **狀態**: [x] 已修復 (2026-01-06)
|
||
- **修復方式**: 新增 `aria-label="Close"` 至所有 Modal 關閉按鈕
|
||
|
||
---
|
||
|
||
### A11Y-004: 顏色對比不足
|
||
|
||
- **檔案**: 多個檔案
|
||
- **問題**: 使用淺灰色文字 (#999) 未達 WCAG AA 對比度標準 (2.85:1 < 4.5:1)。
|
||
- **WCAG**: 1.4.3 Contrast (Minimum)
|
||
- **狀態**: [x] 已修復 (2026-01-06)
|
||
- **修復方式**: 將所有 `#999` 改為 `#767676` (對比度 4.54:1,符合 WCAG AA)
|
||
|
||
---
|
||
|
||
### A11Y-005: 缺少焦點指示器
|
||
|
||
- **檔案**: `frontend/src/pages/Login.tsx`
|
||
- **問題**: Input 樣式設定 `outline: none` 但無自訂焦點樣式。
|
||
- **WCAG**: 2.4.7 Focus Visible
|
||
- **狀態**: [x] 已修復 (2026-01-06)
|
||
- **修復方式**: 在 index.css 新增全域 `*:focus-visible` 樣式和 `.login-input:focus` 自訂樣式
|
||
|
||
---
|
||
|
||
### A11Y-006: Modal 無焦點捕獲
|
||
|
||
- **檔案**: 多個 Modal 元件
|
||
- **問題**: Modal 未捕獲焦點,不支援 Escape 鍵關閉。
|
||
- **WCAG**: 2.1.2 No Keyboard Trap
|
||
- **狀態**: [x] 已修復 (2026-01-06)
|
||
- **修復方式**: 所有 Modal 新增 `useEffect` 監聽 document keydown 事件處理 Escape 鍵,新增 `role="dialog"`, `aria-modal="true"`, `aria-labelledby`, `tabIndex={-1}`
|
||
|
||
---
|
||
|
||
## 程式碼品質建議 (Code Quality)
|
||
|
||
### 後端建議
|
||
|
||
1. **啟用 SQLAlchemy 嚴格模式** - 捕獲潛在的關係問題
|
||
2. **新增 API 文檔測試** - 確保 OpenAPI spec 與實作一致
|
||
3. **統一日誌格式** - 使用結構化日誌 (如 structlog)
|
||
4. **新增健康檢查 endpoint** - `/health` 回傳資料庫/Redis 連線狀態
|
||
|
||
### 前端建議
|
||
|
||
1. **啟用 TypeScript 嚴格模式** - `"strict": true` in tsconfig
|
||
2. **新增 ESLint exhaustive-deps 規則** - 防止 useEffect 依賴問題
|
||
3. **建立共用元件庫** - Button, Modal, Input, Toast 等
|
||
4. **實作錯誤邊界** - 防止元件錯誤影響整個應用
|
||
5. **新增 i18n 支援** - 目前中英文混用
|
||
|
||
---
|
||
|
||
## 統計摘要
|
||
|
||
| 類別 | 數量 |
|
||
|------|------|
|
||
| 嚴重問題 (Critical) | 3 |
|
||
| 高優先問題 (High) | 8 |
|
||
| 中優先問題 (Medium) | 12 |
|
||
| 低優先問題 (Low) | 10 |
|
||
| 未實作功能 | 16 |
|
||
| 可訪問性問題 | 6 |
|
||
| **總計** | **55** |
|
||
|
||
---
|
||
|
||
## 修復進度追蹤
|
||
|
||
- [x] 嚴重問題全部修復 (3/3 已完成)
|
||
- [x] 高優先問題全部修復 (8/8 已完成)
|
||
- [x] 中優先問題全部修復 (12/12 已完成)
|
||
- [x] 核心功能實作完成
|
||
- [x] 可訪問性問題修復 (6/6 已完成)
|
||
- [x] 程式碼品質改善 (LOW-002~010 已完成, LOW-001/LOW-008 待改善)
|
||
|
||
### 本次修復摘要 (2026-01-04)
|
||
|
||
| Issue ID | 問題 | 狀態 |
|
||
|----------|------|------|
|
||
| CRIT-001 | JWT 密鑰硬編碼 | ✅ 已修復 |
|
||
| CRIT-002 | 登入嘗試未記錄稽核日誌 | ✅ 已修復 |
|
||
| CRIT-003 | 前端 API 路徑重複 | ✅ 已修復 |
|
||
| HIGH-001 | 專案刪除使用硬刪除 | ✅ 已修復 |
|
||
| HIGH-002 | Redis Session Token 類型比對 | ✅ 已修復 |
|
||
| HIGH-003 | 無 Rate Limiting 實作 | ✅ 已修復 |
|
||
| HIGH-004 | 附件 API 缺少權限檢查 | ✅ 已修復 |
|
||
| HIGH-005 | 任務視角僅有列表視角 | ✅ 已修復 |
|
||
| HIGH-006 | 資源管理模組前端 UI | ✅ 已修復 |
|
||
| HIGH-007 | 協作/附件/觸發器元件未整合 | ✅ 已修復 |
|
||
| HIGH-008 | 任務指派 UI 缺失 | ✅ 已修復 |
|
||
| MED-001 | 附件 Router 重複 Commit | ✅ 已修復 |
|
||
| MED-002 | 負載熱圖 N+1 查詢 | ✅ 已修復 |
|
||
| MED-003 | datetime.utcnow() 已棄用 | ✅ 已修復 |
|
||
| MED-004 | 錯誤回應格式不一致 | ✅ 已修復 |
|
||
| MED-005 | 阻礙狀態自動設定可能衝突 | ✅ 已修復 |
|
||
| MED-006 | 專案健康看板 | ✅ 已修復 |
|
||
| MED-007 | 容量更新 API | ✅ 已修復 |
|
||
| MED-008 | 排程觸發器執行邏輯 | ✅ 已修復 |
|
||
| MED-009 | 浮水印功能 | ✅ 已修復 |
|
||
| MED-010 | useEffect 依賴缺失 | ✅ 已修復 |
|
||
| MED-011 | DOM 操作在元件外執行 | ✅ 已修復 |
|
||
| MED-012 | PDF 匯出未實作 | ✅ 已修復 |
|
||
|
||
### 本次修復摘要 (2026-01-06)
|
||
|
||
| Issue ID | 問題 | 狀態 |
|
||
|----------|------|------|
|
||
| FEAT-005 | 子任務建立 UI | ✅ 已完成 (SubtaskList.tsx) |
|
||
| FEAT-012 | 版本還原 UI | ✅ 已完成 (AttachmentVersionHistory.tsx) |
|
||
| FEAT-014 | 更新欄位動作 | ✅ 已完成 (action_executor.py UpdateFieldAction) |
|
||
| FEAT-015 | 自動指派動作 | ✅ 已完成 (action_executor.py AutoAssignAction) |
|
||
| FEAT-016 | 稽核完整性驗證 UI | ✅ 已完成 (IntegrityVerificationModal) |
|
||
| A11Y-001 | 表單缺少 Label | ✅ 已修復 (visuallyHidden labels) |
|
||
| A11Y-002 | 非語義化按鈕 | ✅ 已修復 (role, tabIndex, onKeyDown) |
|
||
| A11Y-003 | 圖示按鈕缺少 aria-label | ✅ 已修復 |
|
||
| A11Y-005 | 缺少焦點指示器 | ✅ 已修復 (global focus-visible styles) |
|
||
| A11Y-004 | 顏色對比不足 | ✅ 已修復 (#999 → #767676) |
|
||
| A11Y-006 | Modal 無焦點捕獲 | ✅ 已修復 (Escape key, ARIA attrs) |
|
||
| 機密專案 | 強制加密上傳 | ✅ 已完成 (attachments/router.py) |
|
||
|
||
### 本次修復摘要 (2026-01-07)
|
||
|
||
| Issue ID | 問題 | 狀態 |
|
||
|----------|------|------|
|
||
| LOW-002 | 分頁無最大限制 | ✅ 已修復 (Query validation with max limits) |
|
||
| LOW-003 | 狀態名稱使用魔術字串 | ✅ 已修復 (使用 TaskStatus.is_done flag) |
|
||
| LOW-004 | 觸發器類型驗證不完整 | ✅ 已修復 (新增 "creation" 類型驗證) |
|
||
| LOW-005 | 使用 any 類型 | ✅ 已修復 (使用 unknown + type guard) |
|
||
| LOW-006 | 使用原生 confirm()/alert() | ✅ 已修復 (ConfirmModal 元件 + A11Y 支援) |
|
||
| LOW-007 | 錯誤處理無使用者回饋 | ✅ 已修復 (ToastContext + 整合多頁面) |
|
||
| LOW-009 | 缺少載入骨架 | ✅ 已修復 (Skeleton 元件系列 + 全站 17 處整合) |
|
||
| LOW-010 | 缺少前端測試 | ✅ 已修復 (Vitest + 21 測試) |
|
||
|
||
### 後續待處理
|
||
|
||
| 類別 | 問題 | 備註 |
|
||
|------|------|------|
|
||
| LOW-001 | 缺少完整類型提示 | Backend services 待改善 |
|
||
| LOW-008 | 樣式方法不一致 | 非關鍵,建議後續統一 |
|
||
|
||
### QA 驗證結果
|
||
|
||
**Backend QA (2026-01-04)**:
|
||
- CRIT-001: JWT 驗證 ✅ 正確實現
|
||
- CRIT-002: 登入審計 ✅ 完整記錄成功/失敗
|
||
- HIGH-001: 軟刪除 ✅ 正確使用 is_active 標記
|
||
- HIGH-002: Redis bytes ✅ 正確處理解碼
|
||
- HIGH-003: Rate Limiting ✅ slowapi 實作,5 req/min 限制
|
||
- HIGH-004: 權限檢查 ✅ 所有 endpoints 已驗證
|
||
- MED-006: 專案健康看板 ✅ 32 測試通過,風險評分正確
|
||
- MED-007: 容量更新 API ✅ 14 測試通過,權限和稽核正確
|
||
- MED-008: 排程觸發器 ✅ 35 測試通過,cron 和截止日期提醒正確
|
||
- MED-009: 浮水印功能 ✅ 32 測試通過,圖片和 PDF 浮水印正確
|
||
|
||
**Frontend QA (2026-01-04)**:
|
||
- CRIT-003: API 路徑 ✅ 所有 45+ endpoints 驗證通過
|
||
- HIGH-005: Kanban 視角 ✅ 拖拉功能正常
|
||
- HIGH-007: Comments/Attachments ✅ 整合於 TaskDetailModal
|
||
- HIGH-008: 指派 UI ✅ UserSelect 元件運作正常
|
||
- MED-006: 專案健康看板 ✅ ProjectHealthPage 和 ProjectHealthCard 元件完成
|
||
|
||
### OpenSpec 變更歸檔
|
||
|
||
| 日期 | 變更名稱 | 影響的 Spec |
|
||
|------|----------|-------------|
|
||
| 2025-12-28 | add-user-auth | user-auth |
|
||
| 2025-12-28 | add-task-management | task-management |
|
||
| 2025-12-28 | add-resource-workload | resource-management |
|
||
| 2025-12-29 | add-collaboration | collaboration |
|
||
| 2025-12-29 | add-audit-trail | audit-trail |
|
||
| 2025-12-29 | add-automation | automation |
|
||
| 2025-12-29 | add-document-management | document-management |
|
||
| 2025-12-29 | fix-audit-trail | audit-trail |
|
||
| 2025-12-30 | fix-realtime-notifications | collaboration |
|
||
| 2025-12-30 | fix-weekly-report | automation |
|
||
| 2026-01-04 | add-rate-limiting | user-auth |
|
||
| 2026-01-04 | enhance-frontend-ux | task-management |
|
||
| 2026-01-04 | add-resource-management-ui | resource-management |
|
||
| 2026-01-04 | add-project-health-dashboard | resource-management |
|
||
| 2026-01-04 | add-capacity-update-api | resource-management |
|
||
| 2026-01-04 | add-schedule-triggers | automation |
|
||
| 2026-01-04 | add-watermark-feature | document-management |
|
||
| 2026-01-05 | add-kanban-realtime-sync | collaboration |
|
||
| 2026-01-05 | add-file-encryption | document-management |
|
||
| 2026-01-05 | add-gantt-view | task-management |
|
||
| 2026-01-05 | add-calendar-view | task-management |
|
||
| 2026-01-05 | add-custom-fields | task-management |
|
||
|
||
---
|
||
|
||
## 新發現問題 (New Issues)
|
||
|
||
### NEW-001: 負載快取失效未在任務變更時觸發
|
||
|
||
- **類型**: Bug
|
||
- **模組**: Backend - Resource Management
|
||
- **檔案**: `backend/app/api/tasks/router.py`
|
||
- **問題描述**: `workload_cache.py` 定義了 `invalidate_user_workload_cache()` 函數,但任務指派、時間估算、狀態變更時未調用,導致負載熱圖顯示過期數據。
|
||
- **影響**: 使用者變更任務後,負載熱圖不會即時反映最新分配
|
||
- **建議修復**: 在 `tasks/router.py` 的 `update_task`、`update_task_status`、`assign_task` 等 endpoints 調用 `invalidate_user_workload_cache()`
|
||
- **狀態**: [x] 已修復 (2026-01-04)
|
||
- **修復內容**:
|
||
- 在 `create_task`、`update_task`、`update_task_status`、`delete_task`、`restore_task`、`assign_task` 端點加入 `invalidate_user_workload_cache()` 呼叫
|
||
- 同時清除 `workload:heatmap:*` 快取確保熱圖即時更新
|
||
|
||
---
|
||
|
||
### NEW-002: 看板缺少即時同步功能
|
||
|
||
- **類型**: 功能缺失
|
||
- **模組**: Frontend + Backend - Task Management
|
||
- **檔案**:
|
||
- `backend/app/api/websocket/router.py`
|
||
- `frontend/src/components/KanbanBoard.tsx`
|
||
- **問題描述**: WebSocket 目前僅用於通知推送,看板視角沒有即時同步功能。當其他用戶拖拉任務變更狀態時,當前用戶的看板不會即時更新。
|
||
- **影響**: 多人協作時可能產生狀態衝突
|
||
- **建議修復**: 擴展 WebSocket 支援任務變更事件廣播,前端訂閱並即時更新看板
|
||
- **狀態**: [x] 已修復 (2026-01-05)
|
||
- **修復內容**:
|
||
- Backend: 新增 `/ws/projects/{project_id}` WebSocket endpoint
|
||
- Backend: 實作 Redis Pub/Sub 任務事件廣播 (`project:{project_id}:tasks` 頻道)
|
||
- Backend: 支援 task_created, task_updated, task_status_changed, task_deleted, task_assigned 事件
|
||
- Frontend: 新增 ProjectSyncContext 管理 WebSocket 連線
|
||
- Frontend: Tasks.tsx 整合即時更新,支援 event_id 去重、多分頁支援
|
||
- Frontend: 新增 Live/Offline 連線狀態指示器
|
||
- OpenSpec: 更新 collaboration spec 新增 Project Real-time Sync requirement
|
||
|
||
---
|
||
|
||
*此文件由 Claude Code 自動生成於 2026-01-04*
|
||
*更新於 2026-01-07*
|