新增評分項目設定、資料庫整合
This commit is contained in:
319
scripts/init-database-simple.js
Normal file
319
scripts/init-database-simple.js
Normal file
@@ -0,0 +1,319 @@
|
||||
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 };
|
93
scripts/init-database.js
Normal file
93
scripts/init-database.js
Normal file
@@ -0,0 +1,93 @@
|
||||
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 };
|
69
scripts/test-criteria-api.js
Normal file
69
scripts/test-criteria-api.js
Normal file
@@ -0,0 +1,69 @@
|
||||
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
|
||||
|
||||
const API_BASE = 'http://localhost:3000/api';
|
||||
|
||||
async function testCriteriaAPI() {
|
||||
try {
|
||||
console.log('🔄 測試評分標準 API...');
|
||||
|
||||
// 1. 測試獲取預設模板
|
||||
console.log('\n1. 測試獲取預設模板...');
|
||||
const defaultResponse = await fetch(`${API_BASE}/criteria-templates/default`);
|
||||
const defaultData = await defaultResponse.json();
|
||||
|
||||
if (defaultData.success) {
|
||||
console.log('✅ 預設模板獲取成功');
|
||||
console.log(` 模板名稱: ${defaultData.data.name}`);
|
||||
console.log(` 評分項目數量: ${defaultData.data.items.length}`);
|
||||
defaultData.data.items.forEach((item, index) => {
|
||||
console.log(` ${index + 1}. ${item.name} (權重: ${item.weight}%)`);
|
||||
});
|
||||
} else {
|
||||
console.log('❌ 預設模板獲取失敗:', defaultData.error);
|
||||
}
|
||||
|
||||
// 2. 測試創建新模板
|
||||
console.log('\n2. 測試創建新模板...');
|
||||
const newTemplate = {
|
||||
name: '測試模板',
|
||||
description: '這是一個測試模板',
|
||||
items: [
|
||||
{ name: '測試項目1', description: '測試描述1', weight: 50, maxScore: 10 },
|
||||
{ name: '測試項目2', description: '測試描述2', weight: 50, maxScore: 10 }
|
||||
]
|
||||
};
|
||||
|
||||
const createResponse = await fetch(`${API_BASE}/criteria-templates`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(newTemplate)
|
||||
});
|
||||
const createData = await createResponse.json();
|
||||
|
||||
if (createData.success) {
|
||||
console.log('✅ 新模板創建成功');
|
||||
console.log(` 模板 ID: ${createData.data.id}`);
|
||||
} else {
|
||||
console.log('❌ 新模板創建失敗:', createData.error);
|
||||
}
|
||||
|
||||
// 3. 測試獲取所有模板
|
||||
console.log('\n3. 測試獲取所有模板...');
|
||||
const allResponse = await fetch(`${API_BASE}/criteria-templates`);
|
||||
const allData = await allResponse.json();
|
||||
|
||||
if (allData.success) {
|
||||
console.log('✅ 所有模板獲取成功');
|
||||
console.log(` 模板總數: ${allData.data.length}`);
|
||||
} else {
|
||||
console.log('❌ 所有模板獲取失敗:', allData.error);
|
||||
}
|
||||
|
||||
console.log('\n🎉 API 測試完成!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 測試失敗:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
testCriteriaAPI();
|
54
scripts/test-database.js
Normal file
54
scripts/test-database.js
Normal file
@@ -0,0 +1,54 @@
|
||||
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 testDatabase() {
|
||||
let connection;
|
||||
|
||||
try {
|
||||
console.log('🔄 正在測試資料庫連接...');
|
||||
|
||||
connection = await mysql.createConnection(dbConfig);
|
||||
|
||||
// 測試基本連接
|
||||
await connection.ping();
|
||||
console.log('✅ 資料庫連接成功');
|
||||
|
||||
// 測試查詢
|
||||
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]}`);
|
||||
});
|
||||
|
||||
// 測試預設數據
|
||||
const [criteriaItems] = await connection.query('SELECT * FROM criteria_items ORDER BY sort_order');
|
||||
console.log('📋 預設評分項目:');
|
||||
criteriaItems.forEach(item => {
|
||||
console.log(` - ${item.name} (權重: ${item.weight}%, 滿分: ${item.max_score})`);
|
||||
});
|
||||
|
||||
await connection.end();
|
||||
console.log('🎉 資料庫測試完成!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 資料庫測試失敗:', error.message);
|
||||
console.error('詳細錯誤:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
testDatabase();
|
79
scripts/test-single-template.js
Normal file
79
scripts/test-single-template.js
Normal file
@@ -0,0 +1,79 @@
|
||||
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
|
||||
|
||||
const API_BASE = 'http://localhost:3000/api';
|
||||
|
||||
async function testSingleTemplateMode() {
|
||||
try {
|
||||
console.log('🔄 測試單一模板模式...');
|
||||
|
||||
// 1. 測試獲取現有模板
|
||||
console.log('\n1. 測試獲取現有模板...');
|
||||
const getResponse = await fetch(`${API_BASE}/criteria-templates`);
|
||||
const getData = await getResponse.json();
|
||||
|
||||
if (getData.success) {
|
||||
console.log(`✅ 找到 ${getData.data.length} 個模板`);
|
||||
if (getData.data.length > 0) {
|
||||
const template = getData.data[0];
|
||||
console.log(` 模板名稱: ${template.name}`);
|
||||
console.log(` 評分項目數量: ${template.items.length}`);
|
||||
}
|
||||
} else {
|
||||
console.log('❌ 獲取模板失敗:', getData.error);
|
||||
}
|
||||
|
||||
// 2. 測試覆蓋模板
|
||||
console.log('\n2. 測試覆蓋模板...');
|
||||
const templateData = {
|
||||
name: '我的評分標準',
|
||||
description: '這是我的自定義評分標準',
|
||||
items: [
|
||||
{ name: '內容品質', description: '內容的準確性和完整性', weight: 30, maxScore: 10 },
|
||||
{ name: '視覺設計', description: '版面設計和視覺效果', weight: 25, maxScore: 10 },
|
||||
{ name: '邏輯結構', description: '內容組織的邏輯性', weight: 25, maxScore: 10 },
|
||||
{ name: '創新性', description: '創意思維的展現', weight: 20, maxScore: 10 }
|
||||
]
|
||||
};
|
||||
|
||||
const saveResponse = await fetch(`${API_BASE}/criteria-templates`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(templateData)
|
||||
});
|
||||
const saveData = await saveResponse.json();
|
||||
|
||||
if (saveData.success) {
|
||||
console.log('✅ 模板覆蓋成功');
|
||||
console.log(` 模板 ID: ${saveData.data.id}`);
|
||||
} else {
|
||||
console.log('❌ 模板覆蓋失敗:', saveData.error);
|
||||
}
|
||||
|
||||
// 3. 驗證覆蓋結果
|
||||
console.log('\n3. 驗證覆蓋結果...');
|
||||
const verifyResponse = await fetch(`${API_BASE}/criteria-templates`);
|
||||
const verifyData = await verifyResponse.json();
|
||||
|
||||
if (verifyData.success) {
|
||||
console.log(`✅ 驗證成功,現在有 ${verifyData.data.length} 個模板`);
|
||||
if (verifyData.data.length > 0) {
|
||||
const template = verifyData.data[0];
|
||||
console.log(` 模板名稱: ${template.name}`);
|
||||
console.log(` 模板描述: ${template.description}`);
|
||||
console.log(` 評分項目數量: ${template.items.length}`);
|
||||
template.items.forEach((item, index) => {
|
||||
console.log(` ${index + 1}. ${item.name} (權重: ${item.weight}%)`);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log('❌ 驗證失敗:', verifyData.error);
|
||||
}
|
||||
|
||||
console.log('\n🎉 單一模板模式測試完成!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 測試失敗:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
testSingleTemplateMode();
|
23
scripts/test-weight-display.js
Normal file
23
scripts/test-weight-display.js
Normal file
@@ -0,0 +1,23 @@
|
||||
// 測試權重顯示格式
|
||||
const testWeights = [25.00, 20.00, 20.00, 15.00, 20.00];
|
||||
|
||||
console.log('🔄 測試權重顯示格式...');
|
||||
|
||||
// 計算總權重
|
||||
const totalWeight = testWeights.reduce((sum, weight) => sum + weight, 0);
|
||||
|
||||
console.log('個別權重:');
|
||||
testWeights.forEach((weight, index) => {
|
||||
console.log(` ${index + 1}. ${weight.toFixed(1)}%`);
|
||||
});
|
||||
|
||||
console.log(`\n總權重: ${totalWeight.toFixed(1)}%`);
|
||||
console.log(`是否等於 100%: ${totalWeight === 100 ? '✅' : '❌'}`);
|
||||
|
||||
// 測試權重顯示的各種格式
|
||||
console.log('\n權重顯示格式測試:');
|
||||
console.log(`原始格式: ${totalWeight}%`);
|
||||
console.log(`toFixed(1): ${totalWeight.toFixed(1)}%`);
|
||||
console.log(`toFixed(0): ${totalWeight.toFixed(0)}%`);
|
||||
|
||||
console.log('\n🎉 權重顯示格式測試完成!');
|
41
scripts/test-weight-fix.js
Normal file
41
scripts/test-weight-fix.js
Normal file
@@ -0,0 +1,41 @@
|
||||
// 測試權重修復
|
||||
console.log('🔄 測試權重修復...');
|
||||
|
||||
// 模擬可能出現的權重數據類型
|
||||
const testCases = [
|
||||
{ weight: 25.00 }, // 正常數字
|
||||
{ weight: "25.00" }, // 字符串數字
|
||||
{ weight: "25" }, // 字符串整數
|
||||
{ weight: null }, // null 值
|
||||
{ weight: undefined }, // undefined 值
|
||||
{ weight: "" }, // 空字符串
|
||||
{ weight: "abc" }, // 非數字字符串
|
||||
];
|
||||
|
||||
console.log('\n測試各種權重數據類型:');
|
||||
testCases.forEach((item, index) => {
|
||||
const originalWeight = item.weight;
|
||||
const safeWeight = Number(item.weight) || 0;
|
||||
const formattedWeight = safeWeight.toFixed(1);
|
||||
|
||||
console.log(`${index + 1}. 原始: ${originalWeight} (${typeof originalWeight})`);
|
||||
console.log(` 安全轉換: ${safeWeight} (${typeof safeWeight})`);
|
||||
console.log(` 格式化: ${formattedWeight}%`);
|
||||
console.log('');
|
||||
});
|
||||
|
||||
// 測試總權重計算
|
||||
console.log('測試總權重計算:');
|
||||
const criteria = [
|
||||
{ weight: 25.00 },
|
||||
{ weight: "20.00" },
|
||||
{ weight: 20 },
|
||||
{ weight: "15.00" },
|
||||
{ weight: null },
|
||||
];
|
||||
|
||||
const totalWeight = criteria.reduce((sum, item) => sum + (Number(item.weight) || 0), 0);
|
||||
console.log(`總權重: ${totalWeight} (${typeof totalWeight})`);
|
||||
console.log(`格式化總權重: ${Number(totalWeight).toFixed(1)}%`);
|
||||
|
||||
console.log('\n🎉 權重修復測試完成!');
|
Reference in New Issue
Block a user