實作管理者儀表板、刪除不必要說明文件

This commit is contained in:
2025-09-09 15:28:22 +08:00
parent 3369e3fc0f
commit 22bbe64349
16 changed files with 27 additions and 2473 deletions

View File

@@ -1,187 +0,0 @@
# 管理員存取被拒問題修復總結
## 🎯 問題描述
管理員使用正確的帳號密碼登入後,訪問管理員後台時仍然顯示「存取被拒」錯誤。
## 🔍 問題分析
### 根本原因:
1. **服務器端渲染問題**Next.js 在服務器端渲染時,`localStorage` 不可用
2. **客戶端 hydration 時機**:用戶狀態需要等待客戶端載入 `localStorage` 資料
3. **權限檢查邏輯**:在用戶狀態未載入時就進行權限檢查
### 問題流程:
1. 用戶訪問 `/admin` 頁面
2. 服務器端渲染時,`localStorage` 不可用,`user``null`
3. 權限檢查 `!user || user.role !== "admin"` 返回 `true`
4. 顯示「存取被拒」頁面
5. 客戶端 hydration 後,用戶狀態載入,但頁面已經渲染
## ✅ 修復方案
### 1. 添加初始化狀態管理
**文件:** `contexts/auth-context.tsx`
```typescript
// 添加初始化狀態
const [isInitialized, setIsInitialized] = useState(false)
useEffect(() => {
// Check for stored user session only on client side
if (typeof window !== 'undefined') {
const storedUser = localStorage.getItem("user")
if (storedUser) {
setUser(JSON.parse(storedUser))
}
}
setIsLoading(false)
setIsInitialized(true) // 標記為已初始化
}, [])
```
### 2. 改進權限檢查邏輯
**文件:** `components/admin/admin-layout.tsx`
```typescript
// 如果還在載入中或未初始化,顯示載入畫面
if (!isClient || isLoading || !isInitialized) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-100">
<div className="text-center space-y-4">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto"></div>
<p className="text-gray-600">載入中...</p>
</div>
</div>
)
}
// 檢查用戶權限
if (!user || user.role !== "admin") {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-100">
<div className="text-center space-y-4">
<div className="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center mx-auto">
<AlertTriangle className="w-8 h-8 text-red-600" />
</div>
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-2">存取被拒</h2>
<p className="text-gray-600 mb-4">您沒有管理員權限訪問此頁面</p>
{process.env.NODE_ENV === 'development' && (
<div className="text-xs text-gray-500 mb-4">
調試信息: 用戶={user ? '已登入' : '未登入'}, 角色={user?.role || '無'}
</div>
)}
{/* ... 其他內容 ... */}
</div>
</div>
)
}
```
### 3. 添加調試信息
在開發環境中添加調試信息,幫助診斷問題:
```typescript
{process.env.NODE_ENV === 'development' && (
<div className="text-xs text-gray-500 mb-4">
調試信息: 用戶={user ? '已登入' : '未登入'}, 角色={user?.role || '無'}
</div>
)}
```
## 🧪 測試結果
### 測試腳本:`scripts/test-complete-admin-flow.js`
```
✅ 登入頁面載入成功
✅ 管理員登入成功
用戶資料: {
id: 'c8b26413-00b9-4337-870d-4e37e3e8e375',
name: '系統管理員',
email: 'admin@ai-platform.com',
role: 'admin'
}
✅ 頁面顯示載入中狀態(正常)
```
### 修復驗證:
- ✅ 管理員登入 API 正常工作
- ✅ 用戶角色正確設置為 `admin`
- ✅ 頁面顯示載入中狀態(等待客戶端 hydration
- ✅ 添加了調試信息幫助診斷
## 📋 修復內容總結
### ✅ 已修復的問題:
1. **AuthContext 組件**
- 添加 `isInitialized` 狀態管理
- 改進客戶端狀態載入邏輯
- 確保服務器端和客戶端渲染一致
2. **AdminLayout 組件**
- 添加載入狀態檢查
- 改進權限檢查邏輯
- 添加調試信息顯示
3. **權限檢查流程**
- 等待客戶端初始化完成
- 確保用戶狀態正確載入
- 提供清晰的錯誤信息
### 🔧 技術改進:
1. **狀態管理**:使用 `isInitialized` 狀態確保客戶端載入完成
2. **載入狀態**:顯示載入中畫面而不是錯誤頁面
3. **調試支持**:在開發環境中提供調試信息
4. **用戶體驗**:提供清晰的載入和錯誤狀態
## 🎉 修復效果
### 修復前:
- 管理員登入後仍顯示「存取被拒」
- 服務器端和客戶端渲染不一致
- 無法診斷問題原因
### 修復後:
- 頁面正確顯示載入中狀態
- 等待客戶端載入用戶資料
- 提供調試信息幫助診斷
- 權限檢查邏輯更加健壯
## 🚀 使用方式
### 1. 測試修復效果
```bash
# 測試完整管理員流程
node scripts/test-complete-admin-flow.js
# 測試管理員存取修復
node scripts/test-admin-fix.js
```
### 2. 驗證修復
1. 打開瀏覽器訪問 `http://localhost:3000`
2. 使用管理員帳號登入:
- 電子郵件:`admin@ai-platform.com`
- 密碼:`admin123456`
3. 登入後訪問 `http://localhost:3000/admin`
4. 確認頁面正常載入管理員後台
## 📝 注意事項
1. **登入流程**:用戶需要先登入才能訪問管理員頁面
2. **載入時間**:首次訪問可能需要等待客戶端載入
3. **調試信息**:開發環境中會顯示調試信息
4. **權限檢查**:確保用戶角色為 `admin`
## 🔍 預防措施
1. **狀態管理**:使用適當的狀態管理確保客戶端載入完成
2. **權限檢查**:在用戶狀態載入後再進行權限檢查
3. **載入狀態**:提供清晰的載入和錯誤狀態
4. **調試支持**:在開發環境中提供調試信息
管理員存取被拒問題已修復,現在管理員可以正常訪問後台!

View File

@@ -1,143 +0,0 @@
# 用戶認證系統整合總結
## 🎯 完成的工作
### 1. 資料庫 API 端點 ✅
- **`/api/auth/login`** - 用戶登入
- **`/api/auth/register`** - 用戶註冊
- **`/api/auth/profile`** - 用戶資料管理
### 2. 資料庫服務層 ✅
- 更新 `UserService` 類別,支援實例方法和靜態方法
- 密碼加密使用 `bcryptjs` (12 rounds)
- 完整的 CRUD 操作
### 3. 前端整合 ✅
- 更新 `AuthContext` 以使用資料庫 API
- 保持向後兼容性,支援現有功能
- 錯誤處理和載入狀態管理
### 4. 測試帳號生成 ✅
創建了 5 個測試帳號:
| 角色 | 電子郵件 | 密碼 | 部門 | 描述 |
|------|----------|------|------|------|
| **管理員** | admin@ai-platform.com | admin123456 | ITBU | 系統管理員,擁有所有權限 |
| **開發者** | developer@ai-platform.com | dev123456 | ITBU | 開發者,可以提交應用和提案 |
| **一般用戶** | user@ai-platform.com | user123456 | MBU1 | 一般用戶,可以瀏覽和評分 |
| **評委** | judge@ai-platform.com | judge123456 | HQBU | 評委,可以評分應用和提案 |
| **團隊負責人** | team-lead@ai-platform.com | team123456 | SBU | 團隊負責人 |
## 🔧 技術實現
### 密碼安全
- 使用 `bcryptjs` 進行密碼加密
- 12 rounds 的 salt 強度
- 密碼長度最少 6 個字符
### 資料庫結構
```sql
CREATE TABLE `users` (
`id` VARCHAR(36) PRIMARY KEY,
`name` VARCHAR(100) NOT NULL,
`email` VARCHAR(255) UNIQUE NOT NULL,
`password_hash` VARCHAR(255) NOT NULL,
`avatar` VARCHAR(500) NULL,
`department` VARCHAR(100) NOT NULL,
`role` ENUM('user', 'developer', 'admin') DEFAULT 'user',
`join_date` DATE NOT NULL,
`total_likes` INT DEFAULT 0,
`total_views` INT DEFAULT 0,
`is_active` BOOLEAN DEFAULT TRUE,
`last_login` TIMESTAMP NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
```
### API 端點詳情
#### POST /api/auth/login
```json
{
"email": "user@example.com",
"password": "password123"
}
```
**回應:**
```json
{
"success": true,
"user": {
"id": "uuid",
"name": "用戶名稱",
"email": "user@example.com",
"role": "user",
"department": "ITBU",
// ... 其他用戶資訊(不包含密碼)
}
}
```
#### POST /api/auth/register
```json
{
"name": "用戶名稱",
"email": "user@example.com",
"password": "password123",
"department": "ITBU",
"role": "user" // 可選,預設為 "user"
}
```
#### PUT /api/auth/profile
```json
{
"userId": "user-uuid",
"name": "新名稱",
"department": "新部門"
// ... 其他可更新欄位
}
```
## 🚀 使用方法
### 1. 啟動開發服務器
```bash
pnpm run dev
```
### 2. 創建測試用戶(可選)
```bash
pnpm run create:users
```
### 3. 測試資料庫連接
```bash
pnpm run test:db
```
### 4. 測試認證功能
```bash
node scripts/test-db-auth.js
```
## 🔐 安全特性
1. **密碼加密**:使用 bcryptjs 進行安全的密碼雜湊
2. **SQL 注入防護**:使用參數化查詢
3. **重複註冊防護**:檢查電子郵件唯一性
4. **輸入驗證**API 端點包含完整的輸入驗證
5. **錯誤處理**:統一的錯誤回應格式
## 📝 注意事項
1. **環境變數**:確保 `.env.local` 包含正確的資料庫連接資訊
2. **密碼強度**:建議使用更強的密碼策略
3. **會話管理**:目前使用 localStorage生產環境建議使用 JWT 或 session
4. **權限控制**:角色權限檢查在前端實現,後端需要額外的中間件
## 🎉 整合完成
用戶認證系統已成功從 `localStorage` 遷移到 MySQL 資料庫所有測試帳號已創建API 端點正常運作。您現在可以使用任何測試帳號登入系統進行測試!

View File

@@ -1,296 +0,0 @@
# AI智能助手 (ChatBot) 組件分析
## 1. 組件概述
### 1.1 功能定位
AI智能助手是一個內嵌的聊天機器人組件為用戶提供即時的系統使用指導和問題解答服務。
### 1.2 核心特性
- **即時對話**: 與AI助手進行自然語言對話
- **智能回答**: 基於DeepSeek API的智能回應
- **快速問題**: 提供相關問題的快速選擇
- **上下文記憶**: 保持對話的連續性
## 2. 技術實現
### 2.1 技術棧
```typescript
// 核心技術
- React 19 (Hooks)
- TypeScript 5
- DeepSeek Chat API
- Tailwind CSS
- shadcn/ui 組件庫
```
### 2.2 組件結構
```typescript
// 主要接口定義
interface Message {
id: string
text: string
sender: "user" | "bot"
timestamp: Date
quickQuestions?: string[]
}
// 組件狀態
const [isOpen, setIsOpen] = useState(false) // 對話框開關
const [messages, setMessages] = useState<Message[]>() // 訊息列表
const [inputValue, setInputValue] = useState("") // 輸入值
const [isTyping, setIsTyping] = useState(false) // 打字狀態
const [isLoading, setIsLoading] = useState(false) // 載入狀態
```
### 2.3 API整合
```typescript
// DeepSeek API 配置
const DEEPSEEK_API_KEY = "sk-3640dcff23fe4a069a64f536ac538d75"
const DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat/completions"
// API 調用函數
const callDeepSeekAPI = async (userMessage: string): Promise<string> => {
// 實現細節...
}
```
## 3. 功能詳解
### 3.1 對話能力
#### 3.1.1 前台功能指導
- **註冊流程**: 如何註冊參賽團隊
- **作品提交**: 如何提交和管理作品
- **投票系統**: 如何參與投票和收藏
- **個人中心**: 如何管理個人資料
#### 3.1.2 後台管理協助
- **競賽創建**: 如何創建和管理競賽
- **評審管理**: 如何管理評審團成員
- **評分系統**: 如何設定評分標準
- **獎項設定**: 如何配置獎項類型
#### 3.1.3 系統使用指南
- **操作步驟**: 提供具體的操作指引
- **常見問題**: 解答用戶常見疑問
- **最佳實踐**: 推薦最佳使用方法
### 3.2 智能特性
#### 3.2.1 內容清理
```typescript
const cleanResponse = (text: string): string => {
return text
// 移除 Markdown 格式
.replace(/\*\*(.*?)\*\*/g, '$1')
.replace(/\*(.*?)\*/g, '$1')
.replace(/`(.*?)`/g, '$1')
.replace(/#{1,6}\s/g, '')
.replace(/^- /g, '• ')
.replace(/^\d+\.\s/g, '')
// 移除多餘空行
.replace(/\n\s*\n\s*\n/g, '\n\n')
// 限制文字長度
.slice(0, 300)
.trim()
}
```
#### 3.2.2 快速問題生成
```typescript
const generateQuickQuestions = (userQuestion: string): string[] => {
const question = userQuestion.toLowerCase()
// 根據問題類型生成相關建議
if (question.includes('註冊') || question.includes('團隊')) {
return [
"如何提交作品?",
"怎麼查看競賽詳情?",
"如何收藏作品?",
"怎麼進行投票?"
]
}
// 更多邏輯...
}
```
### 3.3 用戶體驗
#### 3.3.1 界面設計
- **浮動按鈕**: 固定在右下角的聊天入口
- **模態對話框**: 全屏遮罩的聊天界面
- **響應式設計**: 適配不同螢幕尺寸
- **無障礙設計**: 支持鍵盤導航
#### 3.3.2 交互體驗
- **即時反饋**: 輸入狀態和載入動畫
- **自動滾動**: 新訊息自動滾動到底部
- **快捷操作**: Enter鍵發送訊息
- **錯誤處理**: 網路錯誤的優雅處理
## 4. 系統提示詞 (System Prompt)
### 4.1 提示詞結構
```typescript
const systemPrompt = `你是一個競賽管理系統的AI助手專門幫助用戶了解如何使用這個系統。
系統功能包括:
後台管理功能:
1. 競賽管理 - 創建、編輯、刪除競賽
2. 評審管理 - 管理評審團成員
3. 評分系統 - 手動輸入評分或讓評審自行評分
4. 團隊管理 - 管理參賽團隊
5. 獎項管理 - 設定各種獎項
6. 評審連結 - 提供評審登入連結
前台功能:
1. 競賽瀏覽 - 查看所有競賽資訊和詳細內容
2. 團隊註冊 - 如何註冊參賽團隊和提交作品
3. 作品展示 - 瀏覽參賽作品和投票功能
4. 排行榜 - 查看人氣排行榜和得獎名單
5. 個人中心 - 管理個人資料和參賽記錄
6. 收藏功能 - 如何收藏喜歡的作品
7. 評論系統 - 如何對作品進行評論和互動
8. 搜尋功能 - 如何搜尋特定競賽或作品
9. 通知系統 - 查看競賽更新和個人通知
10. 幫助中心 - 常見問題和使用指南
請用友善、專業的語氣回答用戶問題,並提供具體的操作步驟。回答要簡潔明瞭,避免過長的文字。
重要請不要使用任何Markdown格式只使用純文字回答。不要使用**、*、#、-等符號。
回答時請使用繁體中文。`
```
### 4.2 回答規範
- **語言**: 繁體中文
- **格式**: 純文字無Markdown
- **長度**: 限制在300字以內
- **語氣**: 友善、專業
- **內容**: 具體操作步驟
## 5. 錯誤處理
### 5.1 API錯誤處理
```typescript
try {
const response = await fetch(DEEPSEEK_API_URL, {
// API 調用配置...
})
if (!response.ok) {
throw new Error(`API request failed: ${response.status}`)
}
const data = await response.json()
return cleanResponse(data.choices[0]?.message?.content || "抱歉,我現在無法回答您的問題,請稍後再試。")
} catch (error) {
console.error("DeepSeek API error:", error)
return "抱歉我現在無法連接到AI服務請檢查網路連接或稍後再試。"
}
```
### 5.2 用戶體驗錯誤處理
- **網路錯誤**: 提示檢查網路連接
- **API限制**: 提示稍後再試
- **輸入驗證**: 防止空訊息發送
- **載入狀態**: 防止重複發送
## 6. 性能優化
### 6.1 API優化
```typescript
// 限制token數量以獲得更簡潔的回答
max_tokens: 200,
temperature: 0.7
```
### 6.2 組件優化
- **訊息虛擬化**: 大量訊息時的效能優化
- **防抖處理**: 避免頻繁API調用
- **記憶化**: 重複問題的快取處理
- **懶加載**: 按需載入組件
## 7. 安全考量
### 7.1 API密鑰安全
- **環境變數**: API密鑰存儲在環境變數中
- **加密存儲**: 敏感資訊加密處理
- **訪問控制**: 限制API調用頻率
### 7.2 數據隱私
- **聊天記錄**: 本地存儲,不上傳服務器
- **個人資訊**: 不收集敏感個人資訊
- **數據清理**: 定期清理過期數據
## 8. 擴展性設計
### 8.1 多語言支持
```typescript
interface LocalizationConfig {
language: string
systemPrompt: Record<string, string>
quickQuestions: Record<string, string[]>
errorMessages: Record<string, string>
}
```
### 8.2 多AI模型支持
```typescript
interface AIModelConfig {
provider: 'deepseek' | 'openai' | 'anthropic'
model: string
apiKey: string
apiUrl: string
maxTokens: number
temperature: number
}
```
### 8.3 自定義功能
- **知識庫整合**: 連接企業知識庫
- **FAQ系統**: 自動回答常見問題
- **工單系統**: 複雜問題轉人工處理
- **分析報告**: 聊天數據分析
## 9. 使用指南
### 9.1 基本使用
1. 點擊右下角的聊天按鈕
2. 在輸入框中輸入問題
3. 按Enter鍵或點擊發送按鈕
4. 查看AI助手的回答
5. 點擊快速問題進行後續對話
### 9.2 進階功能
- **上下文記憶**: 對話會保持上下文
- **快速問題**: 點擊建議問題快速提問
- **錯誤重試**: 網路錯誤時可重新發送
- **對話重置**: 關閉重開可開始新對話
### 9.3 最佳實踐
- **具體問題**: 提出具體明確的問題
- **分步驟**: 複雜操作分步驟詢問
- **耐心等待**: AI需要時間處理複雜問題
- **反饋提供**: 對回答不滿意時可重新提問
## 10. 未來規劃
### 10.1 短期目標
- [ ] 添加語音輸入功能
- [ ] 支持圖片上傳和識別
- [ ] 增加更多快速問題模板
- [ ] 優化回答品質和速度
### 10.2 長期目標
- [ ] 整合企業知識庫
- [ ] 支持多語言對話
- [ ] 添加情感分析功能
- [ ] 實現智能推薦系統
---
**文檔版本**: v1.0
**最後更新**: 2024年12月
**負責人**: 前端開發團隊

View File

@@ -1,141 +0,0 @@
# 忘記密碼功能實現總結
## 🎯 功能概述
已成功實現完整的忘記密碼功能,包括前端界面、後端 API、資料庫支援和郵件發送。
## ✅ 實現的功能
### 1. 資料庫支援
- **密碼重設 tokens 表**:存儲重設 token 和過期時間
- **外鍵關聯**:與 users 表關聯,支援級聯刪除
- **索引優化**:針對查詢性能優化
### 2. 後端 API
- **`/api/auth/forgot-password`**:發送重設郵件
- **`/api/auth/reset-password`**:驗證 token 並重設密碼
### 3. 前端界面
- **忘記密碼對話框**:整合到登入流程
- **密碼重設頁面**`/reset-password` 專用頁面
- **完整的表單驗證**:密碼強度和確認驗證
### 4. 郵件服務
- **HTML 郵件模板**:美觀的重設郵件
- **SMTP 配置**:支援多種郵件服務商
- **安全 token**UUID + 時間戳生成
## 🔧 技術實現
### 資料庫結構
```sql
CREATE TABLE password_reset_tokens (
id VARCHAR(36) PRIMARY KEY,
user_id VARCHAR(36) NOT NULL,
token VARCHAR(255) NOT NULL UNIQUE,
expires_at TIMESTAMP NOT NULL,
used_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
```
### API 端點
#### POST /api/auth/forgot-password
```json
{
"email": "user@example.com"
}
```
**回應:**
```json
{
"success": true,
"message": "密碼重設連結已發送到您的電子郵件"
}
```
#### POST /api/auth/reset-password
```json
{
"token": "reset-token",
"password": "newpassword123"
}
```
#### GET /api/auth/reset-password?token=xxx
驗證 token 是否有效
### 郵件配置
需要在 `.env.local` 中設定:
```env
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your_email@gmail.com
SMTP_PASS=your_app_password
```
## 🚀 使用流程
### 1. 用戶請求重設密碼
1. 點擊登入頁面的「忘記密碼?」
2. 輸入電子郵件地址
3. 系統發送重設郵件
### 2. 用戶重設密碼
1. 點擊郵件中的重設連結
2. 輸入新密碼和確認密碼
3. 提交後自動跳轉到首頁
### 3. 安全特性
- **Token 過期**1 小時後自動過期
- **一次性使用**Token 使用後立即失效
- **密碼加密**:使用 bcrypt 加密存儲
- **重複保護**:撤銷用戶現有的重設 tokens
## 📧 郵件模板
郵件包含:
- 美觀的 HTML 設計
- 重設按鈕和備用連結
- 安全提醒和過期時間
- 品牌一致性設計
## 🧪 測試結果
- ✅ 資料庫表創建成功
- ✅ API 端點正常運作
- ✅ 前端界面整合完成
- ✅ 郵件發送功能正常
- ✅ 密碼重設流程完整
## 📝 環境變數設定
確保在 `.env.local` 中設定以下變數:
```env
# 郵件配置
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your_email@gmail.com
SMTP_PASS=your_app_password
# 應用配置
NEXT_PUBLIC_APP_NAME=強茂集團 AI 展示平台
NEXT_PUBLIC_APP_URL=http://localhost:3000
```
## 🎉 功能完成
忘記密碼功能已完全實現並測試通過!用戶現在可以:
1. **安全地請求密碼重設**:通過電子郵件驗證身份
2. **收到美觀的重設郵件**:包含清晰的重設指引
3. **方便地重設密碼**:通過專用頁面完成重設
4. **享受安全的體驗**Token 過期和一次性使用保護
所有功能都已整合到現有的認證系統中,與登入和註冊流程無縫配合。

View File

@@ -1,135 +0,0 @@
# 新版忘記密碼流程實現總結
## 🎯 需求背景
根據您的需求,公司內部可能會阻擋郵件,因此將忘記密碼流程改為生成一次性註冊連結,避免依賴郵件發送。
## ✅ 新流程實現
### 1. 流程改進
- **舊流程**:忘記密碼 → 發送郵件 → 點擊郵件連結 → 重設密碼
- **新流程**:忘記密碼 → 生成連結 → 複製連結 → 在新視窗重設密碼
### 2. 技術實現
#### 後端 API 修改
**`/api/auth/forgot-password`** 現在返回:
```json
{
"success": true,
"message": "已生成密碼重設連結",
"resetUrl": "http://localhost:3000/register?token=xxx&email=xxx&mode=reset&name=xxx&department=xxx",
"expiresAt": "2025-09-09T03:07:00.065Z"
}
```
#### 前端對話框更新
忘記密碼對話框現在顯示:
- ✅ 生成的重設連結
- 📋 連結複製功能
- 🔗 在新視窗開啟按鈕
- ⏰ 過期時間提醒
#### 註冊頁面增強
支援密碼重設模式:
- **檢測 `mode=reset` 參數**:自動切換為重設模式
- **預填用戶資料**:從 URL 參數自動填入姓名、郵件、部門
- **簡化表單**:重設模式下隱藏不必要的字段
- **修改提交邏輯**:調用密碼重設 API 而非註冊 API
## 🔧 URL 參數結構
重設連結包含以下參數:
```
/register?token=xxx&email=xxx&mode=reset&name=xxx&department=xxx
```
| 參數 | 說明 | 範例 |
|------|------|------|
| `token` | 重設 token | `301d42b4-fbcc-41ce-bc73-45987482c5a0-1757383620065` |
| `email` | 用戶電子郵件 | `admin@ai-platform.com` |
| `mode` | 模式標識 | `reset` |
| `name` | 用戶姓名 | `系統管理員` |
| `department` | 用戶部門 | `ITBU` |
## 🎨 用戶體驗
### 1. 忘記密碼對話框
- 🎯 **清晰的標題**:「密碼重設連結已生成」
- 📋 **連結顯示**:只讀輸入框顯示完整連結
- 📄 **一鍵複製**:點擊按鈕複製到剪貼板
- 🆕 **新視窗開啟**:避免影響當前頁面
-**過期提醒**:顯示連結過期時間
### 2. 重設頁面
- 🔄 **自動識別**:檢測到重設模式自動調整界面
- 📝 **預填資料**:用戶資料自動填入,無需重複輸入
- 🎯 **簡化表單**:只顯示必要的密碼設定字段
-**清晰提示**:明確的「重設密碼」按鈕和提示
## 🔒 安全特性
1. **Token 安全**
- UUID + 時間戳生成,難以預測
- 1 小時過期時間
- 一次性使用,用後即廢
2. **用戶驗證**
- 檢查用戶是否存在
- Token 與用戶 ID 綁定
- 撤銷現有 tokens 防止重複
3. **資料保護**
- URL 參數編碼處理
- 密碼加密存儲
- 無敏感資訊洩露
## 🧪 測試結果
```
✅ 忘記密碼 API 測試成功
✅ 密碼重設 API 測試成功
✅ URL 參數解析正確
✅ 前端界面整合完成
✅ 用戶體驗流暢
```
## 📝 使用方式
### 1. 用戶操作流程
1. 點擊「忘記密碼?」
2. 輸入電子郵件地址
3. 點擊「生成重設連結」
4. 複製生成的連結
5. 在新視窗中開啟連結
6. 設定新密碼
7. 完成重設
### 2. 管理員測試
```bash
# 測試新流程
pnpm run test:forgot-password-new
```
## 🎉 優勢總結
### ✅ 解決的問題
- **避免郵件阻擋**:不依賴郵件系統
- **提高成功率**直接生成連結100% 可達
- **用戶友好**:一鍵複製,操作簡單
- **安全可靠**:保持原有安全機制
### 📈 改進效果
- **降低支援成本**:減少「沒收到郵件」的問題
- **提升用戶體驗**:即時生成,無需等待
- **增強可靠性**:不受郵件服務影響
- **保持安全性**:所有安全特性完整保留
## 🚀 部署建議
1. **環境變數**:確保 `NEXT_PUBLIC_APP_URL` 設定正確
2. **用戶教育**:可以添加使用說明或工具提示
3. **監控統計**:追蹤重設連結的使用情況
4. **備份方案**:保留郵件功能作為備選(可配置開關)
新的忘記密碼流程已完全實現並測試通過,完美解決了公司內部郵件阻擋的問題!

View File

@@ -1,203 +0,0 @@
# Next.js Hydration 錯誤修復總結
## 🎯 問題描述
出現 Next.js Hydration 錯誤:
```
Hydration failed because the server rendered HTML didn't match the client.
```
錯誤原因:服務器端渲染和客戶端渲染不匹配,通常由以下原因造成:
- 使用 `typeof window !== 'undefined'` 條件渲染
- 使用 `Date.now()``Math.random()` 等動態值
- 外部數據變化沒有快照
## 🔍 問題分析
### 根本原因:
1. **條件渲染不一致**`typeof window !== 'undefined'` 在服務器端為 `false`,客戶端為 `true`
2. **動態內容差異**:服務器端和客戶端渲染的內容不同
3. **Browser API 使用**:直接使用 `window` 對象導致渲染差異
### 問題位置:
- `components/admin/admin-layout.tsx` - 多處使用 `typeof window !== 'undefined'`
- `components/admin/user-management.tsx` - 邀請連結生成中的 window 使用
## ✅ 修復方案
### 1. 添加客戶端狀態管理
**修復前:**
```typescript
// 直接使用 typeof window 檢查
if (typeof window !== 'undefined') {
// 客戶端邏輯
}
```
**修復後:**
```typescript
// 添加客戶端狀態
const [isClient, setIsClient] = useState(false)
// 在 useEffect 中設置客戶端狀態
useEffect(() => {
setIsClient(true)
}, [])
// 使用客戶端狀態檢查
if (isClient) {
// 客戶端邏輯
}
```
### 2. 修復 AdminLayout 組件
**文件:** `components/admin/admin-layout.tsx`
```typescript
// 添加客戶端狀態
const [isClient, setIsClient] = useState(false)
useEffect(() => {
setIsClient(true)
}, [])
// 修復 logout 函數
const handleLogout = () => {
logout()
setShowLogoutDialog(false)
if (isClient) {
if (window.opener && !window.opener.closed) {
window.opener.focus()
window.close()
} else {
window.location.href = "/"
}
}
}
// 修復權限檢查頁面
<Button onClick={() => {
if (isClient) {
window.location.href = "/"
}
}} variant="outline">
返回首頁
</Button>
{isClient && window.opener && !window.opener.closed && (
<Button onClick={() => {
window.opener.focus()
window.close()
}} variant="default">
關閉頁面
</Button>
)}
```
### 3. 修復 UserManagement 組件
**文件:** `components/admin/user-management.tsx`
```typescript
// 添加客戶端狀態
const [isClient, setIsClient] = useState(false)
useEffect(() => {
setIsClient(true)
}, [])
// 修復邀請連結生成
const invitationLink = isClient
? `${window.location.origin}/register?token=${invitationToken}&email=${encodeURIComponent(inviteEmail)}&role=${inviteRole}`
: `/register?token=${invitationToken}&email=${encodeURIComponent(inviteEmail)}&role=${inviteRole}`
// 修復預覽連結按鈕
<Button variant="outline" onClick={() => isClient && window.open(generatedInvitation.invitationLink, "_blank")}>
<ExternalLink className="w-4 h-4 mr-2" />
預覽連結
</Button>
```
## 🧪 測試結果
### 測試腳本:`scripts/test-hydration-fix.js`
```
✅ 管理員頁面載入成功
狀態碼: 200
✅ 直接的 window 檢查已移除
✅ 修復已應用,頁面正常載入
```
### 修復驗證:
- ✅ 移除了所有 `typeof window !== 'undefined'` 檢查
- ✅ 添加了 `isClient` 狀態管理
- ✅ 使用 `useEffect` 確保客戶端狀態正確設置
- ✅ 頁面載入正常,無 hydration 錯誤
## 📋 修復內容總結
### ✅ 已修復的問題:
1. **AdminLayout 組件**
- 添加 `isClient` 狀態管理
- 修復 logout 函數中的 window 使用
- 修復權限檢查頁面的條件渲染
2. **UserManagement 組件**
- 添加 `isClient` 狀態管理
- 修復邀請連結生成邏輯
- 修復預覽連結按鈕
3. **Hydration 一致性**
- 確保服務器端和客戶端渲染一致
- 避免條件渲染導致的差異
- 使用正確的客戶端狀態管理
### 🔧 技術改進:
1. **狀態管理**:使用 `useState``useEffect` 管理客戶端狀態
2. **條件渲染**:避免直接使用 `typeof window` 檢查
3. **渲染一致性**:確保服務器端和客戶端渲染相同
4. **錯誤預防**:防止 hydration 錯誤的發生
## 🎉 修復效果
### 修復前:
- Console 出現 Hydration 錯誤
- 服務器端和客戶端渲染不匹配
- 頁面可能顯示異常或功能失效
### 修復後:
- 無 Hydration 錯誤
- 服務器端和客戶端渲染一致
- 頁面正常載入和功能正常
## 🚀 使用方式
### 1. 測試修復效果
```bash
# 測試 Hydration 錯誤修復
pnpm run test:hydration-fix
```
### 2. 驗證修復
1. 打開瀏覽器開發者工具
2. 查看 Console 是否還有 Hydration 錯誤
3. 確認管理員頁面正常載入
## 📝 注意事項
1. **客戶端狀態**`isClient` 狀態在 hydration 後才會變為 `true`
2. **向後兼容**:修復不影響現有功能
3. **性能影響**:添加的狀態管理對性能影響微乎其微
4. **維護性**:代碼更加健壯,易於維護
## 🔍 預防措施
1. **避免直接 window 檢查**:使用客戶端狀態管理
2. **統一渲染邏輯**:確保服務器端和客戶端一致
3. **動態內容處理**:使用 `useEffect` 處理客戶端特定邏輯
4. **測試覆蓋**:定期測試 hydration 相關功能
Hydration 錯誤已完全修復,管理員頁面現在可以正常載入和運作!

View File

@@ -1,171 +0,0 @@
# 管理員後台載入問題修復總結
## 🎯 問題描述
管理員訪問後台網站時,頁面一直顯示「載入中...」狀態,無法進入管理員後台。
## 🔍 問題分析
### 根本原因:
1. **isInitialized 狀態缺失**`isInitialized` 狀態沒有在 AuthContext 的返回值中提供
2. **isLoading 初始值錯誤**`isLoading` 初始值為 `true`,導致服務器端渲染時一直顯示載入狀態
3. **載入條件過於複雜**:載入條件包含多個狀態檢查,增加了出錯的可能性
### 問題流程:
1. 用戶訪問 `/admin` 頁面
2. 服務器端渲染時,`isLoading``true``isInitialized``false`
3. 載入條件 `!isClient || isLoading || !isInitialized` 返回 `true`
4. 頁面一直顯示「載入中...」狀態
5. 客戶端 hydration 後,狀態沒有正確更新
## ✅ 修復方案
### 1. 修復 isInitialized 狀態缺失
**文件:** `contexts/auth-context.tsx`
```typescript
// 在 AuthContextType 接口中添加 isInitialized
interface AuthContextType {
// ... 其他屬性
isLoading: boolean
isInitialized: boolean // 添加這一行
// ... 其他屬性
}
// 在 AuthContext.Provider 的 value 中添加 isInitialized
return (
<AuthContext.Provider
value={{
// ... 其他屬性
isLoading,
isInitialized, // 添加這一行
// ... 其他屬性
}}
>
{children}
</AuthContext.Provider>
)
```
### 2. 修復 isLoading 初始值
**文件:** `contexts/auth-context.tsx`
```typescript
// 修復前isLoading 初始值為 true
const [isLoading, setIsLoading] = useState(true)
// 修復後isLoading 初始值為 false
const [isLoading, setIsLoading] = useState(false)
```
### 3. 簡化載入條件
**文件:** `components/admin/admin-layout.tsx`
```typescript
// 修復前:複雜的載入條件
if (!isClient || isLoading || !isInitialized) {
// 顯示載入畫面
}
// 修復後:簡化的載入條件
if (isLoading) {
// 顯示載入畫面
}
```
## 🧪 測試結果
### 測試腳本:`scripts/test-complete-login-flow.js`
```
✅ 首頁載入成功
✅ 首頁包含登入功能
✅ 管理員登入 API 成功
用戶資料: {
id: 'c8b26413-00b9-4337-870d-4e37e3e8e375',
name: '系統管理員',
email: 'admin@ai-platform.com',
role: 'admin'
}
✅ 管理員頁面正確顯示存取被拒(未登入)
```
### 修復驗證:
- ✅ 頁面不再一直顯示「載入中...」
- ✅ 未登入時正確顯示「存取被拒」
- ✅ 登入 API 正常工作
- ✅ 權限檢查邏輯正常
## 📋 修復內容總結
### ✅ 已修復的問題:
1. **AuthContext 組件**
- 添加 `isInitialized` 到接口和返回值
- 修復 `isLoading` 初始值
- 確保狀態正確傳遞
2. **AdminLayout 組件**
- 簡化載入條件邏輯
- 移除複雜的狀態檢查
- 提高載入狀態的可靠性
3. **載入狀態管理**
- 修復服務器端渲染問題
- 確保客戶端 hydration 正常
- 提供清晰的載入和錯誤狀態
### 🔧 技術改進:
1. **狀態管理**:確保所有狀態正確傳遞和使用
2. **載入邏輯**:簡化載入條件,提高可靠性
3. **服務器端渲染**:修復 SSR 相關的狀態問題
4. **用戶體驗**:提供正確的載入和錯誤狀態
## 🎉 修復效果
### 修復前:
- 頁面一直顯示「載入中...」狀態
- 無法進入管理員後台
- 用戶體驗差
### 修復後:
- 頁面正確顯示載入狀態
- 未登入時顯示「存取被拒」
- 登入後可以正常訪問後台
- 用戶體驗良好
## 🚀 使用方式
### 1. 測試修復效果
```bash
# 測試完整登入流程
node scripts/test-complete-login-flow.js
# 調試載入問題
node scripts/debug-loading-issue.js
```
### 2. 驗證修復
1. 打開瀏覽器訪問 `http://localhost:3000`
2. 使用管理員帳號登入:
- 電子郵件:`admin@ai-platform.com`
- 密碼:`admin123456`
3. 登入後訪問 `http://localhost:3000/admin`
4. 確認頁面正常載入管理員後台
## 📝 注意事項
1. **登入流程**:用戶需要先登入才能訪問管理員頁面
2. **權限檢查**:未登入時會顯示「存取被拒」
3. **載入狀態**:載入狀態現在正確顯示
4. **狀態管理**:所有狀態都正確傳遞和使用
## 🔍 預防措施
1. **狀態檢查**:確保所有狀態都正確傳遞到組件
2. **載入邏輯**:保持載入條件簡單和可靠
3. **服務器端渲染**:考慮 SSR 對狀態的影響
4. **測試覆蓋**:定期測試載入和權限功能
管理員後台載入問題已完全修復,現在用戶可以正常登入和訪問後台!

View File

@@ -1,143 +0,0 @@
# 資料庫遷移指南
## 🚨 問題解決
如果您遇到 SQL 語法錯誤,請按照以下步驟操作:
### 方法一:使用簡化版遷移(推薦)
```bash
# 1. 先執行基本表結構遷移
pnpm run migrate
# 2. 如果觸發器創建失敗,單獨執行觸發器遷移
pnpm run migrate:triggers
```
### 方法二:手動執行 SQL
如果自動遷移仍然失敗,請手動執行:
```bash
# 1. 連接到資料庫
mysql -h mysql.theaken.com -P 33306 -u AI_Platform -p
# 2. 選擇資料庫
USE db_AI_Platform;
# 3. 執行 SQL 文件
source database-schema-simple.sql;
```
### 方法三:分步執行
```bash
# 1. 測試資料庫連接
pnpm run test:db
# 2. 如果連接成功,執行遷移
pnpm run migrate
# 3. 檢查結果
pnpm run test:db
```
## 🔧 常見問題解決
### 問題 1: SQL 語法錯誤
**錯誤**: `You have an error in your SQL syntax`
**解決方案**:
1. 使用 `database-schema-simple.sql` 而不是 `database-schema.sql`
2. 確保 MySQL 版本支援 JSON 類型MySQL 5.7+
3. 檢查字符集設置
### 問題 2: 觸發器創建失敗
**錯誤**: `Trigger creation failed`
**解決方案**:
```bash
# 單獨執行觸發器遷移
pnpm run migrate:triggers
```
### 問題 3: 權限不足
**錯誤**: `Access denied`
**解決方案**:
1. 檢查資料庫用戶權限
2. 確保用戶有 CREATE、DROP、INSERT 權限
3. 聯繫資料庫管理員
### 問題 4: 連接超時
**錯誤**: `Connection timeout`
**解決方案**:
1. 檢查網路連接
2. 確認資料庫服務正在運行
3. 檢查防火牆設置
## 📋 遷移檢查清單
### 遷移前檢查
- [ ] 資料庫服務正在運行
- [ ] 網路連接正常
- [ ] 用戶權限充足
- [ ] 環境變數設置正確
### 遷移後檢查
- [ ] 所有表創建成功
- [ ] 觸發器創建成功
- [ ] 視圖創建成功
- [ ] 初始數據插入成功
### 驗證命令
```bash
# 檢查表數量
mysql -h mysql.theaken.com -P 33306 -u AI_Platform -p -e "SHOW TABLES;" db_AI_Platform
# 檢查觸發器
mysql -h mysql.theaken.com -P 33306 -u AI_Platform -p -e "SHOW TRIGGERS;" db_AI_Platform
# 檢查視圖
mysql -h mysql.theaken.com -P 33306 -u AI_Platform -p -e "SHOW FULL TABLES WHERE Table_type = 'VIEW';" db_AI_Platform
```
## 🆘 緊急恢復
如果遷移過程中出現問題:
### 1. 停止遷移
```bash
# 按 Ctrl+C 停止當前遷移
```
### 2. 檢查資料庫狀態
```bash
# 檢查是否有部分表創建
pnpm run test:db
```
### 3. 清理並重新開始
```bash
# 刪除所有表(慎用!)
mysql -h mysql.theaken.com -P 33306 -u AI_Platform -p -e "DROP DATABASE IF EXISTS db_AI_Platform; CREATE DATABASE db_AI_Platform CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
# 重新執行遷移
pnpm run migrate
```
## 📞 技術支援
如果問題仍然存在,請提供以下信息:
1. 完整的錯誤訊息
2. MySQL 版本
3. 操作系統
4. Node.js 版本
5. 執行的命令
聯繫方式:
- 技術團隊
- 項目維護者
- 查看專案文檔

View File

@@ -1,164 +0,0 @@
# NaN 數值顯示錯誤修復總結
## 🎯 問題描述
`ActivityRecordsDialog` 組件中出現 Console 錯誤:
```
Received NaN for the `children` attribute. If this is expected, cast the value to a string.
```
錯誤位置:`components/auth/activity-records-dialog.tsx` 第 286 行
```tsx
<div className="text-2xl font-bold">{stats.daysJoined}</div>
```
## 🔍 問題分析
### 根本原因:
1. **日期計算錯誤**`user.joinDate` 可能是無效的日期格式
2. **無效日期處理**`new Date(user.joinDate)` 返回無效日期時,`getTime()` 返回 `NaN`
3. **數學運算結果**`(now.getTime() - joinDate.getTime())` 結果為 `NaN`
4. **React 渲染錯誤**React 不允許 `NaN` 作為 `children` 屬性
### 問題流程:
```typescript
// 問題代碼
const joinDate = new Date(user.joinDate) // 可能是無效日期
const now = new Date()
const daysJoined = Math.floor((now.getTime() - joinDate.getTime()) / (1000 * 60 * 60 * 24))
// 如果 joinDate 無效getTime() 返回 NaN導致 daysJoined 為 NaN
```
## ✅ 修復方案
### 1. 日期有效性檢查
**修復前:**
```typescript
const joinDate = new Date(user.joinDate)
const now = new Date()
const daysJoined = Math.floor((now.getTime() - joinDate.getTime()) / (1000 * 60 * 60 * 24))
```
**修復後:**
```typescript
const joinDate = new Date(user.joinDate)
const now = new Date()
// Check if joinDate is valid
let daysJoined = 0
if (!isNaN(joinDate.getTime())) {
daysJoined = Math.floor((now.getTime() - joinDate.getTime()) / (1000 * 60 * 60 * 24))
}
```
### 2. 顯示值安全檢查
**修復前:**
```tsx
<div className="text-2xl font-bold">{stats.daysJoined}</div>
```
**修復後:**
```tsx
<div className="text-2xl font-bold">{isNaN(stats.daysJoined) ? 0 : stats.daysJoined}</div>
```
### 3. 全面數值保護
為所有統計數值添加 `NaN` 檢查:
```tsx
// 總使用次數
<div className="text-2xl font-bold">{isNaN(stats.totalUsage) ? 0 : stats.totalUsage}</div>
// 使用時長
<div className="text-2xl font-bold">
{isNaN(stats.totalDuration) ? "0分鐘" : (
stats.totalDuration >= 60
? `${(stats.totalDuration / 60).toFixed(1)}小時`
: `${stats.totalDuration}分鐘`
)}
</div>
// 收藏應用
<div className="text-2xl font-bold">{isNaN(stats.favoriteApps) ? 0 : stats.favoriteApps}</div>
// 加入天數
<div className="text-2xl font-bold">{isNaN(stats.daysJoined) ? 0 : stats.daysJoined}</div>
```
## 🧪 測試結果
### 測試腳本:`scripts/test-activity-records.js`
```
✅ 首頁載入成功
狀態碼: 200
✅ 修復已應用,頁面正常載入
```
### 修復驗證:
- ✅ 日期計算添加有效性檢查
- ✅ 所有數值顯示都有 `NaN` 保護
- ✅ 無效日期時顯示預設值 0
- ✅ 頁面載入正常,無 Console 錯誤
## 📋 修復內容總結
### ✅ 已修復的問題:
1. **日期計算安全性**
- 添加 `isNaN(joinDate.getTime())` 檢查
- 無效日期時返回預設值 0
2. **數值顯示安全性**
- 所有統計數值都添加 `isNaN()` 檢查
- 無效數值時顯示預設值
3. **React 渲染安全性**
- 確保 `children` 屬性永遠是有效數值
- 避免 `NaN` 導致的渲染錯誤
4. **用戶體驗改善**
- 無效資料時顯示合理的預設值
- 避免頁面崩潰或顯示錯誤
### 🔧 技術改進:
1. **防禦性編程**:添加多層數值檢查
2. **錯誤處理**:優雅處理無效資料
3. **用戶友好**:顯示有意義的預設值
4. **代碼健壯性**:提高組件的穩定性
## 🎉 修復效果
### 修復前:
- Console 出現 `NaN` 錯誤
- 頁面可能顯示異常
- 用戶體驗受影響
### 修復後:
- 無 Console 錯誤
- 頁面正常顯示
- 無效資料時顯示預設值
- 用戶體驗流暢
## 🚀 使用方式
### 1. 測試修復效果
```bash
# 測試活動紀錄數值顯示
pnpm run test:activity-records
```
### 2. 驗證修復
1. 打開瀏覽器開發者工具
2. 查看 Console 是否還有 `NaN` 錯誤
3. 確認活動紀錄對話框正常顯示
## 📝 注意事項
1. **資料格式**:確保 `user.joinDate` 是有效的日期格式
2. **向後兼容**:修復不影響現有功能
3. **性能影響**:添加的檢查對性能影響微乎其微
4. **維護性**:代碼更加健壯,易於維護
NaN 數值顯示錯誤已完全修復,活動紀錄對話框現在可以安全地處理各種資料情況!

View File

@@ -1,160 +0,0 @@
# 密碼顯示/隱藏功能實現總結
## 🎯 需求背景
根據您的要求,為所有密碼相關的 UI 添加顯示密碼、隱藏密碼功能,提升用戶體驗。
## ✅ 實現範圍
### 已添加密碼顯示/隱藏功能的頁面:
1. **註冊頁面** (`app/register/page.tsx`)
- 密碼欄位
- 確認密碼欄位
2. **登入對話框** (`components/auth/login-dialog.tsx`)
- 密碼欄位 ✅ (已有功能)
3. **重設密碼頁面** (`app/reset-password/page.tsx`)
- 密碼欄位 ✅ (已有功能)
- 確認密碼欄位 ✅ (已有功能)
4. **評審評分頁面** (`app/judge-scoring/page.tsx`)
- 存取碼欄位
5. **註冊對話框** (`components/auth/register-dialog.tsx`)
- 密碼欄位
- 確認密碼欄位
6. **系統設定頁面** (`components/admin/system-settings.tsx`)
- SMTP 密碼欄位
## 🔧 技術實現
### 1. 統一的 UI 設計
```tsx
<div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input
type={showPassword ? "text" : "password"}
className="pl-10 pr-10"
// ... 其他屬性
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showPassword ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
</button>
</div>
```
### 2. 狀態管理
```tsx
const [showPassword, setShowPassword] = useState(false)
const [showConfirmPassword, setShowConfirmPassword] = useState(false)
const [showAccessCode, setShowAccessCode] = useState(false)
const [showSmtpPassword, setShowSmtpPassword] = useState(false)
```
### 3. 圖示導入
```tsx
import { Eye, EyeOff, Lock } from "lucide-react"
```
## 🎨 用戶體驗特點
### 1. 視覺設計
- **鎖頭圖示**:左側顯示鎖頭圖示,清楚標示密碼欄位
- **眼睛圖示**:右側顯示眼睛圖示,點擊切換顯示/隱藏
- **懸停效果**:圖示有懸停變色效果,提升互動性
- **統一風格**:所有密碼欄位使用相同的設計風格
### 2. 互動體驗
- **一鍵切換**:點擊眼睛圖示即可切換顯示/隱藏
- **即時反饋**:圖示會立即更新,顯示當前狀態
- **無需重新輸入**:切換顯示狀態不會影響已輸入的內容
- **鍵盤友好**:支援鍵盤導航和操作
### 3. 安全性考量
- **預設隱藏**:所有密碼欄位預設為隱藏狀態
- **獨立控制**:每個密碼欄位都有獨立的顯示/隱藏控制
- **狀態隔離**:不同頁面的密碼顯示狀態互不影響
## 📋 功能清單
| 頁面/組件 | 密碼欄位 | 狀態 | 功能 |
|-----------|----------|------|------|
| 註冊頁面 | 密碼 | ✅ 新增 | 顯示/隱藏切換 |
| 註冊頁面 | 確認密碼 | ✅ 新增 | 顯示/隱藏切換 |
| 登入對話框 | 密碼 | ✅ 已有 | 顯示/隱藏切換 |
| 重設密碼頁面 | 密碼 | ✅ 已有 | 顯示/隱藏切換 |
| 重設密碼頁面 | 確認密碼 | ✅ 已有 | 顯示/隱藏切換 |
| 評審評分頁面 | 存取碼 | ✅ 新增 | 顯示/隱藏切換 |
| 註冊對話框 | 密碼 | ✅ 新增 | 顯示/隱藏切換 |
| 註冊對話框 | 確認密碼 | ✅ 新增 | 顯示/隱藏切換 |
| 系統設定頁面 | SMTP 密碼 | ✅ 新增 | 顯示/隱藏切換 |
## 🧪 測試結果
### 頁面載入測試
```
✅ 註冊頁面 載入成功 (狀態碼: 200)
✅ 重設密碼頁面 載入成功 (狀態碼: 200)
✅ 評審評分頁面 載入成功 (狀態碼: 200)
```
### 功能驗證
- ✅ 所有密碼欄位都有顯示/隱藏功能
- ✅ 圖示正確切換 (眼睛 ↔ 眼睛斜線)
- ✅ 輸入框類型正確切換 (password ↔ text)
- ✅ 懸停效果正常運作
- ✅ 無語法錯誤或 linting 問題
## 🚀 使用方式
### 1. 用戶操作
1. 在密碼欄位輸入密碼
2. 點擊右側的眼睛圖示
3. 密碼會切換為明文顯示
4. 再次點擊可隱藏密碼
### 2. 開發者測試
```bash
# 測試密碼顯示功能
pnpm run test:password-visibility
```
## 🎉 實現效果
### ✅ 解決的問題
- **提升用戶體驗**:用戶可以輕鬆查看輸入的密碼
- **減少輸入錯誤**:特別是在輸入複雜密碼時
- **統一設計風格**:所有密碼欄位都有一致的互動體驗
- **增強可訪問性**:提供更好的密碼輸入體驗
### 📈 改進效果
- **用戶友好**:一鍵切換,操作簡單
- **視覺清晰**:圖示明確,狀態清楚
- **功能完整**:覆蓋所有密碼相關欄位
- **設計統一**:保持一致的視覺風格
## 🔧 技術細節
### 1. 響應式設計
- 圖示大小適中 (w-4 h-4)
- 位置精確 (right-3 top-1/2)
- 懸停效果平滑
### 2. 無障礙設計
- 按鈕有明確的 type="button"
- 圖示有語義化的意義
- 支援鍵盤操作
### 3. 性能優化
- 使用 useState 管理狀態
- 避免不必要的重新渲染
- 圖示使用 SVG載入快速
所有密碼相關的 UI 現在都具備了顯示/隱藏功能,為用戶提供了更好的密碼輸入體驗!

View File

@@ -1,122 +0,0 @@
# 個人資料功能整合總結
## 🎯 問題解決
您提到的個人資料區塊現在已經完全與資料庫連結!之前缺少的字段已經添加並測試完成。
## ✅ 完成的工作
### 1. 資料庫字段擴展
`users` 表添加了以下字段:
- **`phone`** (VARCHAR(20)) - 電話號碼
- **`location`** (VARCHAR(100)) - 工作地點
- **`bio`** (TEXT) - 個人簡介
### 2. 模型定義更新
更新了以下 TypeScript 接口:
- `User` 模型(資料庫層)
- `UserProfile` 模型(前端層)
- `AuthContext` 中的 `User` 接口
### 3. API 支援
- `/api/auth/profile` 端點已支援新字段的讀取和更新
- 動態更新機制,無需修改 API 代碼
### 4. 前端整合
- 個人資料對話框已包含所有字段
- 表單驗證和錯誤處理完整
- 與現有認證系統無縫整合
## 📋 個人資料字段對照
| 前端顯示 | 資料庫字段 | 類型 | 說明 |
|----------|------------|------|------|
| 姓名 | `name` | VARCHAR(100) | 用戶姓名 |
| 電子郵件 | `email` | VARCHAR(255) | 電子郵件地址 |
| 部門 | `department` | VARCHAR(100) | 所屬部門 |
| 電話 | `phone` | VARCHAR(20) | 電話號碼 ✅ 新增 |
| 地點 | `location` | VARCHAR(100) | 工作地點 ✅ 新增 |
| 個人簡介 | `bio` | TEXT | 個人簡介 ✅ 新增 |
| 角色 | `role` | ENUM | 用戶角色 |
| 頭像 | `avatar` | VARCHAR(500) | 頭像 URL |
## 🔧 技術實現
### 資料庫更新
```sql
ALTER TABLE users
ADD COLUMN `phone` VARCHAR(20) NULL,
ADD COLUMN `location` VARCHAR(100) NULL,
ADD COLUMN `bio` TEXT NULL;
```
### API 端點
```typescript
PUT /api/auth/profile
{
"userId": "user-uuid",
"phone": "0912-345-678",
"location": "台北市信義區",
"bio": "個人簡介內容"
}
```
### 前端組件
- `ProfileDialog` 組件已包含所有字段
- 表單狀態管理完整
- 錯誤處理和成功提示
## 🧪 測試結果
### 資料庫測試 ✅
- 字段添加成功
- 資料更新正常
- 查詢功能正常
### API 測試 ✅
- 個人資料讀取正常
- 個人資料更新正常
- 錯誤處理完整
### 前端測試 ✅
- 表單顯示正確
- 資料綁定正常
- 更新功能正常
## 🚀 使用方法
### 1. 查看個人資料
登入後點擊用戶頭像 → 個人資料
### 2. 更新個人資料
1. 填寫表單字段
2. 點擊「儲存變更」
3. 系統會自動更新資料庫
### 3. 測試功能
```bash
# 測試個人資料更新
pnpm run test:profile
# 添加用戶字段(如需要)
pnpm run add:user-fields
```
## 📝 注意事項
1. **字段可選性**:所有新字段都是可選的,不會影響現有用戶
2. **資料驗證**:前端有基本的表單驗證
3. **向後兼容**:現有功能完全不受影響
4. **安全性**:所有更新都通過 API 進行,有適當的權限檢查
## 🎉 整合完成
個人資料功能現在完全與資料庫連結,支援:
- ✅ 電話號碼
- ✅ 工作地點
- ✅ 個人簡介
- ✅ 完整的 CRUD 操作
- ✅ 前端表單整合
- ✅ API 端點支援
您現在可以正常使用個人資料功能,所有資料都會保存到 MySQL 資料庫中!

View File

@@ -1,371 +0,0 @@
# AI 展示平台專案完整解析
## 📋 專案概述
**強茂集團 AI 展示平台** 是一個企業內部 AI 應用展示與競賽管理系統,旨在促進 AI 技術的創新與應用。系統提供完整的競賽管理、評審系統、用戶互動和數據分析功能。
## 🏗️ 技術架構
### 前端技術棧
- **框架**: Next.js 15.2.4 (App Router)
- **語言**: TypeScript 5
- **UI 庫**:
- Radix UI (無障礙組件)
- shadcn/ui (設計系統)
- Tailwind CSS (樣式框架)
- **狀態管理**: React Context API
- **表單處理**: React Hook Form + Zod
- **圖表**: Recharts
- **包管理器**: pnpm
### 後端技術棧
- **資料庫**: MySQL 8.0
- **ORM**: 自定義資料庫服務層
- **API**: Next.js API Routes
- **認證**: JWT + localStorage
- **文件上傳**: 本地存儲
### 資料庫設計
- **主機**: mysql.theaken.com:33306
- **資料庫**: db_AI_Platform
- **表數量**: 25 個核心表
- **視圖數量**: 3 個統計視圖
- **觸發器**: 4 個自動計算觸發器
## 🎯 核心功能模組
### 1. 用戶管理系統
- **三種角色**:
- 一般用戶 (user): 瀏覽應用、參與投票
- 開發者 (developer): 提交AI應用、參與競賽
- 管理員 (admin): 系統管理、數據分析
- **核心功能**:
- 註冊/登入/登出
- 個人資料管理
- 收藏應用
- 按讚功能 (每日限制)
- 瀏覽記錄追蹤
- 活動統計分析
### 2. 競賽系統
- **競賽類型**:
- 個人賽 (individual)
- 團隊賽 (team)
- 提案賽 (proposal)
- 混合賽 (mixed)
- **競賽狀態**:
- upcoming: 即將開始
- active: 進行中
- judging: 評審中
- completed: 已完成
- **核心功能**:
- 競賽創建與管理
- 參賽報名
- 評審分配
- 評分系統
- 獎項頒發
- 結果統計
### 3. 評審系統
- **評分維度**:
- 創新性 (Innovation)
- 技術性 (Technical)
- 實用性 (Usability)
- 展示效果 (Presentation)
- 影響力 (Impact)
- **評分範圍**: 1-10 分
- **評分權重**: 可自定義
- **評分統計**: 自動計算平均分
### 4. 團隊管理
- **團隊結構**:
- 隊長 (Leader)
- 成員 (Member)
- 角色分配
- **核心功能**:
- 團隊創建與管理
- 成員邀請與管理
- 團隊統計分析
- 團隊競賽參與
### 5. 應用管理
- **應用類型**:
- 機器學習應用
- 自然語言處理
- 計算機視覺
- 數據分析
- 自動化工具
- **核心功能**:
- 應用提交
- 應用展示
- 評分統計
- 用戶互動
### 6. 提案管理
- **提案內容**:
- 問題陳述
- 解決方案
- 預期影響
- 附件支持
- **提案狀態**:
- draft: 草稿
- submitted: 已提交
- under_review: 審核中
- approved: 已批准
- rejected: 已拒絕
### 7. 獎項系統
- **獎項類型**:
- 金獎 (Gold)
- 銀獎 (Silver)
- 銅獎 (Bronze)
- 人氣獎 (Popular)
- 創新獎 (Innovation)
- 技術獎 (Technical)
- 自定義獎項 (Custom)
- **獎項類別**:
- 創新性 (Innovation)
- 技術性 (Technical)
- 實用性 (Practical)
- 人氣 (Popular)
- 團隊合作 (Teamwork)
- 解決方案 (Solution)
- 創意 (Creativity)
### 8. AI 助手系統
- **功能特色**:
- 智能問答
- 操作指導
- 快速問題
- 會話管理
- **技術實現**:
- DeepSeek API 集成
- 上下文管理
- 會話持久化
## 📊 資料庫設計
### 核心表結構
#### 用戶相關表
- **users**: 用戶基本資訊
- **user_favorites**: 用戶收藏
- **user_likes**: 用戶按讚
- **user_views**: 用戶瀏覽記錄
- **user_ratings**: 用戶評分
#### 競賽相關表
- **competitions**: 競賽基本資訊
- **competition_rules**: 競賽規則
- **competition_award_types**: 獎項類型
- **competition_judges**: 評審分配
- **competition_apps**: 參賽應用
- **competition_teams**: 參賽團隊
- **competition_proposals**: 參賽提案
#### 評審相關表
- **judges**: 評審基本資訊
- **app_judge_scores**: 應用評分
- **proposal_judge_scores**: 提案評分
#### 團隊相關表
- **teams**: 團隊基本資訊
- **team_members**: 團隊成員
#### 應用相關表
- **apps**: 應用基本資訊
- **proposals**: 提案基本資訊
- **awards**: 獎項記錄
#### 系統相關表
- **chat_sessions**: 聊天會話
- **chat_messages**: 聊天訊息
- **ai_assistant_configs**: AI 配置
- **system_settings**: 系統設定
- **activity_logs**: 活動日誌
### 統計視圖
- **user_statistics**: 用戶統計
- **app_statistics**: 應用統計
- **competition_statistics**: 競賽統計
### 觸發器
- **calculate_app_total_score**: 應用評分總分計算
- **calculate_proposal_total_score**: 提案評分總分計算
## 🔧 開發環境設置
### 1. 環境要求
- Node.js 18+
- pnpm
- MySQL 8.0+
- Git
### 2. 安裝步驟
```bash
# 克隆專案
git clone <repository-url>
cd ai-showcase-platform
# 安裝依賴
pnpm install
# 設置環境變數
cp env.example .env.local
# 執行資料庫遷移
pnpm run migrate
# 測試資料庫連接
pnpm run test:db
# 啟動開發服務器
pnpm run dev
```
### 3. 環境變數配置
```env
# 資料庫配置
DB_HOST=mysql.theaken.com
DB_PORT=33306
DB_NAME=db_AI_Platform
DB_USER=AI_Platform
DB_PASSWORD=Aa123456
# DeepSeek API 配置
NEXT_PUBLIC_DEEPSEEK_API_KEY=your_api_key
NEXT_PUBLIC_DEEPSEEK_API_URL=https://api.deepseek.com/v1/chat/completions
# JWT 配置
JWT_SECRET=your_jwt_secret
JWT_EXPIRES_IN=7d
```
## 📁 專案結構
```
ai-showcase-platform/
├── app/ # Next.js App Router
│ ├── admin/ # 管理員頁面
│ ├── competition/ # 競賽頁面
│ ├── judge-scoring/ # 評審頁面
│ └── register/ # 註冊頁面
├── components/ # React 組件
│ ├── admin/ # 管理員組件
│ ├── auth/ # 認證組件
│ ├── competition/ # 競賽組件
│ ├── reviews/ # 評分組件
│ └── ui/ # UI 組件庫
├── contexts/ # React Context
│ ├── auth-context.tsx # 認證上下文
│ └── competition-context.tsx # 競賽上下文
├── hooks/ # 自定義 Hooks
├── lib/ # 工具庫
│ ├── database.ts # 資料庫連接
│ ├── models.ts # 資料模型
│ └── services/ # 服務層
├── types/ # TypeScript 類型
├── scripts/ # 腳本文件
├── public/ # 靜態資源
└── styles/ # 樣式文件
```
## 🚀 部署指南
### 1. 生產環境準備
- 設置生產資料庫
- 配置環境變數
- 設置文件上傳目錄
- 配置反向代理
### 2. 部署步驟
```bash
# 構建專案
pnpm run build
# 啟動生產服務器
pnpm run start
```
### 3. 監控與維護
- 資料庫備份
- 日誌監控
- 性能監控
- 錯誤追蹤
## 🔍 功能特色
### 1. 響應式設計
- 移動端適配
- 平板端優化
- 桌面端完整功能
### 2. 無障礙支持
- 鍵盤導航
- 屏幕閱讀器支持
- 高對比度模式
### 3. 國際化支持
- 繁體中文界面
- 多語言擴展準備
### 4. 性能優化
- 代碼分割
- 圖片優化
- 緩存策略
## 📈 未來規劃
### 短期目標
- 完善評審系統
- 優化用戶體驗
- 增加數據分析功能
### 中期目標
- 移動端應用
- 實時通知系統
- 高級搜索功能
### 長期目標
- 多租戶支持
- 微服務架構
- 人工智能集成
## 🤝 貢獻指南
### 1. 代碼規範
- TypeScript 嚴格模式
- ESLint 規則遵循
- Prettier 格式化
### 2. 提交規範
- 清晰的提交信息
- 功能分支開發
- 代碼審查流程
### 3. 測試要求
- 單元測試
- 集成測試
- 端到端測試
## 📞 技術支援
如有任何技術問題,請聯繫:
- 技術團隊
- 項目維護者
- 查看專案文檔
---
**版本**: 1.0.0
**最後更新**: 2024年12月
**維護者**: 強茂集團技術團隊

View File

@@ -1,128 +0,0 @@
# 密碼重設頁面角色顯示修復總結
## 🎯 問題描述
在密碼重設頁面中,管理員帳號的角色顯示為「一般用戶」,而不是從資料庫 `users` 表的 `role` 欄位獲取的正確角色資訊。
## 🔍 問題分析
### 原因分析:
1. **忘記密碼 API** 在生成重設連結時,沒有包含用戶的角色資訊
2. **註冊頁面** 在密碼重設模式下,角色顯示依賴 URL 參數,但該參數缺失
3. **角色資訊** 應該從資料庫中的 `users.role` 欄位獲取,而不是硬編碼
### 原始問題:
```typescript
// 忘記密碼 API 中缺少角色資訊
const resetUrl = `${baseUrl}/register?token=${resetToken.token}&email=${encodeURIComponent(user.email)}&mode=reset&name=${encodeURIComponent(user.name)}&department=${encodeURIComponent(user.department)}`
// 缺少 &role=${encodeURIComponent(user.role)}
```
## ✅ 修復方案
### 1. 修改忘記密碼 API
**文件:** `app/api/auth/forgot-password/route.ts`
```typescript
// 修復前
const resetUrl = `${baseUrl}/register?token=${resetToken.token}&email=${encodeURIComponent(user.email)}&mode=reset&name=${encodeURIComponent(user.name)}&department=${encodeURIComponent(user.department)}`
// 修復後
const resetUrl = `${baseUrl}/register?token=${resetToken.token}&email=${encodeURIComponent(user.email)}&mode=reset&name=${encodeURIComponent(user.name)}&department=${encodeURIComponent(user.department)}&role=${encodeURIComponent(user.role)}`
```
### 2. 修改註冊頁面角色顯示
**文件:** `app/register/page.tsx`
```typescript
// 添加角色顯示變數
const displayRole = isResetMode ? invitedRole : invitedRole
// 更新角色顯示邏輯
{displayRole === "admin" && (
<><Shield className="w-3 h-3 mr-1" />管理員</>
)}
{displayRole === "developer" && (
<><Code className="w-3 h-3 mr-1" />開發者</>
)}
{displayRole === "user" && (
<><User className="w-3 h-3 mr-1" />一般用戶</>
)}
```
## 🧪 測試結果
### 測試腳本:`scripts/test-role-display.js`
```
✅ 忘記密碼 API 測試成功
生成的重設連結: http://localhost:3000/register?token=xxx&email=admin%40ai-platform.com&mode=reset&name=%E7%B3%BB%E7%B5%B1%E7%AE%A1%E7%90%86%E5%93%A1&department=ITBU&role=admin
📋 URL 參數解析:
- token: xxx
- email: admin@ai-platform.com
- mode: reset
- name: 系統管理員
- department: ITBU
- role: admin
✅ 註冊頁面載入成功
✅ 角色顯示正確:管理員
```
## 📋 修復內容總結
### ✅ 已修復的問題:
1. **忘記密碼 API** 現在包含用戶角色資訊
- 從資料庫 `users` 表獲取正確的 `role` 欄位
- 在重設連結中包含 `role` 參數
2. **註冊頁面** 正確顯示角色資訊
- 從 URL 參數獲取角色資訊
- 使用 `displayRole` 變數確保角色顯示正確
- 支援管理員、開發者、一般用戶三種角色
3. **角色顯示邏輯** 基於資料庫資料
- 不再依賴硬編碼的角色資訊
- 確保角色顯示與資料庫中的實際角色一致
### 🔧 技術改進:
1. **資料一致性**:角色資訊直接來自資料庫
2. **URL 參數完整性**:重設連結包含所有必要的用戶資訊
3. **顯示邏輯優化**:使用專門的 `displayRole` 變數
4. **測試覆蓋**:添加專門的角色顯示測試
## 🎉 修復效果
### 修復前:
- 管理員帳號在密碼重設頁面顯示為「一般用戶」
- 角色資訊不準確,可能造成用戶困惑
### 修復後:
- 管理員帳號正確顯示為「管理員」
- 所有角色都基於資料庫中的實際資料
- 角色顯示與用戶實際權限一致
## 🚀 使用方式
### 1. 測試角色顯示
```bash
# 測試角色顯示功能
pnpm run test:role-display
```
### 2. 驗證修復效果
1. 使用管理員帳號 (`admin@ai-platform.com`) 測試忘記密碼
2. 點擊生成的重設連結
3. 確認角色顯示為「管理員」而非「一般用戶」
## 📝 注意事項
1. **資料庫依賴**:角色顯示現在完全依賴資料庫中的 `users.role` 欄位
2. **URL 參數**:重設連結現在包含完整的用戶資訊
3. **向後兼容**:修復不影響現有的其他功能
4. **測試覆蓋**:建議定期運行角色顯示測試確保功能正常
角色顯示問題已完全修復,現在密碼重設頁面會正確顯示用戶在資料庫中的實際角色!

View File

@@ -1,103 +0,0 @@
# SSR 錯誤修復總結
## 🐛 問題描述
在 Next.js 應用中遇到了 `ReferenceError: window is not defined` 錯誤,這是因為在服務器端渲染 (SSR) 時嘗試訪問 `window` 對象導致的。
## ✅ 修復的文件
### 1. `components/admin/admin-layout.tsx`
**問題**:在 SSR 期間直接使用 `window` 對象
**修復**:添加 `typeof window !== 'undefined'` 檢查
```typescript
// 修復前
{window.opener && !window.opener.closed && (
<Button onClick={() => {
window.opener.focus()
window.close()
}}>
關閉頁面
</Button>
)}
// 修復後
{typeof window !== 'undefined' && window.opener && !window.opener.closed && (
<Button onClick={() => {
window.opener.focus()
window.close()
}}>
關閉頁面
</Button>
)}
```
### 2. `components/admin/user-management.tsx`
**問題**:在函數中直接使用 `window.location.origin`
**修復**:添加條件檢查,提供回退值
```typescript
// 修復前
const invitationLink = `${window.location.origin}/register?token=${invitationToken}&email=${encodeURIComponent(inviteEmail)}&role=${inviteRole}`
// 修復後
const invitationLink = typeof window !== "undefined"
? `${window.location.origin}/register?token=${invitationToken}&email=${encodeURIComponent(inviteEmail)}&role=${inviteRole}`
: `/register?token=${invitationToken}&email=${encodeURIComponent(inviteEmail)}&role=${inviteRole}`
```
## 🔧 修復策略
### 1. 條件檢查
```typescript
if (typeof window !== 'undefined') {
// 只在客戶端執行
window.location.href = "/"
}
```
### 2. 三元運算符
```typescript
const url = typeof window !== 'undefined'
? `${window.location.origin}/path`
: "/path"
```
### 3. useEffect Hook
```typescript
useEffect(() => {
// 只在客戶端執行
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])
```
## 📋 已檢查的文件
以下文件已經有正確的 SSR 處理,無需修復:
- `components/ui/use-mobile.tsx` - 使用 useEffect
- `components/admin/competition-management.tsx` - 有條件檢查
- `components/admin/scoring-link-dialog.tsx` - 有條件檢查
## 🎯 修復結果
- ✅ 消除了 `window is not defined` 錯誤
- ✅ 保持了客戶端功能正常運作
- ✅ 確保了 SSR 兼容性
- ✅ 提供了適當的回退值
## 📝 最佳實踐
1. **始終檢查 `window` 對象**:在 Next.js 中,`window` 只在客戶端可用
2. **使用 useEffect**:對於需要在客戶端執行的代碼,使用 `useEffect` Hook
3. **提供回退值**:為 SSR 環境提供適當的默認值
4. **避免在組件頂層使用 `window`**:將 `window` 相關代碼放在函數內部或 useEffect 中
## 🚀 測試建議
1. 檢查管理員頁面是否正常加載
2. 驗證用戶邀請功能是否正常
3. 確認彈窗關閉功能是否正常
4. 測試在不同環境下的表現
修復完成後,應用應該能夠正常進行服務器端渲染,同時保持所有客戶端功能正常運作。

View File

@@ -15,7 +15,7 @@ export function AdminPanel() {
const renderPage = () => { const renderPage = () => {
switch (currentPage) { switch (currentPage) {
case "dashboard": case "dashboard":
return <AdminDashboard /> return <AdminDashboard onPageChange={setCurrentPage} />
case "users": case "users":
return <UserManagement /> return <UserManagement />
case "apps": case "apps":
@@ -27,7 +27,7 @@ export function AdminPanel() {
case "settings": case "settings":
return <SystemSettings /> return <SystemSettings />
default: default:
return <AdminDashboard /> return <AdminDashboard onPageChange={setCurrentPage} />
} }
} }

View File

@@ -39,7 +39,11 @@ interface TopApp {
created_at: string created_at: string
} }
export function AdminDashboard() { interface AdminDashboardProps {
onPageChange?: (page: string) => void
}
export function AdminDashboard({ onPageChange }: AdminDashboardProps) {
const { competitions } = useCompetition() const { competitions } = useCompetition()
const [stats, setStats] = useState<DashboardStats>({ const [stats, setStats] = useState<DashboardStats>({
totalUsers: 0, totalUsers: 0,
@@ -93,6 +97,12 @@ export function AdminDashboard() {
return iconMap[iconName] || Activity return iconMap[iconName] || Activity
} }
const handleQuickAction = (page: string) => {
if (onPageChange) {
onPageChange(page)
}
}
return ( return (
<div className="space-y-6"> <div className="space-y-6">
{/* Welcome Section */} {/* Welcome Section */}
@@ -286,15 +296,26 @@ export function AdminDashboard() {
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Button className="h-20 flex flex-col space-y-2"> <Button
className="h-20 flex flex-col space-y-2"
onClick={() => handleQuickAction('users')}
>
<Users className="w-6 h-6" /> <Users className="w-6 h-6" />
<span></span> <span></span>
</Button> </Button>
<Button className="h-20 flex flex-col space-y-2 bg-transparent" variant="outline"> <Button
className="h-20 flex flex-col space-y-2 bg-transparent"
variant="outline"
onClick={() => handleQuickAction('apps')}
>
<Bot className="w-6 h-6" /> <Bot className="w-6 h-6" />
<span></span> <span></span>
</Button> </Button>
<Button className="h-20 flex flex-col space-y-2 bg-transparent" variant="outline"> <Button
className="h-20 flex flex-col space-y-2 bg-transparent"
variant="outline"
onClick={() => handleQuickAction('competitions')}
>
<Trophy className="w-6 h-6" /> <Trophy className="w-6 h-6" />
<span></span> <span></span>
</Button> </Button>