新增評分項目設定、資料庫整合

This commit is contained in:
2025-09-22 00:33:12 +08:00
parent 8de09129be
commit 9d4c586ad3
20 changed files with 2321 additions and 79 deletions

View 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 };