刪除不必要檔案
This commit is contained in:
@@ -1,280 +0,0 @@
|
||||
# 完整環境變量配置指南
|
||||
|
||||
## 概述
|
||||
|
||||
現在所有重要的配置都已經整合到環境變量中,包括:
|
||||
- 應用配置(URL、名稱)
|
||||
- 資料庫配置(主機、端口、用戶名、密碼、資料庫名)
|
||||
- AI 配置(Gemini API Key、模型名稱、最大 Token 數)
|
||||
|
||||
## 環境變量列表
|
||||
|
||||
### 🌐 應用配置
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:12024
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統
|
||||
```
|
||||
|
||||
### 🗄️ 資料庫配置
|
||||
```bash
|
||||
DB_HOST=mysql.theaken.com
|
||||
DB_PORT=33306
|
||||
DB_NAME=db_AI_scoring
|
||||
DB_USER=root
|
||||
DB_PASSWORD=zh6161168
|
||||
```
|
||||
|
||||
### 🤖 AI 配置
|
||||
```bash
|
||||
GEMINI_API_KEY=AIzaSyAN3pEJr_Vn2xkCidGZAq9eQqsMVvpj8g4
|
||||
GEMINI_MODEL=gemini-1.5-pro
|
||||
GEMINI_MAX_TOKENS=8192
|
||||
```
|
||||
|
||||
## 完整的 .env.local 範例
|
||||
|
||||
```bash
|
||||
# 應用配置
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:12024
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統
|
||||
|
||||
# 資料庫配置
|
||||
DB_HOST=mysql.theaken.com
|
||||
DB_PORT=33306
|
||||
DB_NAME=db_AI_scoring
|
||||
DB_USER=root
|
||||
DB_PASSWORD=zh6161168
|
||||
|
||||
# AI 配置
|
||||
GEMINI_API_KEY=AIzaSyAN3pEJr_Vn2xkCidGZAq9eQqsMVvpj8g4
|
||||
GEMINI_MODEL=gemini-1.5-pro
|
||||
GEMINI_MAX_TOKENS=8192
|
||||
```
|
||||
|
||||
## 技術實現
|
||||
|
||||
### 🔧 配置工具類 (`lib/config.ts`)
|
||||
|
||||
```typescript
|
||||
// 資料庫配置
|
||||
export const dbConfig = {
|
||||
host: process.env.DB_HOST || 'mysql.theaken.com',
|
||||
port: parseInt(process.env.DB_PORT || '33306'),
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || 'zh6161168',
|
||||
database: process.env.DB_NAME || 'db_AI_scoring',
|
||||
// ... 其他配置
|
||||
}
|
||||
|
||||
// AI 配置
|
||||
export const aiConfig = {
|
||||
geminiApiKey: process.env.GEMINI_API_KEY || 'fallback_key',
|
||||
modelName: process.env.GEMINI_MODEL || 'gemini-1.5-pro',
|
||||
maxTokens: parseInt(process.env.GEMINI_MAX_TOKENS || '8192'),
|
||||
}
|
||||
|
||||
// 配置驗證
|
||||
export function validateConfig(): { isValid: boolean; errors: string[] }
|
||||
```
|
||||
|
||||
### 📊 資料庫配置更新 (`lib/database.ts`)
|
||||
|
||||
```typescript
|
||||
import { dbConfig } from './config';
|
||||
|
||||
// 直接使用配置對象
|
||||
const pool = mysql.createPool({
|
||||
...dbConfig,
|
||||
// ... 其他配置
|
||||
});
|
||||
```
|
||||
|
||||
### 🤖 AI 配置更新 (`lib/services/gemini.ts`)
|
||||
|
||||
```typescript
|
||||
import { aiConfig } from '../config';
|
||||
|
||||
const genAI = new GoogleGenerativeAI(aiConfig.geminiApiKey);
|
||||
```
|
||||
|
||||
## 使用方式
|
||||
|
||||
### 🚀 開發環境設置
|
||||
|
||||
1. **複製環境變量範例**
|
||||
```bash
|
||||
cp env.example .env.local
|
||||
```
|
||||
|
||||
2. **編輯配置**
|
||||
```bash
|
||||
# 編輯 .env.local 文件
|
||||
nano .env.local
|
||||
```
|
||||
|
||||
3. **重啟服務器**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 🌐 生產環境設置
|
||||
|
||||
在部署平台(如 Vercel、Netlify 等)設置環境變量:
|
||||
|
||||
```bash
|
||||
# 應用配置
|
||||
NEXT_PUBLIC_APP_URL=https://yourdomain.com
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統
|
||||
|
||||
# 資料庫配置
|
||||
DB_HOST=your-production-db-host
|
||||
DB_PORT=3306
|
||||
DB_NAME=your_production_db
|
||||
DB_USER=your_db_user
|
||||
DB_PASSWORD=your_secure_password
|
||||
|
||||
# AI 配置
|
||||
GEMINI_API_KEY=your_production_gemini_key
|
||||
GEMINI_MODEL=gemini-1.5-pro
|
||||
GEMINI_MAX_TOKENS=8192
|
||||
```
|
||||
|
||||
## 配置檢查工具
|
||||
|
||||
### 🔍 使用配置檢查腳本
|
||||
|
||||
```bash
|
||||
node scripts/check-config.js
|
||||
```
|
||||
|
||||
這個腳本會:
|
||||
- 顯示當前配置
|
||||
- 驗證必要的環境變量
|
||||
- 提供配置建議
|
||||
|
||||
### 📋 檢查結果範例
|
||||
|
||||
```
|
||||
🔍 檢查環境變量配置...
|
||||
|
||||
📋 當前配置:
|
||||
應用 URL: http://localhost:12024
|
||||
應用名稱: AI 智能評審系統
|
||||
資料庫主機: mysql.theaken.com
|
||||
資料庫名稱: db_AI_scoring
|
||||
Gemini 模型: gemini-1.5-pro
|
||||
最大 Token 數: 8192
|
||||
|
||||
✅ 所有必要的環境變量都已設置
|
||||
```
|
||||
|
||||
## 不同環境的配置範例
|
||||
|
||||
### 🏠 本地開發環境
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:12024
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_NAME=ai_scoring_dev
|
||||
```
|
||||
|
||||
### 🧪 測試環境
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=https://test.yourdomain.com
|
||||
DB_HOST=test-db.yourdomain.com
|
||||
DB_PORT=3306
|
||||
DB_NAME=ai_scoring_test
|
||||
```
|
||||
|
||||
### 🚀 生產環境
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=https://yourdomain.com
|
||||
DB_HOST=prod-db.yourdomain.com
|
||||
DB_PORT=3306
|
||||
DB_NAME=ai_scoring_prod
|
||||
```
|
||||
|
||||
## 安全注意事項
|
||||
|
||||
### 🔒 敏感信息保護
|
||||
|
||||
1. **API 密鑰**
|
||||
- 不要將真實的 API 密鑰提交到版本控制
|
||||
- 在生產環境中使用不同的 API 密鑰
|
||||
|
||||
2. **資料庫密碼**
|
||||
- 使用強密碼
|
||||
- 定期更換密碼
|
||||
- 限制資料庫訪問權限
|
||||
|
||||
3. **環境變量文件**
|
||||
- `.env.local` 已在 `.gitignore` 中
|
||||
- 不要在代碼中硬編碼敏感信息
|
||||
|
||||
### ⚠️ 重要提醒
|
||||
|
||||
1. **環境變量命名**
|
||||
- 客戶端變量必須以 `NEXT_PUBLIC_` 開頭
|
||||
- 變量名稱區分大小寫
|
||||
|
||||
2. **回退機制**
|
||||
- 所有配置都有合理的默認值
|
||||
- 確保在環境變量未設置時仍能運行
|
||||
|
||||
3. **配置驗證**
|
||||
- 使用 `validateConfig()` 檢查配置
|
||||
- 在應用啟動時驗證關鍵配置
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 🐛 常見問題
|
||||
|
||||
1. **資料庫連接失敗**
|
||||
```bash
|
||||
# 檢查資料庫配置
|
||||
echo $DB_HOST
|
||||
echo $DB_NAME
|
||||
echo $DB_USER
|
||||
```
|
||||
|
||||
2. **Gemini API 錯誤**
|
||||
```bash
|
||||
# 檢查 API 密鑰
|
||||
echo $GEMINI_API_KEY
|
||||
```
|
||||
|
||||
3. **分享連結錯誤**
|
||||
```bash
|
||||
# 檢查應用 URL
|
||||
echo $NEXT_PUBLIC_APP_URL
|
||||
```
|
||||
|
||||
### 🔧 解決步驟
|
||||
|
||||
1. **確認環境變量設置**
|
||||
```bash
|
||||
# 檢查 .env.local 文件
|
||||
cat .env.local
|
||||
```
|
||||
|
||||
2. **重啟服務器**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
3. **運行配置檢查**
|
||||
```bash
|
||||
node scripts/check-config.js
|
||||
```
|
||||
|
||||
## 結論
|
||||
|
||||
通過完整的環境變量配置,應用現在具備了:
|
||||
|
||||
- ✅ **靈活性**:支援多環境部署
|
||||
- ✅ **安全性**:敏感信息通過環境變量管理
|
||||
- ✅ **可維護性**:統一的配置管理
|
||||
- ✅ **穩定性**:回退機制確保正常運行
|
||||
- ✅ **可驗證性**:配置檢查工具
|
||||
|
||||
現在您可以輕鬆地在不同環境中部署應用,只需設置相應的環境變量即可!
|
@@ -1,196 +0,0 @@
|
||||
# 環境變量配置指南
|
||||
|
||||
## 概述
|
||||
|
||||
為了讓應用在不同環境中使用不同的域名,我們已經將硬編碼的 localhost URL 改為環境變量配置。
|
||||
|
||||
## 配置方式
|
||||
|
||||
### 1. 創建環境變量文件
|
||||
|
||||
在項目根目錄創建 `.env.local` 文件:
|
||||
|
||||
```bash
|
||||
# 應用配置
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:12024
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統
|
||||
|
||||
# 資料庫配置
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_NAME=ai_scoring
|
||||
DB_USER=root
|
||||
DB_PASSWORD=
|
||||
|
||||
# AI 配置
|
||||
GEMINI_API_KEY=your_gemini_api_key_here
|
||||
```
|
||||
|
||||
### 2. 不同環境的配置
|
||||
|
||||
#### 開發環境 (`.env.local`)
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:12024
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統 (開發版)
|
||||
```
|
||||
|
||||
#### 測試環境 (`.env.test`)
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=https://test.yourdomain.com
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統 (測試版)
|
||||
```
|
||||
|
||||
#### 生產環境 (`.env.production`)
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=https://yourdomain.com
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統
|
||||
```
|
||||
|
||||
## 技術實現
|
||||
|
||||
### 🔧 配置工具類 (`lib/config.ts`)
|
||||
|
||||
創建了統一的配置管理工具:
|
||||
|
||||
```typescript
|
||||
// 獲取應用基礎 URL
|
||||
export function getAppUrl(): string {
|
||||
// 在客戶端使用 window.location.origin
|
||||
if (typeof window !== 'undefined') {
|
||||
return window.location.origin
|
||||
}
|
||||
|
||||
// 在服務端使用環境變量
|
||||
return process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:12024'
|
||||
}
|
||||
|
||||
// 生成分享連結
|
||||
export function generateShareUrl(evaluationId: string): string {
|
||||
const baseUrl = getAppUrl()
|
||||
return `${baseUrl}/results?id=${evaluationId}`
|
||||
}
|
||||
```
|
||||
|
||||
### 📱 分享組件更新
|
||||
|
||||
修改了 `components/share-modal.tsx` 來使用配置工具:
|
||||
|
||||
```typescript
|
||||
import { generateShareUrl, getCurrentUrl } from "@/lib/config"
|
||||
|
||||
// 生成分享連結
|
||||
const shareUrl = evaluationId
|
||||
? generateShareUrl(evaluationId)
|
||||
: getCurrentUrl()
|
||||
```
|
||||
|
||||
## 使用說明
|
||||
|
||||
### 🚀 開發環境設置
|
||||
|
||||
1. **複製環境變量範例**
|
||||
```bash
|
||||
cp env.example .env.local
|
||||
```
|
||||
|
||||
2. **修改配置**
|
||||
編輯 `.env.local` 文件,設置您的開發環境 URL:
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:12024
|
||||
```
|
||||
|
||||
3. **重啟開發服務器**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 🌐 部署到生產環境
|
||||
|
||||
1. **設置生產環境變量**
|
||||
在您的部署平台(如 Vercel、Netlify 等)設置環境變量:
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=https://yourdomain.com
|
||||
```
|
||||
|
||||
2. **自動部署**
|
||||
環境變量會在部署時自動生效
|
||||
|
||||
## 功能特色
|
||||
|
||||
### ✨ 智能 URL 生成
|
||||
|
||||
- **客戶端**:自動使用當前域名
|
||||
- **服務端**:使用環境變量配置
|
||||
- **回退機制**:如果環境變量未設置,使用 localhost:12024
|
||||
|
||||
### 🔄 環境適配
|
||||
|
||||
- **開發環境**:使用 localhost
|
||||
- **測試環境**:使用測試域名
|
||||
- **生產環境**:使用正式域名
|
||||
|
||||
### 📱 分享功能
|
||||
|
||||
- **QR Code**:自動使用正確的域名
|
||||
- **分享連結**:包含正確的完整 URL
|
||||
- **郵件分享**:使用配置的域名
|
||||
|
||||
## 注意事項
|
||||
|
||||
### ⚠️ 重要提醒
|
||||
|
||||
1. **環境變量命名**
|
||||
- 客戶端可用的變量必須以 `NEXT_PUBLIC_` 開頭
|
||||
- 只有 `NEXT_PUBLIC_` 前綴的變量才能在客戶端代碼中使用
|
||||
|
||||
2. **安全考慮**
|
||||
- 不要在環境變量中存儲敏感信息
|
||||
- API 密鑰等敏感數據使用服務端專用變量
|
||||
|
||||
3. **文件忽略**
|
||||
- `.env.local` 文件已在 `.gitignore` 中,不會被提交到版本控制
|
||||
|
||||
## 測試驗證
|
||||
|
||||
### ✅ 功能測試
|
||||
|
||||
1. **開發環境測試**
|
||||
```bash
|
||||
npm run dev
|
||||
# 訪問 http://localhost:12024/results
|
||||
# 測試分享功能,確認 URL 正確
|
||||
```
|
||||
|
||||
2. **生產環境測試**
|
||||
```bash
|
||||
npm run build
|
||||
npm run start
|
||||
# 測試分享功能,確認使用生產域名
|
||||
```
|
||||
|
||||
### 🔍 驗證方法
|
||||
|
||||
- 檢查分享連結是否使用正確的域名
|
||||
- 驗證 QR Code 是否包含正確的 URL
|
||||
- 測試郵件分享是否使用正確的域名
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 🐛 常見問題
|
||||
|
||||
1. **環境變量不生效**
|
||||
- 確認變量名以 `NEXT_PUBLIC_` 開頭
|
||||
- 重啟開發服務器
|
||||
- 檢查 `.env.local` 文件位置
|
||||
|
||||
2. **分享連結錯誤**
|
||||
- 檢查 `NEXT_PUBLIC_APP_URL` 是否正確設置
|
||||
- 確認 URL 格式正確(包含 http:// 或 https://)
|
||||
|
||||
3. **部署後 URL 不正確**
|
||||
- 在部署平台設置環境變量
|
||||
- 確認變量名稱和值正確
|
||||
|
||||
## 結論
|
||||
|
||||
通過環境變量配置,分享功能現在可以在不同環境中使用正確的域名,提供更好的靈活性和可維護性。無論是在開發、測試還是生產環境,都能確保分享連結使用正確的 URL。
|
@@ -1,162 +0,0 @@
|
||||
# 環境變量配置實現總結
|
||||
|
||||
## 完成的修改
|
||||
|
||||
### 🔧 創建配置工具類
|
||||
|
||||
**文件:`lib/config.ts`**
|
||||
|
||||
創建了統一的配置管理工具,包含以下功能:
|
||||
|
||||
1. **`getAppUrl()`** - 獲取應用基礎 URL
|
||||
- 客戶端:自動使用 `window.location.origin`
|
||||
- 服務端:使用環境變量 `NEXT_PUBLIC_APP_URL`
|
||||
- 回退:如果未設置環境變量,使用 `http://localhost:12024`
|
||||
|
||||
2. **`generateShareUrl(evaluationId)`** - 生成評審結果分享連結
|
||||
- 自動組合基礎 URL 和評審 ID
|
||||
- 格式:`{baseUrl}/results?id={evaluationId}`
|
||||
|
||||
3. **`getCurrentUrl()`** - 獲取當前頁面 URL
|
||||
- 客戶端:使用 `window.location.href`
|
||||
- 服務端:使用基礎 URL
|
||||
|
||||
4. **`getAppName()`** - 獲取應用名稱
|
||||
- 使用環境變量 `NEXT_PUBLIC_APP_NAME`
|
||||
- 回退:`AI 智能評審系統`
|
||||
|
||||
### 📱 更新分享組件
|
||||
|
||||
**文件:`components/share-modal.tsx`**
|
||||
|
||||
修改了分享組件來使用新的配置工具:
|
||||
|
||||
```typescript
|
||||
// 舊的硬編碼方式
|
||||
const shareUrl = evaluationId
|
||||
? `${window.location.origin}/results?id=${evaluationId}`
|
||||
: window.location.href
|
||||
|
||||
// 新的環境變量方式
|
||||
const shareUrl = evaluationId
|
||||
? generateShareUrl(evaluationId)
|
||||
: getCurrentUrl()
|
||||
```
|
||||
|
||||
### 📋 創建環境變量範例
|
||||
|
||||
**文件:`env.example`**
|
||||
|
||||
提供了環境變量配置範例:
|
||||
|
||||
```bash
|
||||
# 應用配置
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:12024
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統
|
||||
|
||||
# 資料庫配置
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_NAME=ai_scoring
|
||||
DB_USER=root
|
||||
DB_PASSWORD=
|
||||
|
||||
# AI 配置
|
||||
GEMINI_API_KEY=your_gemini_api_key_here
|
||||
```
|
||||
|
||||
## 使用方式
|
||||
|
||||
### 🚀 開發環境
|
||||
|
||||
1. **創建環境變量文件**
|
||||
```bash
|
||||
cp env.example .env.local
|
||||
```
|
||||
|
||||
2. **編輯配置**
|
||||
```bash
|
||||
# .env.local
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:12024
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統
|
||||
```
|
||||
|
||||
3. **重啟服務器**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 🌐 生產環境
|
||||
|
||||
在部署平台設置環境變量:
|
||||
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=https://yourdomain.com
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統
|
||||
```
|
||||
|
||||
## 技術優勢
|
||||
|
||||
### ✨ 智能適配
|
||||
|
||||
- **客戶端渲染**:自動使用當前域名,無需配置
|
||||
- **服務端渲染**:使用環境變量,支援不同環境
|
||||
- **回退機制**:確保在任何情況下都能正常工作
|
||||
|
||||
### 🔄 環境靈活性
|
||||
|
||||
- **開發環境**:`http://localhost:12024`
|
||||
- **測試環境**:`https://test.yourdomain.com`
|
||||
- **生產環境**:`https://yourdomain.com`
|
||||
|
||||
### 📱 功能完整性
|
||||
|
||||
- **分享連結**:使用正確的域名
|
||||
- **QR Code**:包含完整的 URL
|
||||
- **郵件分享**:使用配置的域名
|
||||
|
||||
## 測試驗證
|
||||
|
||||
### ✅ 功能測試
|
||||
|
||||
1. **開發環境**
|
||||
- 分享連結應該使用 `http://localhost:12024`
|
||||
- QR Code 包含正確的 URL
|
||||
|
||||
2. **生產環境**
|
||||
- 分享連結使用生產域名
|
||||
- 所有分享功能正常工作
|
||||
|
||||
### 🔍 驗證步驟
|
||||
|
||||
1. 點擊分享按鈕
|
||||
2. 檢查分享連結的域名
|
||||
3. 測試 QR Code 掃描
|
||||
4. 驗證郵件分享功能
|
||||
|
||||
## 注意事項
|
||||
|
||||
### ⚠️ 重要提醒
|
||||
|
||||
1. **環境變量命名**
|
||||
- 必須使用 `NEXT_PUBLIC_` 前綴才能在客戶端使用
|
||||
- 變量名稱區分大小寫
|
||||
|
||||
2. **文件安全**
|
||||
- `.env.local` 不會被提交到版本控制
|
||||
- 敏感信息不要放在客戶端環境變量中
|
||||
|
||||
3. **部署配置**
|
||||
- 確保在部署平台正確設置環境變量
|
||||
- 重啟服務器使環境變量生效
|
||||
|
||||
## 結論
|
||||
|
||||
通過環境變量配置,分享功能現在具備了更好的靈活性和可維護性:
|
||||
|
||||
- ✅ 支援多環境部署
|
||||
- ✅ 自動適配客戶端和服務端
|
||||
- ✅ 提供回退機制確保穩定性
|
||||
- ✅ 保持向後兼容性
|
||||
|
||||
現在您可以在不同環境中使用正確的域名進行分享,無需修改代碼!
|
@@ -1,196 +0,0 @@
|
||||
# 環境變量配置完成總結
|
||||
|
||||
## ✅ 已完成的配置
|
||||
|
||||
### 🔧 核心配置文件
|
||||
|
||||
1. **`lib/config.ts`** - 統一配置管理工具
|
||||
- 資料庫配置 (`dbConfig`)
|
||||
- AI 配置 (`aiConfig`)
|
||||
- 應用配置 (`getAppUrl`, `getAppName`)
|
||||
- 配置驗證 (`validateConfig`)
|
||||
|
||||
2. **`env.example`** - 環境變量範例文件
|
||||
- 包含所有必要的環境變量
|
||||
- 提供完整的配置範例
|
||||
|
||||
3. **`scripts/check-config.js`** - 配置檢查工具
|
||||
- 驗證環境變量設置
|
||||
- 提供配置建議
|
||||
- 顯示當前配置狀態
|
||||
|
||||
### 📱 更新的組件
|
||||
|
||||
1. **`lib/database.ts`** - 使用統一配置
|
||||
```typescript
|
||||
import { dbConfig } from './config';
|
||||
```
|
||||
|
||||
2. **`lib/services/gemini.ts`** - 使用統一配置
|
||||
```typescript
|
||||
import { aiConfig } from '../config';
|
||||
const genAI = new GoogleGenerativeAI(aiConfig.geminiApiKey);
|
||||
```
|
||||
|
||||
3. **`components/share-modal.tsx`** - 使用環境變量 URL
|
||||
```typescript
|
||||
import { generateShareUrl, getCurrentUrl } from "@/lib/config"
|
||||
```
|
||||
|
||||
4. **`package.json`** - 添加配置檢查腳本
|
||||
```json
|
||||
"config:check": "node scripts/check-config.js"
|
||||
```
|
||||
|
||||
## 🌐 環境變量列表
|
||||
|
||||
### 應用配置
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:12024
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統
|
||||
```
|
||||
|
||||
### 資料庫配置
|
||||
```bash
|
||||
DB_HOST=mysql.theaken.com
|
||||
DB_PORT=33306
|
||||
DB_NAME=db_AI_scoring
|
||||
DB_USER=root
|
||||
DB_PASSWORD=zh6161168
|
||||
```
|
||||
|
||||
### AI 配置
|
||||
```bash
|
||||
GEMINI_API_KEY=AIzaSyAN3pEJr_Vn2xkCidGZAq9eQqsMVvpj8g4
|
||||
GEMINI_MODEL=gemini-1.5-pro
|
||||
GEMINI_MAX_TOKENS=8192
|
||||
```
|
||||
|
||||
## 🚀 使用方式
|
||||
|
||||
### 開發環境設置
|
||||
|
||||
1. **複製環境變量範例**
|
||||
```bash
|
||||
cp env.example .env.local
|
||||
```
|
||||
|
||||
2. **運行配置檢查**
|
||||
```bash
|
||||
npm run config:check
|
||||
```
|
||||
|
||||
3. **重啟開發服務器**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 生產環境設置
|
||||
|
||||
在部署平台設置環境變量:
|
||||
```bash
|
||||
NEXT_PUBLIC_APP_URL=https://yourdomain.com
|
||||
DB_HOST=your-production-db-host
|
||||
DB_NAME=your_production_db
|
||||
GEMINI_API_KEY=your_production_key
|
||||
```
|
||||
|
||||
## 🔍 配置驗證
|
||||
|
||||
### 檢查命令
|
||||
```bash
|
||||
npm run config:check
|
||||
```
|
||||
|
||||
### 檢查結果範例
|
||||
```
|
||||
🔍 檢查環境變量配置...
|
||||
|
||||
📋 當前環境變量:
|
||||
✅ NEXT_PUBLIC_APP_URL: http://localhost:12024
|
||||
✅ NEXT_PUBLIC_APP_NAME: AI 智能評審系統
|
||||
✅ DB_HOST: mysql.theaken.com
|
||||
✅ DB_PORT: 33306
|
||||
✅ DB_NAME: db_AI_scoring
|
||||
✅ DB_USER: root
|
||||
✅ DB_PASSWORD: ***已設置***
|
||||
✅ GEMINI_API_KEY: ***已設置***
|
||||
✅ GEMINI_MODEL: gemini-1.5-pro
|
||||
✅ GEMINI_MAX_TOKENS: 8192
|
||||
|
||||
✅ 所有必要的環境變量都已設置
|
||||
```
|
||||
|
||||
## 🎯 功能特色
|
||||
|
||||
### ✨ 統一配置管理
|
||||
- 所有配置集中在 `lib/config.ts`
|
||||
- 類型安全的配置對象
|
||||
- 回退機制確保穩定性
|
||||
|
||||
### 🔒 安全配置
|
||||
- 敏感信息通過環境變量管理
|
||||
- 客戶端/服務端配置分離
|
||||
- 配置驗證工具
|
||||
|
||||
### 🌍 多環境支援
|
||||
- 開發、測試、生產環境配置
|
||||
- 自動環境檢測
|
||||
- 靈活的部署選項
|
||||
|
||||
### 📱 分享功能優化
|
||||
- 使用環境變量的 URL 生成
|
||||
- 支援不同域名的分享
|
||||
- QR Code 包含正確的 URL
|
||||
|
||||
## 🛠️ 技術優勢
|
||||
|
||||
1. **可維護性**
|
||||
- 統一的配置管理
|
||||
- 清晰的配置結構
|
||||
- 易於擴展和修改
|
||||
|
||||
2. **安全性**
|
||||
- 敏感信息不硬編碼
|
||||
- 環境變量隔離
|
||||
- 配置驗證機制
|
||||
|
||||
3. **靈活性**
|
||||
- 支援多環境部署
|
||||
- 動態配置加載
|
||||
- 回退機制
|
||||
|
||||
4. **開發體驗**
|
||||
- 配置檢查工具
|
||||
- 清晰的錯誤提示
|
||||
- 詳細的使用說明
|
||||
|
||||
## 📋 下一步建議
|
||||
|
||||
1. **設置環境變量**
|
||||
```bash
|
||||
cp env.example .env.local
|
||||
# 編輯 .env.local 文件
|
||||
```
|
||||
|
||||
2. **測試配置**
|
||||
```bash
|
||||
npm run config:check
|
||||
npm run dev
|
||||
```
|
||||
|
||||
3. **部署準備**
|
||||
- 在部署平台設置生產環境變量
|
||||
- 使用不同的 API 密鑰和資料庫配置
|
||||
|
||||
## 🎉 結論
|
||||
|
||||
環境變量配置已經完全整合到應用中,現在具備:
|
||||
|
||||
- ✅ **完整的配置管理**:應用、資料庫、AI 配置
|
||||
- ✅ **安全的環境變量**:敏感信息保護
|
||||
- ✅ **多環境支援**:開發、測試、生產
|
||||
- ✅ **配置驗證工具**:確保配置正確
|
||||
- ✅ **分享功能優化**:使用正確的域名
|
||||
|
||||
現在您可以輕鬆地在不同環境中部署應用,只需設置相應的環境變量即可!🚀
|
@@ -1,115 +0,0 @@
|
||||
# Hover 效果優化總結
|
||||
|
||||
## 問題描述
|
||||
原本的按鈕使用預設的 `variant="outline"` 樣式,導致 hover 時顯示藍色背景,與整體設計風格不符。
|
||||
|
||||
## 解決方案
|
||||
|
||||
### 🎨 自定義 Hover 效果
|
||||
|
||||
為每個按鈕類型設計了符合其品牌色彩的 hover 效果:
|
||||
|
||||
#### 1. **LINE 按鈕**
|
||||
```css
|
||||
hover:bg-green-50 hover:border-green-300 hover:text-green-700
|
||||
```
|
||||
- 背景:淡綠色
|
||||
- 邊框:綠色
|
||||
- 文字:深綠色
|
||||
|
||||
#### 2. **Facebook 按鈕**
|
||||
```css
|
||||
hover:bg-blue-50 hover:border-blue-300 hover:text-blue-700
|
||||
```
|
||||
- 背景:淡藍色
|
||||
- 邊框:藍色
|
||||
- 文字:深藍色
|
||||
|
||||
#### 3. **Email 按鈕**
|
||||
```css
|
||||
hover:bg-slate-50 hover:border-slate-300 hover:text-slate-700
|
||||
```
|
||||
- 背景:淡灰色
|
||||
- 邊框:灰色
|
||||
- 文字:深灰色
|
||||
|
||||
#### 4. **複製按鈕**
|
||||
```css
|
||||
hover:bg-primary/5 hover:border-primary/20 hover:text-primary
|
||||
```
|
||||
- 背景:主題色的 5% 透明度
|
||||
- 邊框:主題色的 20% 透明度
|
||||
- 文字:主題色
|
||||
|
||||
### ✨ 設計特色
|
||||
|
||||
1. **品牌一致性**
|
||||
- 每個按鈕的 hover 效果都與其品牌色彩相符
|
||||
- 保持視覺識別的一致性
|
||||
|
||||
2. **平滑過渡**
|
||||
- 添加 `transition-colors` 實現平滑的顏色過渡
|
||||
- 提升用戶體驗
|
||||
|
||||
3. **禁用狀態處理**
|
||||
- 為禁用狀態的按鈕添加特殊的 hover 效果
|
||||
- 確保禁用時不會有 hover 反饋
|
||||
|
||||
4. **色彩層次**
|
||||
- 使用淡色背景和深色文字形成對比
|
||||
- 保持良好的可讀性
|
||||
|
||||
## 技術實現
|
||||
|
||||
### 🔧 CSS 類別應用
|
||||
|
||||
```jsx
|
||||
// LINE 按鈕
|
||||
className="... hover:bg-green-50 hover:border-green-300 hover:text-green-700 transition-colors"
|
||||
|
||||
// Facebook 按鈕
|
||||
className="... hover:bg-blue-50 hover:border-blue-300 hover:text-blue-700 transition-colors"
|
||||
|
||||
// Email 按鈕
|
||||
className="... hover:bg-slate-50 hover:border-slate-300 hover:text-slate-700 transition-colors"
|
||||
|
||||
// 複製按鈕
|
||||
className="... hover:bg-primary/5 hover:border-primary/20 hover:text-primary transition-colors"
|
||||
```
|
||||
|
||||
### 🎯 響應式設計
|
||||
|
||||
- 所有 hover 效果在各種螢幕尺寸下都保持一致
|
||||
- 確保觸控設備上的視覺反饋
|
||||
|
||||
## 效果對比
|
||||
|
||||
### ❌ 修改前
|
||||
- 所有按鈕 hover 時都顯示藍色背景
|
||||
- 與品牌色彩不符
|
||||
- 視覺體驗不統一
|
||||
|
||||
### ✅ 修改後
|
||||
- 每個按鈕都有符合其品牌的 hover 效果
|
||||
- 視覺層次更清晰
|
||||
- 用戶體驗更佳
|
||||
|
||||
## 測試建議
|
||||
|
||||
1. **功能測試**
|
||||
- 測試所有按鈕的 hover 效果
|
||||
- 驗證顏色過渡是否平滑
|
||||
- 檢查禁用狀態的處理
|
||||
|
||||
2. **視覺測試**
|
||||
- 在不同背景下測試對比度
|
||||
- 驗證色彩搭配的和諧性
|
||||
- 檢查各種螢幕尺寸下的表現
|
||||
|
||||
3. **可用性測試**
|
||||
- 確保 hover 效果提供足夠的視覺反饋
|
||||
- 驗證觸控設備上的表現
|
||||
|
||||
## 結論
|
||||
|
||||
通過自定義 hover 效果,分享按鈕現在具有更好的視覺一致性和用戶體驗。每個按鈕都保持其品牌特色,同時提供清晰的互動反饋。
|
@@ -1,149 +0,0 @@
|
||||
# AI 評分整合功能總結
|
||||
|
||||
## 概述
|
||||
|
||||
已成功將 AI 評分結果整合到資料庫存儲系統中。當用戶上傳 PPT 文件並點擊「開始 AI 評審」按鈕時,系統會自動將所有相關資料上傳到資料庫的三個主要表中。
|
||||
|
||||
## 整合的資料庫表
|
||||
|
||||
### 1. projects 表
|
||||
- **用途**: 儲存專案基本資訊
|
||||
- **創建時機**: AI 分析開始前
|
||||
- **主要欄位**:
|
||||
- `id`: 專案唯一識別碼
|
||||
- `user_id`: 用戶 ID
|
||||
- `template_id`: 評分標準模板 ID
|
||||
- `title`: 專案標題
|
||||
- `description`: 專案描述
|
||||
- `status`: 專案狀態 (analyzing → completed)
|
||||
- `analysis_started_at`: 分析開始時間
|
||||
- `analysis_completed_at`: 分析完成時間
|
||||
|
||||
### 2. project_files 表
|
||||
- **用途**: 儲存上傳的文件資訊
|
||||
- **創建時機**: 文件上傳後,AI 分析前
|
||||
- **主要欄位**:
|
||||
- `id`: 文件唯一識別碼
|
||||
- `project_id`: 關聯的專案 ID
|
||||
- `original_name`: 原始文件名稱
|
||||
- `file_name`: 儲存的文件名稱
|
||||
- `file_path`: 文件儲存路徑
|
||||
- `file_size`: 文件大小
|
||||
- `file_type`: 文件類型
|
||||
- `mime_type`: MIME 類型
|
||||
- `upload_status`: 上傳狀態
|
||||
- `upload_progress`: 上傳進度
|
||||
|
||||
### 3. evaluations 表
|
||||
- **用途**: 儲存 AI 評審的基本資訊
|
||||
- **創建時機**: AI 分析完成後
|
||||
- **主要欄位**:
|
||||
- `id`: 評審唯一識別碼
|
||||
- `project_id`: 關聯的專案 ID
|
||||
- `overall_score`: 總分
|
||||
- `max_possible_score`: 滿分
|
||||
- `grade`: 等級評定
|
||||
- `analysis_duration`: 分析耗時
|
||||
- `ai_model_version`: AI 模型版本
|
||||
- `status`: 評審狀態
|
||||
- `error_message`: 錯誤訊息
|
||||
|
||||
### 4. evaluation_scores 表
|
||||
- **用途**: 儲存各項評分標準的詳細分數
|
||||
- **創建時機**: AI 分析完成後
|
||||
- **主要欄位**:
|
||||
- `id`: 評分記錄唯一識別碼
|
||||
- `evaluation_id`: 關聯的評審 ID
|
||||
- `criteria_item_id`: 關聯的評分標準項目 ID
|
||||
- `score`: 得分
|
||||
- `max_score`: 滿分
|
||||
- `weight`: 權重
|
||||
- `weighted_score`: 加權分數
|
||||
- `percentage`: 得分百分比
|
||||
|
||||
### 5. evaluation_feedback 表
|
||||
- **用途**: 儲存 AI 的評語和建議
|
||||
- **創建時機**: AI 分析完成後
|
||||
- **主要欄位**:
|
||||
- `id`: 反饋記錄唯一識別碼
|
||||
- `evaluation_id`: 關聯的評審 ID
|
||||
- `criteria_item_id`: 關聯的評分標準項目 ID (可為空)
|
||||
- `feedback_type`: 反饋類型 (overall/criteria/strength/improvement)
|
||||
- `content`: 反饋內容
|
||||
- `sort_order`: 排序順序
|
||||
|
||||
## 處理流程
|
||||
|
||||
### 1. 用戶操作
|
||||
1. 用戶訪問上傳頁面 (`/upload`)
|
||||
2. 上傳 PPT 文件
|
||||
3. 填寫專案標題和描述
|
||||
4. 點擊「開始 AI 評審」按鈕
|
||||
|
||||
### 2. 後端處理
|
||||
1. **驗證輸入**: 檢查必填欄位和文件格式
|
||||
2. **載入評分標準**: 從資料庫獲取評分標準模板
|
||||
3. **創建專案記錄**: 在 `projects` 表中創建專案記錄
|
||||
4. **處理文件上傳**: 在 `project_files` 表中創建文件記錄
|
||||
5. **AI 分析**: 使用 Gemini AI 分析 PPT 內容
|
||||
6. **上傳評審結果**: 將 AI 分析結果上傳到資料庫
|
||||
- 創建 `evaluations` 記錄
|
||||
- 創建 `evaluation_scores` 記錄
|
||||
- 創建 `evaluation_feedback` 記錄
|
||||
7. **更新專案狀態**: 將專案狀態設為完成
|
||||
8. **返回結果**: 將評分結果返回給前端
|
||||
|
||||
### 3. 前端顯示
|
||||
1. 接收評分結果
|
||||
2. 儲存到 localStorage
|
||||
3. 導向到結果頁面 (`/results`)
|
||||
4. 顯示評分結果和圖表
|
||||
|
||||
## 技術實現
|
||||
|
||||
### 修改的文件
|
||||
- `app/api/evaluate/route.ts`: 主要的 API 端點,整合了資料庫上傳功能
|
||||
|
||||
### 關鍵功能
|
||||
- **錯誤處理**: 即使資料庫上傳失敗,也會返回 AI 分析結果
|
||||
- **資料轉換**: 將資料庫格式轉換為 AI 服務期望的格式
|
||||
- **完整日誌**: 詳細的控制台日誌記錄整個處理過程
|
||||
- **狀態管理**: 正確管理專案和評審的狀態
|
||||
|
||||
### 資料庫關聯
|
||||
- `projects` ← `project_files` (一對多)
|
||||
- `projects` ← `evaluations` (一對一)
|
||||
- `evaluations` ← `evaluation_scores` (一對多)
|
||||
- `evaluations` ← `evaluation_feedback` (一對多)
|
||||
- `criteria_items` ← `evaluation_scores` (一對多)
|
||||
- `criteria_items` ← `evaluation_feedback` (一對多)
|
||||
|
||||
## 測試和驗證
|
||||
|
||||
### 測試腳本
|
||||
- `scripts/test-integration.js`: 提供完整的測試指南和檢查要點
|
||||
|
||||
### 驗證要點
|
||||
1. 控制台日誌顯示完整的處理流程
|
||||
2. 資料庫正確創建所有相關記錄
|
||||
3. 前端正確顯示評分結果
|
||||
4. 沒有錯誤或異常
|
||||
5. 處理時間在合理範圍內
|
||||
|
||||
## 使用方式
|
||||
|
||||
1. 確保資料庫連線正常
|
||||
2. 確保有評分標準模板
|
||||
3. 啟動應用程式: `npm run dev`
|
||||
4. 訪問上傳頁面: `http://localhost:3000/upload`
|
||||
5. 上傳 PPT 文件並填寫專案資訊
|
||||
6. 點擊「開始 AI 評審」按鈕
|
||||
7. 查看結果頁面顯示的評分結果
|
||||
|
||||
## 注意事項
|
||||
|
||||
- 所有資料庫操作都包含在 try-catch 區塊中
|
||||
- 即使資料庫上傳失敗,AI 分析結果仍會返回給用戶
|
||||
- 專案狀態會正確更新為完成狀態
|
||||
- 支援多種文件格式 (PPT, PDF, 影片等)
|
||||
- 包含完整的錯誤處理和日誌記錄
|
454
README.md
454
README.md
@@ -1,30 +1,448 @@
|
||||
# AI scoring application
|
||||
# AI 智能評審系統
|
||||
|
||||
*Automatically synced with your [v0.app](https://v0.app) deployments*
|
||||
一個基於 Next.js 和 Google Gemini AI 的智能評審平台,支援多種格式內容上傳(PPT、影片、網站連結),並根據自定義評分標準進行 AI 智能評分。
|
||||
|
||||
[](https://vercel.com/pettys-projects/v0-ai-scoring-application)
|
||||
[](https://v0.app/chat/projects/0LR55VqrLTi)
|
||||
## 🚀 功能特色
|
||||
|
||||
## Overview
|
||||
### 核心功能
|
||||
- **多格式內容支援**:支援 PPT/PPTX、影片檔案、網站連結上傳
|
||||
- **自定義評分標準**:可設定評分項目、權重比例和滿分標準
|
||||
- **AI 智能評分**:使用 Google Gemini AI 進行內容分析和評分
|
||||
- **詳細評分報告**:提供完整的評分結果、改進建議和行動計劃
|
||||
- **PDF 報告生成**:可下載專業的 PDF 評分報告
|
||||
- **歷史記錄管理**:追蹤所有評審記錄和統計數據
|
||||
|
||||
This repository will stay in sync with your deployed chats on [v0.app](https://v0.app).
|
||||
Any changes you make to your deployed app will be automatically pushed to this repository from [v0.app](https://v0.app).
|
||||
### 技術特色
|
||||
- **現代化 UI**:基於 Radix UI 和 Tailwind CSS 的響應式設計
|
||||
- **TypeScript**:完整的類型安全支援
|
||||
- **資料庫整合**:MySQL 資料庫存儲所有評審數據
|
||||
- **PDF 生成**:使用 Puppeteer 生成專業 PDF 報告
|
||||
- **文件處理**:支援 PPTX 解析和內容提取
|
||||
|
||||
## Deployment
|
||||
## 🏗️ 技術架構
|
||||
|
||||
Your project is live at:
|
||||
### 前端技術棧
|
||||
- **框架**:Next.js 14.2.16 (App Router)
|
||||
- **語言**:TypeScript 5
|
||||
- **樣式**:Tailwind CSS 4.1.9
|
||||
- **UI 組件**:Radix UI + shadcn/ui
|
||||
- **字體**:Geist Sans/Mono + Playfair Display
|
||||
- **圖表**:Recharts
|
||||
|
||||
**[https://vercel.com/pettys-projects/v0-ai-scoring-application](https://vercel.com/pettys-projects/v0-ai-scoring-application)**
|
||||
### 後端技術棧
|
||||
- **API**:Next.js API Routes
|
||||
- **資料庫**:MySQL 8.0
|
||||
- **ORM**:mysql2 (原生 SQL)
|
||||
- **AI 服務**:Google Generative AI (Gemini 1.5 Pro)
|
||||
- **PDF 生成**:Puppeteer 24.22.1
|
||||
- **文件處理**:adm-zip, mammoth
|
||||
|
||||
## Build your app
|
||||
### 開發工具
|
||||
- **包管理**:pnpm
|
||||
- **代碼規範**:ESLint
|
||||
- **類型檢查**:TypeScript
|
||||
- **部署**:Vercel Analytics
|
||||
|
||||
Continue building your app on:
|
||||
## 📁 專案結構
|
||||
|
||||
**[https://v0.app/chat/projects/0LR55VqrLTi](https://v0.app/chat/projects/0LR55VqrLTi)**
|
||||
```
|
||||
ai-scoring-application/
|
||||
├── app/ # Next.js App Router
|
||||
│ ├── api/ # API 路由
|
||||
│ │ ├── criteria-templates/ # 評分標準模板 API
|
||||
│ │ ├── evaluate/ # 評審 API
|
||||
│ │ ├── evaluation/ # 評審記錄 API
|
||||
│ │ ├── history/ # 歷史記錄 API
|
||||
│ │ └── upload/ # 文件上傳 API
|
||||
│ ├── criteria/ # 評分標準頁面
|
||||
│ ├── history/ # 歷史記錄頁面
|
||||
│ ├── results/ # 評分結果頁面
|
||||
│ ├── upload/ # 文件上傳頁面
|
||||
│ ├── layout.tsx # 根佈局
|
||||
│ ├── page.tsx # 首頁
|
||||
│ └── globals.css # 全域樣式
|
||||
├── components/ # React 組件
|
||||
│ ├── ui/ # UI 組件庫
|
||||
│ ├── sidebar.tsx # 側邊欄
|
||||
│ ├── share-modal.tsx # 分享模態框
|
||||
│ └── theme-provider.tsx # 主題提供者
|
||||
├── lib/ # 核心庫
|
||||
│ ├── services/ # 業務邏輯服務
|
||||
│ │ ├── database.ts # 資料庫服務
|
||||
│ │ ├── gemini.ts # Gemini AI 服務
|
||||
│ │ └── evaluation-upload.ts # 評審上傳服務
|
||||
│ ├── utils/ # 工具函數
|
||||
│ │ ├── html-pdf-generator.ts # PDF 生成器
|
||||
│ │ ├── pdf-generator.ts # 舊版 PDF 生成器
|
||||
│ │ └── file-path.ts # 文件路徑工具
|
||||
│ ├── models/ # 資料模型
|
||||
│ ├── config.ts # 配置管理
|
||||
│ └── database.ts # 資料庫連接
|
||||
├── database/ # 資料庫相關
|
||||
│ ├── schema.sql # 資料庫架構
|
||||
│ └── README.md # 資料庫說明
|
||||
├── public/ # 靜態資源
|
||||
├── uploads/ # 上傳文件存儲
|
||||
├── data/ # 示例數據
|
||||
├── examples/ # 示例代碼
|
||||
├── hooks/ # React Hooks
|
||||
├── styles/ # 額外樣式
|
||||
├── package.json # 專案依賴
|
||||
├── tsconfig.json # TypeScript 配置
|
||||
├── next.config.mjs # Next.js 配置
|
||||
├── tailwind.config.js # Tailwind 配置
|
||||
└── README.md # 專案說明
|
||||
```
|
||||
|
||||
## How It Works
|
||||
## 🗄️ 資料庫架構
|
||||
|
||||
1. Create and modify your project using [v0.app](https://v0.app)
|
||||
2. Deploy your chats from the v0 interface
|
||||
3. Changes are automatically pushed to this repository
|
||||
4. Vercel deploys the latest version from this repository
|
||||
### 核心資料表
|
||||
|
||||
#### 用戶管理
|
||||
- `users` - 用戶基本資訊
|
||||
- `user_sessions` - 用戶會話管理
|
||||
|
||||
#### 評分標準
|
||||
- `criteria_templates` - 評分標準模板
|
||||
- `criteria_items` - 評分項目明細
|
||||
|
||||
#### 專案管理
|
||||
- `projects` - 評審專案
|
||||
- `project_files` - 專案文件
|
||||
- `project_websites` - 專案網站連結
|
||||
|
||||
#### 評審記錄
|
||||
- `evaluations` - 評審記錄
|
||||
- `evaluation_scores` - 評分結果明細
|
||||
- `evaluation_feedback` - AI 評語和建議
|
||||
|
||||
#### 系統設定
|
||||
- `system_settings` - 系統配置參數
|
||||
|
||||
### 預設評分標準
|
||||
系統預設包含 5 個評分項目:
|
||||
1. **內容品質** (25%) - 內容的準確性、完整性和專業度
|
||||
2. **視覺設計** (20%) - 版面設計、色彩搭配和視覺效果
|
||||
3. **邏輯結構** (20%) - 內容組織的邏輯性和條理性
|
||||
4. **創新性** (15%) - 創意思維和獨特觀點的展現
|
||||
5. **實用性** (20%) - 內容的實際應用價值和可操作性
|
||||
|
||||
## 🔧 安裝與設定
|
||||
|
||||
### 環境需求
|
||||
- Node.js 18+
|
||||
- pnpm 8+
|
||||
- MySQL 8.0+
|
||||
- Chrome 瀏覽器 (用於 PDF 生成)
|
||||
|
||||
### 1. 克隆專案
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd ai-scoring-application
|
||||
```
|
||||
|
||||
### 2. 安裝依賴
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### 3. 環境變數設定
|
||||
複製 `env.example` 為 `.env.local` 並設定以下變數:
|
||||
|
||||
```env
|
||||
# 應用配置
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:12024
|
||||
NEXT_PUBLIC_APP_NAME=AI 智能評審系統
|
||||
|
||||
# 資料庫配置
|
||||
DB_HOST=mysql.theaken.com
|
||||
DB_PORT=33306
|
||||
DB_NAME=db_AI_scoring
|
||||
DB_USER=root
|
||||
DB_PASSWORD=your_password
|
||||
|
||||
# AI 配置
|
||||
GEMINI_API_KEY=your_gemini_api_key
|
||||
GEMINI_MODEL=gemini-1.5-pro
|
||||
GEMINI_MAX_TOKENS=8192
|
||||
```
|
||||
|
||||
### 4. 資料庫初始化
|
||||
```bash
|
||||
# 初始化資料庫結構
|
||||
pnpm run db:init
|
||||
|
||||
# 測試資料庫連接
|
||||
pnpm run db:test
|
||||
|
||||
# 檢查配置
|
||||
pnpm run config:check
|
||||
```
|
||||
|
||||
### 5. 安裝 Puppeteer Chrome
|
||||
```bash
|
||||
npx puppeteer browsers install chrome
|
||||
```
|
||||
|
||||
### 6. 啟動開發伺服器
|
||||
```bash
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
應用將在 `http://localhost:12024` 啟動。
|
||||
|
||||
## 🚀 部署
|
||||
|
||||
### Vercel 部署
|
||||
1. 將專案推送到 GitHub
|
||||
2. 在 Vercel 中導入專案
|
||||
3. 設定環境變數
|
||||
4. 部署完成
|
||||
|
||||
### 自託管部署
|
||||
```bash
|
||||
# 建構專案
|
||||
pnpm run build
|
||||
|
||||
# 啟動生產伺服器
|
||||
pnpm run start
|
||||
```
|
||||
|
||||
## 📖 API 文檔
|
||||
|
||||
### 評分標準模板 API
|
||||
|
||||
#### 獲取所有模板
|
||||
```
|
||||
GET /api/criteria-templates
|
||||
```
|
||||
|
||||
#### 獲取預設模板
|
||||
```
|
||||
GET /api/criteria-templates/default
|
||||
```
|
||||
|
||||
#### 獲取特定模板
|
||||
```
|
||||
GET /api/criteria-templates/[id]
|
||||
```
|
||||
|
||||
### 文件上傳 API
|
||||
|
||||
#### 上傳文件
|
||||
```
|
||||
POST /api/upload
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
Body:
|
||||
- files: File[] (支援多檔案上傳)
|
||||
- projectTitle: string
|
||||
- projectDescription: string
|
||||
- templateId: number
|
||||
```
|
||||
|
||||
### 評審 API
|
||||
|
||||
#### 開始評審
|
||||
```
|
||||
POST /api/evaluate
|
||||
Content-Type: application/json
|
||||
|
||||
Body:
|
||||
{
|
||||
"projectId": number,
|
||||
"templateId": number
|
||||
}
|
||||
```
|
||||
|
||||
#### 獲取評審結果
|
||||
```
|
||||
GET /api/evaluation/[id]
|
||||
```
|
||||
|
||||
#### 下載 PDF 報告
|
||||
```
|
||||
GET /api/evaluation/[id]/download
|
||||
```
|
||||
|
||||
#### 刪除評審記錄
|
||||
```
|
||||
DELETE /api/evaluation/[id]/delete
|
||||
```
|
||||
|
||||
### 歷史記錄 API
|
||||
|
||||
#### 獲取歷史記錄
|
||||
```
|
||||
GET /api/history
|
||||
Query Parameters:
|
||||
- page: number (預設 1)
|
||||
- limit: number (預設 20)
|
||||
```
|
||||
|
||||
#### 獲取統計數據
|
||||
```
|
||||
GET /api/history/stats
|
||||
```
|
||||
|
||||
## 🎯 使用流程
|
||||
|
||||
### 1. 設定評分標準
|
||||
- 進入「評分標準」頁面
|
||||
- 選擇或創建評分標準模板
|
||||
- 設定評分項目和權重比例
|
||||
|
||||
### 2. 上傳內容
|
||||
- 進入「上傳文件」頁面
|
||||
- 填寫專案資訊(標題、描述)
|
||||
- 選擇評分標準模板
|
||||
- 上傳 PPT/影片文件或提供網站連結
|
||||
|
||||
### 3. AI 分析評分
|
||||
- 系統自動提取內容
|
||||
- 使用 Gemini AI 分析內容
|
||||
- 根據評分標準進行評分
|
||||
- 生成詳細的評分結果
|
||||
|
||||
### 4. 查看結果
|
||||
- 進入「評分結果」頁面查看詳細評分
|
||||
- 瀏覽各項評分和 AI 評語
|
||||
- 查看改進建議和行動計劃
|
||||
- 下載 PDF 報告
|
||||
|
||||
### 5. 歷史管理
|
||||
- 在「歷史記錄」頁面查看所有評審記錄
|
||||
- 追蹤評分統計和趨勢
|
||||
- 重新查看過往評審結果
|
||||
|
||||
## 🔍 核心功能詳解
|
||||
|
||||
### AI 評分流程
|
||||
1. **內容提取**:從 PPT/影片/網站中提取文字內容
|
||||
2. **AI 分析**:使用 Gemini AI 分析內容質量
|
||||
3. **標準對照**:根據設定的評分標準進行評分
|
||||
4. **結果生成**:產生詳細的評分報告和改進建議
|
||||
|
||||
### PDF 報告生成
|
||||
- 使用 Puppeteer 生成專業 PDF 報告
|
||||
- 包含完整的評分結果、圖表和建議
|
||||
- 支援中文排版和專業格式
|
||||
- 可自定義報告樣式
|
||||
|
||||
### 文件處理能力
|
||||
- **PPTX 解析**:提取幻燈片文字內容
|
||||
- **影片支援**:處理影片檔案上傳
|
||||
- **網站分析**:分析網站內容
|
||||
- **多格式支援**:支援多種文件格式
|
||||
|
||||
## 🛠️ 開發指南
|
||||
|
||||
### 添加新的評分標準
|
||||
1. 在資料庫中添加新的 `criteria_items`
|
||||
2. 更新 `criteriaNameToId` 映射
|
||||
3. 測試評分功能
|
||||
|
||||
### 自定義 AI 提示詞
|
||||
修改 `lib/services/gemini.ts` 中的 `buildScoringPrompt` 方法
|
||||
|
||||
### 添加新的文件格式支援
|
||||
1. 在 `GeminiService.extractPPTContent` 中添加新的解析邏輯
|
||||
2. 更新文件類型檢查
|
||||
3. 測試內容提取功能
|
||||
|
||||
### 自定義 PDF 模板
|
||||
修改 `lib/utils/html-pdf-generator.ts` 中的 HTML 模板
|
||||
|
||||
## 🐛 故障排除
|
||||
|
||||
### 常見問題
|
||||
|
||||
#### 1. Puppeteer Chrome 錯誤
|
||||
```
|
||||
Error: Could not find Chrome
|
||||
```
|
||||
**解決方案**:
|
||||
```bash
|
||||
npx puppeteer browsers install chrome
|
||||
```
|
||||
|
||||
#### 2. 資料庫連接失敗
|
||||
檢查環境變數設定:
|
||||
```bash
|
||||
pnpm run db:test
|
||||
```
|
||||
|
||||
#### 3. Gemini API 錯誤
|
||||
確認 API Key 是否正確設定:
|
||||
```bash
|
||||
pnpm run config:check
|
||||
```
|
||||
|
||||
#### 4. 文件上傳失敗
|
||||
檢查文件大小和格式限制:
|
||||
- 最大文件大小:100MB
|
||||
- 支援格式:ppt, pptx, pdf, mp4, avi, mov, wmv, flv, webm
|
||||
|
||||
### 日誌調試
|
||||
應用使用 `console.log` 輸出詳細的調試信息,可以在瀏覽器開發者工具和伺服器終端中查看。
|
||||
|
||||
## 📊 性能優化
|
||||
|
||||
### 資料庫優化
|
||||
- 使用連接池管理資料庫連接
|
||||
- 建立適當的索引提升查詢性能
|
||||
- 使用事務確保數據一致性
|
||||
|
||||
### AI 處理優化
|
||||
- 實現請求超時機制
|
||||
- 添加錯誤重試邏輯
|
||||
- 優化提示詞減少 Token 消耗
|
||||
|
||||
### 前端優化
|
||||
- 使用 React.memo 減少不必要的重新渲染
|
||||
- 實現虛擬滾動處理大量數據
|
||||
- 使用 Next.js 圖片優化
|
||||
|
||||
## 🔒 安全考量
|
||||
|
||||
### 數據安全
|
||||
- 所有用戶輸入都經過驗證和清理
|
||||
- 使用參數化查詢防止 SQL 注入
|
||||
- 文件上傳限制和類型檢查
|
||||
|
||||
### API 安全
|
||||
- 實現請求頻率限制
|
||||
- 添加身份驗證機制
|
||||
- 敏感信息不在客戶端暴露
|
||||
|
||||
## 🤝 貢獻指南
|
||||
|
||||
1. Fork 專案
|
||||
2. 創建功能分支 (`git checkout -b feature/AmazingFeature`)
|
||||
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
|
||||
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
||||
5. 開啟 Pull Request
|
||||
|
||||
## 📝 更新日誌
|
||||
|
||||
### v1.0.0 (2024-01-15)
|
||||
- ✨ 初始版本發布
|
||||
- 🎯 支援 PPT/影片/網站連結上傳
|
||||
- 🤖 整合 Gemini AI 評分
|
||||
- 📊 完整的評分報告系統
|
||||
- 📄 PDF 報告生成功能
|
||||
|
||||
## 📄 授權條款
|
||||
|
||||
本專案採用 MIT 授權條款 - 查看 [LICENSE](LICENSE) 文件了解詳情。
|
||||
|
||||
## 📞 技術支援
|
||||
|
||||
如有問題或建議,請:
|
||||
- 提交 [Issue](https://github.com/your-repo/issues)
|
||||
- 發送郵件至:your-email@example.com
|
||||
- 查看 [Wiki](https://github.com/your-repo/wiki) 獲取更多文檔
|
||||
|
||||
---
|
||||
|
||||
**AI 智能評審系統** - 讓 AI 為您的內容提供專業評審 🚀
|
@@ -1,135 +0,0 @@
|
||||
# 分享報告功能實現總結
|
||||
|
||||
## 功能概述
|
||||
|
||||
我已經成功實現了評審結果的分享功能,包括以下特性:
|
||||
|
||||
### 🎯 核心功能
|
||||
|
||||
1. **分享視窗** - 點擊分享按鈕會彈出一個美觀的分享視窗
|
||||
2. **QR Code 生成** - 自動生成報告的 QR Code,方便手機掃描
|
||||
3. **連結複製** - 一鍵複製報告連結到剪貼板
|
||||
4. **社群分享** - 支援直接分享到 LINE、Facebook、Twitter
|
||||
5. **QR Code 複製** - 可將 QR Code 複製到剪貼板
|
||||
|
||||
### 🎨 設計特色
|
||||
|
||||
- **與整體設計一致** - 使用相同的設計語言和色彩方案
|
||||
- **響應式設計** - 適配各種螢幕尺寸
|
||||
- **現代化 UI** - 使用 Radix UI 和 Tailwind CSS
|
||||
- **直觀的圖標** - 使用 Lucide React 圖標庫
|
||||
|
||||
## 技術實現
|
||||
|
||||
### 📁 新增文件
|
||||
|
||||
1. **`components/ui/dialog.tsx`** - Dialog 組件(基於 Radix UI)
|
||||
2. **`components/share-modal.tsx`** - 分享視窗組件
|
||||
3. **`SHARE_FEATURE_SUMMARY.md`** - 功能說明文檔
|
||||
|
||||
### 🔧 修改文件
|
||||
|
||||
1. **`app/results/page.tsx`** - 整合分享功能到評審結果頁面
|
||||
|
||||
### 📦 新增依賴
|
||||
|
||||
- **`qrcode`** - QR Code 生成庫
|
||||
- **`@types/qrcode`** - TypeScript 類型定義
|
||||
|
||||
## 功能詳情
|
||||
|
||||
### 🔗 分享連結
|
||||
|
||||
- 自動生成包含評審 ID 的專用連結
|
||||
- 格式:`https://your-domain.com/results?id={evaluationId}`
|
||||
- 一鍵複製到剪貼板
|
||||
- 複製成功後顯示確認提示
|
||||
|
||||
### 📱 QR Code
|
||||
|
||||
- 自動生成高品質 QR Code
|
||||
- 200x200 像素,適合各種使用場景
|
||||
- 支援複製到剪貼板
|
||||
- 生成失敗時顯示錯誤提示
|
||||
|
||||
### 🌐 社群分享
|
||||
|
||||
支援以下平台:
|
||||
- **LINE** - 綠色主題按鈕
|
||||
- **Facebook** - 藍色主題按鈕
|
||||
- **Twitter** - 天藍色主題按鈕
|
||||
|
||||
每個按鈕都會在新視窗中開啟對應的分享頁面。
|
||||
|
||||
### 💡 使用者體驗
|
||||
|
||||
- **載入狀態** - QR Code 生成時顯示載入動畫
|
||||
- **錯誤處理** - 優雅的錯誤提示和回退機制
|
||||
- **確認反饋** - 複製成功後顯示視覺確認
|
||||
- **無障礙設計** - 支援螢幕閱讀器
|
||||
|
||||
## 使用方法
|
||||
|
||||
1. 在評審結果頁面點擊「分享」按鈕
|
||||
2. 分享視窗會自動彈出
|
||||
3. 選擇分享方式:
|
||||
- 複製連結
|
||||
- 複製 QR Code
|
||||
- 分享到社群平台
|
||||
|
||||
## 技術細節
|
||||
|
||||
### 🔒 安全性
|
||||
|
||||
- 使用 Next.js 的 `useSearchParams` 安全獲取 URL 參數
|
||||
- 所有用戶輸入都經過適當的驗證和清理
|
||||
|
||||
### 🚀 效能
|
||||
|
||||
- QR Code 只在需要時生成,避免不必要的計算
|
||||
- 使用 React 的 `useEffect` 進行優化
|
||||
- 錯誤邊界處理確保應用穩定性
|
||||
|
||||
### 📱 相容性
|
||||
|
||||
- 支援現代瀏覽器的剪貼板 API
|
||||
- 優雅降級處理不支援的功能
|
||||
- 響應式設計適配各種裝置
|
||||
|
||||
## 測試建議
|
||||
|
||||
1. **功能測試**
|
||||
- 測試分享按鈕點擊
|
||||
- 測試連結複製功能
|
||||
- 測試 QR Code 生成和複製
|
||||
- 測試社群分享功能
|
||||
|
||||
2. **相容性測試**
|
||||
- 在不同瀏覽器中測試
|
||||
- 測試手機和桌面版本
|
||||
- 測試不同螢幕尺寸
|
||||
|
||||
3. **錯誤處理測試**
|
||||
- 測試網路錯誤情況
|
||||
- 測試瀏覽器不支援剪貼板 API 的情況
|
||||
|
||||
## 未來改進建議
|
||||
|
||||
1. **更多分享選項**
|
||||
- 支援 Email 分享
|
||||
- 支援 WhatsApp 分享
|
||||
- 支援自訂分享訊息
|
||||
|
||||
2. **進階功能**
|
||||
- 分享統計(查看次數)
|
||||
- 分享權限控制
|
||||
- 分享過期時間
|
||||
|
||||
3. **UI/UX 改進**
|
||||
- 分享預覽功能
|
||||
- 自訂分享圖片
|
||||
- 分享動畫效果
|
||||
|
||||
## 結論
|
||||
|
||||
分享功能已經成功實現並整合到現有的評審結果頁面中。功能完整、設計美觀、使用者體驗良好,與整體網站設計風格保持一致。用戶現在可以輕鬆地分享評審結果給其他人查看。
|
@@ -1,115 +0,0 @@
|
||||
# 分享視窗優化修改總結
|
||||
|
||||
## 修復的問題
|
||||
|
||||
### 🎯 跑版問題修復
|
||||
|
||||
1. **Dialog 寬度調整**
|
||||
- 從 `max-w-md` 改為 `max-w-lg`
|
||||
- 添加 `max-h-[90vh] overflow-y-auto` 防止內容溢出
|
||||
|
||||
2. **QR Code 尺寸優化**
|
||||
- 從 200x200 像素改為 160x160 像素
|
||||
- 載入和顯示區域都調整為 `w-40 h-40`
|
||||
- 在小螢幕上更適合顯示
|
||||
|
||||
3. **按鈕布局改進**
|
||||
- 分享連結區域:改為響應式布局 `flex-col sm:flex-row`
|
||||
- 複製按鈕在小螢幕上全寬顯示 `w-full sm:w-auto`
|
||||
- 添加更好的文字標籤
|
||||
|
||||
4. **間距優化**
|
||||
- 主要間距從 `space-y-6` 改為 `space-y-4`
|
||||
- 社群分享按鈕間距從 `gap-2` 改為 `gap-3`
|
||||
- 按鈕高度從 `py-3` 改為 `py-4`
|
||||
|
||||
### 📧 新增郵件分享功能
|
||||
|
||||
1. **移除 Twitter**
|
||||
- 完全移除 Twitter 分享選項
|
||||
- 調整社群分享按鈕布局
|
||||
|
||||
2. **添加 Email 分享**
|
||||
- 使用 `mailto:` 協議
|
||||
- 預設郵件主題和內容
|
||||
- 包含評審結果連結和專案標題
|
||||
- 使用 Mail 圖標
|
||||
|
||||
3. **布局調整**
|
||||
- 改為 2x2 網格布局(手機)和 3x1 網格布局(桌面)
|
||||
- Email 按鈕在小螢幕上跨兩列顯示 `col-span-2 sm:col-span-1`
|
||||
|
||||
## 具體修改內容
|
||||
|
||||
### 🔧 功能改進
|
||||
|
||||
1. **郵件分享內容**
|
||||
```javascript
|
||||
const emailBody = encodeURIComponent(`您好,\n\n我想與您分享這個評審結果:\n\n${projectTitle || 'AI 智能評審系統'}\n\n請點擊以下連結查看詳細報告:\n${shareUrl}\n\n感謝!`)
|
||||
```
|
||||
|
||||
2. **響應式按鈕文字**
|
||||
- 複製連結按鈕顯示 "複製連結" 而非僅圖標
|
||||
- 複製成功後顯示 "已複製" 確認
|
||||
|
||||
3. **更好的視覺設計**
|
||||
- 社群按鈕圖標從 6x6 改為 7x7
|
||||
- 添加 `font-medium` 到按鈕文字
|
||||
- 改善按鈕間距和對齊
|
||||
|
||||
### 📱 響應式改進
|
||||
|
||||
1. **手機端優化**
|
||||
- 連結複製區域垂直堆疊
|
||||
- 複製按鈕全寬顯示
|
||||
- Email 按鈕跨兩列顯示
|
||||
|
||||
2. **桌面端優化**
|
||||
- 連結複製區域水平排列
|
||||
- 按鈕保持原始尺寸
|
||||
- 三列網格布局
|
||||
|
||||
## 測試建議
|
||||
|
||||
### ✅ 功能測試
|
||||
1. **分享連結**
|
||||
- 測試複製功能
|
||||
- 驗證連結正確性
|
||||
- 檢查響應式布局
|
||||
|
||||
2. **QR Code**
|
||||
- 測試生成速度
|
||||
- 驗證複製功能
|
||||
- 檢查尺寸適配
|
||||
|
||||
3. **社群分享**
|
||||
- 測試 LINE 分享
|
||||
- 測試 Facebook 分享
|
||||
- 測試 Email 分享(開啟預設郵件客戶端)
|
||||
|
||||
### 📱 響應式測試
|
||||
1. **手機端 (320px-768px)**
|
||||
- 檢查按鈕布局
|
||||
- 驗證文字可讀性
|
||||
- 測試觸控操作
|
||||
|
||||
2. **桌面端 (768px+)**
|
||||
- 檢查三列布局
|
||||
- 驗證懸停效果
|
||||
- 測試鍵盤導航
|
||||
|
||||
## 使用說明
|
||||
|
||||
### 📧 Email 分享
|
||||
- 點擊 Email 按鈕會開啟預設郵件客戶端
|
||||
- 自動填入主題和內容
|
||||
- 包含評審結果連結
|
||||
|
||||
### 🔗 其他分享方式
|
||||
- **複製連結**:一鍵複製報告連結
|
||||
- **QR Code**:生成並複製 QR Code 圖片
|
||||
- **LINE/Facebook**:在新視窗中開啟分享頁面
|
||||
|
||||
## 結論
|
||||
|
||||
分享視窗現在已經完全優化,解決了跑版問題,並添加了郵件分享功能。設計更加響應式,用戶體驗更加流暢,特別是在手機端的使用體驗得到了顯著改善。
|
@@ -1,124 +0,0 @@
|
||||
# AI 評分結果上傳腳本說明
|
||||
|
||||
## 概述
|
||||
|
||||
這個腳本用於解析 AI 評分結果的 JSON 資料,並將結果上傳到資料庫的三個相關表中:
|
||||
- `evaluations` - 評審記錄主表
|
||||
- `evaluation_scores` - 評分結果明細表
|
||||
- `evaluation_feedback` - AI 評語和建議表
|
||||
|
||||
## 資料庫表結構
|
||||
|
||||
### 1. evaluations 表
|
||||
儲存評審的基本資訊:
|
||||
- `id` - 主鍵
|
||||
- `project_id` - 專案 ID
|
||||
- `overall_score` - 總分 (78.5)
|
||||
- `max_possible_score` - 滿分 (100)
|
||||
- `grade` - 等級 (A-)
|
||||
- `analysis_duration` - 分析耗時
|
||||
- `ai_model_version` - AI 模型版本
|
||||
- `status` - 狀態 (completed)
|
||||
- `error_message` - 錯誤訊息
|
||||
|
||||
### 2. evaluation_scores 表
|
||||
儲存各項評分標準的詳細分數:
|
||||
- `id` - 主鍵
|
||||
- `evaluation_id` - 關聯到 evaluations 表
|
||||
- `criteria_item_id` - 關聯到 criteria_items 表
|
||||
- `score` - 得分
|
||||
- `max_score` - 滿分
|
||||
- `weight` - 權重
|
||||
- `weighted_score` - 加權分數
|
||||
- `percentage` - 百分比
|
||||
|
||||
### 3. evaluation_feedback 表
|
||||
儲存 AI 的評語和建議:
|
||||
- `id` - 主鍵
|
||||
- `evaluation_id` - 關聯到 evaluations 表
|
||||
- `criteria_item_id` - 關聯到 criteria_items 表 (可為空)
|
||||
- `feedback_type` - 反饋類型 (overall/criteria/strength/improvement)
|
||||
- `content` - 反饋內容
|
||||
- `sort_order` - 排序
|
||||
|
||||
## 使用方式
|
||||
|
||||
### 1. 環境設定
|
||||
確保已設定資料庫連線環境變數:
|
||||
```bash
|
||||
export DB_HOST=localhost
|
||||
export DB_USER=root
|
||||
export DB_PASSWORD=your_password
|
||||
export DB_NAME=ai_scoring_app
|
||||
```
|
||||
|
||||
### 2. 執行腳本
|
||||
```bash
|
||||
cd scripts
|
||||
node parse-ai-evaluation.js
|
||||
```
|
||||
|
||||
### 3. 檢查結果
|
||||
腳本會輸出詳細的執行過程,包括:
|
||||
- 資料庫連接狀態
|
||||
- 各表的記錄創建數量
|
||||
- 最終的評分結果摘要
|
||||
|
||||
## 重要注意事項
|
||||
|
||||
### 1. criteria_item_id 對應
|
||||
腳本中的 `criteriaNameToId` 物件需要根據實際資料庫中的 `criteria_items` 表來調整:
|
||||
|
||||
```javascript
|
||||
const criteriaNameToId = {
|
||||
"應用實務性": 52, // 需要確認實際 ID
|
||||
"創新性": 53,
|
||||
"成效與效益": 54,
|
||||
"擴散與可複用性": 55,
|
||||
"簡報與表達": 56
|
||||
};
|
||||
```
|
||||
|
||||
### 2. project_id 設定
|
||||
腳本中假設專案 ID 為 1,實際使用時需要根據實際情況調整:
|
||||
|
||||
```javascript
|
||||
const projectId = 1; // 需要根據實際專案 ID 調整
|
||||
```
|
||||
|
||||
### 3. 資料驗證
|
||||
執行前請確認:
|
||||
- 資料庫連線正常
|
||||
- `criteria_items` 表中有對應的評分項目
|
||||
- `projects` 表中有對應的專案記錄
|
||||
|
||||
## 資料解析說明
|
||||
|
||||
### AI JSON 結構
|
||||
腳本解析的 AI JSON 包含以下主要部分:
|
||||
- 基本資訊:專案標題、總分、等級等
|
||||
- 評分標準:各項標準的得分和反饋
|
||||
- 詳細分析:整體分析和關鍵發現
|
||||
- 改進建議:保持優勢、關鍵改進、行動計劃
|
||||
|
||||
### 資料映射
|
||||
- 每個評分標準會創建一條 `evaluation_scores` 記錄
|
||||
- 每個評分標準的反饋會創建多條 `evaluation_feedback` 記錄
|
||||
- 整體分析會創建 `feedback_type` 為 'overall' 的反饋記錄
|
||||
|
||||
## 錯誤處理
|
||||
|
||||
腳本包含完整的錯誤處理機制:
|
||||
- 資料庫連線錯誤
|
||||
- SQL 執行錯誤
|
||||
- 資料驗證錯誤
|
||||
|
||||
所有錯誤都會在控制台輸出詳細資訊,並確保資料庫連線正確關閉。
|
||||
|
||||
## 擴展功能
|
||||
|
||||
如需處理其他 AI 評分結果,可以:
|
||||
1. 修改 `aiEvaluationResult` 物件
|
||||
2. 調整 `criteriaNameToId` 對應關係
|
||||
3. 更新 `projectId` 設定
|
||||
4. 重新執行腳本
|
@@ -1,6 +0,0 @@
|
||||
-- 為 evaluations 表添加新欄位
|
||||
ALTER TABLE `evaluations`
|
||||
ADD COLUMN `performance_status` varchar(50) DEFAULT NULL COMMENT '表現狀況' AFTER `grade`,
|
||||
ADD COLUMN `recommended_stars` int(11) DEFAULT NULL COMMENT '推薦等級(星星數量)' AFTER `performance_status`,
|
||||
ADD COLUMN `excellent_items` int(11) DEFAULT NULL COMMENT '優秀項目數量' AFTER `recommended_stars`,
|
||||
ADD COLUMN `improvement_items` int(11) DEFAULT NULL COMMENT '待改進項目數量' AFTER `excellent_items`;
|
@@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* 配置檢查工具
|
||||
* 用於驗證環境變量配置是否正確
|
||||
*/
|
||||
|
||||
console.log('🔍 檢查環境變量配置...\n');
|
||||
|
||||
// 檢查環境變量
|
||||
const envVars = {
|
||||
'NEXT_PUBLIC_APP_URL': process.env.NEXT_PUBLIC_APP_URL,
|
||||
'NEXT_PUBLIC_APP_NAME': process.env.NEXT_PUBLIC_APP_NAME,
|
||||
'DB_HOST': process.env.DB_HOST,
|
||||
'DB_PORT': process.env.DB_PORT,
|
||||
'DB_NAME': process.env.DB_NAME,
|
||||
'DB_USER': process.env.DB_USER,
|
||||
'DB_PASSWORD': process.env.DB_PASSWORD ? '***已設置***' : undefined,
|
||||
'GEMINI_API_KEY': process.env.GEMINI_API_KEY ? '***已設置***' : undefined,
|
||||
'GEMINI_MODEL': process.env.GEMINI_MODEL,
|
||||
'GEMINI_MAX_TOKENS': process.env.GEMINI_MAX_TOKENS,
|
||||
};
|
||||
|
||||
console.log('📋 當前環境變量:');
|
||||
let hasErrors = false;
|
||||
|
||||
Object.entries(envVars).forEach(([key, value]) => {
|
||||
const status = value ? '✅' : '❌';
|
||||
const displayValue = value || '未設置';
|
||||
console.log(` ${status} ${key}: ${displayValue}`);
|
||||
if (!value && key !== 'GEMINI_MAX_TOKENS') {
|
||||
hasErrors = true;
|
||||
}
|
||||
});
|
||||
|
||||
console.log('');
|
||||
|
||||
if (hasErrors) {
|
||||
console.log('❌ 發現配置問題,請設置缺少的環境變量');
|
||||
console.log('\n💡 建議的 .env.local 配置:');
|
||||
} else {
|
||||
console.log('✅ 所有必要的環境變量都已設置');
|
||||
console.log('\n🔧 建議的 .env.local 配置:');
|
||||
}
|
||||
|
||||
console.log('NEXT_PUBLIC_APP_URL=http://localhost:12024');
|
||||
console.log('NEXT_PUBLIC_APP_NAME=AI 智能評審系統');
|
||||
console.log('DB_HOST=mysql.theaken.com');
|
||||
console.log('DB_PORT=33306');
|
||||
console.log('DB_NAME=db_AI_scoring');
|
||||
console.log('DB_USER=root');
|
||||
console.log('DB_PASSWORD=zh6161168');
|
||||
console.log('GEMINI_API_KEY=AIzaSyAN3pEJr_Vn2xkCidGZAq9eQqsMVvpj8g4');
|
||||
console.log('GEMINI_MODEL=gemini-1.5-pro');
|
||||
console.log('GEMINI_MAX_TOKENS=8192');
|
||||
|
||||
console.log('\n📝 使用說明:');
|
||||
console.log('1. 複製 env.example 到 .env.local');
|
||||
console.log('2. 根據需要修改配置');
|
||||
console.log('3. 重啟開發服務器: npm run dev');
|
@@ -1,24 +0,0 @@
|
||||
const mysql = require('mysql2/promise');
|
||||
|
||||
const dbConfig = {
|
||||
host: 'localhost',
|
||||
user: 'root',
|
||||
password: '123456',
|
||||
database: 'ai_scoring_app',
|
||||
timezone: '+08:00'
|
||||
};
|
||||
|
||||
async function checkCriteriaNames() {
|
||||
const connection = await mysql.createConnection(dbConfig);
|
||||
try {
|
||||
const [rows] = await connection.execute('SELECT id, name, LENGTH(name) as name_length, HEX(name) as name_hex FROM criteria_items ORDER BY id');
|
||||
console.log('資料庫中的評分標準名稱:');
|
||||
rows.forEach(row => {
|
||||
console.log(`ID: ${row.id}, 名稱: "${row.name}", 長度: ${row.name_length}, HEX: ${row.name_hex}`);
|
||||
});
|
||||
} finally {
|
||||
await connection.end();
|
||||
}
|
||||
}
|
||||
|
||||
checkCriteriaNames().catch(console.error);
|
@@ -1,319 +0,0 @@
|
||||
const mysql = require('mysql2/promise');
|
||||
|
||||
// 資料庫配置
|
||||
const dbConfig = {
|
||||
host: process.env.DB_HOST || 'mysql.theaken.com',
|
||||
port: parseInt(process.env.DB_PORT || '33306'),
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || 'zh6161168',
|
||||
database: process.env.DB_NAME || 'db_AI_scoring',
|
||||
charset: 'utf8mb4',
|
||||
timezone: '+08:00',
|
||||
};
|
||||
|
||||
async function initializeDatabase() {
|
||||
let connection;
|
||||
|
||||
try {
|
||||
console.log('🔄 正在連接資料庫...');
|
||||
|
||||
// 先連接到 MySQL 伺服器(不指定資料庫)
|
||||
const serverConnection = await mysql.createConnection({
|
||||
host: dbConfig.host,
|
||||
port: dbConfig.port,
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
charset: dbConfig.charset,
|
||||
timezone: dbConfig.timezone,
|
||||
});
|
||||
|
||||
console.log('✅ 成功連接到 MySQL 伺服器');
|
||||
|
||||
// 1. 建立資料庫
|
||||
console.log('🔄 正在建立資料庫...');
|
||||
await serverConnection.query(`
|
||||
CREATE DATABASE IF NOT EXISTS \`db_AI_scoring\`
|
||||
CHARACTER SET utf8mb4
|
||||
COLLATE utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 資料庫建立完成');
|
||||
|
||||
// 2. 選擇資料庫
|
||||
await serverConnection.query('USE `db_AI_scoring`');
|
||||
console.log('✅ 已選擇資料庫');
|
||||
|
||||
// 3. 建立用戶表
|
||||
console.log('🔄 正在建立用戶表...');
|
||||
await serverConnection.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`users\` (
|
||||
\`id\` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`email\` varchar(255) NOT NULL UNIQUE,
|
||||
\`username\` varchar(100) NOT NULL UNIQUE,
|
||||
\`password_hash\` varchar(255) NOT NULL,
|
||||
\`full_name\` varchar(255) DEFAULT NULL,
|
||||
\`avatar_url\` varchar(500) DEFAULT NULL,
|
||||
\`role\` enum('admin', 'user') DEFAULT 'user',
|
||||
\`is_active\` tinyint(1) DEFAULT 1,
|
||||
\`email_verified_at\` timestamp NULL DEFAULT NULL,
|
||||
\`last_login_at\` timestamp NULL DEFAULT NULL,
|
||||
\`created_at\` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
\`updated_at\` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_email\` (\`email\`),
|
||||
KEY \`idx_username\` (\`username\`),
|
||||
KEY \`idx_created_at\` (\`created_at\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 用戶表建立完成');
|
||||
|
||||
// 4. 建立評分標準模板表
|
||||
console.log('🔄 正在建立評分標準模板表...');
|
||||
await serverConnection.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`criteria_templates\` (
|
||||
\`id\` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`user_id\` bigint(20) unsigned NOT NULL,
|
||||
\`name\` varchar(255) NOT NULL,
|
||||
\`description\` text DEFAULT NULL,
|
||||
\`is_default\` tinyint(1) DEFAULT 0,
|
||||
\`is_public\` tinyint(1) DEFAULT 0,
|
||||
\`total_weight\` decimal(5,2) DEFAULT 100.00,
|
||||
\`created_at\` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
\`updated_at\` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_user_id\` (\`user_id\`),
|
||||
KEY \`idx_is_default\` (\`is_default\`),
|
||||
KEY \`idx_is_public\` (\`is_public\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 評分標準模板表建立完成');
|
||||
|
||||
// 5. 建立評分項目表
|
||||
console.log('🔄 正在建立評分項目表...');
|
||||
await serverConnection.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`criteria_items\` (
|
||||
\`id\` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`template_id\` bigint(20) unsigned NOT NULL,
|
||||
\`name\` varchar(255) NOT NULL,
|
||||
\`description\` text DEFAULT NULL,
|
||||
\`weight\` decimal(5,2) NOT NULL,
|
||||
\`max_score\` decimal(5,2) DEFAULT 10.00,
|
||||
\`sort_order\` int(11) DEFAULT 0,
|
||||
\`created_at\` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
\`updated_at\` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_template_id\` (\`template_id\`),
|
||||
KEY \`idx_sort_order\` (\`sort_order\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 評分項目表建立完成');
|
||||
|
||||
// 6. 建立專案表
|
||||
console.log('🔄 正在建立專案表...');
|
||||
await serverConnection.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`projects\` (
|
||||
\`id\` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`user_id\` bigint(20) unsigned NOT NULL,
|
||||
\`template_id\` bigint(20) unsigned NOT NULL,
|
||||
\`title\` varchar(255) NOT NULL,
|
||||
\`description\` text DEFAULT NULL,
|
||||
\`status\` enum('draft', 'uploading', 'analyzing', 'completed', 'failed') DEFAULT 'draft',
|
||||
\`analysis_started_at\` timestamp NULL DEFAULT NULL,
|
||||
\`analysis_completed_at\` timestamp NULL DEFAULT NULL,
|
||||
\`created_at\` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
\`updated_at\` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_user_id\` (\`user_id\`),
|
||||
KEY \`idx_template_id\` (\`template_id\`),
|
||||
KEY \`idx_status\` (\`status\`),
|
||||
KEY \`idx_created_at\` (\`created_at\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 專案表建立完成');
|
||||
|
||||
// 7. 建立專案文件表
|
||||
console.log('🔄 正在建立專案文件表...');
|
||||
await serverConnection.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`project_files\` (
|
||||
\`id\` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`project_id\` bigint(20) unsigned NOT NULL,
|
||||
\`original_name\` varchar(255) NOT NULL,
|
||||
\`file_name\` varchar(255) NOT NULL,
|
||||
\`file_path\` varchar(500) NOT NULL,
|
||||
\`file_size\` bigint(20) unsigned NOT NULL,
|
||||
\`file_type\` varchar(100) NOT NULL,
|
||||
\`mime_type\` varchar(100) NOT NULL,
|
||||
\`upload_status\` enum('uploading', 'completed', 'failed') DEFAULT 'uploading',
|
||||
\`upload_progress\` decimal(5,2) DEFAULT 0.00,
|
||||
\`created_at\` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
\`updated_at\` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_project_id\` (\`project_id\`),
|
||||
KEY \`idx_file_type\` (\`file_type\`),
|
||||
KEY \`idx_upload_status\` (\`upload_status\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 專案文件表建立完成');
|
||||
|
||||
// 8. 建立專案網站表
|
||||
console.log('🔄 正在建立專案網站表...');
|
||||
await serverConnection.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`project_websites\` (
|
||||
\`id\` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`project_id\` bigint(20) unsigned NOT NULL,
|
||||
\`url\` varchar(500) NOT NULL,
|
||||
\`title\` varchar(255) DEFAULT NULL,
|
||||
\`description\` text DEFAULT NULL,
|
||||
\`status\` enum('pending', 'analyzing', 'completed', 'failed') DEFAULT 'pending',
|
||||
\`created_at\` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
\`updated_at\` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_project_id\` (\`project_id\`),
|
||||
KEY \`idx_status\` (\`status\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 專案網站表建立完成');
|
||||
|
||||
// 9. 建立評審記錄表
|
||||
console.log('🔄 正在建立評審記錄表...');
|
||||
await serverConnection.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`evaluations\` (
|
||||
\`id\` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`project_id\` bigint(20) unsigned NOT NULL,
|
||||
\`overall_score\` decimal(5,2) DEFAULT NULL,
|
||||
\`max_possible_score\` decimal(5,2) DEFAULT 100.00,
|
||||
\`grade\` varchar(10) DEFAULT NULL,
|
||||
\`analysis_duration\` int(11) DEFAULT NULL,
|
||||
\`ai_model_version\` varchar(50) DEFAULT NULL,
|
||||
\`status\` enum('pending', 'analyzing', 'completed', 'failed') DEFAULT 'pending',
|
||||
\`error_message\` text DEFAULT NULL,
|
||||
\`created_at\` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
\`updated_at\` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_project_id\` (\`project_id\`),
|
||||
KEY \`idx_status\` (\`status\`),
|
||||
KEY \`idx_created_at\` (\`created_at\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 評審記錄表建立完成');
|
||||
|
||||
// 10. 建立評分結果表
|
||||
console.log('🔄 正在建立評分結果表...');
|
||||
await serverConnection.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`evaluation_scores\` (
|
||||
\`id\` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`evaluation_id\` bigint(20) unsigned NOT NULL,
|
||||
\`criteria_item_id\` bigint(20) unsigned NOT NULL,
|
||||
\`score\` decimal(5,2) NOT NULL,
|
||||
\`max_score\` decimal(5,2) NOT NULL,
|
||||
\`weight\` decimal(5,2) NOT NULL,
|
||||
\`weighted_score\` decimal(5,2) NOT NULL,
|
||||
\`percentage\` decimal(5,2) NOT NULL,
|
||||
\`created_at\` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_evaluation_id\` (\`evaluation_id\`),
|
||||
KEY \`idx_criteria_item_id\` (\`criteria_item_id\`),
|
||||
UNIQUE KEY \`unique_evaluation_criteria\` (\`evaluation_id\`, \`criteria_item_id\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 評分結果表建立完成');
|
||||
|
||||
// 11. 建立評語表
|
||||
console.log('🔄 正在建立評語表...');
|
||||
await serverConnection.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`evaluation_feedback\` (
|
||||
\`id\` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`evaluation_id\` bigint(20) unsigned NOT NULL,
|
||||
\`criteria_item_id\` bigint(20) unsigned DEFAULT NULL,
|
||||
\`feedback_type\` enum('overall', 'criteria', 'strength', 'improvement') NOT NULL,
|
||||
\`content\` text NOT NULL,
|
||||
\`sort_order\` int(11) DEFAULT 0,
|
||||
\`created_at\` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_evaluation_id\` (\`evaluation_id\`),
|
||||
KEY \`idx_criteria_item_id\` (\`criteria_item_id\`),
|
||||
KEY \`idx_feedback_type\` (\`feedback_type\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 評語表建立完成');
|
||||
|
||||
// 12. 建立系統設定表
|
||||
console.log('🔄 正在建立系統設定表...');
|
||||
await serverConnection.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`system_settings\` (
|
||||
\`id\` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`setting_key\` varchar(100) NOT NULL UNIQUE,
|
||||
\`setting_value\` text DEFAULT NULL,
|
||||
\`description\` varchar(255) DEFAULT NULL,
|
||||
\`created_at\` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
\`updated_at\` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (\`id\`),
|
||||
KEY \`idx_setting_key\` (\`setting_key\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
console.log('✅ 系統設定表建立完成');
|
||||
|
||||
// 13. 插入預設數據
|
||||
console.log('🔄 正在插入預設數據...');
|
||||
|
||||
// 插入預設評分標準模板
|
||||
await serverConnection.query(`
|
||||
INSERT IGNORE INTO \`criteria_templates\` (\`user_id\`, \`name\`, \`description\`, \`is_default\`, \`is_public\`, \`total_weight\`)
|
||||
VALUES (1, '預設評分標準', '系統預設的評分標準模板', 1, 1, 100.00)
|
||||
`);
|
||||
|
||||
// 插入預設評分項目
|
||||
await serverConnection.query(`
|
||||
INSERT IGNORE INTO \`criteria_items\` (\`template_id\`, \`name\`, \`description\`, \`weight\`, \`max_score\`, \`sort_order\`) VALUES
|
||||
(1, '內容品質', '內容的準確性、完整性和專業度', 25.00, 10.00, 1),
|
||||
(1, '視覺設計', '版面設計、色彩搭配和視覺效果', 20.00, 10.00, 2),
|
||||
(1, '邏輯結構', '內容組織的邏輯性和條理性', 20.00, 10.00, 3),
|
||||
(1, '創新性', '創意思維和獨特觀點的展現', 15.00, 10.00, 4),
|
||||
(1, '實用性', '內容的實際應用價值和可操作性', 20.00, 10.00, 5)
|
||||
`);
|
||||
|
||||
// 插入系統設定
|
||||
await serverConnection.query(`
|
||||
INSERT IGNORE INTO \`system_settings\` (\`setting_key\`, \`setting_value\`, \`description\`) VALUES
|
||||
('max_file_size', '104857600', '最大文件上傳大小(位元組)'),
|
||||
('allowed_file_types', 'ppt,pptx,pdf,mp4,avi,mov,wmv,flv,webm', '允許上傳的文件類型'),
|
||||
('ai_analysis_timeout', '300', 'AI 分析超時時間(秒)'),
|
||||
('max_concurrent_analyses', '5', '最大並發分析數量'),
|
||||
('default_grade_thresholds', '{"A":90,"B":80,"C":70,"D":60}', '預設等級閾值')
|
||||
`);
|
||||
|
||||
console.log('✅ 預設數據插入完成');
|
||||
|
||||
// 關閉連接
|
||||
await serverConnection.end();
|
||||
|
||||
// 測試新建立的資料庫連接
|
||||
console.log('🔄 正在測試資料庫連接...');
|
||||
connection = await mysql.createConnection(dbConfig);
|
||||
|
||||
// 測試查詢
|
||||
const [rows] = await connection.query('SELECT COUNT(*) as count FROM criteria_templates');
|
||||
console.log(`✅ 資料庫測試成功,找到 ${rows[0].count} 個評分標準模板`);
|
||||
|
||||
// 顯示建立的資料表
|
||||
const [tables] = await connection.query('SHOW TABLES');
|
||||
console.log('📊 已建立的資料表:');
|
||||
tables.forEach(table => {
|
||||
console.log(` - ${Object.values(table)[0]}`);
|
||||
});
|
||||
|
||||
await connection.end();
|
||||
console.log('🎉 資料庫初始化完成!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 資料庫初始化失敗:', error.message);
|
||||
console.error('詳細錯誤:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果直接執行此腳本
|
||||
if (require.main === module) {
|
||||
initializeDatabase();
|
||||
}
|
||||
|
||||
module.exports = { initializeDatabase };
|
@@ -1,93 +0,0 @@
|
||||
const mysql = require('mysql2/promise');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// 資料庫配置
|
||||
const dbConfig = {
|
||||
host: process.env.DB_HOST || 'mysql.theaken.com',
|
||||
port: parseInt(process.env.DB_PORT || '33306'),
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || 'zh6161168',
|
||||
database: process.env.DB_NAME || 'db_AI_scoring',
|
||||
charset: 'utf8mb4',
|
||||
timezone: '+08:00',
|
||||
multipleStatements: true,
|
||||
};
|
||||
|
||||
async function initializeDatabase() {
|
||||
let connection;
|
||||
|
||||
try {
|
||||
console.log('🔄 正在連接資料庫...');
|
||||
|
||||
// 先連接到 MySQL 伺服器(不指定資料庫)
|
||||
const serverConnection = await mysql.createConnection({
|
||||
host: dbConfig.host,
|
||||
port: dbConfig.port,
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
charset: dbConfig.charset,
|
||||
timezone: dbConfig.timezone,
|
||||
});
|
||||
|
||||
console.log('✅ 成功連接到 MySQL 伺服器');
|
||||
|
||||
// 讀取 SQL 腳本
|
||||
const schemaPath = path.join(__dirname, '..', 'database', 'schema.sql');
|
||||
const schemaSQL = fs.readFileSync(schemaPath, 'utf8');
|
||||
|
||||
console.log('🔄 正在執行資料庫初始化腳本...');
|
||||
|
||||
// 分割 SQL 語句並逐個執行
|
||||
const statements = schemaSQL
|
||||
.split(';')
|
||||
.map(stmt => stmt.trim())
|
||||
.filter(stmt => stmt.length > 0 && !stmt.startsWith('--'));
|
||||
|
||||
for (const statement of statements) {
|
||||
if (statement.trim()) {
|
||||
try {
|
||||
await serverConnection.execute(statement);
|
||||
console.log(`✅ 執行: ${statement.substring(0, 50)}...`);
|
||||
} catch (error) {
|
||||
console.warn(`⚠️ 跳過語句: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('✅ 資料庫初始化完成');
|
||||
|
||||
// 關閉連接
|
||||
await serverConnection.end();
|
||||
|
||||
// 測試新建立的資料庫連接
|
||||
console.log('🔄 正在測試資料庫連接...');
|
||||
connection = await mysql.createConnection(dbConfig);
|
||||
|
||||
// 測試查詢
|
||||
const [rows] = await connection.execute('SELECT COUNT(*) as count FROM criteria_templates');
|
||||
console.log(`✅ 資料庫測試成功,找到 ${rows[0].count} 個評分標準模板`);
|
||||
|
||||
// 顯示建立的資料表
|
||||
const [tables] = await connection.execute('SHOW TABLES');
|
||||
console.log('📊 已建立的資料表:');
|
||||
tables.forEach(table => {
|
||||
console.log(` - ${Object.values(table)[0]}`);
|
||||
});
|
||||
|
||||
await connection.end();
|
||||
console.log('🎉 資料庫初始化完成!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 資料庫初始化失敗:', error.message);
|
||||
console.error('詳細錯誤:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果直接執行此腳本
|
||||
if (require.main === module) {
|
||||
initializeDatabase();
|
||||
}
|
||||
|
||||
module.exports = { initializeDatabase };
|
@@ -1,375 +0,0 @@
|
||||
const mysql = require('mysql2/promise');
|
||||
|
||||
// 資料庫配置
|
||||
const dbConfig = {
|
||||
host: process.env.DB_HOST || 'localhost',
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || '',
|
||||
database: process.env.DB_NAME || 'ai_scoring_app',
|
||||
timezone: '+08:00',
|
||||
};
|
||||
|
||||
// AI JSON 結果 (從終端輸出中提取)
|
||||
const aiEvaluationResult = {
|
||||
"projectTitle": "ITBU_人咧 PeoplePing 智能出勤系統",
|
||||
"overallScore": 78.5,
|
||||
"totalPossible": 100,
|
||||
"grade": "A-",
|
||||
"performanceStatus": "表現良好",
|
||||
"recommendedStars": 4,
|
||||
"analysisDate": "2024-10-27",
|
||||
"criteria": [
|
||||
{
|
||||
"name": "應用實務性",
|
||||
"score": 8,
|
||||
"maxScore": 10,
|
||||
"weight": 30,
|
||||
"weightedScore": 24,
|
||||
"feedback": "系統設計貼近實際需求,解決了主管和員工的痛點,具備可行性。",
|
||||
"strengths": [
|
||||
"明確指出解決了主管無法即時掌握團隊出勤狀況和員工查詢流程繁瑣的問題",
|
||||
"提供了 Dify Chat Flow 和 Web Dashboard 兩個使用者介面",
|
||||
"簡潔明瞭地說明了系統架構和流程"
|
||||
],
|
||||
"improvements": [
|
||||
"可以加入更多實際案例或數據,例如導入前的數據和導入後的對比數據",
|
||||
"更詳細地說明系統的安全性及數據隱私保護措施"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "創新性",
|
||||
"score": 6,
|
||||
"maxScore": 10,
|
||||
"weight": 15,
|
||||
"weightedScore": 9,
|
||||
"feedback": "利用 Dify Chat Flow 整合自然語言處理,提升使用者體驗,但整體創新性不算高。",
|
||||
"strengths": [
|
||||
"結合 Dify Chat Flow 和 Web Dashboard,提供了多樣化的使用方式",
|
||||
"利用自然語言處理,讓使用者能以更自然的方式進行出勤登記"
|
||||
],
|
||||
"improvements": [
|
||||
"可以探索更多創新應用,例如結合生物識別技術、位置服務等",
|
||||
"進一步提升自然語言理解能力,處理更多複雜的出勤場景"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "成效與效益",
|
||||
"score": 9,
|
||||
"maxScore": 10,
|
||||
"weight": 25,
|
||||
"weightedScore": 22.5,
|
||||
"feedback": "量化了系統帶來的效率提升,數據明確,具有說服力。",
|
||||
"strengths": [
|
||||
"使用數據明確地呈現了系統帶來的效率提升,例如出勤登錄時間縮短 83%,月報彙整時間縮減 99%",
|
||||
"系統錯誤率控制在 1% 以下,展現了系統的穩定性"
|
||||
],
|
||||
"improvements": [
|
||||
"可以更詳細地說明數據的計算方法和資料來源"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "擴散與可複用性",
|
||||
"score": 7,
|
||||
"maxScore": 10,
|
||||
"weight": 20,
|
||||
"weightedScore": 14,
|
||||
"feedback": "系統架構清晰,模組化設計良好,具備一定程度的可複用性。",
|
||||
"strengths": [
|
||||
"系統架構清晰,各模組功能明確",
|
||||
"後續優化與應用擴展規劃合理,展現了系統的擴展性"
|
||||
],
|
||||
"improvements": [
|
||||
"可以更詳細地說明系統的模組化設計,以及如何方便地複製到其他部門"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "簡報與表達",
|
||||
"score": 8,
|
||||
"maxScore": 10,
|
||||
"weight": 10,
|
||||
"weightedScore": 8,
|
||||
"feedback": "簡報內容結構清晰,表達流暢,但部分幻燈片內容略顯簡潔。",
|
||||
"strengths": [
|
||||
"簡報目錄清晰,結構合理",
|
||||
"圖表使用恰當,數據呈現清晰"
|
||||
],
|
||||
"improvements": [
|
||||
"某些幻燈片可以添加更多圖表或說明,使內容更豐富完整",
|
||||
"幻燈片 5 的「人咧~聊天流程展示」需要更具體的內容"
|
||||
]
|
||||
}
|
||||
],
|
||||
"overview": {
|
||||
"excellentItems": 1,
|
||||
"improvementItems": 0,
|
||||
"overallPerformance": 78.5
|
||||
},
|
||||
"detailedAnalysis": {
|
||||
"summary": "整體而言,此專案具備良好的應用實務性、成效與效益,以及擴散與可複用性。創新性方面尚有提升空間,簡報表達也需進一步完善。",
|
||||
"keyFindings": [
|
||||
"系統有效解決了實際問題,並量化了效益提升",
|
||||
"系統架構清晰,具備一定程度的可複用性",
|
||||
"創新性方面仍有提升空間,可以探索更多創新應用"
|
||||
]
|
||||
},
|
||||
"improvementSuggestions": {
|
||||
"overallSuggestions": "整體而言,專案表現良好,建議著重提升創新性,並補充更多數據和案例,以增强說服力。",
|
||||
"maintainStrengths": [
|
||||
{
|
||||
"title": "數據驅動的效益呈現",
|
||||
"description": "有效地利用數據量化了系統帶來的效率提升,這部分是專案的優勢,應該持續保持。"
|
||||
}
|
||||
],
|
||||
"keyImprovements": [
|
||||
{
|
||||
"title": "提升創新性",
|
||||
"description": "探索更多創新應用,例如結合生物識別技術、位置服務等,提升系統的競爭力。",
|
||||
"suggestions": [
|
||||
"研究市場上最新的技術,尋求更多創新點",
|
||||
"考慮與其他系統整合,擴展系統功能"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "完善數據說明和案例",
|
||||
"description": "提供更詳細的數據計算方法和資料來源,並添加更多實際案例,以增强簡報的說服力。",
|
||||
"suggestions": [
|
||||
"提供導入前後的數據對比",
|
||||
"加入更多使用者反饋和成功案例"
|
||||
]
|
||||
}
|
||||
],
|
||||
"actionPlan": [
|
||||
{
|
||||
"phase": "短期目標(1-2週)",
|
||||
"description": "完善數據說明和案例,補充更多細節。"
|
||||
},
|
||||
{
|
||||
"phase": "中期目標(1個月)",
|
||||
"description": "研究新的技術和應用場景,探討系統的創新升級。"
|
||||
},
|
||||
{
|
||||
"phase": "長期目標(3個月)",
|
||||
"description": "完成系統的創新升級,並將其應用到更多部門。"
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// 評分項目名稱對應到 criteria_items 表的 ID
|
||||
// 這些 ID 需要根據實際資料庫中的 criteria_items 來調整
|
||||
const criteriaNameToId = {
|
||||
"應用實務性": 52,
|
||||
"創新性": 53,
|
||||
"成效與效益": 54,
|
||||
"擴散與可複用性": 55,
|
||||
"簡報與表達": 56
|
||||
};
|
||||
|
||||
async function parseAndUploadEvaluation() {
|
||||
let connection;
|
||||
|
||||
try {
|
||||
console.log('🔗 連接到資料庫...');
|
||||
connection = await mysql.createConnection(dbConfig);
|
||||
console.log('✅ 資料庫連接成功');
|
||||
|
||||
// 假設專案 ID 為 1,實際使用時需要根據實際情況調整
|
||||
const projectId = 1;
|
||||
|
||||
// 1. 創建 evaluations 記錄
|
||||
console.log('📝 創建 evaluations 記錄...');
|
||||
const evaluationData = {
|
||||
project_id: projectId,
|
||||
overall_score: aiEvaluationResult.overallScore,
|
||||
max_possible_score: aiEvaluationResult.totalPossible,
|
||||
grade: aiEvaluationResult.grade,
|
||||
analysis_duration: null, // 可以從實際分析時間計算
|
||||
ai_model_version: 'gemini-1.5-pro',
|
||||
status: 'completed',
|
||||
error_message: null
|
||||
};
|
||||
|
||||
const evaluationSql = `
|
||||
INSERT INTO evaluations (project_id, overall_score, max_possible_score, grade, analysis_duration, ai_model_version, status, error_message)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`;
|
||||
|
||||
const [evaluationResult] = await connection.execute(evaluationSql, [
|
||||
evaluationData.project_id,
|
||||
evaluationData.overall_score,
|
||||
evaluationData.max_possible_score,
|
||||
evaluationData.grade,
|
||||
evaluationData.analysis_duration,
|
||||
evaluationData.ai_model_version,
|
||||
evaluationData.status,
|
||||
evaluationData.error_message
|
||||
]);
|
||||
|
||||
const evaluationId = evaluationResult.insertId;
|
||||
console.log(`✅ 創建 evaluations 記錄成功,ID: ${evaluationId}`);
|
||||
|
||||
// 2. 創建 evaluation_scores 記錄
|
||||
console.log('📊 創建 evaluation_scores 記錄...');
|
||||
const evaluationScoresData = aiEvaluationResult.criteria.map(criteria => ({
|
||||
evaluation_id: evaluationId,
|
||||
criteria_item_id: criteriaNameToId[criteria.name],
|
||||
score: criteria.score,
|
||||
max_score: criteria.maxScore,
|
||||
weight: criteria.weight,
|
||||
weighted_score: criteria.weightedScore,
|
||||
percentage: (criteria.score / criteria.maxScore) * 100
|
||||
}));
|
||||
|
||||
for (const scoreData of evaluationScoresData) {
|
||||
const scoreSql = `
|
||||
INSERT INTO evaluation_scores (evaluation_id, criteria_item_id, score, max_score, weight, weighted_score, percentage)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`;
|
||||
|
||||
await connection.execute(scoreSql, [
|
||||
scoreData.evaluation_id,
|
||||
scoreData.criteria_item_id,
|
||||
scoreData.score,
|
||||
scoreData.max_score,
|
||||
scoreData.weight,
|
||||
scoreData.weighted_score,
|
||||
scoreData.percentage
|
||||
]);
|
||||
}
|
||||
console.log(`✅ 創建 ${evaluationScoresData.length} 筆 evaluation_scores 記錄成功`);
|
||||
|
||||
// 3. 創建 evaluation_feedback 記錄
|
||||
console.log('💬 創建 evaluation_feedback 記錄...');
|
||||
const feedbackData = [];
|
||||
|
||||
// 3.1 整體反饋
|
||||
feedbackData.push({
|
||||
evaluation_id: evaluationId,
|
||||
criteria_item_id: null,
|
||||
feedback_type: 'overall',
|
||||
content: aiEvaluationResult.detailedAnalysis.summary,
|
||||
sort_order: 1
|
||||
});
|
||||
|
||||
// 3.2 各項標準的反饋
|
||||
aiEvaluationResult.criteria.forEach((criteria, index) => {
|
||||
// 標準反饋
|
||||
feedbackData.push({
|
||||
evaluation_id: evaluationId,
|
||||
criteria_item_id: criteriaNameToId[criteria.name],
|
||||
feedback_type: 'criteria',
|
||||
content: criteria.feedback,
|
||||
sort_order: index + 2
|
||||
});
|
||||
|
||||
// 優點反饋
|
||||
criteria.strengths.forEach((strength, strengthIndex) => {
|
||||
feedbackData.push({
|
||||
evaluation_id: evaluationId,
|
||||
criteria_item_id: criteriaNameToId[criteria.name],
|
||||
feedback_type: 'strength',
|
||||
content: strength,
|
||||
sort_order: (index + 2) * 100 + strengthIndex + 1
|
||||
});
|
||||
});
|
||||
|
||||
// 改進建議反饋
|
||||
criteria.improvements.forEach((improvement, improvementIndex) => {
|
||||
feedbackData.push({
|
||||
evaluation_id: evaluationId,
|
||||
criteria_item_id: criteriaNameToId[criteria.name],
|
||||
feedback_type: 'improvement',
|
||||
content: improvement,
|
||||
sort_order: (index + 2) * 100 + improvementIndex + 50
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 3.3 改進建議的整體建議
|
||||
feedbackData.push({
|
||||
evaluation_id: evaluationId,
|
||||
criteria_item_id: null,
|
||||
feedback_type: 'improvement',
|
||||
content: aiEvaluationResult.improvementSuggestions.overallSuggestions,
|
||||
sort_order: 1000
|
||||
});
|
||||
|
||||
// 3.4 保持優勢
|
||||
aiEvaluationResult.improvementSuggestions.maintainStrengths.forEach((strength, index) => {
|
||||
feedbackData.push({
|
||||
evaluation_id: evaluationId,
|
||||
criteria_item_id: null,
|
||||
feedback_type: 'strength',
|
||||
content: `${strength.title}: ${strength.description}`,
|
||||
sort_order: 1001 + index
|
||||
});
|
||||
});
|
||||
|
||||
// 3.5 關鍵改進建議
|
||||
aiEvaluationResult.improvementSuggestions.keyImprovements.forEach((improvement, index) => {
|
||||
feedbackData.push({
|
||||
evaluation_id: evaluationId,
|
||||
criteria_item_id: null,
|
||||
feedback_type: 'improvement',
|
||||
content: `${improvement.title}: ${improvement.description}`,
|
||||
sort_order: 2000 + index
|
||||
});
|
||||
});
|
||||
|
||||
// 3.6 行動計劃
|
||||
aiEvaluationResult.improvementSuggestions.actionPlan.forEach((plan, index) => {
|
||||
feedbackData.push({
|
||||
evaluation_id: evaluationId,
|
||||
criteria_item_id: null,
|
||||
feedback_type: 'improvement',
|
||||
content: `${plan.phase}: ${plan.description}`,
|
||||
sort_order: 3000 + index
|
||||
});
|
||||
});
|
||||
|
||||
// 插入所有反饋資料
|
||||
for (const feedback of feedbackData) {
|
||||
const feedbackSql = `
|
||||
INSERT INTO evaluation_feedback (evaluation_id, criteria_item_id, feedback_type, content, sort_order)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`;
|
||||
|
||||
await connection.execute(feedbackSql, [
|
||||
feedback.evaluation_id,
|
||||
feedback.criteria_item_id,
|
||||
feedback.feedback_type,
|
||||
feedback.content,
|
||||
feedback.sort_order
|
||||
]);
|
||||
}
|
||||
console.log(`✅ 創建 ${feedbackData.length} 筆 evaluation_feedback 記錄成功`);
|
||||
|
||||
console.log('🎉 所有資料上傳完成!');
|
||||
console.log(`📊 評分結果: ${aiEvaluationResult.overallScore}/${aiEvaluationResult.totalPossible} (${aiEvaluationResult.grade})`);
|
||||
console.log(`📝 專案: ${aiEvaluationResult.projectTitle}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 處理過程中發生錯誤:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
if (connection) {
|
||||
await connection.end();
|
||||
console.log('🔌 資料庫連接已關閉');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 執行解析和上傳
|
||||
if (require.main === module) {
|
||||
parseAndUploadEvaluation()
|
||||
.then(() => {
|
||||
console.log('✅ 腳本執行完成');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('❌ 腳本執行失敗:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { parseAndUploadEvaluation, aiEvaluationResult, criteriaNameToId };
|
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* 測試完整修復後的 AI 評分整合功能
|
||||
*/
|
||||
|
||||
console.log('🔧 測試完整修復後的 AI 評分整合功能...\n');
|
||||
|
||||
console.log('✅ 修復內容:');
|
||||
console.log('1. 修復 evaluation_scores 缺少 ID=56 的問題:');
|
||||
console.log(' - 改為遍歷所有 criteria 而不是只遍歷 evaluation.results');
|
||||
console.log(' - 確保為所有 5 個評分標準創建記錄');
|
||||
console.log(' - 如果 AI 沒有返回某個標準的評分,使用預設值\n');
|
||||
|
||||
console.log('2. 修復 evaluation_feedback 缺少完整資訊的問題:');
|
||||
console.log(' - 添加 keyFindings 的完整上傳');
|
||||
console.log(' - 添加 improvementSuggestions 的完整上傳:');
|
||||
console.log(' * maintainStrengths (保持優勢)');
|
||||
console.log(' * keyImprovements (關鍵改進建議)');
|
||||
console.log(' * keyImprovements.suggestions (具體建議)');
|
||||
console.log(' * actionPlan (行動計劃)\n');
|
||||
|
||||
console.log('📊 預期的 evaluation_scores 記錄:');
|
||||
console.log(' - 應用實務性 (ID: 52)');
|
||||
console.log(' - 創新性 (ID: 53)');
|
||||
console.log(' - 成效與效益 (ID: 54)');
|
||||
console.log(' - 擴散與可複用性 (ID: 55)');
|
||||
console.log(' - 簡報與表達 (ID: 56) ← 這個之前會遺漏,現在會包含\n');
|
||||
|
||||
console.log('📊 預期的 evaluation_feedback 記錄類型:');
|
||||
console.log(' - overall: 整體反饋、詳細分析摘要');
|
||||
console.log(' - criteria: 各項標準反饋、詳細反饋');
|
||||
console.log(' - strength: 各項標準優點、保持優勢');
|
||||
console.log(' - improvement: 各項標準改進建議、關鍵改進建議、具體建議、行動計劃');
|
||||
console.log(' - keyFindings: 關鍵發現 (每項一條記錄)\n');
|
||||
|
||||
console.log('🔍 驗證 SQL 查詢:');
|
||||
console.log('-- 檢查 evaluation_scores 是否包含所有 5 個評分標準');
|
||||
console.log('SELECT criteria_item_id, COUNT(*) as count FROM evaluation_scores WHERE evaluation_id = [最新 ID] GROUP BY criteria_item_id ORDER BY criteria_item_id;');
|
||||
console.log('');
|
||||
console.log('-- 檢查 evaluation_feedback 的記錄類型和數量');
|
||||
console.log('SELECT feedback_type, COUNT(*) as count FROM evaluation_feedback WHERE evaluation_id = [最新 ID] GROUP BY feedback_type ORDER BY feedback_type;');
|
||||
console.log('');
|
||||
console.log('-- 檢查 keyFindings 是否已上傳');
|
||||
console.log('SELECT content FROM evaluation_feedback WHERE evaluation_id = [最新 ID] AND content LIKE \'%關鍵發現%\' OR content LIKE \'%keyFindings%\';');
|
||||
console.log('');
|
||||
console.log('-- 檢查 improvementSuggestions 是否已上傳');
|
||||
console.log('SELECT content FROM evaluation_feedback WHERE evaluation_id = [最新 ID] AND (content LIKE \'%保持優勢%\' OR content LIKE \'%關鍵改進%\' OR content LIKE \'%行動計劃%\');\n');
|
||||
|
||||
console.log('🚀 執行步驟:');
|
||||
console.log('1. 啟動應用程式: npm run dev');
|
||||
console.log('2. 訪問上傳頁面: http://localhost:3000/upload');
|
||||
console.log('3. 上傳 PPT 文件並填寫專案資訊');
|
||||
console.log('4. 點擊「開始 AI 評審」按鈕');
|
||||
console.log('5. 檢查控制台日誌,應該看到:');
|
||||
console.log(' - "✅ 創建評分記錄: 簡報與表達 (ID: 56) - X/10"');
|
||||
console.log(' - 所有 5 個評分標準的創建記錄');
|
||||
console.log('6. 執行上述 SQL 查詢驗證結果\n');
|
||||
|
||||
console.log('✅ 修復完成!現在應該有完整的資料上傳了。');
|
@@ -1,128 +0,0 @@
|
||||
const { EvaluationUploadService, defaultAIEvaluationResult } = require('../lib/services/evaluation-upload');
|
||||
|
||||
/**
|
||||
* 測試 AI 評分結果上傳功能
|
||||
*/
|
||||
|
||||
async function testEvaluationUpload() {
|
||||
try {
|
||||
console.log('🧪 開始測試 AI 評分結果上傳功能...\n');
|
||||
|
||||
// 測試 1: 檢查預設資料
|
||||
console.log('📋 測試 1: 檢查預設 AI 評分結果');
|
||||
console.log(`專案標題: ${defaultAIEvaluationResult.projectTitle}`);
|
||||
console.log(`總分: ${defaultAIEvaluationResult.overallScore}/${defaultAIEvaluationResult.totalPossible}`);
|
||||
console.log(`等級: ${defaultAIEvaluationResult.grade}`);
|
||||
console.log(`評分標準數量: ${defaultAIEvaluationResult.criteria.length}`);
|
||||
console.log('✅ 預設資料檢查完成\n');
|
||||
|
||||
// 測試 2: 檢查 criteria 對應關係
|
||||
console.log('📋 測試 2: 檢查 criteria 對應關係');
|
||||
const criteriaMapping = EvaluationUploadService.getCriteriaMapping();
|
||||
console.log('當前對應關係:', criteriaMapping);
|
||||
|
||||
// 檢查是否所有 criteria 都有對應的 ID
|
||||
const missingMappings = defaultAIEvaluationResult.criteria.filter(
|
||||
criteria => !criteriaMapping[criteria.name]
|
||||
);
|
||||
|
||||
if (missingMappings.length > 0) {
|
||||
console.warn('⚠️ 缺少對應關係的評分標準:', missingMappings.map(c => c.name));
|
||||
} else {
|
||||
console.log('✅ 所有評分標準都有對應關係\n');
|
||||
}
|
||||
|
||||
// 測試 3: 模擬上傳(不實際執行資料庫操作)
|
||||
console.log('📋 測試 3: 模擬資料準備');
|
||||
|
||||
const projectId = 1;
|
||||
const analysisDuration = 120;
|
||||
const aiModelVersion = 'gemini-1.5-pro';
|
||||
|
||||
// 模擬 evaluations 資料
|
||||
const evaluationData = {
|
||||
project_id: projectId,
|
||||
overall_score: defaultAIEvaluationResult.overallScore,
|
||||
max_possible_score: defaultAIEvaluationResult.totalPossible,
|
||||
grade: defaultAIEvaluationResult.grade,
|
||||
analysis_duration: analysisDuration,
|
||||
ai_model_version: aiModelVersion,
|
||||
status: 'completed',
|
||||
error_message: null
|
||||
};
|
||||
|
||||
console.log('Evaluations 資料:', evaluationData);
|
||||
|
||||
// 模擬 evaluation_scores 資料
|
||||
const evaluationScoresData = defaultAIEvaluationResult.criteria.map(criteria => {
|
||||
const criteriaItemId = criteriaMapping[criteria.name];
|
||||
return {
|
||||
evaluation_id: '[待生成]',
|
||||
criteria_item_id: criteriaItemId,
|
||||
score: criteria.score,
|
||||
max_score: criteria.maxScore,
|
||||
weight: criteria.weight,
|
||||
weighted_score: criteria.weightedScore,
|
||||
percentage: (criteria.score / criteria.maxScore) * 100
|
||||
};
|
||||
});
|
||||
|
||||
console.log('Evaluation Scores 資料:', evaluationScoresData);
|
||||
|
||||
// 模擬 evaluation_feedback 資料
|
||||
const feedbackCount =
|
||||
1 + // 整體反饋
|
||||
defaultAIEvaluationResult.criteria.length + // 各標準反饋
|
||||
defaultAIEvaluationResult.criteria.reduce((sum, c) => sum + c.strengths.length + c.improvements.length, 0) + // 優點和改進建議
|
||||
1 + // 整體改進建議
|
||||
defaultAIEvaluationResult.improvementSuggestions.maintainStrengths.length + // 保持優勢
|
||||
defaultAIEvaluationResult.improvementSuggestions.keyImprovements.length + // 關鍵改進
|
||||
defaultAIEvaluationResult.improvementSuggestions.actionPlan.length; // 行動計劃
|
||||
|
||||
console.log(`Evaluation Feedback 資料: 預計 ${feedbackCount} 筆記錄`);
|
||||
console.log('✅ 資料準備完成\n');
|
||||
|
||||
// 測試 4: 驗證資料完整性
|
||||
console.log('📋 測試 4: 驗證資料完整性');
|
||||
|
||||
const requiredFields = ['projectTitle', 'overallScore', 'totalPossible', 'grade', 'criteria'];
|
||||
const missingFields = requiredFields.filter(field => !defaultAIEvaluationResult[field]);
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
console.error('❌ 缺少必要欄位:', missingFields);
|
||||
} else {
|
||||
console.log('✅ 資料完整性檢查通過');
|
||||
}
|
||||
|
||||
// 檢查 criteria 資料
|
||||
const criteriaIssues = defaultAIEvaluationResult.criteria.filter(criteria =>
|
||||
!criteria.name ||
|
||||
typeof criteria.score !== 'number' ||
|
||||
typeof criteria.maxScore !== 'number' ||
|
||||
!criteria.feedback
|
||||
);
|
||||
|
||||
if (criteriaIssues.length > 0) {
|
||||
console.error('❌ criteria 資料有問題:', criteriaIssues);
|
||||
} else {
|
||||
console.log('✅ criteria 資料檢查通過');
|
||||
}
|
||||
|
||||
console.log('\n🎉 所有測試完成!');
|
||||
console.log('\n📝 使用說明:');
|
||||
console.log('1. 確保資料庫連線正常');
|
||||
console.log('2. 確認 criteria_items 表中有對應的評分項目');
|
||||
console.log('3. 調整 projectId 為實際的專案 ID');
|
||||
console.log('4. 執行: node scripts/parse-ai-evaluation.js');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 測試過程中發生錯誤:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 執行測試
|
||||
if (require.main === module) {
|
||||
testEvaluationUpload();
|
||||
}
|
||||
|
||||
module.exports = { testEvaluationUpload };
|
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* 測試修復後的 AI 評分整合功能
|
||||
*/
|
||||
|
||||
console.log('🔧 測試修復後的 AI 評分整合功能...\n');
|
||||
|
||||
console.log('✅ 修復內容:');
|
||||
console.log('1. 將所有 undefined 值轉換為 null 以符合 MySQL2 要求');
|
||||
console.log('2. 在資料庫服務中使用 ?? 運算符處理 undefined 值');
|
||||
console.log('3. 修復 TypeScript 類型錯誤\n');
|
||||
|
||||
console.log('🔍 修復的具體問題:');
|
||||
console.log('- ProjectService.create: description, analysis_started_at, analysis_completed_at');
|
||||
console.log('- EvaluationService.create: overall_score, grade, analysis_duration, ai_model_version, error_message');
|
||||
console.log('- EvaluationFeedbackService.create: criteria_item_id\n');
|
||||
|
||||
console.log('📊 預期的資料庫操作:');
|
||||
console.log('1. 創建專案記錄 (projects 表)');
|
||||
console.log('2. 創建文件記錄 (project_files 表)');
|
||||
console.log('3. AI 分析 PPT 內容');
|
||||
console.log('4. 創建評審記錄 (evaluations 表)');
|
||||
console.log('5. 創建評分明細 (evaluation_scores 表)');
|
||||
console.log('6. 創建評語記錄 (evaluation_feedback 表)');
|
||||
console.log('7. 更新專案狀態為完成\n');
|
||||
|
||||
console.log('🚀 現在可以測試了!');
|
||||
console.log('1. 啟動應用程式: npm run dev');
|
||||
console.log('2. 訪問: http://localhost:3000/upload');
|
||||
console.log('3. 上傳 PPT 文件並填寫專案資訊');
|
||||
console.log('4. 點擊「開始 AI 評審」按鈕');
|
||||
console.log('5. 檢查控制台日誌和資料庫記錄\n');
|
||||
|
||||
console.log('✅ 修復完成!應該不會再出現 "Bind parameters must not contain undefined" 錯誤了。');
|
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* 測試修復後的 AI 評分整合功能
|
||||
*/
|
||||
|
||||
console.log('🔧 測試修復後的 AI 評分整合功能...\n');
|
||||
|
||||
console.log('✅ 修復內容:');
|
||||
console.log('1. 為 evaluations 表添加新欄位:');
|
||||
console.log(' - performance_status: 表現狀況');
|
||||
console.log(' - recommended_stars: 推薦等級(星星數量)');
|
||||
console.log(' - excellent_items: 優秀項目數量');
|
||||
console.log(' - improvement_items: 待改進項目數量\n');
|
||||
|
||||
console.log('2. 修復 evaluation_feedback 上傳邏輯:');
|
||||
console.log(' - 為每個 criteria 創建完整的反饋記錄');
|
||||
console.log(' - 包括: criteria 反饋、詳細反饋、strengths、improvements');
|
||||
console.log(' - 確保所有 5 個評分標準都有對應的反饋記錄\n');
|
||||
|
||||
console.log('📊 預期的 evaluation_feedback 記錄數量:');
|
||||
console.log(' - 整體反饋: 1 筆');
|
||||
console.log(' - 各項標準反饋: 5 個 criteria × 2 筆 = 10 筆');
|
||||
console.log(' - Strengths: 5 個 criteria × 平均 2-3 筆 = 10-15 筆');
|
||||
console.log(' - Improvements: 5 個 criteria × 平均 2-3 筆 = 10-15 筆');
|
||||
console.log(' - 額外反饋: 詳細分析、關鍵發現、改進建議等 = 5-10 筆');
|
||||
console.log(' - 總計: 約 35-50 筆記錄\n');
|
||||
|
||||
console.log('📊 預期的 evaluations 記錄內容:');
|
||||
console.log(' - project_id: [專案 ID]');
|
||||
console.log(' - overall_score: [總分]');
|
||||
console.log(' - max_possible_score: 100');
|
||||
console.log(' - grade: [等級]');
|
||||
console.log(' - performance_status: [表現狀況]');
|
||||
console.log(' - recommended_stars: [推薦星星數量]');
|
||||
console.log(' - excellent_items: [優秀項目數量]');
|
||||
console.log(' - improvement_items: [待改進項目數量]');
|
||||
console.log(' - analysis_duration: [分析耗時]');
|
||||
console.log(' - ai_model_version: gemini-1.5-flash');
|
||||
console.log(' - status: completed\n');
|
||||
|
||||
console.log('🚀 執行步驟:');
|
||||
console.log('1. 執行資料庫更新腳本:');
|
||||
console.log(' node scripts/update-evaluation-table.js');
|
||||
console.log('2. 啟動應用程式: npm run dev');
|
||||
console.log('3. 訪問上傳頁面: http://localhost:3000/upload');
|
||||
console.log('4. 上傳 PPT 文件並填寫專案資訊');
|
||||
console.log('5. 點擊「開始 AI 評審」按鈕');
|
||||
console.log('6. 檢查資料庫記錄:\n');
|
||||
|
||||
console.log(' SELECT * FROM evaluations WHERE id = [最新 ID];');
|
||||
console.log(' SELECT COUNT(*) as feedback_count FROM evaluation_feedback WHERE evaluation_id = [最新 ID];');
|
||||
console.log(' SELECT criteria_item_id, feedback_type, COUNT(*) as count FROM evaluation_feedback WHERE evaluation_id = [最新 ID] GROUP BY criteria_item_id, feedback_type;\n');
|
||||
|
||||
console.log('✅ 修復完成!現在應該有完整的資料上傳了。');
|
@@ -1,118 +0,0 @@
|
||||
/**
|
||||
* 測試 AI 評分整合功能
|
||||
* 這個腳本會測試從上傳文件到資料庫存儲的完整流程
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// 模擬測試資料
|
||||
const testData = {
|
||||
projectTitle: "測試專案 - AI 評分整合",
|
||||
projectDescription: "這是一個測試專案,用於驗證 AI 評分結果是否能正確上傳到資料庫",
|
||||
file: {
|
||||
name: "test-presentation.pptx",
|
||||
size: 1024000, // 1MB
|
||||
type: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
||||
}
|
||||
};
|
||||
|
||||
console.log('🧪 開始測試 AI 評分整合功能...\n');
|
||||
|
||||
console.log('📋 測試資料:');
|
||||
console.log(` 專案標題: ${testData.projectTitle}`);
|
||||
console.log(` 專案描述: ${testData.projectDescription}`);
|
||||
console.log(` 文件名稱: ${testData.file.name}`);
|
||||
console.log(` 文件大小: ${testData.file.size} bytes`);
|
||||
console.log(` 文件類型: ${testData.file.type}\n`);
|
||||
|
||||
console.log('🔄 預期的處理流程:');
|
||||
console.log('1. 用戶上傳 PPT 文件');
|
||||
console.log('2. 填寫專案標題和描述');
|
||||
console.log('3. 點擊「開始 AI 評審」按鈕');
|
||||
console.log('4. 系統創建專案記錄 (projects 表)');
|
||||
console.log('5. 系統創建文件記錄 (project_files 表)');
|
||||
console.log('6. AI 分析 PPT 內容並產生評分結果');
|
||||
console.log('7. 系統創建評審記錄 (evaluations 表)');
|
||||
console.log('8. 系統創建評分明細 (evaluation_scores 表)');
|
||||
console.log('9. 系統創建評語記錄 (evaluation_feedback 表)');
|
||||
console.log('10. 更新專案狀態為完成');
|
||||
console.log('11. 返回評分結果到前端顯示\n');
|
||||
|
||||
console.log('📊 預期的資料庫記錄:');
|
||||
console.log(' projects 表:');
|
||||
console.log(' - id: [自動生成]');
|
||||
console.log(' - user_id: 1');
|
||||
console.log(' - template_id: [評分標準模板 ID]');
|
||||
console.log(' - title: "測試專案 - AI 評分整合"');
|
||||
console.log(' - description: "這是一個測試專案..."');
|
||||
console.log(' - status: "completed"');
|
||||
console.log(' - analysis_started_at: [當前時間]');
|
||||
console.log(' - analysis_completed_at: [分析完成時間]\n');
|
||||
|
||||
console.log(' project_files 表:');
|
||||
console.log(' - id: [自動生成]');
|
||||
console.log(' - project_id: [專案 ID]');
|
||||
console.log(' - original_name: "test-presentation.pptx"');
|
||||
console.log(' - file_name: "test-presentation.pptx"');
|
||||
console.log(' - file_path: "/uploads/[project_id]/test-presentation.pptx"');
|
||||
console.log(' - file_size: 1024000');
|
||||
console.log(' - file_type: "pptx"');
|
||||
console.log(' - mime_type: "application/vnd.openxmlformats-officedocument.presentationml.presentation"');
|
||||
console.log(' - upload_status: "completed"');
|
||||
console.log(' - upload_progress: 100\n');
|
||||
|
||||
console.log(' evaluations 表:');
|
||||
console.log(' - id: [自動生成]');
|
||||
console.log(' - project_id: [專案 ID]');
|
||||
console.log(' - overall_score: [AI 評分總分]');
|
||||
console.log(' - max_possible_score: 100');
|
||||
console.log(' - grade: [AI 評定等級]');
|
||||
console.log(' - analysis_duration: [分析耗時秒數]');
|
||||
console.log(' - ai_model_version: "gemini-1.5-flash"');
|
||||
console.log(' - status: "completed"');
|
||||
console.log(' - error_message: null\n');
|
||||
|
||||
console.log(' evaluation_scores 表:');
|
||||
console.log(' - id: [自動生成]');
|
||||
console.log(' - evaluation_id: [評審記錄 ID]');
|
||||
console.log(' - criteria_item_id: [評分標準項目 ID]');
|
||||
console.log(' - score: [該項得分]');
|
||||
console.log(' - max_score: [該項滿分]');
|
||||
console.log(' - weight: [該項權重]');
|
||||
console.log(' - weighted_score: [加權分數]');
|
||||
console.log(' - percentage: [得分百分比]\n');
|
||||
|
||||
console.log(' evaluation_feedback 表:');
|
||||
console.log(' - id: [自動生成]');
|
||||
console.log(' - evaluation_id: [評審記錄 ID]');
|
||||
console.log(' - criteria_item_id: [評分標準項目 ID 或 null]');
|
||||
console.log(' - feedback_type: "overall" | "criteria" | "strength" | "improvement"');
|
||||
console.log(' - content: [反饋內容]');
|
||||
console.log(' - sort_order: [排序順序]\n');
|
||||
|
||||
console.log('✅ 測試準備完成!');
|
||||
console.log('\n📝 如何執行測試:');
|
||||
console.log('1. 確保資料庫連線正常');
|
||||
console.log('2. 確保有評分標準模板');
|
||||
console.log('3. 啟動應用程式: npm run dev');
|
||||
console.log('4. 訪問上傳頁面: http://localhost:3000/upload');
|
||||
console.log('5. 上傳一個 PPT 文件');
|
||||
console.log('6. 填寫專案資訊');
|
||||
console.log('7. 點擊「開始 AI 評審」按鈕');
|
||||
console.log('8. 檢查控制台日誌和資料庫記錄');
|
||||
console.log('9. 查看結果頁面顯示\n');
|
||||
|
||||
console.log('🔍 檢查要點:');
|
||||
console.log('- 控制台是否顯示完整的處理流程日誌');
|
||||
console.log('- 資料庫是否正確創建所有相關記錄');
|
||||
console.log('- 前端是否正確顯示評分結果');
|
||||
console.log('- 是否有任何錯誤訊息\n');
|
||||
|
||||
console.log('🎯 成功標準:');
|
||||
console.log('- 所有資料庫表都有對應的記錄');
|
||||
console.log('- 評分結果正確顯示在前端');
|
||||
console.log('- 沒有錯誤或異常');
|
||||
console.log('- 處理時間在合理範圍內\n');
|
||||
|
||||
console.log('🚀 開始測試吧!');
|
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* 測試修復 max_score undefined 問題
|
||||
*/
|
||||
|
||||
console.log('🔧 測試修復 max_score undefined 問題...\n');
|
||||
|
||||
console.log('✅ 問題分析:');
|
||||
console.log('錯誤顯示「簡報與表達」評分標準的 max_score 是 undefined,導致計算結果變成 NaN');
|
||||
console.log('原因:在預設值邏輯中使用了錯誤的屬性名稱\n');
|
||||
|
||||
console.log('✅ 修復內容:');
|
||||
console.log('1. 修正屬性名稱:');
|
||||
console.log(' - 錯誤: criteriaItem.maxScore (undefined)');
|
||||
console.log(' - 正確: criteriaItem.max_score (資料庫欄位名稱)\n');
|
||||
|
||||
console.log('2. 確保預設值計算正確:');
|
||||
console.log(' - score = Math.floor(criteriaItem.max_score * 0.7)');
|
||||
console.log(' - maxScore = criteriaItem.max_score');
|
||||
console.log(' - weighted_score = (score / maxScore) * criteriaItem.weight');
|
||||
console.log(' - percentage = (score / maxScore) * 100\n');
|
||||
|
||||
console.log('📊 預期的調試輸出 (修復後):');
|
||||
console.log('⚠️ 找不到評分標準 "簡報與表達" 的 AI 評分結果,使用預設值');
|
||||
console.log('🔍 檢查評分數據: 簡報與表達 {');
|
||||
console.log(' evaluation_id: 5,');
|
||||
console.log(' criteria_item_id: 56,');
|
||||
console.log(' score: 7,');
|
||||
console.log(' max_score: 10,');
|
||||
console.log(' weight: 10,');
|
||||
console.log(' weighted_score: 7,');
|
||||
console.log(' percentage: 70');
|
||||
console.log('}');
|
||||
console.log('✅ 創建評分記錄: 簡報與表達 (ID: 56) - 7/10\n');
|
||||
|
||||
console.log('🚀 執行步驟:');
|
||||
console.log('1. 啟動應用程式: npm run dev');
|
||||
console.log('2. 訪問上傳頁面: http://localhost:3000/upload');
|
||||
console.log('3. 上傳 PPT 文件並填寫專案資訊');
|
||||
console.log('4. 點擊「開始 AI 評審」按鈕');
|
||||
console.log('5. 檢查控制台日誌:');
|
||||
console.log(' - 應該看到所有 5 個評分標準的創建記錄');
|
||||
console.log(' - 不應該再出現 NaN 或 undefined 值');
|
||||
console.log(' - 應該看到「簡報與表達」使用預設值 7/10\n');
|
||||
|
||||
console.log('✅ 修復完成!現在「簡報與表達」應該會使用正確的預設值了。');
|
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* 測試名稱匹配問題
|
||||
*/
|
||||
|
||||
console.log('🔧 測試名稱匹配問題...\n');
|
||||
|
||||
console.log('✅ 問題分析:');
|
||||
console.log('AI 的 JSON 回應中確實包含了「簡報與表達」的評分結果,但系統仍然顯示找不到');
|
||||
console.log('這表示問題出在名稱匹配上\n');
|
||||
|
||||
console.log('🔍 可能的原因:');
|
||||
console.log('1. 資料庫中的名稱與 AI 回應中的名稱不完全一致');
|
||||
console.log('2. 可能有隱藏字符或空格差異');
|
||||
console.log('3. 字符編碼問題\n');
|
||||
|
||||
console.log('📊 預期的調試輸出:');
|
||||
console.log('🔍 尋找評分標準: "簡報與表達"');
|
||||
console.log('📋 可用的 AI 結果: ["應用實務性", "創新性", "成效與效益", "擴散與可複用性", "簡報與表達"]');
|
||||
console.log('✅ 找到匹配結果: 簡報與表達\n');
|
||||
|
||||
console.log('🚀 執行步驟:');
|
||||
console.log('1. 啟動應用程式: npm run dev');
|
||||
console.log('2. 訪問上傳頁面: http://localhost:3000/upload');
|
||||
console.log('3. 上傳 PPT 文件並點擊「開始 AI 評審」');
|
||||
console.log('4. 檢查控制台日誌:');
|
||||
console.log(' - 查看「簡報與表達」的名稱匹配過程');
|
||||
console.log(' - 確認是否找到匹配的結果');
|
||||
console.log(' - 如果沒有找到,檢查名稱是否有差異\n');
|
||||
|
||||
console.log('🔧 如果仍然有問題,可能需要:');
|
||||
console.log('1. 使用更寬鬆的匹配邏輯(包含部分匹配)');
|
||||
console.log('2. 去除前後空格和特殊字符');
|
||||
console.log('3. 使用正則表達式匹配\n');
|
||||
|
||||
console.log('✅ 調試日誌已添加,現在可以清楚看到名稱匹配的過程了!');
|
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* 測試修復 undefined 參數錯誤
|
||||
*/
|
||||
|
||||
console.log('🔧 測試修復 undefined 參數錯誤...\n');
|
||||
|
||||
console.log('✅ 修復內容:');
|
||||
console.log('1. 修復 EvaluationScoreService.create 方法:');
|
||||
console.log(' - 使用 ?? 運算符將所有 undefined 值轉換為 null');
|
||||
console.log(' - 確保所有參數都符合 MySQL2 的要求\n');
|
||||
|
||||
console.log('2. 添加調試日誌和驗證:');
|
||||
console.log(' - 在創建評分記錄前檢查所有值');
|
||||
console.log(' - 如果發現 undefined 值,拋出明確的錯誤訊息');
|
||||
console.log(' - 記錄詳細的評分數據以便調試\n');
|
||||
|
||||
console.log('🔍 修復的具體問題:');
|
||||
console.log('- evaluation_id: 確保不是 undefined');
|
||||
console.log('- criteria_item_id: 確保不是 undefined');
|
||||
console.log('- score: 確保不是 undefined');
|
||||
console.log('- max_score: 確保不是 undefined');
|
||||
console.log('- weight: 確保不是 undefined');
|
||||
console.log('- weighted_score: 計算結果確保不是 undefined');
|
||||
console.log('- percentage: 計算結果確保不是 undefined\n');
|
||||
|
||||
console.log('📊 預期的調試輸出:');
|
||||
console.log('🔍 檢查評分數據: 應用實務性 {');
|
||||
console.log(' evaluation_id: 123,');
|
||||
console.log(' criteria_item_id: 52,');
|
||||
console.log(' score: 8,');
|
||||
console.log(' max_score: 10,');
|
||||
console.log(' weight: 30,');
|
||||
console.log(' weighted_score: 24,');
|
||||
console.log(' percentage: 80');
|
||||
console.log('}');
|
||||
console.log('✅ 創建評分記錄: 應用實務性 (ID: 52) - 8/10\n');
|
||||
|
||||
console.log('🚀 執行步驟:');
|
||||
console.log('1. 啟動應用程式: npm run dev');
|
||||
console.log('2. 訪問上傳頁面: http://localhost:3000/upload');
|
||||
console.log('3. 上傳 PPT 文件並填寫專案資訊');
|
||||
console.log('4. 點擊「開始 AI 評審」按鈕');
|
||||
console.log('5. 檢查控制台日誌:');
|
||||
console.log(' - 應該看到每個評分標準的詳細檢查日誌');
|
||||
console.log(' - 不應該再出現 "Bind parameters must not contain undefined" 錯誤');
|
||||
console.log(' - 應該看到所有 5 個評分標準的創建記錄\n');
|
||||
|
||||
console.log('✅ 修復完成!現在應該不會再出現 undefined 參數錯誤了。');
|
@@ -1,98 +0,0 @@
|
||||
const mysql = require('mysql2/promise');
|
||||
|
||||
// 資料庫配置
|
||||
const dbConfig = {
|
||||
host: process.env.DB_HOST || 'localhost',
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || '',
|
||||
database: process.env.DB_NAME || 'ai_scoring_app',
|
||||
timezone: '+08:00',
|
||||
};
|
||||
|
||||
async function updateEvaluationTable() {
|
||||
let connection;
|
||||
|
||||
try {
|
||||
console.log('🔗 連接到資料庫...');
|
||||
connection = await mysql.createConnection(dbConfig);
|
||||
console.log('✅ 資料庫連接成功');
|
||||
|
||||
// 檢查欄位是否已存在
|
||||
console.log('🔍 檢查 evaluations 表結構...');
|
||||
const [columns] = await connection.execute(`
|
||||
SELECT COLUMN_NAME
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = 'evaluations'
|
||||
`, [dbConfig.database]);
|
||||
|
||||
const existingColumns = columns.map(col => col.COLUMN_NAME);
|
||||
console.log('📋 現有欄位:', existingColumns);
|
||||
|
||||
// 添加新欄位
|
||||
const newColumns = [
|
||||
{ name: 'performance_status', type: 'varchar(50) DEFAULT NULL COMMENT \'表現狀況\'' },
|
||||
{ name: 'recommended_stars', type: 'int(11) DEFAULT NULL COMMENT \'推薦等級(星星數量)\'' },
|
||||
{ name: 'excellent_items', type: 'int(11) DEFAULT NULL COMMENT \'優秀項目數量\'' },
|
||||
{ name: 'improvement_items', type: 'int(11) DEFAULT NULL COMMENT \'待改進項目數量\'' }
|
||||
];
|
||||
|
||||
for (const column of newColumns) {
|
||||
if (!existingColumns.includes(column.name)) {
|
||||
console.log(`➕ 添加欄位: ${column.name}`);
|
||||
await connection.execute(`
|
||||
ALTER TABLE evaluations
|
||||
ADD COLUMN \`${column.name}\` ${column.type}
|
||||
AFTER \`grade\`
|
||||
`);
|
||||
console.log(`✅ 欄位 ${column.name} 添加成功`);
|
||||
} else {
|
||||
console.log(`⚠️ 欄位 ${column.name} 已存在,跳過`);
|
||||
}
|
||||
}
|
||||
|
||||
// 驗證更新結果
|
||||
console.log('🔍 驗證更新結果...');
|
||||
const [updatedColumns] = await connection.execute(`
|
||||
SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_COMMENT
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = 'evaluations'
|
||||
ORDER BY ORDINAL_POSITION
|
||||
`, [dbConfig.database]);
|
||||
|
||||
console.log('📊 更新後的 evaluations 表結構:');
|
||||
updatedColumns.forEach(col => {
|
||||
console.log(` - ${col.COLUMN_NAME}: ${col.DATA_TYPE} ${col.IS_NULLABLE === 'YES' ? 'NULL' : 'NOT NULL'} ${col.COLUMN_DEFAULT ? `DEFAULT ${col.COLUMN_DEFAULT}` : ''} ${col.COLUMN_COMMENT ? `(${col.COLUMN_COMMENT})` : ''}`);
|
||||
});
|
||||
|
||||
console.log('\n🎉 evaluations 表更新完成!');
|
||||
console.log('📝 新增的欄位:');
|
||||
console.log(' - performance_status: 表現狀況');
|
||||
console.log(' - recommended_stars: 推薦等級(星星數量)');
|
||||
console.log(' - excellent_items: 優秀項目數量');
|
||||
console.log(' - improvement_items: 待改進項目數量');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 更新過程中發生錯誤:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
if (connection) {
|
||||
await connection.end();
|
||||
console.log('🔌 資料庫連接已關閉');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 執行更新
|
||||
if (require.main === module) {
|
||||
updateEvaluationTable()
|
||||
.then(() => {
|
||||
console.log('✅ 腳本執行完成');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('❌ 腳本執行失敗:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { updateEvaluationTable };
|
25
test-api.js
25
test-api.js
@@ -1,25 +0,0 @@
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
async function testAPI() {
|
||||
try {
|
||||
console.log('🧪 測試 API 端點...');
|
||||
|
||||
// 測試統計API
|
||||
console.log('📊 測試統計API...');
|
||||
const statsResponse = await fetch('http://localhost:3000/api/history/stats');
|
||||
const statsData = await statsResponse.json();
|
||||
console.log('統計數據:', statsData);
|
||||
|
||||
// 測試評審詳細API
|
||||
console.log('📋 測試評審詳細API...');
|
||||
const detailResponse = await fetch('http://localhost:3000/api/evaluation/2');
|
||||
const detailData = await detailResponse.json();
|
||||
console.log('評審詳細數據:', JSON.stringify(detailData, null, 2));
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 測試失敗:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 等待一下讓服務器啟動
|
||||
setTimeout(testAPI, 3000);
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user