feat: implement collaboration module

- Backend (FastAPI):
  - Task comments with nested replies and soft delete
  - @mention parsing with 10-mention limit per comment
  - Notification system with read/unread tracking
  - Blocker management with project owner notification
  - WebSocket endpoint with JWT auth and keepalive
  - User search API for @mention autocomplete
  - Alembic migration for 4 new tables

- Frontend (React + Vite):
  - Comments component with @mention autocomplete
  - NotificationBell with real-time WebSocket updates
  - BlockerDialog for task blocking workflow
  - NotificationContext for state management

- OpenSpec:
  - 4 requirements with scenarios defined
  - add-collaboration change archived

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
beabigegg
2025-12-29 20:45:07 +08:00
parent 61fe01cb6b
commit 3470428411
38 changed files with 3088 additions and 4 deletions

View File

@@ -0,0 +1,125 @@
## Context
協作功能需要整合多個子系統:留言、@提及、阻礙管理、即時通知。這些功能與現有的 Task 模組緊密耦合,且需要引入 WebSocket 即時通訊機制。
## Goals / Non-Goals
**Goals:**
- 提供任務內留言討論功能
- 實作 @提及與即時通知
- 建立阻礙追蹤與主管通知機制
- 使用 Redis Pub/Sub 處理即時推播
**Non-Goals:**
- 不實作 Email 通知(未來功能)
- 不實作離線訊息佇列
- 不實作留言的 Markdown 編輯器(僅純文字)
## Decisions
### 1. 留言儲存結構
- **決策**: 使用巢狀結構parent_comment_id支援回覆
- **理由**: 簡單且符合大多數專案管理工具的 UX 模式
### 2. @提及解析
- **決策**: 後端解析留言內容,提取 `@username` 模式並建立 Mention 記錄
- **理由**: 前端負責顯示建議,後端負責實際通知邏輯
### 3. 即時通知架構
- **決策**: Redis Pub/Sub + WebSocket (FastAPI WebSocket)
- **替代方案**:
- Server-Sent Events (SSE) - 單向,不支援雙向互動
- Polling - 延遲高,資源浪費
- **理由**: WebSocket 提供低延遲雙向通訊Redis 已在架構中使用
### 4. 阻礙管理
- **決策**: 新增獨立 `pjctrl_blockers` 表記錄阻礙詳情
- **理由**: Task 的 `blocker_flag` 只是布林值,需要追蹤原因、處理人、解除說明
## Risks / Trade-offs
| 風險 | 緩解措施 |
|------|----------|
| WebSocket 連線管理複雜度 | 使用連線池,實作心跳機制 |
| 通知量過大導致效能問題 | 實作批次處理、設定通知合併策略 |
| @提及被濫用 | 限制單則留言最多提及 10 人 |
## Data Model
```
pjctrl_comments
├── id: UUID (PK)
├── task_id: UUID (FK -> tasks)
├── parent_comment_id: UUID (FK -> comments, nullable)
├── author_id: UUID (FK -> users)
├── content: TEXT
├── is_edited: BOOLEAN DEFAULT false
├── created_at: TIMESTAMP
└── updated_at: TIMESTAMP
pjctrl_mentions
├── id: UUID (PK)
├── comment_id: UUID (FK -> comments)
├── mentioned_user_id: UUID (FK -> users)
└── created_at: TIMESTAMP
pjctrl_notifications
├── id: UUID (PK)
├── user_id: UUID (FK -> users)
├── type: ENUM('mention', 'assignment', 'blocker', 'status_change', 'comment')
├── reference_type: VARCHAR(50)
├── reference_id: UUID
├── title: VARCHAR(200)
├── message: TEXT
├── is_read: BOOLEAN DEFAULT false
├── created_at: TIMESTAMP
└── read_at: TIMESTAMP
pjctrl_blockers
├── id: UUID (PK)
├── task_id: UUID (FK -> tasks)
├── reported_by: UUID (FK -> users)
├── reason: TEXT
├── resolved_by: UUID (FK -> users, nullable)
├── resolution_note: TEXT
├── created_at: TIMESTAMP
└── resolved_at: TIMESTAMP
```
## API Design
```
# Comments
POST /api/tasks/{task_id}/comments # 新增留言
GET /api/tasks/{task_id}/comments # 取得任務留言列表
PUT /api/comments/{comment_id} # 編輯留言
DELETE /api/comments/{comment_id} # 刪除留言
# Notifications
GET /api/notifications # 取得通知列表
PUT /api/notifications/{id}/read # 標記已讀
PUT /api/notifications/read-all # 全部已讀
GET /api/notifications/unread-count # 取得未讀數量
# Blockers
POST /api/tasks/{task_id}/blockers # 標記阻礙
PUT /api/blockers/{blocker_id}/resolve # 解除阻礙
GET /api/tasks/{task_id}/blockers # 取得阻礙歷史
# WebSocket
WS /ws/notifications # 即時通知連線
# User Search (for @mention autocomplete)
GET /api/users/search?q={query} # 搜尋使用者
```
## Migration Plan
1. 新增資料表(無 breaking changes
2. Task model 新增 comments relationship
3. User model 新增 notifications relationship
4. 前端漸進式整合
## Open Questions
無(已與現有架構對齊)

View File

@@ -0,0 +1,18 @@
# Change: Add Collaboration Features
## Why
專案管理系統需要協作功能,讓團隊成員能在任務內進行討論、標記相關人員,並處理任務阻礙。目前系統缺乏這些核心協作機制,導致使用者仍需依賴 Email 或其他工具進行溝通。
## What Changes
- 新增任務留言系統(支援巢狀回覆)
- 實作 @提及功能(自動完成 + 即時通知)
- 建立阻礙管理機制(標記原因、主管通知、解除追蹤)
- 實作即時通知系統Redis Pub/Sub + WebSocket
## Impact
- Affected specs: `collaboration`
- Affected code:
- 新增 models: Comment, Mention, Notification, Blocker
- 新增 API routes: `/comments`, `/notifications`
- 新增 services: NotificationService, WebSocketManager
- 前端: 任務詳情頁新增留言區、通知中心

View File

@@ -0,0 +1,97 @@
## ADDED Requirements
### Requirement: Task Comments
系統 SHALL 支援任務內部的討論留言,減少 Email 往返。
#### Scenario: 新增留言
- **GIVEN** 使用者擁有任務的存取權限
- **WHEN** 使用者在任務中新增留言
- **THEN** 系統儲存留言並顯示在討論區
- **AND** 記錄留言者與時間戳記
#### Scenario: 回覆留言
- **GIVEN** 任務已有留言
- **WHEN** 使用者回覆特定留言
- **THEN** 系統建立巢狀回覆結構
- **AND** 通知原留言者
#### Scenario: 編輯留言
- **GIVEN** 使用者是留言的作者
- **WHEN** 使用者編輯自己的留言
- **THEN** 系統更新留言內容
- **AND** 標示「已編輯」及編輯時間
#### Scenario: 刪除留言
- **GIVEN** 使用者是留言的作者
- **WHEN** 使用者刪除自己的留言
- **THEN** 系統移除留言
- **AND** 若有回覆則顯示「此留言已刪除」
### Requirement: User Mentions
系統 SHALL 支援 @相關人員 功能,提及時發送即時通知。
#### Scenario: @提及通知
- **GIVEN** 使用者在留言中使用 @username 提及某人
- **WHEN** 留言送出
- **THEN** 被提及者收到即時通知
- **AND** 通知包含任務連結與留言摘要
#### Scenario: @提及自動完成
- **GIVEN** 使用者輸入 @ 符號
- **WHEN** 使用者繼續輸入
- **THEN** 系統顯示符合的使用者名單供選擇
- **AND** 可用鍵盤或滑鼠選擇
#### Scenario: @提及數量限制
- **GIVEN** 使用者在單則留言中提及超過 10 人
- **WHEN** 留言送出
- **THEN** 系統拒絕並顯示錯誤訊息
### Requirement: Blocker Management
系統 SHALL 提供阻礙 (Blocker) 機制,強制要求主管介入排解。
#### Scenario: 標記阻礙
- **GIVEN** 工程師的任務遇到阻礙無法進行
- **WHEN** 工程師將任務標記為 "Blocked"
- **THEN** 系統設定 Task.blocker_flag = true
- **AND** 建立 Blocker 記錄
- **AND** 發送即時通知給該任務所屬專案的 Owner
#### Scenario: 阻礙原因說明
- **GIVEN** 任務被標記為 Blocked
- **WHEN** 使用者標記阻礙
- **THEN** 系統要求填寫阻礙原因
- **AND** 原因顯示在任務詳情與通知中
#### Scenario: 解除阻礙
- **GIVEN** 主管或被指派者處理完阻礙
- **WHEN** 使用者解除 Blocked 狀態
- **THEN** 系統設定 Task.blocker_flag = false
- **AND** 記錄解除時間與處理說明
### Requirement: Real-time Notifications
系統 SHALL 透過 Redis Pub/Sub 與 WebSocket 推播即時通知。
#### Scenario: 即時通知推播
- **GIVEN** 發生需要通知的事件(被指派任務、被 @提及、阻礙標記)
- **WHEN** 事件發生
- **THEN** 系統透過 WebSocket 即時推播通知給相關使用者
- **AND** 未讀通知顯示數量標示
#### Scenario: 通知已讀標記
- **GIVEN** 使用者有未讀通知
- **WHEN** 使用者查看通知
- **THEN** 系統標記為已讀
- **AND** 更新未讀數量
#### Scenario: 通知清單查詢
- **GIVEN** 使用者需要查看歷史通知
- **WHEN** 使用者開啟通知中心
- **THEN** 系統顯示通知列表(依時間降序)
- **AND** 支援分頁與已讀/未讀篩選
#### Scenario: WebSocket 重連
- **GIVEN** 使用者的 WebSocket 連線中斷
- **WHEN** 連線恢復
- **THEN** 系統自動重新建立連線
- **AND** 補送中斷期間的未讀通知

View File

@@ -0,0 +1,76 @@
## 1. Database Schema
- [x] 1.1 建立 Comment model (`pjctrl_comments`)
- [x] 1.2 建立 Mention model (`pjctrl_mentions`)
- [x] 1.3 建立 Notification model (`pjctrl_notifications`)
- [x] 1.4 建立 Blocker model (`pjctrl_blockers`)
- [x] 1.5 建立 Alembic migration
- [x] 1.6 更新 Task model 加入 comments relationship
- [x] 1.7 更新 User model 加入 notifications relationship
## 2. Backend API - Comments
- [x] 2.1 建立 Comment schemas (request/response)
- [x] 2.2 實作 POST `/api/tasks/{task_id}/comments` - 新增留言
- [x] 2.3 實作 GET `/api/tasks/{task_id}/comments` - 取得留言列表
- [x] 2.4 實作 PUT `/api/comments/{comment_id}` - 編輯留言
- [x] 2.5 實作 DELETE `/api/comments/{comment_id}` - 刪除留言
- [x] 2.6 實作 @mention 解析邏輯(從留言內容提取 @username
## 3. Backend API - Notifications
- [x] 3.1 建立 Notification schemas
- [x] 3.2 實作 NotificationService建立、發送通知
- [x] 3.3 實作 GET `/api/notifications` - 取得通知列表
- [x] 3.4 實作 PUT `/api/notifications/{id}/read` - 標記已讀
- [x] 3.5 實作 PUT `/api/notifications/read-all` - 全部已讀
- [x] 3.6 實作 GET `/api/notifications/unread-count` - 未讀數量
## 4. Backend API - Blockers
- [x] 4.1 建立 Blocker schemas
- [x] 4.2 實作 POST `/api/tasks/{task_id}/blockers` - 標記阻礙
- [x] 4.3 實作 PUT `/api/blockers/{blocker_id}/resolve` - 解除阻礙
- [x] 4.4 實作 GET `/api/tasks/{task_id}/blockers` - 取得阻礙歷史
- [x] 4.5 整合阻礙通知(通知專案 Owner
## 5. WebSocket Integration
- [x] 5.1 建立 WebSocket connection manager
- [x] 5.2 實作 `/ws/notifications` endpoint
- [x] 5.3 整合 Redis Pub/Sub 發布通知
- [x] 5.4 實作 WebSocket 認證JWT token
- [x] 5.5 實作心跳機制keepalive
## 6. Backend API - User Search
- [x] 6.1 實作 GET `/api/users/search?q={query}` - 使用者搜尋(支援 @mention 自動完成)
## 7. Frontend - Comments
- [x] 7.1 建立 CommentList 元件
- [x] 7.2 建立 CommentItem 元件(支援巢狀回覆)
- [x] 7.3 建立 CommentForm 元件(含 @mention 自動完成)
- [x] 7.4 整合至 Task 詳情頁
## 8. Frontend - Notifications
- [x] 8.1 建立 NotificationContext狀態管理
- [x] 8.2 建立 NotificationBell 元件(未讀數量 badge
- [x] 8.3 建立 NotificationList 元件
- [x] 8.4 建立 NotificationItem 元件
- [x] 8.5 整合 WebSocket 連線
## 9. Frontend - Blockers
- [x] 9.1 建立 BlockerDialog 元件(標記阻礙表單)
- [x] 9.2 建立 BlockerHistory 元件
- [x] 9.3 整合至 Task 詳情頁
## 10. Testing
- [x] 10.1 Comment API 單元測試
- [x] 10.2 Notification API 單元測試
- [x] 10.3 Blocker API 單元測試
- [x] 10.4 WebSocket 連線測試
- [x] 10.5 @mention 解析測試