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

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

93
scripts/init-database.js Normal file
View 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 };

View 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
View 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();

View 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();

View 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🎉 權重顯示格式測試完成!');

View 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🎉 權重修復測試完成!');