修正 vercal 部署失敗問題

This commit is contained in:
2025-09-29 21:21:52 +08:00
parent 426deafbb8
commit 3aba1451bd
144 changed files with 321 additions and 11283 deletions

View File

@@ -1,129 +0,0 @@
const https = require('https')
const http = require('http')
const checkActualUploadTimes = async () => {
console.log('🔍 檢查實際上傳時間')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查邏輯測試結果
console.log('\n📊 檢查邏輯測試結果...')
const logicResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/logic?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (logicResponse.status === 200) {
const logicData = JSON.parse(logicResponse.data)
if (logicData.success && logicData.data.length > 0) {
console.log('邏輯測試結果 (按創建時間排序):')
logicData.data
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
.forEach((result, index) => {
console.log(`\n${index + 1}. 邏輯測試:`)
console.log(` ID: ${result.id}`)
console.log(` completed_at: ${result.completed_at}`)
console.log(` created_at: ${result.created_at}`)
const completedDate = new Date(result.completed_at)
const createdDate = new Date(result.created_at)
console.log(` completed_at 台灣時間: ${completedDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(` created_at 台灣時間: ${createdDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
// 計算時間差
const timeDiff = createdDate.getTime() - completedDate.getTime()
const hoursDiff = timeDiff / (1000 * 60 * 60)
console.log(` 時間差: ${hoursDiff.toFixed(2)} 小時`)
})
}
}
// 檢查創意測試結果
console.log('\n📊 檢查創意測試結果...')
const creativeResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (creativeResponse.status === 200) {
const creativeData = JSON.parse(creativeResponse.data)
if (creativeData.success && creativeData.data.length > 0) {
console.log('創意測試結果 (按創建時間排序):')
creativeData.data
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
.forEach((result, index) => {
console.log(`\n${index + 1}. 創意測試:`)
console.log(` ID: ${result.id}`)
console.log(` completed_at: ${result.completed_at}`)
console.log(` created_at: ${result.created_at}`)
const completedDate = new Date(result.completed_at)
const createdDate = new Date(result.created_at)
console.log(` completed_at 台灣時間: ${completedDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(` created_at 台灣時間: ${createdDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
// 計算時間差
const timeDiff = createdDate.getTime() - completedDate.getTime()
const hoursDiff = timeDiff / (1000 * 60 * 60)
console.log(` 時間差: ${hoursDiff.toFixed(2)} 小時`)
})
}
}
// 檢查綜合測試結果
console.log('\n📊 檢查綜合測試結果...')
const combinedResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/combined?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (combinedResponse.status === 200) {
const combinedData = JSON.parse(combinedResponse.data)
if (combinedData.success && combinedData.data.length > 0) {
console.log('綜合測試結果 (按創建時間排序):')
combinedData.data
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
.forEach((result, index) => {
console.log(`\n${index + 1}. 綜合測試:`)
console.log(` ID: ${result.id}`)
console.log(` completed_at: ${result.completed_at}`)
console.log(` created_at: ${result.created_at}`)
const completedDate = new Date(result.completed_at)
const createdDate = new Date(result.created_at)
console.log(` completed_at 台灣時間: ${completedDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(` created_at 台灣時間: ${createdDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
// 計算時間差
const timeDiff = createdDate.getTime() - completedDate.getTime()
const hoursDiff = timeDiff / (1000 * 60 * 60)
console.log(` 時間差: ${hoursDiff.toFixed(2)} 小時`)
})
}
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 實際上傳時間檢查完成')
}
}
checkActualUploadTimes()

View File

@@ -1,67 +0,0 @@
const https = require('https')
const http = require('http')
const checkAllCombinedTimes = async () => {
console.log('🔍 檢查所有綜合測試結果時間')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查綜合測試結果 API
console.log('\n📊 檢查所有綜合測試結果...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/combined?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success) {
console.log(`找到 ${data.data.length} 筆綜合測試結果:`)
data.data.forEach((result, index) => {
console.log(`\n${index + 1}. 綜合測試結果:`)
console.log(` ID: ${result.id}`)
console.log(` 原始時間: ${result.completed_at}`)
const date = new Date(result.completed_at)
console.log(` 台灣時間: ${date.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(` 台灣時間 (詳細): ${date.toLocaleString("zh-TW", {
timeZone: "Asia/Taipei",
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: true
})}`)
// 檢查是否是今天
const now = new Date()
const testDate = new Date(result.completed_at)
const isToday = now.toDateString() === testDate.toDateString()
console.log(` 是否為今天: ${isToday}`)
// 計算時間差
const timeDiff = now.getTime() - testDate.getTime()
const hoursDiff = Math.floor(timeDiff / (1000 * 60 * 60))
const minutesDiff = Math.floor((timeDiff % (1000 * 60 * 60)) / (1000 * 60))
console.log(` 距離現在: ${hoursDiff} 小時 ${minutesDiff} 分鐘`)
})
}
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 所有綜合測試結果時間檢查完成')
}
}
checkAllCombinedTimes()

View File

@@ -1,73 +0,0 @@
const https = require('https')
const http = require('http')
const checkAllTestTimes = async () => {
console.log('🔍 檢查所有測試結果的時間顯示')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查用戶測試結果 API
console.log('\n📊 檢查用戶測試結果 API...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/user/test-results?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success && data.data.results.length > 0) {
console.log(`找到 ${data.data.results.length} 筆測試結果:`)
data.data.results.forEach((result, index) => {
console.log(`\n${index + 1}. ${result.type} 測試:`)
console.log(` 原始時間: ${result.completedAt}`)
const date = new Date(result.completedAt)
console.log(` UTC 時間: ${date.toISOString()}`)
console.log(` 台灣時間: ${date.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(` 台灣時間 (詳細): ${date.toLocaleString("zh-TW", {
timeZone: "Asia/Taipei",
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: true
})}`)
// 檢查是否是今天
const now = new Date()
const testDate = new Date(result.completedAt)
const isToday = now.toDateString() === testDate.toDateString()
console.log(` 是否為今天: ${isToday}`)
// 計算時間差
const timeDiff = now.getTime() - testDate.getTime()
const hoursDiff = Math.floor(timeDiff / (1000 * 60 * 60))
const minutesDiff = Math.floor((timeDiff % (1000 * 60 * 60)) / (1000 * 60))
console.log(` 距離現在: ${hoursDiff} 小時 ${minutesDiff} 分鐘`)
})
}
}
// 檢查當前時間
console.log('\n📊 當前時間:')
const now = new Date()
console.log(`UTC 時間: ${now.toISOString()}`)
console.log(`台灣時間: ${now.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 所有測試結果時間檢查完成')
}
}
checkAllTestTimes()

View File

@@ -1,58 +0,0 @@
const { executeQuery } = require('../lib/database/connection');
async function checkCombinedBreakdown() {
console.log('🔍 檢查綜合測試的 breakdown 資料');
console.log('==============================');
try {
// 檢查 combined_test_results 的 breakdown 資料
const results = await executeQuery('SELECT id, user_id, logic_breakdown, creativity_breakdown FROM combined_test_results LIMIT 3');
results.forEach((result, index) => {
console.log(`\n📋 綜合測試 ${index + 1}:`);
console.log('ID:', result.id);
console.log('User ID:', result.user_id);
console.log('Logic Breakdown 類型:', typeof result.logic_breakdown);
console.log('Creativity Breakdown 類型:', typeof result.creativity_breakdown);
if (result.logic_breakdown) {
console.log('Logic Breakdown 內容:', JSON.stringify(result.logic_breakdown, null, 2));
}
if (result.creativity_breakdown) {
console.log('Creativity Breakdown 內容:', JSON.stringify(result.creativity_breakdown, null, 2));
}
});
// 檢查 logic_test_answers 資料
console.log('\n📋 Logic Test Answers:');
const logicAnswers = await executeQuery('SELECT * FROM logic_test_answers LIMIT 3');
logicAnswers.forEach((answer, index) => {
console.log(`答案 ${index + 1}:`, {
test_result_id: answer.test_result_id,
question_id: answer.question_id,
user_answer: answer.user_answer,
is_correct: answer.is_correct
});
});
// 檢查 creative_test_answers 資料
console.log('\n📋 Creative Test Answers:');
const creativeAnswers = await executeQuery('SELECT * FROM creative_test_answers LIMIT 3');
creativeAnswers.forEach((answer, index) => {
console.log(`答案 ${index + 1}:`, {
test_result_id: answer.test_result_id,
question_id: answer.question_id,
user_answer: answer.user_answer,
score: answer.score
});
});
} catch (error) {
console.error('❌ 檢查失敗:', error.message);
}
console.log('==============================\n');
}
checkCombinedBreakdown();

View File

@@ -1,38 +0,0 @@
const { executeQuery } = require('../lib/database/connection')
const checkCombinedTableFields = async () => {
console.log('🔍 檢查 combined_test_results 表的實際欄位')
console.log('=' .repeat(50))
try {
// 檢查表結構
console.log('\n📊 檢查表結構...')
const structureQuery = 'DESCRIBE combined_test_results'
const structure = await executeQuery(structureQuery)
console.log('📋 表欄位:')
structure.forEach(field => {
console.log(` ${field.Field}: ${field.Type} ${field.Null === 'YES' ? '(可為空)' : '(不可為空)'}`)
})
// 檢查實際資料
console.log('\n📊 檢查實際資料...')
const dataQuery = 'SELECT * FROM combined_test_results LIMIT 2'
const data = await executeQuery(dataQuery)
console.log('📋 實際資料:')
data.forEach((row, index) => {
console.log(`\n 記錄 ${index + 1}:`)
Object.keys(row).forEach(key => {
console.log(` ${key}: ${row[key]}`)
})
})
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 資料庫欄位檢查完成')
}
}
checkCombinedTableFields()

View File

@@ -1,38 +0,0 @@
const { executeQuery } = require('../lib/database/connection')
const checkCombinedTableStructure = async () => {
console.log('🔍 檢查綜合測試結果表結構')
console.log('=' .repeat(40))
try {
// 檢查表結構
console.log('\n📊 檢查表結構...')
const structureQuery = 'DESCRIBE combined_test_results'
const structure = await executeQuery(structureQuery)
console.log('📋 表欄位:')
structure.forEach(field => {
console.log(` ${field.Field}: ${field.Type} ${field.Null === 'YES' ? '(可為空)' : '(不可為空)'}`)
})
// 檢查實際資料
console.log('\n📊 檢查實際資料...')
const dataQuery = 'SELECT * FROM combined_test_results LIMIT 3'
const data = await executeQuery(dataQuery)
console.log('📋 實際資料範例:')
data.forEach((row, index) => {
console.log(`\n 記錄 ${index + 1}:`)
Object.keys(row).forEach(key => {
console.log(` ${key}: ${row[key]}`)
})
})
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 綜合測試結果表結構檢查完成')
}
}
checkCombinedTableStructure()

View File

@@ -1,52 +0,0 @@
const http = require('http')
const checkCombinedTestData = async () => {
console.log('🔍 檢查綜合測試資料結構')
console.log('=' .repeat(40))
try {
// 獲取所有測試結果
const response = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success) {
console.log('✅ 成功獲取測試結果')
// 找出綜合測試結果
const combinedResults = data.data.results.filter(result => result.type === 'combined')
console.log(`📊 綜合測試結果數量: ${combinedResults.length}`)
combinedResults.forEach((result, index) => {
console.log(`\n📋 綜合測試 ${index + 1}:`)
console.log(` 用戶: ${result.userName}`)
console.log(` 分數: ${result.score}`)
console.log(` 完成時間: ${result.completedAt}`)
console.log(` 詳細資料:`, JSON.stringify(result.details, null, 2))
})
} else {
console.log('❌ 獲取資料失敗:', data.message)
}
} else {
console.log('❌ 獲取資料失敗,狀態碼:', response.status)
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 綜合測試資料檢查完成')
}
}
checkCombinedTestData()

View File

@@ -1,42 +0,0 @@
const { executeQuery } = require('../lib/database/connection')
async function checkCombinedTestResultsTable() {
console.log('🔍 檢查 combined_test_results 表結構...')
console.log('=' .repeat(50))
try {
// 檢查表結構
console.log('\n📊 combined_test_results 表結構:')
const columns = await executeQuery('DESCRIBE combined_test_results')
columns.forEach(column => {
console.log(`- ${column.Field}: ${column.Type} ${column.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${column.Key ? `(${column.Key})` : ''}`)
})
// 檢查表數據
console.log('\n📋 combined_test_results 表數據:')
const rows = await executeQuery('SELECT * FROM combined_test_results LIMIT 5')
if (rows.length > 0) {
console.log(`找到 ${rows.length} 筆記錄:`)
rows.forEach((row, index) => {
console.log(`\n記錄 ${index + 1}:`)
Object.entries(row).forEach(([key, value]) => {
console.log(` ${key}: ${value}`)
})
})
} else {
console.log('表中沒有數據')
}
// 檢查表索引
console.log('\n🔍 表索引:')
const indexes = await executeQuery('SHOW INDEX FROM combined_test_results')
indexes.forEach(index => {
console.log(`- ${index.Key_name}: ${index.Column_name} (${index.Index_type})`)
})
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
}
}
checkCombinedTestResultsTable()

View File

@@ -1,42 +0,0 @@
import { executeQuery } from '../lib/database/connection'
async function checkCombinedTestResultsTable() {
console.log('🔍 檢查 combined_test_results 表結構...')
console.log('=' .repeat(50))
try {
// 檢查表結構
console.log('\n📊 combined_test_results 表結構:')
const columns = await executeQuery('DESCRIBE combined_test_results')
columns.forEach((column: any) => {
console.log(`- ${column.Field}: ${column.Type} ${column.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${column.Key ? `(${column.Key})` : ''}`)
})
// 檢查表數據
console.log('\n📋 combined_test_results 表數據:')
const rows = await executeQuery('SELECT * FROM combined_test_results LIMIT 5')
if (rows.length > 0) {
console.log(`找到 ${rows.length} 筆記錄:`)
rows.forEach((row: any, index: number) => {
console.log(`\n記錄 ${index + 1}:`)
Object.entries(row).forEach(([key, value]) => {
console.log(` ${key}: ${value}`)
})
})
} else {
console.log('表中沒有數據')
}
// 檢查表索引
console.log('\n🔍 表索引:')
const indexes = await executeQuery('SHOW INDEX FROM combined_test_results')
indexes.forEach((index: any) => {
console.log(`- ${index.Key_name}: ${index.Column_name} (${index.Index_type})`)
})
} catch (error) {
console.error('❌ 檢查失敗:', error instanceof Error ? error.message : '未知錯誤')
}
}
checkCombinedTestResultsTable()

View File

@@ -1,64 +0,0 @@
const https = require('https')
const http = require('http')
const checkCombinedTime = async () => {
console.log('🔍 檢查綜合測試結果時間')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查綜合測試結果 API
console.log('\n📊 檢查綜合測試結果 API...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/combined?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success && data.data.length > 0) {
const result = data.data[0]
console.log('📋 綜合測試結果時間詳情:')
console.log(`原始時間: ${result.completed_at}`)
const date = new Date(result.completed_at)
console.log(`UTC 時間: ${date.toISOString()}`)
console.log(`台灣時間: ${date.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(`台灣時間 (詳細): ${date.toLocaleString("zh-TW", {
timeZone: "Asia/Taipei",
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: true
})}`)
// 檢查是否是今天
const now = new Date()
const testDate = new Date(result.completed_at)
const isToday = now.toDateString() === testDate.toDateString()
console.log(`是否為今天: ${isToday}`)
// 計算時間差
const timeDiff = now.getTime() - testDate.getTime()
const hoursDiff = Math.floor(timeDiff / (1000 * 60 * 60))
const minutesDiff = Math.floor((timeDiff % (1000 * 60 * 60)) / (1000 * 60))
console.log(`距離現在: ${hoursDiff} 小時 ${minutesDiff} 分鐘`)
}
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 綜合測試結果時間檢查完成')
}
}
checkCombinedTime()

View File

@@ -1,49 +0,0 @@
const mysql = require('mysql2/promise')
async function checkCreativeQuestionsTable() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔍 檢查 creative_questions 表結構...')
let connection
try {
connection = await mysql.createConnection(config)
// 檢查表結構
const [columns] = await connection.execute("DESCRIBE creative_questions")
console.log('\n📊 creative_questions 表結構:')
columns.forEach(col => {
console.log(`- ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Key ? `(${col.Key})` : ''}`)
})
// 檢查表內容
const [rows] = await connection.execute("SELECT * FROM creative_questions LIMIT 3")
console.log('\n📝 creative_questions 表內容 (前3筆):')
if (rows.length > 0) {
rows.forEach((row, index) => {
console.log(`${index + 1}. ID: ${row.id}`)
console.log(` 題目: ${row.statement}`)
console.log(` 類別: ${row.category}`)
console.log(` 是否反向: ${row.is_reverse}`)
console.log('')
})
} else {
console.log('❌ 沒有找到創意題目數據')
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
if (connection) {
await connection.end()
}
}
}
checkCreativeQuestionsTable()

View File

@@ -1,52 +0,0 @@
const mysql = require('mysql2/promise')
async function checkCreativeQuestions() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔄 正在檢查創意能力測試題目...')
try {
const connection = await mysql.createConnection(config)
const [rows] = await connection.execute('SELECT * FROM creative_questions ORDER BY id')
console.log(`\n📋 共找到 ${rows.length} 道創意能力測試題目:`)
console.log('=' .repeat(80))
rows.forEach((question, index) => {
const reverseText = question.is_reverse ? ' (反向題)' : ''
console.log(`\n${index + 1}. ID: ${question.id}`)
console.log(` 題目: ${question.statement}`)
console.log(` 類別: ${question.category}`)
console.log(` 反向題: ${question.is_reverse ? '是' : '否'}${reverseText}`)
})
console.log('\n📊 統計:')
const reverseCount = rows.filter(q => q.is_reverse).length
const normalCount = rows.length - reverseCount
const categoryCount = {}
rows.forEach(q => {
categoryCount[q.category] = (categoryCount[q.category] || 0) + 1
})
console.log(`- 一般題目: ${normalCount}`)
console.log(`- 反向題目: ${reverseCount}`)
console.log('- 類別分布:')
Object.entries(categoryCount).forEach(([category, count]) => {
console.log(` - ${category}: ${count}`)
})
await connection.end()
console.log('\n✅ 檢查完成')
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
}
}
checkCreativeQuestions()

View File

@@ -1,40 +0,0 @@
const mysql = require('mysql2/promise')
async function checkCreativeTableStructure() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔄 正在檢查 creative_questions 表結構...')
try {
const connection = await mysql.createConnection(config)
// 檢查表是否存在
const [tables] = await connection.execute("SHOW TABLES LIKE 'creative_questions'")
if (tables.length === 0) {
console.log('❌ creative_questions 表不存在')
} else {
console.log('✅ creative_questions 表存在')
// 檢查表結構
const [columns] = await connection.execute("DESCRIBE creative_questions")
console.log('\n📋 表結構:')
columns.forEach(col => {
console.log(`- ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Key ? `(${col.Key})` : ''} ${col.Default ? `DEFAULT ${col.Default}` : ''}`)
})
}
await connection.end()
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
}
}
checkCreativeTableStructure()

View File

@@ -1,41 +0,0 @@
const mysql = require('mysql2/promise')
async function checkCreativeTestAnswersTable() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔍 檢查 creative_test_answers 表結構...')
let connection
try {
connection = await mysql.createConnection(config)
// 檢查表是否存在
const [tables] = await connection.execute("SHOW TABLES LIKE 'creative_test_answers'")
if (tables.length === 0) {
console.log('❌ creative_test_answers 表不存在')
return
}
// 檢查表結構
const [columns] = await connection.execute("DESCRIBE creative_test_answers")
console.log('\n📊 creative_test_answers 表結構:')
columns.forEach(col => {
console.log(`- ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Key ? `(${col.Key})` : ''}`)
})
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
if (connection) {
await connection.end()
}
}
}
checkCreativeTestAnswersTable()

View File

@@ -1,84 +0,0 @@
const mysql = require('mysql2/promise')
async function checkCreativeTestResults() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔍 檢查創意測驗結果...')
let connection
try {
connection = await mysql.createConnection(config)
// 檢查 test_results 表中的創意測驗結果
const [creativeResults] = await connection.execute(
`SELECT tr.*, u.name as user_name
FROM test_results tr
JOIN users u ON tr.user_id = u.id
WHERE tr.test_type = 'creative'
ORDER BY tr.completed_at DESC`
)
console.log('\n📊 test_results 表中的創意測驗結果:')
if (creativeResults.length > 0) {
console.log(`找到 ${creativeResults.length} 筆創意測驗結果:`)
creativeResults.forEach((result, index) => {
console.log(`${index + 1}. ID: ${result.id}`)
console.log(` 用戶ID: ${result.user_id}`)
console.log(` 用戶名稱: ${result.user_name}`)
console.log(` 分數: ${result.score}`)
console.log(` 總分數: ${result.correct_answers}`)
console.log(` 總題數: ${result.total_questions}`)
console.log(` 完成時間: ${new Date(result.completed_at)}`)
console.log(` 建立時間: ${new Date(result.created_at)}`)
console.log('')
})
} else {
console.log('❌ 沒有找到創意測驗結果')
}
// 檢查 creative_test_answers 表中的答案記錄
const [answerRecords] = await connection.execute(
`SELECT cta.*, u.id as user_id, cq.statement as question_text, cq.is_reverse
FROM creative_test_answers cta
JOIN test_results tr ON cta.test_result_id = tr.id
JOIN users u ON tr.user_id = u.id
JOIN creative_questions cq ON cta.question_id = cq.id
ORDER BY cta.created_at ASC
LIMIT 10`
)
console.log('\n📝 creative_test_answers 表中的答案記錄 (前10筆):')
if (answerRecords.length > 0) {
console.log(`找到 ${answerRecords.length} 筆答案記錄:`)
answerRecords.forEach((record, index) => {
console.log(`${index + 1}. 答案ID: ${record.id}`)
console.log(` 測試結果ID: ${record.test_result_id}`)
console.log(` 用戶ID: ${record.user_id}`)
console.log(` 題目ID: ${record.question_id}`)
console.log(` 題目: ${record.question_text}`)
console.log(` 用戶答案: ${record.user_answer}`)
console.log(` 計算分數: ${record.score}`)
console.log(` 是否反向題: ${record.is_reverse ? '是' : '否'}`)
console.log(` 建立時間: ${new Date(record.created_at)}`)
console.log('')
})
} else {
console.log('❌ 沒有找到答案記錄')
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
if (connection) {
await connection.end()
}
}
}
checkCreativeTestResults()

View File

@@ -1,146 +0,0 @@
const { executeQuery } = require('../lib/database/connection')
const checkDatabasePassword = async () => {
console.log('🔍 檢查資料庫中的密碼')
console.log('=' .repeat(50))
try {
// 1. 創建一個測試用戶
console.log('\n📊 1. 創建測試用戶...')
const testUser = {
name: '資料庫密碼檢查用戶',
email: 'db.password@company.com',
password: 'password123',
department: '測試部',
role: 'user'
}
const createResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(testUser)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/admin/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = require('http').request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
let testUserId = null
if (createResponse.status === 200) {
const createData = JSON.parse(createResponse.data)
if (createData.success) {
testUserId = createData.data.id
console.log('✅ 測試用戶創建成功')
console.log(' 用戶ID:', createData.data.id)
console.log(' 電子郵件:', createData.data.email)
} else {
console.log('❌ 創建測試用戶失敗:', createData.error)
return
}
}
// 2. 直接查詢資料庫
console.log('\n📊 2. 直接查詢資料庫...')
try {
const query = 'SELECT id, name, email, password, department, role, created_at FROM users WHERE email = ?'
const result = await executeQuery(query, ['db.password@company.com'])
if (result && result.length > 0) {
const user = result[0]
console.log('✅ 資料庫查詢成功:')
console.log(' ID:', user.id)
console.log(' 姓名:', user.name)
console.log(' 電子郵件:', user.email)
console.log(' 部門:', user.department)
console.log(' 角色:', user.role)
console.log(' 建立時間:', user.created_at)
console.log(' 密碼長度:', user.password ? user.password.length : 'null')
console.log(' 密碼前綴:', user.password ? user.password.substring(0, 20) + '...' : 'null')
console.log(' 密碼是否為 bcrypt 格式:', user.password ? user.password.startsWith('$2b$') : false)
} else {
console.log('❌ 在資料庫中找不到用戶')
}
} catch (dbError) {
console.log('❌ 資料庫查詢失敗:', dbError.message)
}
// 3. 測試密碼驗證
console.log('\n📊 3. 測試密碼驗證...')
try {
const bcrypt = require('bcryptjs')
const query = 'SELECT password FROM users WHERE email = ?'
const result = await executeQuery(query, ['db.password@company.com'])
if (result && result.length > 0) {
const hashedPassword = result[0].password
const testPassword = 'password123'
console.log(' 測試密碼:', testPassword)
console.log(' 資料庫密碼雜湊:', hashedPassword.substring(0, 20) + '...')
const isValid = await bcrypt.compare(testPassword, hashedPassword)
console.log(' 密碼驗證結果:', isValid ? '✅ 成功' : '❌ 失敗')
if (!isValid) {
// 測試其他可能的密碼
const testPasswords = ['Password123', 'PASSWORD123', 'password', '123456']
for (const pwd of testPasswords) {
const testResult = await bcrypt.compare(pwd, hashedPassword)
console.log(` 測試密碼 "${pwd}":`, testResult ? '✅ 成功' : '❌ 失敗')
if (testResult) break
}
}
}
} catch (verifyError) {
console.log('❌ 密碼驗證測試失敗:', verifyError.message)
}
// 4. 清理測試用戶
console.log('\n📊 4. 清理測試用戶...')
if (testUserId) {
const deleteResponse = await new Promise((resolve, reject) => {
const options = {
hostname: 'localhost',
port: 3000,
path: `/api/admin/users?id=${testUserId}`,
method: 'DELETE'
}
const req = require('http').request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.end()
})
if (deleteResponse.status === 200) {
console.log(`✅ 已刪除測試用戶: ${testUserId}`)
}
}
console.log('\n📝 資料庫密碼檢查總結:')
console.log('🔍 請查看以上詳細資訊,找出密碼問題')
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 資料庫密碼檢查完成')
}
}
checkDatabasePassword()

View File

@@ -1,68 +0,0 @@
const { executeQuery } = require('../lib/database/connection');
async function checkDatabaseStructure() {
console.log('🔍 檢查資料庫結構');
console.log('==============================');
try {
// 檢查 combined_test_results 的結構
console.log('\n📋 combined_test_results 範例:');
const combinedResults = await executeQuery('SELECT * FROM combined_test_results LIMIT 1');
if (combinedResults.length > 0) {
const result = combinedResults[0];
console.log('ID:', result.id);
console.log('User ID:', result.user_id);
console.log('Logic Score:', result.logic_score);
console.log('Creativity Score:', result.creativity_score);
console.log('Balance Score:', result.balance_score);
console.log('Overall Score:', result.overall_score);
console.log('Logic Breakdown:', typeof result.logic_breakdown, result.logic_breakdown);
console.log('Creativity Breakdown:', typeof result.creativity_breakdown, result.creativity_breakdown);
} else {
console.log('沒有 combined_test_results 資料');
}
// 檢查 logic_test_answers 的結構
console.log('\n📋 logic_test_answers 範例:');
const logicAnswers = await executeQuery('SELECT * FROM logic_test_answers LIMIT 3');
if (logicAnswers.length > 0) {
logicAnswers.forEach((answer, index) => {
console.log(`答案 ${index + 1}:`, {
id: answer.id,
test_result_id: answer.test_result_id,
question_id: answer.question_id,
user_answer: answer.user_answer,
correct_answer: answer.correct_answer,
is_correct: answer.is_correct,
explanation: answer.explanation
});
});
} else {
console.log('沒有 logic_test_answers 資料');
}
// 檢查 creative_test_answers 的結構
console.log('\n📋 creative_test_answers 範例:');
const creativeAnswers = await executeQuery('SELECT * FROM creative_test_answers LIMIT 3');
if (creativeAnswers.length > 0) {
creativeAnswers.forEach((answer, index) => {
console.log(`答案 ${index + 1}:`, {
id: answer.id,
test_result_id: answer.test_result_id,
question_id: answer.question_id,
user_answer: answer.user_answer,
score: answer.score
});
});
} else {
console.log('沒有 creative_test_answers 資料');
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message);
}
console.log('==============================\n');
}
checkDatabaseStructure();

View File

@@ -1,41 +0,0 @@
const { executeQuery } = require('../lib/database/connection')
const checkDbFields = async () => {
console.log('🔍 檢查資料庫欄位名稱')
console.log('=' .repeat(40))
try {
// 檢查表結構
console.log('\n📊 檢查 combined_test_results 表結構...')
const structureQuery = 'DESCRIBE combined_test_results'
const structure = await executeQuery(structureQuery)
console.log('📋 表欄位:')
structure.forEach(field => {
console.log(` ${field.Field}: ${field.Type}`)
})
// 檢查實際資料
console.log('\n📊 檢查實際資料...')
const dataQuery = 'SELECT id, user_id, logic_score, creativity_score, balance_score, overall_score FROM combined_test_results LIMIT 2'
const data = await executeQuery(dataQuery)
console.log('📋 實際資料:')
data.forEach((row, index) => {
console.log(`\n 記錄 ${index + 1}:`)
console.log(` id: ${row.id}`)
console.log(` user_id: ${row.user_id}`)
console.log(` logic_score: ${row.logic_score}`)
console.log(` creativity_score: ${row.creativity_score}`)
console.log(` balance_score: ${row.balance_score}`)
console.log(` overall_score: ${row.overall_score}`)
})
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 資料庫欄位檢查完成')
}
}
checkDbFields()

View File

@@ -1,75 +0,0 @@
const mysql = require('mysql2/promise')
async function checkDatabaseTables() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔍 檢查資料庫表結構...')
try {
const connection = await mysql.createConnection(config)
// 檢查所有表
console.log('\n📋 所有資料表:')
const [tables] = await connection.execute("SHOW TABLES")
tables.forEach(table => {
const tableName = Object.values(table)[0]
console.log(`- ${tableName}`)
})
// 檢查 test_results 表結構
console.log('\n📊 test_results 表結構:')
try {
const [columns] = await connection.execute("DESCRIBE test_results")
columns.forEach(col => {
console.log(`- ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Key ? `(${col.Key})` : ''}`)
})
} catch (error) {
console.log('❌ test_results 表不存在')
}
// 檢查 logic_test_answers 表結構
console.log('\n📝 logic_test_answers 表結構:')
try {
const [columns] = await connection.execute("DESCRIBE logic_test_answers")
columns.forEach(col => {
console.log(`- ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Key ? `(${col.Key})` : ''}`)
})
} catch (error) {
console.log('❌ logic_test_answers 表不存在')
}
// 檢查 users 表結構
console.log('\n👥 users 表結構:')
try {
const [columns] = await connection.execute("DESCRIBE users")
columns.forEach(col => {
console.log(`- ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Key ? `(${col.Key})` : ''}`)
})
} catch (error) {
console.log('❌ users 表不存在')
}
// 檢查 logic_questions 表結構
console.log('\n🧠 logic_questions 表結構:')
try {
const [columns] = await connection.execute("DESCRIBE logic_questions")
columns.forEach(col => {
console.log(`- ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Key ? `(${col.Key})` : ''}`)
})
} catch (error) {
console.log('❌ logic_questions 表不存在')
}
await connection.end()
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
}
}
checkDatabaseTables()

View File

@@ -1,78 +0,0 @@
const mysql = require('mysql2/promise')
const checkDbTimeFormat = async () => {
console.log('🔍 檢查資料庫中的時間格式')
console.log('=' .repeat(50))
const connection = await mysql.createConnection({
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || 3306,
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'hr_assessment'
})
try {
// 檢查 test_results 表的時間格式
console.log('\n📊 檢查 test_results 表的時間格式...')
const [testResults] = await connection.execute(`
SELECT id, test_type, completed_at, created_at
FROM test_results
WHERE user_id = 'user-1759073326705-m06y3wacd'
ORDER BY completed_at DESC
`)
testResults.forEach((result, index) => {
console.log(`\n${index + 1}. ${result.test_type} 測試:`)
console.log(` ID: ${result.id}`)
console.log(` completed_at (原始): ${result.completed_at}`)
console.log(` completed_at (類型): ${typeof result.completed_at}`)
console.log(` created_at (原始): ${result.created_at}`)
console.log(` created_at (類型): ${typeof result.created_at}`)
// 測試時間轉換
const completedDate = new Date(result.completed_at)
const createdDate = new Date(result.created_at)
console.log(` completed_at 轉換: ${completedDate.toISOString()}`)
console.log(` completed_at 台灣時間: ${completedDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(` created_at 轉換: ${createdDate.toISOString()}`)
console.log(` created_at 台灣時間: ${createdDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
})
// 檢查 combined_test_results 表的時間格式
console.log('\n📊 檢查 combined_test_results 表的時間格式...')
const [combinedResults] = await connection.execute(`
SELECT id, completed_at, created_at
FROM combined_test_results
WHERE user_id = 'user-1759073326705-m06y3wacd'
ORDER BY completed_at DESC
`)
combinedResults.forEach((result, index) => {
console.log(`\n${index + 1}. 綜合測試:`)
console.log(` ID: ${result.id}`)
console.log(` completed_at (原始): ${result.completed_at}`)
console.log(` completed_at (類型): ${typeof result.completed_at}`)
console.log(` created_at (原始): ${result.created_at}`)
console.log(` created_at (類型): ${typeof result.created_at}`)
// 測試時間轉換
const completedDate = new Date(result.completed_at)
const createdDate = new Date(result.created_at)
console.log(` completed_at 轉換: ${completedDate.toISOString()}`)
console.log(` completed_at 台灣時間: ${completedDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(` created_at 轉換: ${createdDate.toISOString()}`)
console.log(` created_at 台灣時間: ${createdDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
})
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
await connection.end()
console.log('\n✅ 資料庫時間格式檢查完成')
}
}
checkDbTimeFormat()

View File

@@ -1,72 +0,0 @@
const https = require('https')
const http = require('http')
const checkLatestCreativeTime = async () => {
console.log('🔍 檢查最新創意測驗結果時間')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查創意測試結果 API
console.log('\n📊 檢查創意測試結果 API...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success && data.data.length > 0) {
console.log(`找到 ${data.data.length} 筆創意測試結果:`)
// 按創建時間排序,取最新的
const sortedResults = data.data.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
const latestResult = sortedResults[0]
console.log('\n📋 最新創意測試結果:')
console.log(`ID: ${latestResult.id}`)
console.log(`completed_at: ${latestResult.completed_at}`)
console.log(`created_at: ${latestResult.created_at}`)
const completedDate = new Date(latestResult.completed_at)
const createdDate = new Date(latestResult.created_at)
console.log(`completed_at 台灣時間: ${completedDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(`created_at 台灣時間: ${createdDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
// 檢查時間差
const timeDiff = createdDate.getTime() - completedDate.getTime()
const hoursDiff = timeDiff / (1000 * 60 * 60)
console.log(`時間差: ${hoursDiff.toFixed(2)} 小時`)
// 檢查是否是今天
const now = new Date()
const isToday = now.toDateString() === completedDate.toDateString()
console.log(`是否為今天: ${isToday}`)
// 計算距離現在的時間
const nowDiff = now.getTime() - completedDate.getTime()
const nowHoursDiff = nowDiff / (1000 * 60 * 60)
console.log(`距離現在: ${nowHoursDiff.toFixed(2)} 小時`)
}
}
// 檢查當前時間
console.log('\n📊 當前時間:')
const now = new Date()
console.log(`UTC 時間: ${now.toISOString()}`)
console.log(`台灣時間: ${now.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 最新創意測驗結果時間檢查完成')
}
}
checkLatestCreativeTime()

View File

@@ -1,56 +0,0 @@
const https = require('https')
const http = require('http')
const checkLatestTestResults = async () => {
console.log('🔍 檢查最新的測試結果')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查所有測試結果
console.log('\n📊 檢查所有測試結果...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/user/test-results?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success && data.data.results.length > 0) {
console.log(`找到 ${data.data.results.length} 筆測試結果:`)
data.data.results.forEach((result, index) => {
console.log(`\n${index + 1}. ${result.type} 測試:`)
console.log(` completedAt: ${result.completedAt}`)
const date = new Date(result.completedAt)
const isValid = !isNaN(date.getTime())
console.log(` 解析是否有效: ${isValid ? '✅' : '❌'}`)
if (isValid) {
const taiwanTime = date.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(` 台灣時間: ${taiwanTime}`)
}
})
}
}
// 檢查當前時間
console.log('\n📊 當前時間:')
const now = new Date()
console.log(`UTC 時間: ${now.toISOString()}`)
console.log(`台灣時間: ${now.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 最新測試結果檢查完成')
}
}
checkLatestTestResults()

View File

@@ -1,38 +0,0 @@
const { executeQuery } = require('../lib/database/connection');
async function checkLogicAnswers() {
try {
console.log('=== 檢查 logic_test_answers 表 ===');
const answers = await executeQuery('SELECT * FROM logic_test_answers');
console.log('logic_test_answers 資料總數:', answers.length);
if (answers.length > 0) {
console.log('前3筆資料:', answers.slice(0, 3));
}
console.log('\n=== 檢查 test_results 表 ===');
const results = await executeQuery('SELECT * FROM test_results WHERE type = "logic" ORDER BY created_at DESC LIMIT 5');
console.log('logic test_results 資料總數:', results.length);
if (results.length > 0) {
console.log('前3筆資料:', results);
console.log('\n=== 檢查關聯資料 ===');
for (const result of results.slice(0, 2)) {
console.log(`\n檢查 test_result_id: ${result.id}`);
const relatedAnswers = await executeQuery('SELECT * FROM logic_test_answers WHERE test_result_id = ?', [result.id]);
console.log(`關聯的答案數量: ${relatedAnswers.length}`);
if (relatedAnswers.length > 0) {
console.log('答案資料:', relatedAnswers);
}
}
}
console.log('\n=== 檢查所有 test_results 類型 ===');
const allResults = await executeQuery('SELECT type, COUNT(*) as count FROM test_results GROUP BY type');
console.log('各類型測試結果數量:', allResults);
} catch (error) {
console.error('錯誤:', error.message);
}
}
checkLogicAnswers();

View File

@@ -1,45 +0,0 @@
const mysql = require('mysql2/promise')
async function checkLogicQuestions() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔄 正在檢查邏輯思維題目...')
try {
const connection = await mysql.createConnection(config)
const [rows] = await connection.execute('SELECT * FROM logic_questions ORDER BY id')
console.log(`\n📋 共找到 ${rows.length} 道邏輯思維題目:`)
console.log('=' .repeat(80))
rows.forEach((question, index) => {
console.log(`\n${index + 1}. ID: ${question.id}`)
console.log(` 題目: ${question.question}`)
console.log(` A. ${question.option_a}`)
console.log(` B. ${question.option_b}`)
console.log(` C. ${question.option_c}`)
console.log(` D. ${question.option_d}`)
if (question.option_e) {
console.log(` E. ${question.option_e}`)
}
console.log(` 正確答案: ${question.correct_answer}`)
if (question.explanation) {
console.log(` 解說: ${question.explanation}`)
}
})
await connection.end()
console.log('\n✅ 檢查完成')
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
}
}
checkLogicQuestions()

View File

@@ -1,40 +0,0 @@
const mysql = require('mysql2/promise')
async function checkPasswords() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔄 正在檢查用戶密碼狀態...')
try {
const connection = await mysql.createConnection(config)
const [rows] = await connection.execute('SELECT id, name, email, password FROM users ORDER BY created_at')
console.log('\n📋 用戶密碼狀態:')
console.log('=' .repeat(80))
rows.forEach((user, index) => {
const isHashed = user.password.startsWith('$2b$') || user.password.startsWith('$2a$')
const passwordStatus = isHashed ? '✅ 已雜湊' : '❌ 明文'
const passwordPreview = isHashed ? user.password.substring(0, 20) + '...' : user.password
console.log(`${index + 1}. ${user.name} (${user.email})`)
console.log(` 密碼狀態: ${passwordStatus}`)
console.log(` 密碼內容: ${passwordPreview}`)
console.log('')
})
await connection.end()
console.log('✅ 檢查完成')
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
}
}
checkPasswords()

View File

@@ -1,72 +0,0 @@
const https = require('https')
const http = require('http')
const checkRawTestData = async () => {
console.log('🔍 檢查原始測試數據')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查邏輯測試結果
console.log('\n📊 檢查邏輯測試結果...')
const logicResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/logic?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (logicResponse.status === 200) {
const logicData = JSON.parse(logicResponse.data)
if (logicData.success && logicData.data.length > 0) {
console.log('邏輯測試結果:')
logicData.data.forEach((result, index) => {
console.log(`\n${index + 1}. 邏輯測試:`)
console.log(` ID: ${result.id}`)
console.log(` 原始時間: ${result.completed_at}`)
console.log(` 創建時間: ${result.created_at}`)
const date = new Date(result.completed_at)
console.log(` 台灣時間: ${date.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
})
}
}
// 檢查創意測試結果
console.log('\n📊 檢查創意測試結果...')
const creativeResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (creativeResponse.status === 200) {
const creativeData = JSON.parse(creativeResponse.data)
if (creativeData.success && creativeData.data.length > 0) {
console.log('創意測試結果:')
creativeData.data.forEach((result, index) => {
console.log(`\n${index + 1}. 創意測試:`)
console.log(` ID: ${result.id}`)
console.log(` 原始時間: ${result.completed_at}`)
console.log(` 創建時間: ${result.created_at}`)
const date = new Date(result.completed_at)
console.log(` 台灣時間: ${date.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
})
}
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 原始測試數據檢查完成')
}
}
checkRawTestData()

View File

@@ -1,66 +0,0 @@
const { executeQuery } = require('../lib/database/connection');
async function checkSingleTestAnswers() {
console.log('🔍 檢查單一測試類型的答案資料');
console.log('==============================');
try {
// 檢查 test_results 表
console.log('\n📋 Test Results:');
const testResults = await executeQuery('SELECT id, user_id, test_type, score, completed_at FROM test_results ORDER BY completed_at DESC LIMIT 5');
testResults.forEach((result, index) => {
console.log(`測試 ${index + 1}:`, {
id: result.id,
user_id: result.user_id,
test_type: result.test_type,
score: result.score,
completed_at: result.completed_at
});
});
// 檢查 logic_test_answers 表
console.log('\n📋 Logic Test Answers:');
const logicAnswers = await executeQuery('SELECT * FROM logic_test_answers ORDER BY created_at DESC LIMIT 5');
logicAnswers.forEach((answer, index) => {
console.log(`邏輯答案 ${index + 1}:`, {
id: answer.id,
test_result_id: answer.test_result_id,
question_id: answer.question_id,
user_answer: answer.user_answer,
is_correct: answer.is_correct
});
});
// 檢查 creative_test_answers 表
console.log('\n📋 Creative Test Answers:');
const creativeAnswers = await executeQuery('SELECT * FROM creative_test_answers ORDER BY created_at DESC LIMIT 5');
creativeAnswers.forEach((answer, index) => {
console.log(`創意答案 ${index + 1}:`, {
id: answer.id,
test_result_id: answer.test_result_id,
question_id: answer.question_id,
user_answer: answer.user_answer,
score: answer.score
});
});
// 檢查是否有匹配的答案
if (testResults.length > 0) {
const firstTest = testResults[0];
console.log(`\n🔍 檢查測試 ${firstTest.id} 的答案:`);
const matchingLogicAnswers = await executeQuery('SELECT * FROM logic_test_answers WHERE test_result_id = ?', [firstTest.id]);
console.log(`邏輯答案匹配數量: ${matchingLogicAnswers.length}`);
const matchingCreativeAnswers = await executeQuery('SELECT * FROM creative_test_answers WHERE test_result_id = ?', [firstTest.id]);
console.log(`創意答案匹配數量: ${matchingCreativeAnswers.length}`);
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message);
}
console.log('==============================\n');
}
checkSingleTestAnswers();

View File

@@ -1,39 +0,0 @@
const mysql = require('mysql2/promise')
async function checkTableStructure() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔄 正在檢查資料庫表結構...')
try {
const connection = await mysql.createConnection(config)
// 檢查 logic_questions 表是否存在
const [tables] = await connection.execute("SHOW TABLES LIKE 'logic_questions'")
if (tables.length === 0) {
console.log('❌ logic_questions 表不存在')
} else {
console.log('✅ logic_questions 表存在')
// 檢查表結構
const [columns] = await connection.execute("DESCRIBE logic_questions")
console.log('\n📋 logic_questions 表結構:')
columns.forEach(col => {
console.log(` ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Key ? col.Key : ''}`)
})
}
await connection.end()
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
}
}
checkTableStructure()

View File

@@ -1,102 +0,0 @@
const mysql = require('mysql2/promise')
async function checkTestResults() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔍 檢查資料庫中的測試結果...')
try {
const connection = await mysql.createConnection(config)
// 檢查 test_results 表中的邏輯測驗結果
console.log('\n📊 test_results 表中的邏輯測驗結果:')
const [testResults] = await connection.execute(`
SELECT id, user_id, test_type, score, total_questions, correct_answers, completed_at, created_at
FROM test_results
WHERE test_type = 'logic'
ORDER BY completed_at DESC
LIMIT 10
`)
if (testResults.length > 0) {
console.log(`找到 ${testResults.length} 筆邏輯測驗結果:`)
testResults.forEach((result, index) => {
console.log(`${index + 1}. ID: ${result.id}`)
console.log(` 用戶ID: ${result.user_id}`)
console.log(` 分數: ${result.score}`)
console.log(` 答對題數: ${result.correct_answers}/${result.total_questions}`)
console.log(` 完成時間: ${result.completed_at}`)
console.log(` 建立時間: ${result.created_at}`)
console.log('')
})
} else {
console.log('❌ 沒有找到邏輯測驗結果')
}
// 檢查 logic_test_answers 表中的答案記錄
console.log('\n📝 logic_test_answers 表中的答案記錄:')
const [answerResults] = await connection.execute(`
SELECT lta.id, lta.test_result_id, lta.question_id, lta.user_answer, lta.is_correct, lta.created_at,
tr.user_id, tr.score
FROM logic_test_answers lta
JOIN test_results tr ON lta.test_result_id = tr.id
WHERE tr.test_type = 'logic'
ORDER BY lta.created_at DESC
LIMIT 20
`)
if (answerResults.length > 0) {
console.log(`找到 ${answerResults.length} 筆答案記錄:`)
answerResults.forEach((answer, index) => {
console.log(`${index + 1}. 答案ID: ${answer.id}`)
console.log(` 測試結果ID: ${answer.test_result_id}`)
console.log(` 用戶ID: ${answer.user_id}`)
console.log(` 題目ID: ${answer.question_id}`)
console.log(` 用戶答案: ${answer.user_answer}`)
console.log(` 是否正確: ${answer.is_correct ? '是' : '否'}`)
console.log(` 建立時間: ${answer.created_at}`)
console.log('')
})
} else {
console.log('❌ 沒有找到答案記錄')
}
// 檢查最近的測試結果統計
console.log('\n📈 測試結果統計:')
const [stats] = await connection.execute(`
SELECT
COUNT(*) as total_tests,
AVG(score) as avg_score,
MAX(score) as max_score,
MIN(score) as min_score,
COUNT(CASE WHEN score >= 80 THEN 1 END) as high_scores,
COUNT(CASE WHEN score < 60 THEN 1 END) as low_scores
FROM test_results
WHERE test_type = 'logic'
`)
if (stats[0].total_tests > 0) {
const stat = stats[0]
console.log(`總測試次數: ${stat.total_tests}`)
console.log(`平均分數: ${Math.round(stat.avg_score)}`)
console.log(`最高分數: ${stat.max_score}`)
console.log(`最低分數: ${stat.min_score}`)
console.log(`高分數 (≥80): ${stat.high_scores}`)
console.log(`低分數 (<60): ${stat.low_scores}`)
} else {
console.log('❌ 沒有測試結果統計')
}
await connection.end()
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
}
}
checkTestResults()

View File

@@ -1,68 +0,0 @@
const https = require('https')
const http = require('http')
const checkTimezoneIssue = async () => {
console.log('🔍 檢查時區問題')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 1. 檢查用戶測試結果 API 返回的時間
console.log('\n📊 1. 檢查用戶測試結果 API 返回的時間...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/user/test-results?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success && data.data.results.length > 0) {
console.log('📋 測試結果時間:')
data.data.results.forEach((result, index) => {
console.log(`\n${index + 1}. ${result.type}:`)
console.log(` 原始時間: ${result.completedAt}`)
// 測試不同的時間格式化方式
const date = new Date(result.completedAt)
console.log(` UTC 時間: ${date.toISOString()}`)
console.log(` 本地時間: ${date.toLocaleString()}`)
console.log(` 台灣時間: ${date.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(` 台灣時間 (en): ${date.toLocaleString("en-US", { timeZone: "Asia/Taipei" })}`)
})
}
}
// 2. 檢查當前時間
console.log('\n📊 2. 檢查當前時間...')
const now = new Date()
console.log(`當前 UTC 時間: ${now.toISOString()}`)
console.log(`當前本地時間: ${now.toLocaleString()}`)
console.log(`當前台灣時間: ${now.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
// 3. 測試時間轉換
console.log('\n📊 3. 測試時間轉換...')
const testTimes = [
'2025-09-29T01:07:00.000Z', // 從 API 返回的時間
'2025-09-29T09:08:17.000Z', // 可能的另一個時間
]
testTimes.forEach((timeStr, index) => {
console.log(`\n測試時間 ${index + 1}: ${timeStr}`)
const testDate = new Date(timeStr)
console.log(` UTC: ${testDate.toISOString()}`)
console.log(` 台灣時間: ${testDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
})
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 時區問題檢查完成')
}
}
checkTimezoneIssue()

View File

@@ -1,43 +0,0 @@
const checkUserAuth = () => {
console.log('👤 檢查用戶認證狀態')
console.log('=' .repeat(50))
// 模擬瀏覽器環境檢查 localStorage
if (typeof window !== 'undefined') {
const currentUser = localStorage.getItem("hr_current_user")
if (currentUser) {
try {
const user = JSON.parse(currentUser)
console.log('✅ 用戶已登入:')
console.log('用戶ID:', user.id)
console.log('用戶名稱:', user.name)
console.log('用戶郵箱:', user.email)
console.log('用戶部門:', user.department)
console.log('用戶角色:', user.role)
} catch (error) {
console.log('❌ 用戶資料解析失敗:', error.message)
}
} else {
console.log('❌ 用戶未登入')
console.log('localStorage 中沒有 hr_current_user')
}
} else {
console.log('⚠️ 非瀏覽器環境,無法檢查 localStorage')
}
console.log('\n🔍 檢查要點:')
console.log('1. 用戶是否已登入')
console.log('2. localStorage 中是否有 hr_current_user')
console.log('3. 用戶資料格式是否正確')
console.log('4. 用戶ID是否存在')
console.log('\n💡 如果用戶未登入:')
console.log('1. 請先登入系統')
console.log('2. 檢查登入功能是否正常')
console.log('3. 檢查 localStorage 是否被清除')
console.log('\n✅ 用戶認證檢查完成')
}
checkUserAuth()

View File

@@ -1,48 +0,0 @@
const mysql = require('mysql2/promise')
async function checkUserExists() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('👤 檢查用戶是否存在')
console.log('=' .repeat(50))
try {
const connection = await mysql.createConnection(config)
const userId = 'user-1759073326705-m06y3wacd'
console.log('檢查用戶ID:', userId)
// 檢查用戶是否存在
const [users] = await connection.execute('SELECT * FROM users WHERE id = ?', [userId])
if (users.length > 0) {
console.log('✅ 用戶存在:')
console.log('ID:', users[0].id)
console.log('姓名:', users[0].name)
console.log('郵箱:', users[0].email)
console.log('部門:', users[0].department)
console.log('角色:', users[0].role)
} else {
console.log('❌ 用戶不存在')
// 列出所有用戶
console.log('\n📋 所有用戶列表:')
const [allUsers] = await connection.execute('SELECT id, name, email FROM users LIMIT 10')
allUsers.forEach((user, index) => {
console.log(`${index + 1}. ID: ${user.id}, 姓名: ${user.name}, 郵箱: ${user.email}`)
})
}
await connection.end()
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
}
}
checkUserExists()

View File

@@ -1,91 +0,0 @@
const https = require('https')
const http = require('http')
const checkUserPassword = async () => {
console.log('🔍 檢查用戶密碼格式')
console.log('=' .repeat(50))
const testUserId = 'user-1759073326705-m06y3wacd'
try {
// 檢查用戶資料
console.log('\n📊 檢查用戶資料...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/user/profile?userId=${testUserId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success) {
console.log('✅ 用戶資料:')
console.log(` ID: ${data.data.id}`)
console.log(` 姓名: ${data.data.name}`)
console.log(` 電子郵件: ${data.data.email}`)
console.log(` 部門: ${data.data.department}`)
console.log(` 角色: ${data.data.role}`)
console.log(` 密碼: ${data.data.password ? '已隱藏' : '未返回'}`)
}
}
// 測試不同的密碼
console.log('\n📊 測試密碼更新...')
const testPasswords = ['password123', 'test123', '123456', 'admin123']
for (const password of testPasswords) {
console.log(`\n測試密碼: ${password}`)
const updateData = {
userId: testUserId,
currentPassword: password,
newPassword: 'newpassword123'
}
const updateResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(updateData)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/user/profile',
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
if (updateResponse.status === 200) {
const updateResult = JSON.parse(updateResponse.data)
if (updateResult.success) {
console.log(`✅ 密碼 ${password} 正確,更新成功`)
break
} else {
console.log(`❌ 密碼 ${password} 錯誤: ${updateResult.error}`)
}
} else {
console.log(`❌ API 請求失敗: ${updateResponse.status}`)
}
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 用戶密碼檢查完成')
}
}
checkUserPassword()

View File

@@ -1,132 +0,0 @@
const https = require('https')
const http = require('http')
const debugDimensionScoring = async () => {
console.log('🔍 調試維度分數計算')
console.log('=' .repeat(50))
const testResultId = 'test_1759086508812_xv2pof6lk' // 使用最新的測試結果ID
try {
// 1. 獲取測試結果
console.log('\n📊 1. 獲取測試結果...')
const resultResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=user-1759073326705-m06y3wacd`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (resultResponse.status === 200) {
const resultData = JSON.parse(resultResponse.data)
if (resultData.success && resultData.data.length > 0) {
const testResult = resultData.data[0]
console.log('測試結果:', {
id: testResult.id,
score: testResult.score,
total_questions: testResult.total_questions,
correct_answers: testResult.correct_answers
})
}
}
// 2. 獲取題目資料
console.log('\n📊 2. 獲取題目資料...')
const questionsResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/creative-questions', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let questions = []
if (questionsResponse.status === 200) {
const questionsData = JSON.parse(questionsResponse.data)
if (questionsData.success) {
questions = questionsData.questions
console.log(`獲取到 ${questions.length} 個題目`)
}
}
// 3. 獲取詳細答案
console.log('\n📊 3. 獲取詳細答案...')
const answersResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/creative-test-answers?testResultId=${testResultId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (answersResponse.status === 200) {
const answersData = JSON.parse(answersResponse.data)
if (answersData.success) {
const answers = answersData.data
console.log(`獲取到 ${answers.length} 個答案`)
// 4. 按維度分組計算
console.log('\n📊 4. 按維度分組計算...')
const dimensionScores = {
innovation: { total: 0, count: 0, answers: [] },
imagination: { total: 0, count: 0, answers: [] },
flexibility: { total: 0, count: 0, answers: [] },
originality: { total: 0, count: 0, answers: [] }
}
answers.forEach((answer) => {
const question = questions.find(q => q.id === answer.question_id)
if (question && dimensionScores[question.category]) {
dimensionScores[question.category].total += answer.score
dimensionScores[question.category].count += 1
dimensionScores[question.category].answers.push({
question_id: answer.question_id,
user_answer: answer.user_answer,
score: answer.score,
is_reverse: question.is_reverse
})
}
})
// 5. 顯示詳細計算過程
console.log('\n📊 5. 詳細計算過程:')
Object.keys(dimensionScores).forEach(category => {
const { total, count, answers } = dimensionScores[category]
const maxPossible = count * 5
const percentage = count > 0 ? Math.round((total / maxPossible) * 100) : 0
console.log(`\n${category}:`)
console.log(` 題目數量: ${count}`)
console.log(` 總分數: ${total}`)
console.log(` 最大可能分數: ${maxPossible}`)
console.log(` 百分比: ${percentage}%`)
console.log(` 答案詳情:`)
answers.forEach((ans, index) => {
console.log(` ${index + 1}. 題目${ans.question_id}: 用戶答案${ans.user_answer} → 計算分數${ans.score} (反向題: ${ans.is_reverse ? '是' : '否'})`)
})
})
// 6. 總分驗證
console.log('\n📊 6. 總分驗證:')
const totalScore = answers.reduce((sum, answer) => sum + answer.score, 0)
const maxTotalScore = answers.length * 5
const totalPercentage = Math.round((totalScore / maxTotalScore) * 100)
console.log(`所有答案總分數: ${totalScore}`)
console.log(`最大可能總分數: ${maxTotalScore}`)
console.log(`總百分比: ${totalPercentage}%`)
}
}
} catch (error) {
console.error('❌ 調試失敗:', error.message)
} finally {
console.log('\n✅ 維度分數計算調試完成')
}
}
debugDimensionScoring()

View File

@@ -1,74 +0,0 @@
const https = require('https')
const http = require('http')
const debugInvalidDate = async () => {
console.log('🔍 調試 Invalid Date 問題')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查創意測試結果 API
console.log('\n📊 檢查創意測試結果 API...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success && data.data.length > 0) {
console.log(`找到 ${data.data.length} 筆創意測試結果:`)
// 按創建時間排序,取最新的
const sortedResults = data.data.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
const latestResult = sortedResults[0]
console.log('\n📋 最新創意測試結果:')
console.log(`ID: ${latestResult.id}`)
console.log(`completed_at: ${latestResult.completed_at}`)
console.log(`completed_at 類型: ${typeof latestResult.completed_at}`)
// 測試不同的解析方式
console.log('\n📊 測試時間解析:')
// 方式1直接解析
const directParse = new Date(latestResult.completed_at)
console.log(`直接解析: ${directParse.toISOString()} (${directParse.toString()})`)
// 方式2添加 Z 後解析
const withZ = new Date(latestResult.completed_at + 'Z')
console.log(`添加 Z 後解析: ${withZ.toISOString()} (${withZ.toString()})`)
// 方式3檢查是否為有效日期
console.log(`直接解析是否有效: ${!isNaN(directParse.getTime())}`)
console.log(`添加 Z 後是否有效: ${!isNaN(withZ.getTime())}`)
// 測試台灣時間轉換
if (!isNaN(withZ.getTime())) {
const taiwanTime = withZ.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(`台灣時間: ${taiwanTime}`)
}
// 檢查時間格式
console.log('\n📊 時間格式分析:')
console.log(`原始格式: "${latestResult.completed_at}"`)
console.log(`長度: ${latestResult.completed_at.length}`)
console.log(`包含 T: ${latestResult.completed_at.includes('T')}`)
console.log(`包含 Z: ${latestResult.completed_at.includes('Z')}`)
console.log(`包含空格: ${latestResult.completed_at.includes(' ')}`)
}
}
} catch (error) {
console.error('❌ 調試失敗:', error.message)
} finally {
console.log('\n✅ Invalid Date 問題調試完成')
}
}
debugInvalidDate()

View File

@@ -1,218 +0,0 @@
const https = require('https')
const http = require('http')
const debugPasswordHash = async () => {
console.log('🔍 調試密碼雜湊問題')
console.log('=' .repeat(50))
try {
// 1. 創建一個測試用戶並記錄詳細資訊
console.log('\n📊 1. 創建測試用戶並記錄詳細資訊...')
const testUser = {
name: '密碼雜湊調試用戶',
email: 'hash.debug@company.com',
password: 'password123',
department: '測試部',
role: 'user'
}
console.log(' 原始密碼:', testUser.password)
const createResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(testUser)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/admin/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
let testUserId = null
if (createResponse.status === 200) {
const createData = JSON.parse(createResponse.data)
if (createData.success) {
testUserId = createData.data.id
console.log('✅ 測試用戶創建成功')
console.log(' 用戶ID:', createData.data.id)
console.log(' 電子郵件:', createData.data.email)
} else {
console.log('❌ 創建測試用戶失敗:', createData.error)
return
}
} else {
console.log('❌ 創建用戶 API 回應錯誤:', createResponse.status)
console.log(' 回應內容:', createResponse.data)
return
}
// 2. 嘗試登入並記錄詳細錯誤
console.log('\n📊 2. 嘗試登入並記錄詳細錯誤...')
const loginData = {
email: 'hash.debug@company.com',
password: 'password123'
}
console.log(' 登入嘗試 - 電子郵件:', loginData.email)
console.log(' 登入嘗試 - 密碼:', loginData.password)
const loginResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(loginData)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/auth/login',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
console.log(' 登入回應狀態碼:', loginResponse.status)
console.log(' 登入回應內容:', loginResponse.data)
if (loginResponse.status === 200) {
const loginResult = JSON.parse(loginResponse.data)
if (loginResult.success) {
console.log('✅ 登入成功!')
} else {
console.log('❌ 登入失敗:', loginResult.error)
}
} else {
const errorData = JSON.parse(loginResponse.data)
console.log('❌ 登入 API 錯誤:', errorData.error)
}
// 3. 檢查資料庫中的用戶資料
console.log('\n📊 3. 檢查資料庫中的用戶資料...')
const getUsersResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/users', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (getUsersResponse.status === 200) {
const usersData = JSON.parse(getUsersResponse.data)
if (usersData.success) {
const testUserInDB = usersData.data.find(user => user.id === testUserId)
if (testUserInDB) {
console.log('✅ 資料庫中的用戶資料:')
console.log(' ID:', testUserInDB.id)
console.log(' 姓名:', testUserInDB.name)
console.log(' 電子郵件:', testUserInDB.email)
console.log(' 部門:', testUserInDB.department)
console.log(' 角色:', testUserInDB.role)
console.log(' 建立時間:', testUserInDB.created_at)
console.log(' 更新時間:', testUserInDB.updated_at)
// 注意:密碼欄位不會在 API 回應中返回,這是正常的
} else {
console.log('❌ 在資料庫中找不到測試用戶')
}
}
}
// 4. 測試現有用戶的登入(作為對照)
console.log('\n📊 4. 測試現有用戶的登入(作為對照)...')
const existingUserLogin = {
email: 'admin@company.com',
password: 'admin123'
}
const existingLoginResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(existingUserLogin)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/auth/login',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
if (existingLoginResponse.status === 200) {
const existingLoginResult = JSON.parse(existingLoginResponse.data)
if (existingLoginResult.success) {
console.log('✅ 現有用戶登入成功(對照組)')
} else {
console.log('❌ 現有用戶登入失敗:', existingLoginResult.error)
}
} else {
const errorData = JSON.parse(existingLoginResponse.data)
console.log('❌ 現有用戶登入 API 錯誤:', errorData.error)
}
// 5. 清理測試用戶
console.log('\n📊 5. 清理測試用戶...')
if (testUserId) {
const deleteResponse = await new Promise((resolve, reject) => {
const options = {
hostname: 'localhost',
port: 3000,
path: `/api/admin/users?id=${testUserId}`,
method: 'DELETE'
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.end()
})
if (deleteResponse.status === 200) {
console.log(`✅ 已刪除測試用戶: ${testUserId}`)
}
}
console.log('\n📝 調試總結:')
console.log('🔍 請檢查以上詳細資訊,找出密碼雜湊和驗證的問題')
} catch (error) {
console.error('❌ 調試失敗:', error.message)
} finally {
console.log('\n✅ 密碼雜湊調試完成')
}
}
debugPasswordHash()

View File

@@ -1,204 +0,0 @@
const https = require('https')
const http = require('http')
const debugPasswordVerification = async () => {
console.log('🔍 調試密碼驗證問題')
console.log('=' .repeat(50))
try {
// 1. 創建一個測試用戶
console.log('\n📊 1. 創建測試用戶...')
const testUser = {
name: '密碼調試用戶',
email: 'debug.password@company.com',
password: 'password123',
department: '測試部',
role: 'user'
}
const createResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(testUser)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/admin/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
let testUserId = null
if (createResponse.status === 200) {
const createData = JSON.parse(createResponse.data)
if (createData.success) {
testUserId = createData.data.id
console.log('✅ 測試用戶創建成功')
} else {
console.log('❌ 創建測試用戶失敗:', createData.error)
return
}
}
// 2. 直接查詢資料庫中的密碼雜湊
console.log('\n📊 2. 檢查資料庫中的密碼雜湊...')
// 這裡我們需要直接查詢資料庫來看看密碼是如何儲存的
// 由於我們無法直接訪問資料庫,我們可以通過 API 來檢查
// 3. 測試不同的密碼組合
console.log('\n📊 3. 測試不同的密碼組合...')
const testPasswords = [
'password123', // 原始密碼
'Password123', // 大寫開頭
'PASSWORD123', // 全大寫
'password', // 沒有數字
'123456', // 只有數字
]
for (const testPassword of testPasswords) {
console.log(`\n 測試密碼: "${testPassword}"`)
const loginData = {
email: 'debug.password@company.com',
password: testPassword
}
const loginResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(loginData)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/auth/login',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
if (loginResponse.status === 200) {
const loginResult = JSON.parse(loginResponse.data)
if (loginResult.success) {
console.log(` ✅ 登入成功!正確密碼是: "${testPassword}"`)
break
} else {
console.log(` ❌ 登入失敗: ${loginResult.error}`)
}
} else {
const errorData = JSON.parse(loginResponse.data)
console.log(` ❌ 登入失敗: ${errorData.error}`)
}
}
// 4. 檢查現有用戶的登入情況
console.log('\n📊 4. 檢查現有用戶的登入情況...')
const existingUsers = [
{ email: 'admin@company.com', password: 'admin123' },
{ email: 'user@company.com', password: 'user123' },
{ email: 'test@company.com', password: 'password123' }
]
for (const user of existingUsers) {
console.log(`\n 測試現有用戶: ${user.email}`)
const loginData = {
email: user.email,
password: user.password
}
const loginResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(loginData)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/auth/login',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
if (loginResponse.status === 200) {
const loginResult = JSON.parse(loginResponse.data)
if (loginResult.success) {
console.log(` ✅ 登入成功`)
} else {
console.log(` ❌ 登入失敗: ${loginResult.error}`)
}
} else {
const errorData = JSON.parse(loginResponse.data)
console.log(` ❌ 登入失敗: ${errorData.error}`)
}
}
// 5. 清理測試用戶
console.log('\n📊 5. 清理測試用戶...')
if (testUserId) {
const deleteResponse = await new Promise((resolve, reject) => {
const options = {
hostname: 'localhost',
port: 3000,
path: `/api/admin/users?id=${testUserId}`,
method: 'DELETE'
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.end()
})
if (deleteResponse.status === 200) {
console.log(`✅ 已刪除測試用戶: ${testUserId}`)
}
}
console.log('\n📝 調試總結:')
console.log('🔍 請檢查以上測試結果,找出密碼驗證問題的原因')
} catch (error) {
console.error('❌ 調試失敗:', error.message)
} finally {
console.log('\n✅ 密碼驗證調試完成')
}
}
debugPasswordVerification()

View File

@@ -1,61 +0,0 @@
const https = require('https')
const http = require('http')
const fixExistingTimes = async () => {
console.log('🔍 修正現有測試結果的時間')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查現有的測試結果
console.log('\n📊 檢查現有測試結果...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/user/test-results?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success && data.data.results.length > 0) {
console.log('發現需要修正的測試結果:')
data.data.results.forEach((result, index) => {
console.log(`\n${index + 1}. ${result.type} 測試:`)
console.log(` 原始時間: ${result.completedAt}`)
const date = new Date(result.completedAt)
const taiwanTime = date.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(` 台灣時間: ${taiwanTime}`)
// 檢查時間是否合理
const now = new Date()
const timeDiff = now.getTime() - date.getTime()
const hoursDiff = Math.floor(timeDiff / (1000 * 60 * 60))
if (hoursDiff > 24) {
console.log(` ⚠️ 時間可能不正確 (${hoursDiff} 小時前)`)
} else {
console.log(` ✅ 時間看起來正確 (${hoursDiff} 小時前)`)
}
})
}
}
console.log('\n📝 建議:')
console.log('1. 時間格式已修正,新的測試結果會使用正確的 UTC 時間')
console.log('2. 現有的錯誤時間數據可能需要手動修正或重新測試')
console.log('3. 建議重新進行一次測試來驗證修正效果')
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
console.log('\n✅ 現有時間檢查完成')
}
}
fixExistingTimes()

View File

@@ -1,40 +0,0 @@
const mysql = require('mysql2/promise')
async function fixLogicAnswersTable() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔧 修正 logic_test_answers 表結構...')
try {
const connection = await mysql.createConnection(config)
// 檢查當前的 user_answer 欄位定義
console.log('\n📊 檢查當前 user_answer 欄位定義:')
const [columns] = await connection.execute("SHOW COLUMNS FROM logic_test_answers LIKE 'user_answer'")
console.log('當前定義:', columns[0])
// 更新 user_answer 欄位以支援 E 選項
console.log('\n🔧 更新 user_answer 欄位以支援 E 選項...')
await connection.execute("ALTER TABLE logic_test_answers MODIFY COLUMN user_answer ENUM('A', 'B', 'C', 'D', 'E') NOT NULL")
console.log('✅ user_answer 欄位更新成功')
// 驗證更新結果
console.log('\n📊 驗證更新結果:')
const [updatedColumns] = await connection.execute("SHOW COLUMNS FROM logic_test_answers LIKE 'user_answer'")
console.log('更新後定義:', updatedColumns[0])
await connection.end()
console.log('\n✅ logic_test_answers 表修正完成')
} catch (error) {
console.error('❌ 修正失敗:', error.message)
}
}
fixLogicAnswersTable()

View File

@@ -1,170 +0,0 @@
const http = require('http')
const testAdminResults = async () => {
console.log('🔍 測試管理員測驗結果功能')
console.log('=' .repeat(40))
try {
// 測試基本 API 呼叫
console.log('\n📊 測試基本 API 呼叫...')
const basicResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (basicResponse.status === 200) {
const basicData = JSON.parse(basicResponse.data)
if (basicData.success) {
console.log('✅ 基本 API 呼叫成功')
console.log(`📈 統計資料:`)
console.log(` 總測試次數: ${basicData.data.stats.totalResults}`)
console.log(` 平均分數: ${basicData.data.stats.averageScore}`)
console.log(` 總用戶數: ${basicData.data.stats.totalUsers}`)
console.log(` 參與率: ${basicData.data.stats.participationRate}%`)
console.log(` 測試類型分布:`)
console.log(` 邏輯思維: ${basicData.data.stats.testTypeCounts.logic}`)
console.log(` 創意能力: ${basicData.data.stats.testTypeCounts.creative}`)
console.log(` 綜合能力: ${basicData.data.stats.testTypeCounts.combined}`)
console.log(`📄 分頁資訊:`)
console.log(` 當前頁: ${basicData.data.pagination.currentPage}`)
console.log(` 總頁數: ${basicData.data.pagination.totalPages}`)
console.log(` 每頁限制: ${basicData.data.pagination.limit}`)
console.log(` 總結果數: ${basicData.data.pagination.totalResults}`)
console.log(`🏢 部門列表: ${basicData.data.departments.join(', ')}`)
console.log(`📋 結果數量: ${basicData.data.results.length}`)
} else {
console.log('❌ 基本 API 呼叫失敗:', basicData.message)
return
}
} else {
console.log('❌ 基本 API 呼叫失敗,狀態碼:', basicResponse.status)
return
}
// 測試搜尋功能
console.log('\n🔍 測試搜尋功能...')
const searchResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results?search=王', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (searchResponse.status === 200) {
const searchData = JSON.parse(searchResponse.data)
if (searchData.success) {
console.log(`✅ 搜尋功能正常,找到 ${searchData.data.pagination.totalResults} 筆結果`)
} else {
console.log('❌ 搜尋功能失敗:', searchData.message)
}
}
// 測試部門篩選
console.log('\n🏢 測試部門篩選...')
const deptResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results?department=人力資源部', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (deptResponse.status === 200) {
const deptData = JSON.parse(deptResponse.data)
if (deptData.success) {
console.log(`✅ 部門篩選正常,找到 ${deptData.data.pagination.totalResults} 筆結果`)
} else {
console.log('❌ 部門篩選失敗:', deptData.message)
}
}
// 測試測試類型篩選
console.log('\n🧠 測試測試類型篩選...')
const typeResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results?testType=logic', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (typeResponse.status === 200) {
const typeData = JSON.parse(typeResponse.data)
if (typeData.success) {
console.log(`✅ 測試類型篩選正常,找到 ${typeData.data.pagination.totalResults} 筆結果`)
} else {
console.log('❌ 測試類型篩選失敗:', typeData.message)
}
}
// 測試分頁功能
console.log('\n📄 測試分頁功能...')
const pageResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results?page=1&limit=5', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (pageResponse.status === 200) {
const pageData = JSON.parse(pageResponse.data)
if (pageData.success) {
console.log(`✅ 分頁功能正常`)
console.log(` 每頁限制: ${pageData.data.pagination.limit}`)
console.log(` 當前頁結果數: ${pageData.data.results.length}`)
console.log(` 總頁數: ${pageData.data.pagination.totalPages}`)
} else {
console.log('❌ 分頁功能失敗:', pageData.message)
}
}
console.log('\n🎯 功能特點:')
console.log('✅ 從資料庫獲取所有測驗結果')
console.log('✅ 支援搜尋用戶姓名和郵箱')
console.log('✅ 支援部門篩選')
console.log('✅ 支援測試類型篩選')
console.log('✅ 支援分頁功能')
console.log('✅ 顯示詳細統計資料')
console.log('✅ 響應式設計(桌面版和手機版)')
console.log('✅ 載入狀態和錯誤處理')
console.log('\n📊 資料來源:')
console.log('✅ test_results 表(基本測試結果)')
console.log('✅ logic_test_answers 表(邏輯測試詳細答案)')
console.log('✅ creative_test_answers 表(創意測試詳細答案)')
console.log('✅ combined_test_results 表(綜合測試結果)')
console.log('✅ users 表(用戶資訊)')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 管理員測驗結果功能測試完成')
}
}
testAdminResults()

View File

@@ -1,73 +0,0 @@
const testAPIDirect = async () => {
console.log('🧪 直接測試 API 路由')
console.log('=' .repeat(50))
// 模擬測試數據
const testData = {
userId: 'user-1759073326705-m06y3wacd',
answers: ['A', 'B', 'C', 'D', 'E', 'A', 'B', 'C', 'D', 'E'], // 10個答案
completedAt: new Date().toISOString().replace('Z', '').replace('T', ' ')
}
console.log('\n📝 測試數據:')
console.log(JSON.stringify(testData, null, 2))
try {
console.log('\n🔄 測試 API 路由...')
// 先測試資料庫連接
console.log('1. 測試資料庫連接...')
const dbTestResponse = await fetch('http://localhost:3000/api/test-db')
if (dbTestResponse.ok) {
console.log('✅ 資料庫連接正常')
} else {
console.log('❌ 資料庫連接失敗')
}
// 測試邏輯測驗 API
console.log('\n2. 測試邏輯測驗 API...')
const response = await fetch('http://localhost:3000/api/test-results/logic', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(testData)
})
console.log('📊 響應狀態:', response.status)
console.log('📊 響應狀態文字:', response.statusText)
let result
try {
const text = await response.text()
console.log('📊 原始響應:', text)
result = JSON.parse(text)
console.log('📊 解析後響應:', JSON.stringify(result, null, 2))
} catch (parseError) {
console.log('❌ JSON 解析失敗:', parseError.message)
return
}
if (result.success) {
console.log('\n✅ API 測試成功!')
} else {
console.log('\n❌ API 測試失敗!')
console.log('錯誤訊息:', result.error)
}
} catch (error) {
console.log('\n❌ 請求失敗:')
console.log('錯誤類型:', error.name)
console.log('錯誤訊息:', error.message)
if (error.code === 'ECONNREFUSED') {
console.log('\n💡 建議:')
console.log('1. 確保開發伺服器正在運行 (npm run dev)')
console.log('2. 檢查端口 3000 是否可用')
}
}
console.log('\n✅ API 直接測試完成')
}
testAPIDirect()

View File

@@ -1,122 +0,0 @@
const http = require('http')
const fs = require('fs')
const testChineseExport = async () => {
console.log('🔍 測試中文匯出功能')
console.log('=' .repeat(30))
try {
// 測試創意題目匯出(包含中文)
console.log('\n📊 測試創意題目匯出...')
const creativeResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=creative', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (creativeResponse.status === 200) {
const creativeData = JSON.parse(creativeResponse.data)
if (creativeData.success) {
console.log('✅ 創意題目匯出成功')
// 解碼並檢查中文內容
const csvContent = Buffer.from(creativeData.data, 'base64').toString('utf8')
const lines = csvContent.split('\n')
console.log(`\n📋 匯出內容預覽:`)
console.log(`標題行: ${lines[0]}`)
console.log(`\n前3行資料:`)
for (let i = 1; i <= Math.min(3, lines.length - 1); i++) {
if (lines[i].trim()) {
console.log(`${i}行: ${lines[i]}`)
}
}
// 檢查是否包含正確的中文字符
const hasChinese = /[\u4e00-\u9fff]/.test(csvContent)
console.log(`\n🔤 中文字符檢測: ${hasChinese ? '✅ 包含中文字符' : '❌ 未檢測到中文字符'}`)
// 檢查 BOM
const hasBOM = csvContent.charCodeAt(0) === 0xFEFF
console.log(`📝 UTF-8 BOM: ${hasBOM ? '✅ 包含 BOM' : '❌ 未包含 BOM'}`)
// 保存到檔案進行測試
fs.writeFileSync('test-creative-export.csv', csvContent, 'utf8')
console.log(`💾 已保存測試檔案: test-creative-export.csv`)
} else {
console.log('❌ 創意題目匯出失敗:', creativeData.message)
}
} else {
console.log('❌ 創意題目匯出失敗,狀態碼:', creativeResponse.status)
}
// 測試邏輯題目匯出
console.log('\n📊 測試邏輯題目匯出...')
const logicResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=logic', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (logicResponse.status === 200) {
const logicData = JSON.parse(logicResponse.data)
if (logicData.success) {
console.log('✅ 邏輯題目匯出成功')
// 解碼並檢查中文內容
const csvContent = Buffer.from(logicData.data, 'base64').toString('utf8')
const lines = csvContent.split('\n')
console.log(`\n📋 匯出內容預覽:`)
console.log(`標題行: ${lines[0]}`)
console.log(`\n第1行資料:`)
if (lines[1]) {
console.log(`第1行: ${lines[1]}`)
}
// 檢查是否包含正確的中文字符
const hasChinese = /[\u4e00-\u9fff]/.test(csvContent)
console.log(`\n🔤 中文字符檢測: ${hasChinese ? '✅ 包含中文字符' : '❌ 未檢測到中文字符'}`)
// 檢查 BOM
const hasBOM = csvContent.charCodeAt(0) === 0xFEFF
console.log(`📝 UTF-8 BOM: ${hasBOM ? '✅ 包含 BOM' : '❌ 未包含 BOM'}`)
// 保存到檔案進行測試
fs.writeFileSync('test-logic-export.csv', csvContent, 'utf8')
console.log(`💾 已保存測試檔案: test-logic-export.csv`)
} else {
console.log('❌ 邏輯題目匯出失敗:', logicData.message)
}
} else {
console.log('❌ 邏輯題目匯出失敗,狀態碼:', logicResponse.status)
}
console.log('\n📝 修正說明:')
console.log('✅ 添加了 UTF-8 BOM (Byte Order Mark)')
console.log('✅ 確保 Excel 能正確識別中文編碼')
console.log('✅ 使用 Base64 編碼避免 API 路由字符限制')
console.log('✅ 前端正確解碼並生成 CSV 檔案')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 中文匯出功能測試完成')
}
}
testChineseExport()

View File

@@ -1,90 +0,0 @@
const testCombinedCreativityLevels = () => {
console.log('💡 綜合能力測試創意能力評語功能測試')
console.log('=' .repeat(50))
// 模擬創意能力評語函數
const getCreativityLevel = (score) => {
if (score >= 90) return {
level: "創意巔峰者",
color: "bg-purple-600",
description: "創意力近乎無窮,你是團隊裡的靈感源泉,總能帶來突破性的想法。",
suggestion: "你不只創造靈感,更能影響他人。如果能結合執行力,你將成為真正的創新領袖。"
}
if (score >= 75) return {
level: "創意引領者",
color: "bg-blue-500",
description: "你是靈感的推動者!總是能在團體中主動拋出新想法,激發別人跟進。",
suggestion: "持續累積學習,讓你的靈感不僅是點子,而能帶動真正的行動。"
}
if (score >= 55) return {
level: "創意實踐者",
color: "bg-green-500",
description: "靈感已經隨手可得,在團體中也常被認為是「有創意的人」。",
suggestion: "再給自己一點勇氣,不要害怕挑戰慣例,你的創意將更有力量。"
}
if (score >= 35) return {
level: "創意開拓者",
color: "bg-yellow-500",
description: "你其實有自己的想法,但有時習慣跟隨大多數人的步伐。",
suggestion: "試著勇敢說出腦中天馬行空的念頭,你會發現,這些點子或許就是團隊需要的突破口。"
}
return {
level: "創意萌芽者",
color: "bg-red-500",
description: "還在創意旅程的起點。雖然暫時表現平淡,但這正是無限潛力的開端!",
suggestion: "觀察生活小事,或閱讀不同領域的內容,讓靈感一點一滴積累。"
}
}
console.log('\n📊 測試案例:')
// 測試各個分數區間
const testScores = [0, 20, 30, 45, 60, 70, 80, 90, 95]
testScores.forEach(score => {
const level = getCreativityLevel(score)
console.log(`\n分數: ${score}`)
console.log(`等級: ${level.level}`)
console.log(`顏色: ${level.color}`)
console.log(`描述: ${level.description}`)
console.log(`建議: ${level.suggestion}`)
})
console.log('\n🎯 評語等級對應:')
console.log('90分以上: 創意巔峰者 (紫色)')
console.log('75-89分: 創意引領者 (藍色)')
console.log('55-74分: 創意實踐者 (綠色)')
console.log('35-54分: 創意開拓者 (黃色)')
console.log('0-34分: 創意萌芽者 (紅色)')
console.log('\n🎨 UI設計特色:')
console.log('- 等級標示: 彩色圓點 + 等級名稱')
console.log('- 描述文字: 生動有趣的比喻和描述')
console.log('- 建議區塊: 淺色背景,包含👉圖示')
console.log('- 響應式設計: 適配手機和桌面版')
console.log('\n📝 評語內容特色:')
console.log('- 使用生動的比喻 (靈感源泉、天馬行空、創新領袖)')
console.log('- 提供具體的改進建議')
console.log('- 鼓勵性的語言風格')
console.log('- 符合不同能力水平的描述')
console.log('\n🌟 創意能力評語亮點:')
console.log('- 創意巔峰者: 強調影響力和領導力')
console.log('- 創意引領者: 強調推動和激發他人')
console.log('- 創意實踐者: 強調勇氣和挑戰慣例')
console.log('- 創意開拓者: 強調勇敢表達想法')
console.log('- 創意萌芽者: 強調潛力和積累')
console.log('\n🔍 測試要點:')
console.log('1. 各分數區間顯示正確的等級')
console.log('2. 顏色標示與等級匹配')
console.log('3. 描述文字生動有趣')
console.log('4. 建議內容實用具體')
console.log('5. UI佈局美觀整齊')
console.log('6. 與邏輯思維評語風格一致')
console.log('\n✅ 綜合能力測試創意能力評語功能測試完成')
}
testCombinedCreativityLevels()

View File

@@ -1,114 +0,0 @@
const https = require('https')
const http = require('http')
const testCombinedDBIntegration = async () => {
console.log('🧪 測試綜合測試結果資料庫整合功能')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 1. 測試綜合測試結果上傳 API
console.log('\n📊 1. 測試綜合測試結果上傳 API...')
const testData = {
userId: userId,
logicScore: 10,
creativityScore: 78,
overallScore: 48,
level: '待提升',
description: '綜合能力有待提升,建議系統性訓練邏輯思維和創意能力',
logicBreakdown: {
correct: 1,
total: 10,
answers: { 0: 'A', 1: 'B', 2: 'C' }
},
creativityBreakdown: {
total: 70,
maxScore: 90,
answers: { 0: 5, 1: 4, 2: 3 }
},
balanceScore: 66,
completedAt: new Date().toISOString().replace('Z', '').replace('T', ' ')
}
console.log('測試數據:', JSON.stringify(testData, null, 2))
const uploadResponse = await new Promise((resolve, reject) => {
const req = http.request({
hostname: 'localhost',
port: 3000,
path: '/api/test-results/combined',
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
}, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(JSON.stringify(testData))
req.end()
})
console.log('📊 上傳響應狀態:', uploadResponse.status)
if (uploadResponse.status === 200) {
const uploadResult = JSON.parse(uploadResponse.data)
console.log('✅ 上傳成功!')
console.log('📡 響應內容:', JSON.stringify(uploadResult, null, 2))
if (uploadResult.success) {
console.log('測試結果ID:', uploadResult.data.testResult.id)
}
} else {
console.log('❌ 上傳失敗,狀態碼:', uploadResponse.status)
console.log('響應內容:', uploadResponse.data)
}
// 2. 測試綜合測試結果獲取 API
console.log('\n📊 2. 測試綜合測試結果獲取 API...')
const getResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/combined?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
console.log('📊 獲取響應狀態:', getResponse.status)
if (getResponse.status === 200) {
const getResult = JSON.parse(getResponse.data)
console.log('✅ 獲取成功!')
console.log('📡 響應內容:', JSON.stringify(getResult, null, 2))
if (getResult.success && getResult.data.length > 0) {
console.log(`找到 ${getResult.data.length} 筆綜合測試結果`)
getResult.data.forEach((result, index) => {
console.log(`\n結果 ${index + 1}:`)
console.log(` ID: ${result.id}`)
console.log(` 邏輯分數: ${result.logic_score}`)
console.log(` 創意分數: ${result.creativity_score}`)
console.log(` 總分: ${result.overall_score}`)
console.log(` 等級: ${result.level}`)
console.log(` 完成時間: ${result.completed_at}`)
})
}
} else {
console.log('❌ 獲取失敗,狀態碼:', getResponse.status)
console.log('響應內容:', getResponse.data)
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 綜合測試結果資料庫整合功能測試完成')
}
}
testCombinedDBIntegration()

View File

@@ -1,80 +0,0 @@
const testCombinedIntegration = () => {
console.log('🔄 綜合能力測試資料庫整合測試')
console.log('=' .repeat(50))
console.log('\n📋 測試目標:')
console.log('- 整合 logic_questions 資料表')
console.log('- 整合 creative_questions 資料表')
console.log('- 移除硬編碼的題目資料')
console.log('- 確保題目、答案與資料庫一致')
console.log('\n🔧 主要修改:')
console.log('1. 移除硬編碼的題目匯入')
console.log(' - 移除: import { logicQuestions } from "@/lib/questions/logic-questions"')
console.log(' - 移除: import { creativeQuestions } from "@/lib/questions/creative-questions"')
console.log('\n2. 新增資料庫介面')
console.log(' - LogicQuestion 介面 (id, question, option_a-e, correct_answer, explanation)')
console.log(' - CreativeQuestion 介面 (id, statement, category, is_reverse)')
console.log('\n3. 新增狀態管理')
console.log(' - logicQuestions: LogicQuestion[]')
console.log(' - creativeQuestions: CreativeQuestion[]')
console.log(' - isLoading: boolean')
console.log('\n4. 新增資料載入邏輯')
console.log(' - useEffect 載入邏輯題目 (/api/logic-questions)')
console.log(' - useEffect 載入創意題目 (/api/creative-questions)')
console.log(' - 錯誤處理和載入狀態')
console.log('\n5. 修改題目渲染')
console.log(' - 邏輯題目: 使用 option_a 到 option_e 欄位')
console.log(' - 創意題目: 使用 statement 和 is_reverse 欄位')
console.log(' - 移除數值顯示 (5, 4, 3, 2, 1)')
console.log('\n6. 新增載入和錯誤狀態')
console.log(' - 載入中: 顯示載入動畫')
console.log(' - 載入失敗: 顯示錯誤訊息和重新載入按鈕')
console.log('\n📊 資料庫欄位對應:')
console.log('邏輯題目 (logic_questions):')
console.log(' - question -> 題目內容')
console.log(' - option_a, option_b, option_c, option_d, option_e -> 選項 A-E')
console.log(' - correct_answer -> 正確答案 (A-E)')
console.log(' - explanation -> 解釋說明')
console.log('\n創意題目 (creative_questions):')
console.log(' - statement -> 題目描述')
console.log(' - category -> 能力類別 (innovation, imagination, flexibility, originality)')
console.log(' - is_reverse -> 是否反向計分')
console.log('\n🎯 測試流程:')
console.log('1. 載入綜合能力測試頁面')
console.log('2. 檢查是否從資料庫載入題目')
console.log('3. 驗證邏輯題目選項顯示 (A-E)')
console.log('4. 驗證創意題目選項顯示 (無數值)')
console.log('5. 完成測試並檢查結果頁面')
console.log('\n✅ 預期結果:')
console.log('- 題目完全來自資料庫,無硬編碼')
console.log('- 邏輯題目顯示 A-E 選項')
console.log('- 創意題目不顯示數值')
console.log('- 載入狀態正常顯示')
console.log('- 錯誤處理完善')
console.log('\n🔍 驗證要點:')
console.log('- 檢查 Network 標籤中的 API 請求')
console.log('- 確認題目內容與資料庫一致')
console.log('- 測試載入失敗情況')
console.log('- 驗證計分邏輯正確性')
console.log('\n📝 注意事項:')
console.log('- 確保 API 路由正常運作')
console.log('- 檢查資料庫連線狀態')
console.log('- 驗證題目數量正確')
console.log('- 測試反向計分邏輯')
console.log('\n✅ 綜合能力測試資料庫整合測試完成')
}
testCombinedIntegration()

View File

@@ -1,89 +0,0 @@
const testCombinedLogicAnswers = () => {
console.log('🔍 綜合能力測試邏輯題目答案驗證')
console.log('=' .repeat(50))
// 模擬資料庫中的邏輯題目 (使用正確的欄位名稱)
const mockLogicQuestions = [
{
id: 1,
question: "如果所有的玫瑰都是花,所有的花都需要水,那麼可以得出什麼結論?",
option_a: "所有的玫瑰都需要水",
option_b: "所有需要水的都是玫瑰",
option_c: "有些花不是玫瑰",
option_d: "玫瑰不需要土壤",
option_e: "以上都不對",
correct_answer: "A", // 正確的欄位名稱
explanation: "根據邏輯推理,如果所有玫瑰都是花,所有花都需要水,那麼所有玫瑰都需要水。"
},
{
id: 2,
question: "在一個密碼中A=1, B=2, C=3...Z=26。如果「CAT」的數值和是24那麼「DOG」的數值和是",
option_a: "26",
option_b: "27",
option_c: "28",
option_d: "29",
option_e: "30",
correct_answer: "C", // 正確的欄位名稱
explanation: "C=3, A=1, T=20所以CAT=24。D=4, O=15, G=7所以DOG=4+15+7=26。"
},
{
id: 3,
question: "如果今天是星期三,那麼後天是星期幾?",
option_a: "星期四",
option_b: "星期五",
option_c: "星期六",
option_d: "星期日",
option_e: "星期一",
correct_answer: "B", // 正確的欄位名稱
explanation: "今天是星期三,明天是星期四,後天是星期五。"
}
]
console.log('\n📊 測試案例: 邏輯題目答案比較')
console.log('題目資料:')
mockLogicQuestions.forEach((q, i) => {
console.log(`\n題目 ${i+1}: ${q.question}`)
console.log(` 選項: A.${q.option_a}, B.${q.option_b}, C.${q.option_c}, D.${q.option_d}, E.${q.option_e}`)
console.log(` 正確答案: ${q.correct_answer}`)
})
// 模擬用戶答案
const userAnswers = ["A", "C", "B"] // 用戶選擇的答案
console.log('\n用戶答案:', userAnswers)
console.log('\n計分過程 (修正後):')
let logicCorrect = 0
mockLogicQuestions.forEach((question, index) => {
const userAnswer = userAnswers[index]
const correctAnswer = question.correct_answer // 使用正確的欄位名稱
const isCorrect = userAnswer === correctAnswer
console.log(`\n題目 ${index + 1}:`)
console.log(` 用戶答案: ${userAnswer}`)
console.log(` 正確答案: ${correctAnswer}`)
console.log(` 是否正確: ${isCorrect}`)
if (isCorrect) logicCorrect++
})
const logicScore = Math.round((logicCorrect / mockLogicQuestions.length) * 100)
console.log(`\n邏輯思維答對: ${logicCorrect} / ${mockLogicQuestions.length} = ${logicScore}%`)
console.log('\n🔧 修正內容:')
console.log('錯誤: logicAnswers[index] === question.correctAnswer')
console.log('正確: logicAnswers[index] === question.correct_answer')
console.log('\n原因: 資料庫欄位名稱是 correct_answer不是 correctAnswer')
console.log('\n📈 修正效果:')
console.log('- 現在會正確讀取資料庫中的正確答案')
console.log('- 邏輯題目計分會與單獨的邏輯測試一致')
console.log('- 用戶應該能獲得正確的分數')
console.log('\n✅ 綜合能力測試邏輯題目答案驗證完成')
console.log('\n🎯 結論:')
console.log('- 修正了欄位名稱錯誤')
console.log('- 現在使用資料庫中的正確答案進行比較')
console.log('- 計分邏輯與單獨測試頁面完全一致')
}
testCombinedLogicAnswers()

View File

@@ -1,79 +0,0 @@
const testCombinedLogicInstructions = () => {
console.log('📝 綜合能力測試邏輯題註記文字測試')
console.log('=' .repeat(50))
console.log('\n🎯 添加內容:')
console.log('位置: 綜合能力測試中邏輯題標題下方')
console.log('文字: "請仔細閱讀題目,選擇最正確的答案,每題均為單選。"')
console.log('條件: 僅在邏輯題階段顯示')
console.log('\n🎨 UI設計特色:')
console.log('邏輯題階段:')
console.log('- 標題: 題目內容')
console.log('- 說明: 請仔細閱讀題目,選擇最正確的答案,每題均為單選。')
console.log('- 樣式: text-sm text-muted-foreground mt-2')
console.log('\n創意題階段:')
console.log('- 標題: 題目描述')
console.log('- 說明: 請根據您的實際情況選擇最符合的選項5=非常符合1=完全不符合)。')
console.log('- 樣式: text-sm text-muted-foreground')
console.log('\n📊 條件渲染邏輯:')
console.log('1. phase === "logic": 顯示邏輯題說明')
console.log('2. phase === "creative": 顯示創意題說明')
console.log('3. 兩個階段都有各自的說明文字')
console.log('4. 樣式保持一致,但內容不同')
console.log('\n💡 設計理念:')
console.log('- 根據測試階段顯示相應說明')
console.log('- 邏輯題強調仔細閱讀和單選')
console.log('- 創意題強調根據實際情況選擇')
console.log('- 保持與單獨邏輯測試的一致性')
console.log('- 簡潔明瞭,不干擾主要內容')
console.log('\n📱 響應式設計:')
console.log('- 手機版: 文字大小適中,易於閱讀')
console.log('- 桌面版: 保持一致的視覺效果')
console.log('- 文字換行: 自動換行,保持可讀性')
console.log('- 間距: 與標題保持適當距離')
console.log('\n🎯 用戶體驗提升:')
console.log('- 清楚說明不同階段的答題規則')
console.log('- 邏輯題階段提醒仔細閱讀')
console.log('- 創意題階段說明評分標準')
console.log('- 視覺上不突兀,融入整體設計')
console.log('- 與單獨測試頁面保持一致')
console.log('\n🔍 與單獨邏輯測試對比:')
console.log('單獨邏輯測試:')
console.log('- 標題: 題目內容')
console.log('- 說明: 請仔細閱讀題目,選擇最正確的答案,每題均為單選。')
console.log('- 樣式: text-sm text-muted-foreground mt-2')
console.log('\n綜合能力測試邏輯題:')
console.log('- 標題: 題目內容')
console.log('- 說明: 請仔細閱讀題目,選擇最正確的答案,每題均為單選。')
console.log('- 樣式: text-sm text-muted-foreground mt-2')
console.log('\n✅ 一致性:')
console.log('- 文字內容完全一致 ✓')
console.log('- 樣式設計完全一致 ✓')
console.log('- 用戶體驗保持一致 ✓')
console.log('\n🔍 測試要點:')
console.log('1. 邏輯題階段是否顯示正確說明')
console.log('2. 創意題階段是否顯示正確說明')
console.log('3. 樣式是否與單獨測試一致')
console.log('4. 條件渲染是否正常工作')
console.log('5. 整體設計是否協調')
console.log('\n✅ 預期效果:')
console.log('- 用戶在邏輯題階段看到相應說明')
console.log('- 用戶在創意題階段看到相應說明')
console.log('- 與單獨測試頁面保持一致性')
console.log('- 整體用戶體驗更加完善')
console.log('\n✅ 綜合能力測試邏輯題註記文字測試完成')
}
testCombinedLogicInstructions()

View File

@@ -1,82 +0,0 @@
const testCombinedLogicLevels = () => {
console.log('🧠 綜合能力測試邏輯思維評語功能測試')
console.log('=' .repeat(50))
// 模擬邏輯思維評語函數
const getLogicLevel = (score) => {
if (score >= 100) return {
level: "邏輯巔峰者",
color: "bg-purple-600",
description: "近乎完美的邏輯典範!你像一台「推理引擎」,嚴謹又高效,幾乎不受陷阱干擾。",
suggestion: "多和他人分享你的思考路徑,能幫助團隊整體邏輯力提升。"
}
if (score >= 80) return {
level: "邏輯大師",
color: "bg-blue-500",
description: "你的思維如同精密儀器,能快速抓住題目關鍵,並做出有效推理。常常是團隊中「冷靜的分析者」。",
suggestion: "挑戰更高層次的難題,讓你的邏輯力更加精進。"
}
if (score >= 60) return {
level: "邏輯高手",
color: "bg-green-500",
description: "邏輯清晰穩定,大部分情境都能正確判斷。偶爾會因粗心錯過陷阱。",
suggestion: "在思維縝密之餘,更加留心細節,就能把錯誤率降到最低。"
}
if (score >= 30) return {
level: "邏輯學徒",
color: "bg-yellow-500",
description: "已經抓到一些邏輯規律,能解決中等難度的問題。遇到複雜情境時,仍可能卡關。",
suggestion: "嘗試將問題拆解成小步驟,就像組裝樂高,每一塊拼好,答案就自然浮現。"
}
return {
level: "邏輯探險新手",
color: "bg-red-500",
description: "還在邏輯森林的入口徘徊。思考時可能忽略細節,或被陷阱誤導。",
suggestion: "多練習經典邏輯題,像是在拼拼圖般,慢慢建立清晰的分析步驟。"
}
}
console.log('\n📊 測試案例:')
// 測試各個分數區間
const testScores = [0, 15, 25, 45, 65, 85, 95, 100]
testScores.forEach(score => {
const level = getLogicLevel(score)
console.log(`\n分數: ${score}`)
console.log(`等級: ${level.level}`)
console.log(`顏色: ${level.color}`)
console.log(`描述: ${level.description}`)
console.log(`建議: ${level.suggestion}`)
})
console.log('\n🎯 評語等級對應:')
console.log('100分: 邏輯巔峰者 (紫色)')
console.log('80-99分: 邏輯大師 (藍色)')
console.log('60-79分: 邏輯高手 (綠色)')
console.log('30-59分: 邏輯學徒 (黃色)')
console.log('0-29分: 邏輯探險新手 (紅色)')
console.log('\n🎨 UI設計特色:')
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. 各分數區間顯示正確的等級')
console.log('2. 顏色標示與等級匹配')
console.log('3. 描述文字生動有趣')
console.log('4. 建議內容實用具體')
console.log('5. UI佈局美觀整齊')
console.log('\n✅ 綜合能力測試邏輯思維評語功能測試完成')
}
testCombinedLogicLevels()

View File

@@ -1,68 +0,0 @@
const testCombinedMobileButtons = () => {
console.log('📱 綜合能力測試結果頁面手機版按鈕修正測試')
console.log('=' .repeat(50))
console.log('\n🔍 問題分析:')
console.log('原始問題: 手機版「返回首頁」文字消失')
console.log('原因: 使用了 hidden sm:inline 類別,在手機版隱藏文字')
console.log('\n🔧 修正內容:')
console.log('舊代碼: <span className="hidden sm:inline">返回首頁</span>')
console.log('新代碼: <span>返回首頁</span>')
console.log('效果: 移除 hidden sm:inline讓文字在所有螢幕尺寸都顯示')
console.log('\n📊 按鈕區域分析:')
console.log('按鈕容器: flex flex-col sm:flex-row gap-4 justify-center')
console.log('- 手機版: 垂直排列 (flex-col)')
console.log('- 桌面版: 水平排列 (sm:flex-row)')
console.log('- 間距: 4 (16px)')
console.log('- 對齊: 置中')
console.log('\n🎯 三個按鈕:')
console.log('1. 返回首頁按鈕:')
console.log(' - 樣式: 主要按鈕 (solid blue)')
console.log(' - 圖示: Home 圖示')
console.log(' - 文字: 返回首頁 (現在所有螢幕都顯示)')
console.log(' - 連結: / (首頁)')
console.log('\n2. 重新測試按鈕:')
console.log(' - 樣式: 次要按鈕 (outline)')
console.log(' - 圖示: RotateCcw 圖示')
console.log(' - 文字: 重新測試')
console.log(' - 連結: /tests/combined')
console.log('\n3. 查看所有成績按鈕:')
console.log(' - 樣式: 次要按鈕 (outline)')
console.log(' - 圖示: 無')
console.log(' - 文字: 查看所有成績')
console.log(' - 連結: /results')
console.log('\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('- 手機版「返回首頁」文字現在會顯示')
console.log('- 保持桌面版的良好體驗')
console.log('- 所有按鈕在各種螢幕尺寸都清晰可見')
console.log('- 用戶體驗一致性提升')
console.log('\n🔍 測試要點:')
console.log('1. 手機版檢查「返回首頁」文字是否顯示')
console.log('2. 桌面版檢查按鈕排列是否正常')
console.log('3. 所有按鈕點擊功能正常')
console.log('4. 圖示和文字對齊美觀')
console.log('5. 響應式設計在不同螢幕尺寸都正常')
console.log('\n✅ 綜合能力測試結果頁面手機版按鈕修正測試完成')
}
testCombinedMobileButtons()

View File

@@ -1,74 +0,0 @@
const testCombinedMobileUI = () => {
console.log('📱 綜合能力測試結果頁面手機版UI優化')
console.log('=' .repeat(50))
console.log('\n🎯 優化目標:')
console.log('- 邏輯思維、創意能力、能力平衡在手機版並排顯示')
console.log('- 改善手機版UI感受')
console.log('- 保持桌面版的良好體驗')
console.log('\n🔧 主要修改:')
console.log('1. 網格佈局調整:')
console.log(' 舊: grid-cols-1 md:grid-cols-3 (手機版單欄)')
console.log(' 新: grid-cols-3 (手機版和桌面版都3欄)')
console.log('\n2. 間距優化:')
console.log(' 舊: gap-6 (固定間距)')
console.log(' 新: gap-4 md:gap-6 (手機版較小間距)')
console.log('\n3. 字體大小響應式:')
console.log(' 分數: text-2xl md:text-3xl (手機版較小)')
console.log(' 標籤: text-xs md:text-sm (手機版較小)')
console.log('\n4. 邊距優化:')
console.log(' 分數下方邊距: mb-1 md:mb-2 (手機版較小)')
console.log('\n📊 響應式設計:')
console.log('手機版 (< 768px):')
console.log(' - 3欄並排顯示')
console.log(' - 分數: 2xl (24px)')
console.log(' - 標籤: xs (12px)')
console.log(' - 間距: 4 (16px)')
console.log(' - 邊距: 1 (4px)')
console.log('\n桌面版 (≥ 768px):')
console.log(' - 3欄並排顯示')
console.log(' - 分數: 3xl (30px)')
console.log(' - 標籤: sm (14px)')
console.log(' - 間距: 6 (24px)')
console.log(' - 邊距: 2 (8px)')
console.log('\n🎨 視覺效果:')
console.log('- 手機版: 緊湊但清晰的3欄佈局')
console.log('- 桌面版: 寬鬆舒適的3欄佈局')
console.log('- 保持一致的視覺層次')
console.log('- 分數顏色根據表現動態變化')
console.log('\n📱 手機版優勢:')
console.log('- 三個分數一目了然')
console.log('- 節省垂直空間')
console.log('- 更好的視覺平衡')
console.log('- 與其他測試結果頁面保持一致')
console.log('\n🖥 桌面版保持:')
console.log('- 較大的字體和間距')
console.log('- 舒適的閱讀體驗')
console.log('- 清晰的視覺層次')
console.log('\n✅ 預期效果:')
console.log('- 手機版UI感受大幅改善')
console.log('- 三個分數並排顯示,易於比較')
console.log('- 響應式設計適配各種螢幕尺寸')
console.log('- 與創意測試結果頁面設計一致')
console.log('\n🔍 測試要點:')
console.log('1. 手機版 (< 768px) 檢查3欄並排')
console.log('2. 桌面版 (≥ 768px) 檢查字體和間距')
console.log('3. 分數顏色根據數值正確顯示')
console.log('4. 標籤文字完整顯示')
console.log('5. 整體佈局平衡美觀')
console.log('\n✅ 綜合能力測試結果頁面手機版UI優化完成')
}
testCombinedMobileUI()

View File

@@ -1,59 +0,0 @@
const testCombinedScoreDisplay = () => {
console.log('📊 綜合能力測試分數顯示修正測試')
console.log('=' .repeat(50))
console.log('\n🔍 問題分析:')
console.log('原始問題: 總得分 70 與上面 78 分不一致')
console.log('原因: 標籤誤導,實際上是不同的分數類型')
console.log('\n📈 分數類型說明:')
console.log('1. creativityScore (78分): 百分比分數')
console.log(' - 計算方式: (creativityTotal / creativityMaxScore) * 100')
console.log(' - 用途: 用於評語等級判斷和進度條顯示')
console.log(' - 顯示位置: 主要得分區域')
console.log('\n2. creativityTotal (70分): 原始總分')
console.log(' - 計算方式: 所有題目分數的總和')
console.log(' - 用途: 顯示實際獲得的原始分數')
console.log(' - 顯示位置: 詳細分數區域')
console.log('\n3. creativityMaxScore (90分): 滿分')
console.log(' - 計算方式: 題目數量 * 5 (每題最高5分)')
console.log(' - 用途: 作為原始分數的滿分基準')
console.log(' - 顯示位置: 詳細分數區域')
console.log('\n🔧 修正內容:')
console.log('舊標籤: "總得分" (容易誤解)')
console.log('新標籤: "原始得分" (更清楚)')
console.log('\n📊 修正後的顯示邏輯:')
console.log('主要得分區域:')
console.log(' - 得分: 78分 (百分比分數)')
console.log(' - 進度條: 78% 填充')
console.log('\n詳細分數區域:')
console.log(' - 原始得分: 70分 (實際獲得的分數)')
console.log(' - 滿分: 90分 (最高可能分數)')
console.log('\n🎯 修正效果:')
console.log('- 消除了分數不一致的誤解')
console.log('- 清楚區分百分比分數和原始分數')
console.log('- 用戶更容易理解分數含義')
console.log('\n📝 計算範例:')
console.log('假設有18題創意題目:')
console.log('- 每題最高5分滿分 = 18 * 5 = 90分')
console.log('- 用戶實際獲得70分')
console.log('- 百分比分數 = (70 / 90) * 100 = 77.78% ≈ 78分')
console.log('- 評語等級基於78分判斷')
console.log('\n✅ 修正要點:')
console.log('1. 主要得分顯示百分比分數 (用於評語)')
console.log('2. 詳細區域顯示原始分數 (用於參考)')
console.log('3. 標籤清楚區分兩種分數類型')
console.log('4. 保持計算邏輯的一致性')
console.log('\n✅ 綜合能力測試分數顯示修正測試完成')
}
testCombinedScoreDisplay()

View File

@@ -1,130 +0,0 @@
const testCombinedScoringLogic = () => {
console.log('🧮 綜合能力測試計分邏輯驗證')
console.log('=' .repeat(50))
// 模擬資料庫中的創意題目
const mockCreativeQuestions = [
{
id: 1,
statement: "我常能從不同角度看事情,接受多元觀點。",
category: "flexibility",
is_reverse: false
},
{
id: 2,
statement: "我習慣一次只做一件事,不輕易嘗試新方法。",
category: "flexibility",
is_reverse: true
},
{
id: 3,
statement: "當靈感枯竭時,我仍能找到突破的方法。",
category: "imagination",
is_reverse: false
},
{
id: 4,
statement: "我很少質疑現有的做法或流程。",
category: "innovation",
is_reverse: true
}
]
// 模擬資料庫中的邏輯題目
const mockLogicQuestions = [
{
id: 1,
question: "如果所有的玫瑰都是花,所有的花都需要水,那麼可以得出什麼結論?",
correct_answer: "A"
},
{
id: 2,
question: "在一個密碼中A=1, B=2, C=3...Z=26。如果「CAT」的數值和是24那麼「DOG」的數值和是",
correct_answer: "C"
}
]
console.log('\n📊 測試案例 1: 創意題目計分')
console.log('題目資料:')
mockCreativeQuestions.forEach((q, i) => {
console.log(` ${i+1}. ${q.statement}`)
console.log(` 類別: ${q.category}, 反向: ${q.is_reverse}`)
})
// 模擬用戶答案 (1-5 分)
const creativeAnswers = [5, 2, 4, 1] // 用戶選擇的分數
console.log('\n用戶答案:', creativeAnswers)
console.log('\n計分過程:')
let creativityTotal = 0
mockCreativeQuestions.forEach((question, index) => {
const answer = creativeAnswers[index] || 1
const originalScore = answer
const actualScore = question.is_reverse ? 6 - answer : answer
console.log(`\n題目 ${index + 1}:`)
console.log(` 原始分數: ${originalScore}`)
console.log(` 是否反向: ${question.is_reverse}`)
console.log(` 實際分數: ${actualScore}`)
console.log(` 計算: ${question.is_reverse ? `6 - ${answer} = ${actualScore}` : `直接使用 ${answer}`}`)
creativityTotal += actualScore
})
const creativityMaxScore = mockCreativeQuestions.length * 5
const creativityScore = Math.round((creativityTotal / creativityMaxScore) * 100)
console.log(`\n創意能力總分: ${creativityTotal} / ${creativityMaxScore} = ${creativityScore}%`)
console.log('\n📊 測試案例 2: 邏輯題目計分')
console.log('題目資料:')
mockLogicQuestions.forEach((q, i) => {
console.log(` ${i+1}. ${q.question}`)
console.log(` 正確答案: ${q.correct_answer}`)
})
// 模擬用戶答案
const logicAnswers = ["A", "B"] // 用戶選擇的答案
console.log('\n用戶答案:', logicAnswers)
console.log('\n計分過程:')
let logicCorrect = 0
mockLogicQuestions.forEach((question, index) => {
const userAnswer = logicAnswers[index]
const correctAnswer = question.correct_answer
const isCorrect = userAnswer === correctAnswer
console.log(`\n題目 ${index + 1}:`)
console.log(` 用戶答案: ${userAnswer}`)
console.log(` 正確答案: ${correctAnswer}`)
console.log(` 是否正確: ${isCorrect}`)
if (isCorrect) logicCorrect++
})
const logicScore = Math.round((logicCorrect / mockLogicQuestions.length) * 100)
console.log(`\n邏輯思維答對: ${logicCorrect} / ${mockLogicQuestions.length} = ${logicScore}%`)
console.log('\n🔍 問題檢查:')
console.log('1. 邏輯題目計分:')
console.log(' ✅ 使用 question.correctAnswer 與用戶答案比較')
console.log(' ✅ 計分邏輯正確')
console.log('\n2. 創意題目計分:')
console.log(' ✅ 使用 question.is_reverse 判斷是否反向計分')
console.log(' ✅ 反向計分: 6 - 用戶答案')
console.log(' ✅ 正向計分: 直接使用用戶答案')
console.log('\n📈 反向計分範例:')
console.log('題目: "我習慣一次只做一件事,不輕易嘗試新方法。" (is_reverse: true)')
console.log('用戶選擇: 2分 (不太符合)')
console.log('反向計分: 6 - 2 = 4分 (因為不習慣 = 靈活性高)')
console.log('\n✅ 綜合能力測試計分邏輯驗證完成')
console.log('\n🎯 結論:')
console.log('- 邏輯題目計分與資料庫正確答案一致')
console.log('- 創意題目反向計分邏輯正確')
console.log('- 計分方式與單獨測試頁面一致')
}
testCombinedScoringLogic()

View File

@@ -1,107 +0,0 @@
const testCombinedScoring = () => {
console.log('🧮 綜合能力計分邏輯測試')
console.log('=' .repeat(50))
// 模擬修正後的計分函數
const calculateCombinedScore = (logicScore, creativityScore) => {
const logicWeight = 0.4
const creativityWeight = 0.4
const balanceWeight = 0.2
// 修正後的平衡性計算
const scoreDiff = Math.abs(logicScore - creativityScore)
const balanceScore = Math.max(0, 100 - Math.min(scoreDiff * 0.5, 50))
const overallScore = Math.round(
logicScore * logicWeight + creativityScore * creativityWeight + balanceScore * balanceWeight,
)
let level, description, color
if (overallScore >= 90) {
level = "卓越"
color = "bg-gradient-to-r from-purple-500 to-blue-500"
description = "綜合能力卓越,邏輯思維與創意能力並重,是理想的複合型人才"
} else if (overallScore >= 80) {
level = "優秀"
color = "bg-gradient-to-r from-blue-500 to-green-500"
description = "綜合能力優秀,在邏輯思維和創意能力方面都有良好表現"
} else if (overallScore >= 70) {
level = "良好"
color = "bg-gradient-to-r from-green-500 to-yellow-500"
description = "綜合能力良好,具備一定的邏輯思維和創意能力"
} else if (overallScore >= 60) {
level = "中等"
color = "bg-gradient-to-r from-yellow-500 to-orange-500"
description = "綜合能力中等,建議針對性提升薄弱環節"
} else {
level = "待提升"
color = "bg-gradient-to-r from-orange-500 to-red-500"
description = "綜合能力有待提升,建議系統性訓練邏輯思維和創意能力"
}
return {
overallScore,
level,
description,
color,
breakdown: {
logic: logicScore,
creativity: creativityScore,
balance: Math.round(balanceScore),
},
}
}
console.log('\n📊 測試案例:')
// 測試案例 1: 用戶的情況 (邏輯 0, 創意 100)
const testCase1 = calculateCombinedScore(0, 100)
console.log('\n案例 1: 邏輯思維 0 分,創意能力 100 分')
console.log(` 分數差距: ${Math.abs(0 - 100)}`)
console.log(` 平衡性分數: ${testCase1.breakdown.balance}`)
console.log(` 綜合分數: ${testCase1.overallScore}`)
console.log(` 等級: ${testCase1.level}`)
console.log(` 描述: ${testCase1.description}`)
// 測試案例 2: 平衡的情況
const testCase2 = calculateCombinedScore(80, 80)
console.log('\n案例 2: 邏輯思維 80 分,創意能力 80 分')
console.log(` 分數差距: ${Math.abs(80 - 80)}`)
console.log(` 平衡性分數: ${testCase2.breakdown.balance}`)
console.log(` 綜合分數: ${testCase2.overallScore}`)
console.log(` 等級: ${testCase2.level}`)
// 測試案例 3: 中等差距
const testCase3 = calculateCombinedScore(60, 90)
console.log('\n案例 3: 邏輯思維 60 分,創意能力 90 分')
console.log(` 分數差距: ${Math.abs(60 - 90)}`)
console.log(` 平衡性分數: ${testCase3.breakdown.balance}`)
console.log(` 綜合分數: ${testCase3.overallScore}`)
console.log(` 等級: ${testCase3.level}`)
// 測試案例 4: 極端情況
const testCase4 = calculateCombinedScore(100, 0)
console.log('\n案例 4: 邏輯思維 100 分,創意能力 0 分')
console.log(` 分數差距: ${Math.abs(100 - 0)}`)
console.log(` 平衡性分數: ${testCase4.breakdown.balance}`)
console.log(` 綜合分數: ${testCase4.overallScore}`)
console.log(` 等級: ${testCase4.level}`)
console.log('\n🔧 修正內容:')
console.log('舊公式: balanceScore = Math.max(0, 100 - scoreDiff * 2)')
console.log('新公式: balanceScore = Math.max(0, 100 - Math.min(scoreDiff * 0.5, 50))')
console.log('\n修正說明:')
console.log('- 降低平衡性扣分比例 (從 2 倍改為 0.5 倍)')
console.log('- 設定最大扣分上限 (最多扣 50 分)')
console.log('- 避免極端情況下的平衡性為 0')
console.log('\n📈 修正效果:')
console.log('- 邏輯 0, 創意 100: 綜合分數從 40 提升到 60')
console.log('- 平衡性分數從 0 提升到 50')
console.log('- 更合理的綜合能力評估')
console.log('\n✅ 綜合能力計分邏輯測試完成')
}
testCombinedScoring()

View File

@@ -1,131 +0,0 @@
const http = require('http')
const testCompleteExcelFunctionality = async () => {
console.log('🔍 測試完整的 Excel 匯入匯出功能')
console.log('=' .repeat(50))
try {
// 1. 測試邏輯題目匯出
console.log('\n📊 1. 測試邏輯題目匯出...')
const logicExportResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=logic', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (logicExportResponse.status === 200) {
const logicData = JSON.parse(logicExportResponse.data)
if (logicData.success) {
console.log('✅ 邏輯題目匯出成功')
console.log(` 檔案名: ${logicData.filename}`)
console.log(` 內容類型: ${logicData.contentType}`)
console.log(` 資料大小: ${logicData.data.length} 字符`)
// 解碼並檢查內容
const csvContent = Buffer.from(logicData.data, 'base64').toString('utf8')
const lines = csvContent.split('\n')
console.log(` 總行數: ${lines.length}`)
console.log(` 標題行: ${lines[0]}`)
if (lines.length > 1) {
console.log(` 第一題: ${lines[1].substring(0, 100)}...`)
}
} else {
console.log('❌ 邏輯題目匯出失敗:', logicData.message)
}
} else {
console.log('❌ 邏輯題目匯出失敗,狀態碼:', logicExportResponse.status)
}
// 2. 測試創意題目匯出
console.log('\n📊 2. 測試創意題目匯出...')
const creativeExportResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=creative', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (creativeExportResponse.status === 200) {
const creativeData = JSON.parse(creativeExportResponse.data)
if (creativeData.success) {
console.log('✅ 創意題目匯出成功')
console.log(` 檔案名: ${creativeData.filename}`)
console.log(` 內容類型: ${creativeData.contentType}`)
console.log(` 資料大小: ${creativeData.data.length} 字符`)
// 解碼並檢查內容
const csvContent = Buffer.from(creativeData.data, 'base64').toString('utf8')
const lines = csvContent.split('\n')
console.log(` 總行數: ${lines.length}`)
console.log(` 標題行: ${lines[0]}`)
if (lines.length > 1) {
console.log(` 第一題: ${lines[1].substring(0, 100)}...`)
}
} else {
console.log('❌ 創意題目匯出失敗:', creativeData.message)
}
} else {
console.log('❌ 創意題目匯出失敗,狀態碼:', creativeExportResponse.status)
}
// 3. 功能特點總結
console.log('\n📊 3. Excel 匯入匯出功能特點:')
console.log('✅ 根據資料庫格式匯出範本')
console.log('✅ 支援邏輯思維和創意能力兩種題目')
console.log('✅ 使用 Base64 編碼避免中文字符問題')
console.log('✅ 支援 A-E 選項(邏輯題目)')
console.log('✅ 支援反向計分標記(創意題目)')
console.log('✅ 匯入時覆蓋現有資料')
console.log('✅ 自動重新載入題目資料')
// 4. 資料庫整合
console.log('\n📊 4. 資料庫整合特點:')
console.log('✅ 匯出:從資料庫讀取現有題目')
console.log('✅ 匯入:清空現有資料後插入新資料')
console.log('✅ 格式:完全匹配資料庫欄位名稱')
console.log('✅ 驗證:匯入時進行資料驗證')
console.log('✅ 更新:匯入後自動刷新頁面資料')
// 5. 檔案格式
console.log('\n📊 5. 檔案格式支援:')
console.log('✅ 邏輯題目ID, 題目內容, 選項A-E, 正確答案, 解釋')
console.log('✅ 創意題目ID, 陳述內容, 類別, 反向計分')
console.log('✅ CSV 格式:.csv 檔案')
console.log('✅ 中文支援UTF-8 編碼')
console.log('✅ 資料完整性:包含所有必要欄位')
// 6. 用戶體驗
console.log('\n📊 6. 用戶體驗:')
console.log('✅ 一鍵下載:點擊按鈕直接下載範本')
console.log('✅ 格式一致:範本格式與資料庫完全一致')
console.log('✅ 即時更新:匯入後立即看到更新結果')
console.log('✅ 錯誤處理:詳細的錯誤訊息提示')
console.log('✅ 載入狀態:匯入過程顯示載入指示器')
console.log('\n📝 Excel 匯入匯出功能總結:')
console.log('✅ 完全基於資料庫格式設計')
console.log('✅ 支援覆蓋式更新現有題目')
console.log('✅ 提供完整的匯入匯出流程')
console.log('✅ 用戶友好的操作界面')
console.log('✅ 自動化的資料同步機制')
console.log('✅ 解決了中文字符編碼問題')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ Excel 匯入匯出功能測試完成')
}
}
testCompleteExcelFunctionality()

View File

@@ -1,157 +0,0 @@
const https = require('https')
const http = require('http')
const testCompleteProfileSystem = async () => {
console.log('🔍 測試完整的個人資訊系統')
console.log('=' .repeat(50))
const testUserId = 'user-1759073326705-m06y3wacd'
try {
// 1. 獲取初始用戶資料
console.log('\n📊 1. 獲取初始用戶資料...')
const initialResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/user/profile?userId=${testUserId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let initialData = null
if (initialResponse.status === 200) {
const data = JSON.parse(initialResponse.data)
if (data.success) {
initialData = data.data
console.log('✅ 初始用戶資料:')
console.log(` 姓名: ${initialData.name}`)
console.log(` 電子郵件: ${initialData.email}`)
console.log(` 部門: ${initialData.department}`)
console.log(` 角色: ${initialData.role}`)
}
}
// 2. 測試個人資料更新
console.log('\n📊 2. 測試個人資料更新...')
const profileUpdateData = {
userId: testUserId,
name: '王測試',
email: 'test@company.com',
department: '測試部'
}
const profileResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(profileUpdateData)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/user/profile',
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
if (profileResponse.status === 200) {
const profileResult = JSON.parse(profileResponse.data)
if (profileResult.success) {
console.log('✅ 個人資料更新成功')
} else {
console.log('❌ 個人資料更新失敗:', profileResult.error)
}
}
// 3. 測試密碼更新
console.log('\n📊 3. 測試密碼更新...')
const passwordUpdateData = {
userId: testUserId,
currentPassword: 'newpassword123',
newPassword: 'test123'
}
const passwordResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(passwordUpdateData)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/user/profile',
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
if (passwordResponse.status === 200) {
const passwordResult = JSON.parse(passwordResponse.data)
if (passwordResult.success) {
console.log('✅ 密碼更新成功')
} else {
console.log('❌ 密碼更新失敗:', passwordResult.error)
}
}
// 4. 驗證最終狀態
console.log('\n📊 4. 驗證最終狀態...')
const finalResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/user/profile?userId=${testUserId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (finalResponse.status === 200) {
const finalData = JSON.parse(finalResponse.data)
if (finalData.success) {
console.log('✅ 最終用戶資料:')
console.log(` 姓名: ${finalData.data.name}`)
console.log(` 電子郵件: ${finalData.data.email}`)
console.log(` 部門: ${finalData.data.department}`)
console.log(` 角色: ${finalData.data.role}`)
// 檢查是否恢復到初始狀態
const isRestored = finalData.data.name === '王測試' &&
finalData.data.email === 'test@company.com' &&
finalData.data.department === '測試部'
console.log(`資料是否恢復: ${isRestored ? '✅' : '❌'}`)
}
}
console.log('\n📝 功能總結:')
console.log('✅ 個人資料更新功能正常')
console.log('✅ 密碼更新功能正常')
console.log('✅ 資料庫整合成功')
console.log('✅ API 端點運作正常')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 完整個人資訊系統測試完成')
}
}
testCompleteProfileSystem()

View File

@@ -1,57 +0,0 @@
const https = require('https')
const http = require('http')
const testCorrectedApiTime = async () => {
console.log('🔍 測試修正後的 API 時間處理')
console.log('=' .repeat(50))
try {
// 測試當前時間
console.log('\n📊 當前時間:')
const now = new Date()
const utcTime = now.toISOString()
const taiwanTime = now.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(`UTC 時間: ${utcTime}`)
console.log(`台灣時間: ${taiwanTime}`)
// 測試修正後的 API 時間轉換
console.log('\n📊 修正後的 API 時間轉換:')
const apiInput = utcTime // 前端傳入的 UTC 時間
const utcDate = new Date(apiInput)
const apiOutput = utcDate.toISOString().replace('Z', '').replace('T', ' ')
console.log(`API 輸入 (前端): ${apiInput}`)
console.log(`API 輸出 (資料庫): ${apiOutput}`)
// 測試前端讀取
console.log('\n📊 前端讀取測試:')
const frontendRead = new Date(apiOutput + 'Z') // 重新添加 Z 來正確解析
const frontendDisplay = frontendRead.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(`前端讀取: ${frontendRead.toISOString()}`)
console.log(`前端顯示: ${frontendDisplay}`)
// 驗證轉換是否正確
const isCorrect = frontendRead.toISOString() === utcTime
console.log(`轉換是否正確: ${isCorrect ? '✅' : '❌'}`)
if (!isCorrect) {
console.log(`期望: ${utcTime}`)
console.log(`實際: ${frontendRead.toISOString()}`)
}
console.log('\n📝 修正說明:')
console.log('1. 前端傳入: UTC 時間 (2025-09-29T09:37:40.867Z)')
console.log('2. API 轉換: 先解析為 Date再轉換為 MySQL 格式')
console.log('3. 資料庫儲存: UTC 時間格式 (2025-09-29 09:37:40.867)')
console.log('4. 前端讀取: 添加 Z 後解析,正確轉換為台灣時間')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修正後的 API 時間處理測試完成')
}
}
testCorrectedApiTime()

View File

@@ -1,42 +0,0 @@
const https = require('https')
const http = require('http')
const testCorrectedMysqlFormat = async () => {
console.log('🔍 測試修正後的 MySQL 時間格式')
console.log('=' .repeat(50))
try {
// 測試時間格式轉換
console.log('\n📊 測試時間格式轉換:')
const now = new Date()
const isoTime = now.toISOString()
const mysqlTime = isoTime.replace('Z', '').replace('T', ' ')
console.log(`ISO 8601 格式: ${isoTime}`)
console.log(`MySQL 格式: ${mysqlTime}`)
// 測試轉換後的時間解析
const parsedTime = new Date(mysqlTime + 'Z') // 重新添加 Z 來正確解析
const taiwanTime = parsedTime.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(`轉換後解析: ${parsedTime.toISOString()}`)
console.log(`台灣時間: ${taiwanTime}`)
// 驗證轉換是否正確
const isCorrect = parsedTime.toISOString() === isoTime
console.log(`轉換是否正確: ${isCorrect ? '✅' : '❌'}`)
console.log('\n📝 修正說明:')
console.log('1. 前端使用 ISO 8601 格式 (2025-09-29T09:30:00.000Z)')
console.log('2. API 直接替換格式 (2025-09-29 09:30:00.000)')
console.log('3. 資料庫儲存 UTC 時間')
console.log('4. 前端讀取時正確轉換為台灣時間')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修正後的 MySQL 時間格式測試完成')
}
}
testCorrectedMysqlFormat()

View File

@@ -1,49 +0,0 @@
const https = require('https')
const http = require('http')
const testCorrectedTime = async () => {
console.log('🔍 測試修正後的時間格式')
console.log('=' .repeat(50))
try {
// 測試當前時間
console.log('\n📊 當前時間測試:')
const now = new Date()
const utcTime = now.toISOString()
const taiwanTime = now.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(`當前 UTC 時間: ${utcTime}`)
console.log(`當前台灣時間: ${taiwanTime}`)
// 模擬舊格式和新格式的差異
console.log('\n📊 格式比較:')
const oldFormat = now.toISOString().replace('Z', '').replace('T', ' ')
const newFormat = now.toISOString()
console.log(`舊格式: ${oldFormat}`)
console.log(`新格式: ${newFormat}`)
// 測試兩種格式的轉換
const oldDate = new Date(oldFormat)
const newDate = new Date(newFormat)
console.log(`\n舊格式轉換:`)
console.log(` UTC: ${oldDate.toISOString()}`)
console.log(` 台灣時間: ${oldDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(`\n新格式轉換:`)
console.log(` UTC: ${newDate.toISOString()}`)
console.log(` 台灣時間: ${newDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
// 驗證新格式是否正確
const isCorrect = newDate.toISOString() === utcTime
console.log(`\n新格式是否正確: ${isCorrect ? '✅' : '❌'}`)
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修正後時間格式測試完成')
}
}
testCorrectedTime()

View File

@@ -1,72 +0,0 @@
const mysql = require('mysql2/promise')
async function testCreateResult() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🧪 測試 createTestResult 函數')
console.log('=' .repeat(50))
try {
const connection = await mysql.createConnection(config)
// 模擬 createTestResult 函數的邏輯
const testResultData = {
user_id: 'user-1759073326705-m06y3wacd',
test_type: 'logic',
score: 80,
total_questions: 10,
correct_answers: 8,
completed_at: new Date().toISOString()
}
console.log('測試數據:', testResultData)
const id = `test_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
console.log('生成的ID:', id)
const insertQuery = `
INSERT INTO test_results (
id, user_id, test_type, score, total_questions,
correct_answers, completed_at
) VALUES (?, ?, ?, ?, ?, ?, ?)
`
const insertData = [
id,
testResultData.user_id,
testResultData.test_type,
testResultData.score,
testResultData.total_questions,
testResultData.correct_answers,
testResultData.completed_at
]
console.log('插入數據:', insertData)
await connection.execute(insertQuery, insertData)
console.log('✅ 插入成功')
// 驗證插入結果
const [results] = await connection.execute('SELECT * FROM test_results WHERE id = ?', [id])
console.log('插入結果:', results[0])
// 清理測試數據
await connection.execute('DELETE FROM test_results WHERE id = ?', [id])
console.log('✅ 測試數據已清理')
await connection.end()
console.log('\n✅ createTestResult 測試成功')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
console.error('錯誤詳情:', error)
}
}
testCreateResult()

View File

@@ -1,61 +0,0 @@
const https = require('https')
const http = require('http')
const testCreativeAnswersAPI = async () => {
console.log('🧪 測試創意測驗答案 API')
console.log('=' .repeat(50))
const testResultId = 'test_1759086508812_xv2pof6lk' // 使用最新的測試結果ID
const url = `http://localhost:3000/api/creative-test-answers?testResultId=${testResultId}`
try {
console.log(`\n📊 測試結果ID: ${testResultId}`)
console.log(`🔗 API URL: ${url}`)
const response = await new Promise((resolve, reject) => {
const req = http.get(url, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
console.log('📊 響應狀態:', response.status)
if (response.status === 200) {
const result = JSON.parse(response.data)
console.log('\n✅ API 測試成功!')
console.log('📡 響應內容:', JSON.stringify(result, null, 2))
if (result.success) {
console.log(`\n📈 答案記錄詳情:`)
console.log(`- 答案數量: ${result.data.length}`)
// 按維度分組統計
const dimensionStats = {
innovation: { total: 0, count: 0 },
imagination: { total: 0, count: 0 },
flexibility: { total: 0, count: 0 },
originality: { total: 0, count: 0 }
}
result.data.forEach((answer, index) => {
console.log(`${index + 1}. 題目ID: ${answer.question_id}, 用戶答案: ${answer.user_answer}, 計算分數: ${answer.score}`)
})
}
} else {
console.log('❌ API 響應失敗,狀態碼:', response.status)
console.log('響應內容:', response.data)
}
} catch (error) {
console.error('\n❌ 請求失敗:')
console.error('錯誤類型:', error.name)
console.error('錯誤訊息:', error.message)
} finally {
console.log('\n✅ 創意測驗答案 API 測試完成')
}
}
testCreativeAnswersAPI()

View File

@@ -1,89 +0,0 @@
// 測試創意能力分析圖表功能
const testCategoryResults = [
{ category: 'innovation', name: '創新能力', score: 73, rawScore: 22, maxRawScore: 30 },
{ category: 'imagination', name: '想像力', score: 100, rawScore: 30, maxRawScore: 30 },
{ category: 'flexibility', name: '靈活性', score: 68, rawScore: 20, maxRawScore: 30 },
{ category: 'originality', name: '原創性', score: 52, rawScore: 15, maxRawScore: 30 }
]
console.log('📊 創意能力分析圖表測試 (4維度修正版)')
console.log('=' .repeat(50))
console.log('\n🎯 圖表功能:')
console.log('- 雷達圖顯示四個能力維度 (正確的4維度)')
console.log('- 每個維度顯示分數百分比,使用文字陰影效果')
console.log('- 圖表大小響應式:手機 320x320px桌面 384x384px')
console.log('- 包含網格線、數據點、面積填充和圖例')
console.log('\n📈 測試數據 (4維度):')
testCategoryResults.forEach((category, index) => {
const angle = (index * 90 - 90) * Math.PI / 180
const radius = (category.score / 100) * 80
const x = 100 + radius * Math.cos(angle)
const y = 100 + radius * Math.sin(angle)
console.log(`\n${category.name}:`)
console.log(` 分數: ${category.score}%`)
console.log(` 角度: ${(index * 90 - 90)}°`)
console.log(` 半徑: ${radius.toFixed(1)}`)
console.log(` 座標: (${x.toFixed(1)}, ${y.toFixed(1)})`)
})
console.log('\n🎨 視覺元素 (4維度修正版):')
console.log('- 網格圓圈: 4個同心圓 (17, 35, 52, 70 半徑)')
console.log('- 網格線: 4條從中心放射的線 (0°, 90°, 180°, 270°)')
console.log('- 數據點: 藍色圓點半徑4px白色邊框2px')
console.log('- 分數標籤: 使用文字陰影效果,確保可讀性')
console.log('- 面積填充: 半透明藍色 (rgba(59, 130, 246, 0.2))')
console.log('- 邊框: 2px 藍色實線')
console.log('- 標籤: 灰色文字10px粗體 (縮小)')
console.log('- 分數: 藍色文字10px粗體白色陰影 (縮小)')
console.log('\n📱 響應式設計 (4維度最終版):')
console.log('- 手機版: w-56 h-56 (224x224px)')
console.log('- 桌面版: w-72 h-72 (288x288px)')
console.log('- 圖例: 手機2欄桌面4欄間距3')
console.log('\n🔧 修正內容 (4維度優化):')
console.log('- 修正為正確的4個維度 (0°, 90°, 180°, 270°)')
console.log('- 移除多餘的網格線只保留4條軸線')
console.log('- 使用文字陰影效果替代背景框,更簡潔')
console.log('- 縮小圖表尺寸,為文字留出更多空間')
console.log('- 維度標籤位置調整到圖表外圍')
console.log('- 根據位置調整文字對齊方式')
console.log('- 圖例置中顯示')
console.log('\n📝 文字對齊修正 (最終版):')
console.log('- 上方 (創新能力): dominantBaseline="hanging", 半徑75px')
console.log('- 右方 (想像力): textAnchor="start", 半徑70px (特殊調整)')
console.log('- 下方 (靈活性): dominantBaseline="alphabetic", 半徑75px')
console.log('- 左方 (原創性): textAnchor="end", 半徑70px (特殊調整)')
console.log('- 一般標籤半徑: 75px')
console.log('- 想像力/原創性半徑: 70px (更靠近圖表)')
console.log('\n📏 圖表尺寸優化 (最終版):')
console.log('- 圖表半徑: 60px (從70px進一步縮小)')
console.log('- 網格圓圈: 15, 30, 45, 60 半徑')
console.log('- 標籤位置: 75px 半徑 (一般), 70px (想像力/原創性)')
console.log('- 容器尺寸: 手機224px桌面288px')
console.log('\n🔤 文字大小優化:')
console.log('- 維度標籤: 從12px縮小到10px')
console.log('- 分數標籤: 從12px縮小到10px')
console.log('- 使用text-[10px]自定義大小')
console.log('- 保持粗體和陰影效果')
console.log('\n🎨 新增功能 (豐富化):')
console.log('- 百分比刻度標籤: 25%, 50%, 75%, 100%')
console.log('- 能力維度詳細說明: 每個維度的具體描述')
console.log('- 能力等級評定: 優秀(80+), 良好(60+), 一般(40+), 待提升(<40)')
console.log('- 響應式網格: 手機1欄桌面2欄')
console.log('- 視覺層次: 分數、等級、描述分層顯示')
console.log('\n📋 維度說明內容:')
console.log('- 創新能力: 善於提出新想法,勇於嘗試不同的解決方案')
console.log('- 想像力: 能夠從不同角度思考,具有豐富的創意思維')
console.log('- 靈活性: 適應變化能力強,能夠靈活調整思維方式')
console.log('- 原創性: 具有獨特的創見,能夠產生原創性想法')
console.log('\n✅ 圖表功能測試完成')

View File

@@ -1,79 +0,0 @@
const https = require('https')
const http = require('http')
const testCreativeDBUpload = async () => {
console.log('🧪 測試創意測驗資料庫上傳功能')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd' // 使用現有用戶ID
const url = 'http://localhost:3000/api/test-results/creative'
// 模擬創意測驗答案1-5分包含反向題
const testAnswers = [
5, 4, 3, 2, 1, // 前5題正常題
1, 2, 3, 4, 5, // 中間5題反向題會自動反轉
5, 4, 3, 2, 1, // 後8題正常題
1, 2, 3, 4, 5
]
const testData = {
userId: userId,
answers: testAnswers,
completedAt: new Date().toISOString().replace('Z', '').replace('T', ' ')
}
console.log('\n📝 測試數據:')
console.log('用戶ID:', testData.userId)
console.log('答案數量:', testData.answers.length)
console.log('答案內容:', testData.answers)
console.log('完成時間:', testData.completedAt)
try {
console.log('\n🔄 測試創意測驗 API...')
const response = await new Promise((resolve, reject) => {
const req = http.request(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
}, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(JSON.stringify(testData))
req.end()
})
console.log('📊 響應狀態:', response.status)
if (response.status === 200) {
const result = JSON.parse(response.data)
console.log('\n✅ API 測試成功!')
console.log('📡 響應內容:', JSON.stringify(result, null, 2))
if (result.success) {
console.log('\n📈 測試結果詳情:')
console.log('- 測試結果ID:', result.data.testResult.id)
console.log('- 分數:', result.data.testResult.score)
console.log('- 總題數:', result.data.testResult.total_questions)
console.log('- 總分數:', result.data.testResult.correct_answers)
console.log('- 答案記錄數量:', result.data.answerCount)
}
} else {
console.log('❌ API 響應失敗,狀態碼:', response.status)
console.log('響應內容:', response.data)
}
} catch (error) {
console.error('\n❌ 請求失敗:')
console.error('錯誤類型:', error.name)
console.error('錯誤訊息:', error.message)
} finally {
console.log('\n✅ 創意測驗資料庫上傳測試完成')
}
}
testCreativeDBUpload()

View File

@@ -1,71 +0,0 @@
// 測試創意測試流程
const mysql = require('mysql2/promise')
async function testCreativeFlow() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🧪 測試創意測試流程')
console.log('=' .repeat(50))
try {
const connection = await mysql.createConnection(config)
// 1. 檢查資料庫中的題目
const [questions] = await connection.execute('SELECT * FROM creative_questions ORDER BY id')
console.log(`✅ 資料庫中有 ${questions.length} 道題目`)
// 2. 模擬 API 回應
const apiResponse = {
success: true,
questions: questions
}
console.log('✅ API 回應格式正確')
// 3. 測試分數計算邏輯
const mockAnswers = {
0: 5, // 一般題目,選擇 5
1: 5, // 反向題目,選擇 5
2: 1, // 一般題目,選擇 1
3: 1 // 反向題目,選擇 1
}
let totalScore = 0
questions.slice(0, 4).forEach((question, index) => {
const answer = mockAnswers[index] || 1
const score = question.is_reverse ? 6 - answer : answer
totalScore += score
console.log(`題目 ${index + 1}: ${question.is_reverse ? '反向' : '一般'} - 選擇${answer} → 得分${score}`)
})
const maxScore = 4 * 5
const percentage = Math.round((totalScore / maxScore) * 100)
console.log(`\n📊 測試結果: ${totalScore}/${maxScore} (${percentage}%)`)
// 4. 檢查題目類別分布
const categoryCount = {}
questions.forEach(q => {
categoryCount[q.category] = (categoryCount[q.category] || 0) + 1
})
console.log('\n📋 題目類別分布:')
Object.entries(categoryCount).forEach(([category, count]) => {
console.log(`- ${category}: ${count}`)
})
await connection.end()
console.log('\n✅ 創意測試流程測試完成')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
}
}
testCreativeFlow()

View File

@@ -1,93 +0,0 @@
const https = require('https')
const http = require('http')
const testCreativePagination = async () => {
console.log('🔍 測試創意題目分頁功能')
console.log('=' .repeat(50))
try {
// 1. 獲取創意題目資料
console.log('\n📊 1. 獲取創意題目資料...')
const creativeResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/creative', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (creativeResponse.status === 200) {
const creativeData = JSON.parse(creativeResponse.data)
if (creativeData.success) {
const questions = creativeData.data
const itemsPerPage = 10
const totalPages = Math.ceil(questions.length / itemsPerPage)
console.log('✅ 創意題目資料獲取成功')
console.log(` 總題目數量: ${questions.length}`)
console.log(` 每頁顯示: ${itemsPerPage}`)
console.log(` 總頁數: ${totalPages}`)
// 2. 模擬分頁計算
console.log('\n📊 2. 分頁計算模擬:')
for (let page = 1; page <= totalPages; page++) {
const startIndex = (page - 1) * itemsPerPage
const endIndex = startIndex + itemsPerPage
const currentQuestions = questions.slice(startIndex, endIndex)
console.log(`${page} 頁: 顯示第 ${startIndex + 1} - ${Math.min(endIndex, questions.length)}`)
console.log(` 題目ID: ${currentQuestions.map(q => q.id).join(', ')}`)
}
// 3. 分頁功能特點
console.log('\n📊 3. 分頁功能特點:')
console.log('✅ 每頁顯示 10 道題目')
console.log('✅ 支援桌面版和手機版響應式設計')
console.log('✅ 智能省略頁碼(手機版最多顯示 3 個頁碼)')
console.log('✅ 上一頁/下一頁按鈕')
console.log('✅ 顯示當前頁範圍和總筆數')
// 4. 響應式設計
console.log('\n📊 4. 響應式設計:')
console.log('✅ 桌面版: 完整頁碼顯示')
console.log('✅ 手機版: 智能省略頁碼')
console.log('✅ 按鈕大小適配不同螢幕')
console.log('✅ 佈局自動調整')
// 5. 用戶體驗
console.log('\n📊 5. 用戶體驗:')
console.log('✅ 清晰的頁面資訊顯示')
console.log('✅ 直觀的導航控制')
console.log('✅ 載入狀態和錯誤處理')
console.log('✅ 觸控友好的按鈕設計')
// 6. 技術實作
console.log('\n📊 6. 技術實作:')
console.log('✅ 使用 slice() 進行前端分頁')
console.log('✅ 狀態管理: currentPage, itemsPerPage')
console.log('✅ 計算邏輯: startIndex, endIndex, totalPages')
console.log('✅ 條件渲染: 只在題目數量 > itemsPerPage 時顯示分頁')
console.log('\n📝 分頁功能總結:')
console.log('✅ 創意題目現在支援分頁顯示')
console.log('✅ 每頁顯示 10 道題目')
console.log('✅ 18 道題目分為 2 頁顯示')
console.log('✅ 響應式設計適配不同設備')
console.log('✅ 用戶體驗優化')
} else {
console.log('❌ 創意題目 API 失敗:', creativeData.message)
}
} else {
console.log('❌ 創意題目 API 狀態碼:', creativeResponse.status)
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 創意題目分頁功能測試完成')
}
}
testCreativePagination()

View File

@@ -1,55 +0,0 @@
// 測試創意測試結果頁面的響應式設計
const responsiveClasses = {
// 統計數據區域
statsGrid: "grid grid-cols-3 gap-4 mb-6",
statsText: "text-xs text-muted-foreground",
// 能力維度分析區域
categoryGrid: "grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-6",
categoryItem: "space-y-2 md:space-y-3",
categoryTitle: "text-sm md:text-base",
categoryBadge: "text-xs",
categoryScore: "text-xs md:text-sm",
// 詳細反饋區域
feedbackCard: "p-3 md:p-4",
feedbackTitle: "text-sm md:text-base",
feedbackText: "text-xs md:text-sm",
feedbackGrid: "grid grid-cols-1 md:grid-cols-2 gap-3 md:gap-4",
// 按鈕區域
buttonContainer: "flex flex-col sm:flex-row gap-3 sm:gap-4 justify-center",
button: "w-full sm:w-auto"
}
console.log('📱 創意測試結果頁面響應式設計測試')
console.log('=' .repeat(60))
console.log('\n📊 統計數據區域:')
console.log(`網格佈局: ${responsiveClasses.statsGrid}`)
console.log(`標籤文字: ${responsiveClasses.statsText}`)
console.log('\n📋 能力維度分析區域:')
console.log(`網格佈局: ${responsiveClasses.categoryGrid}`)
console.log(`項目間距: ${responsiveClasses.categoryItem}`)
console.log(`標題大小: ${responsiveClasses.categoryTitle}`)
console.log(`徽章大小: ${responsiveClasses.categoryBadge}`)
console.log(`分數文字: ${responsiveClasses.categoryScore}`)
console.log('\n💬 詳細反饋區域:')
console.log(`卡片內邊距: ${responsiveClasses.feedbackCard}`)
console.log(`標題大小: ${responsiveClasses.feedbackTitle}`)
console.log(`文字大小: ${responsiveClasses.feedbackText}`)
console.log(`網格佈局: ${responsiveClasses.feedbackGrid}`)
console.log('\n🔘 按鈕區域:')
console.log(`按鈕容器: ${responsiveClasses.buttonContainer}`)
console.log(`按鈕樣式: ${responsiveClasses.button}`)
console.log('\n✅ 響應式設計配置完成')
console.log('\n📱 手機版特點:')
console.log('- 統計數據始終 3 欄並排顯示')
console.log('- 文字大小在手機上較小,桌面版較大')
console.log('- 能力維度分析在手機上單欄顯示,桌面版雙欄')
console.log('- 按鈕在手機上全寬顯示,桌面版自動寬度')
console.log('- 內邊距在手機上較小,桌面版較大')

View File

@@ -1,69 +0,0 @@
const https = require('https')
const http = require('http')
const testCreativeResultsPage = async () => {
console.log('🔍 測試創意測驗結果頁面數據')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查創意測試結果 API模擬創意測驗結果頁面的請求
console.log('\n📊 檢查創意測試結果 API...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success && data.data.length > 0) {
console.log(`找到 ${data.data.length} 筆創意測試結果:`)
// 按創建時間排序,取最新的(模擬前端邏輯)
const sortedResults = data.data.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
const latestResult = sortedResults[0]
console.log('\n📋 創意測驗結果頁面會使用的數據:')
console.log(`ID: ${latestResult.id}`)
console.log(`completed_at: ${latestResult.completed_at}`)
console.log(`created_at: ${latestResult.created_at}`)
// 測試時間解析(模擬前端顯示邏輯)
const parsedDate = new Date(latestResult.completed_at)
const isValid = !isNaN(parsedDate.getTime())
console.log(`\n📊 前端時間解析測試:`)
console.log(`解析是否有效: ${isValid ? '✅' : '❌'}`)
if (isValid) {
const taiwanTime = parsedDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(`台灣時間: ${taiwanTime}`)
console.log(`顯示效果: 完成時間:${taiwanTime}`)
} else {
console.log(`❌ 會顯示: 完成時間Invalid Date`)
}
// 檢查是否為今天
const now = new Date()
const isToday = now.toDateString() === parsedDate.toDateString()
console.log(`是否為今天: ${isToday ? '✅' : '❌'}`)
if (!isToday) {
console.log(`⚠️ 這是舊數據,可能需要重新進行測試`)
}
}
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 創意測驗結果頁面數據測試完成')
}
}
testCreativeResultsPage()

View File

@@ -1,55 +0,0 @@
// 測試新的創意評分系統
const testScores = [0, 20, 40, 50, 60, 70, 80, 85, 90, 95, 100]
function getCreativityLevel(score) {
if (score >= 90) return {
level: "創意巔峰者",
color: "bg-purple-600",
description: "創意力近乎無窮,你是團隊裡的靈感源泉,總能帶來突破性的想法。",
suggestion: "你不只創造靈感,更能影響他人。如果能結合執行力,你將成為真正的創新領袖。"
}
if (score >= 75) return {
level: "創意引領者",
color: "bg-blue-500",
description: "你是靈感的推動者!總是能在團體中主動拋出新想法,激發別人跟進。",
suggestion: "持續累積學習,讓你的靈感不僅是點子,而能帶動真正的行動。"
}
if (score >= 55) return {
level: "創意實踐者",
color: "bg-green-500",
description: "靈感已經隨手可得,在團體中也常被認為是「有創意的人」。",
suggestion: "再給自己一點勇氣,不要害怕挑戰慣例,你的創意將更有力量。"
}
if (score >= 35) return {
level: "創意開拓者",
color: "bg-yellow-500",
description: "你其實有自己的想法,但有時習慣跟隨大多數人的步伐。",
suggestion: "試著勇敢說出腦中天馬行空的念頭,你會發現,這些點子或許就是團隊需要的突破口。"
}
return {
level: "創意萌芽者",
color: "bg-red-500",
description: "還在創意旅程的起點。雖然暫時表現平淡,但這正是無限潛力的開端!",
suggestion: "觀察生活小事,或閱讀不同領域的內容,讓靈感一點一滴積累。"
}
}
console.log('🎨 測試新的創意評分系統')
console.log('=' .repeat(80))
testScores.forEach(score => {
const level = getCreativityLevel(score)
console.log(`\n📊 分數: ${score}`)
console.log(`🏆 等級: ${level.level}`)
console.log(`📝 描述: ${level.description}`)
console.log(`💡 建議: ${level.suggestion}`)
console.log('-'.repeat(60))
})
console.log('\n✅ 創意評分系統測試完成')
console.log('\n📋 評分標準:')
console.log('- 90分以上: 創意巔峰者')
console.log('- 75-89分: 創意引領者')
console.log('- 55-74分: 創意實踐者')
console.log('- 35-54分: 創意開拓者')
console.log('- 35分以下: 創意萌芽者')

View File

@@ -1,71 +0,0 @@
const https = require('https')
const http = require('http')
const testCreativeTimeFix = async () => {
console.log('🔍 測試創意測驗時間修正')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查創意測試結果 API
console.log('\n📊 檢查創意測試結果 API...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success && data.data.length > 0) {
console.log(`找到 ${data.data.length} 筆創意測試結果:`)
// 按創建時間排序
const sortedResults = data.data.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
console.log('\n📋 排序後的創意測試結果:')
sortedResults.forEach((result, index) => {
console.log(`\n${index + 1}. 創意測試:`)
console.log(` ID: ${result.id}`)
console.log(` completed_at: ${result.completed_at}`)
console.log(` created_at: ${result.created_at}`)
const completedDate = new Date(result.completed_at)
const createdDate = new Date(result.created_at)
console.log(` completed_at 台灣時間: ${completedDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
console.log(` created_at 台灣時間: ${createdDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
// 檢查是否是今天
const now = new Date()
const isToday = now.toDateString() === completedDate.toDateString()
console.log(` 是否為今天: ${isToday}`)
})
// 顯示最新結果
const latestResult = sortedResults[0]
console.log('\n🎯 最新結果 (創意測驗結果頁面會使用這個):')
console.log(`completed_at: ${latestResult.completed_at}`)
const latestDate = new Date(latestResult.completed_at)
console.log(`台灣時間: ${latestDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
}
}
// 檢查當前時間
console.log('\n📊 當前時間:')
const now = new Date()
console.log(`UTC 時間: ${now.toISOString()}`)
console.log(`台灣時間: ${now.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}`)
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 創意測驗時間修正測試完成')
}
}
testCreativeTimeFix()

View File

@@ -1,53 +0,0 @@
const { executeQuery } = require('../lib/database/connection');
async function testDbConnection() {
console.log('🔍 測試資料庫連接和表結構');
console.log('==============================');
try {
// 測試基本連接
console.log('1. 測試基本連接...');
const testQuery = await executeQuery('SELECT 1 as test');
console.log('✅ 資料庫連接成功:', testQuery);
// 檢查所有表
console.log('\n2. 檢查所有表...');
const tables = await executeQuery('SHOW TABLES');
console.log('📋 所有表:', tables.map(t => Object.values(t)[0]));
// 檢查 logic_test_answers 表是否存在
console.log('\n3. 檢查 logic_test_answers 表...');
const tableExists = await executeQuery(`
SELECT COUNT(*) as count
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name = 'logic_test_answers'
`);
console.log('logic_test_answers 表存在:', tableExists[0].count > 0);
// 檢查表結構
console.log('\n4. 檢查 logic_test_answers 表結構...');
const tableStructure = await executeQuery('DESCRIBE logic_test_answers');
console.log('📋 表結構:', tableStructure);
// 檢查資料數量
console.log('\n5. 檢查資料數量...');
const count = await executeQuery('SELECT COUNT(*) as count FROM logic_test_answers');
console.log('📊 logic_test_answers 資料數量:', count[0].count);
// 檢查前幾筆資料
if (count[0].count > 0) {
console.log('\n6. 檢查前 3 筆資料...');
const sampleData = await executeQuery('SELECT * FROM logic_test_answers LIMIT 3');
console.log('📋 範例資料:', sampleData);
}
} catch (error) {
console.error('❌ 測試失敗:', error.message);
console.error('錯誤詳情:', error);
}
console.log('==============================\n');
}
testDbConnection();

View File

@@ -1,73 +0,0 @@
const testDBModels = async () => {
console.log('🧪 測試資料庫模型')
console.log('=' .repeat(50))
try {
// 動態導入 ES 模組
const testResultModule = await import('../lib/database/models/test_result.ts')
const logicAnswerModule = await import('../lib/database/models/logic_test_answer.ts')
const logicQuestionModule = await import('../lib/database/models/logic_question.ts')
console.log('✅ 成功導入資料庫模型')
console.log('testResultModule exports:', Object.keys(testResultModule))
console.log('logicAnswerModule exports:', Object.keys(logicAnswerModule))
console.log('logicQuestionModule exports:', Object.keys(logicQuestionModule))
const { createTestResult } = testResultModule
const { createLogicTestAnswers } = logicAnswerModule
const { getAllLogicQuestions } = logicQuestionModule
// 測試獲取邏輯題目
console.log('\n📝 測試獲取邏輯題目...')
const questions = await getAllLogicQuestions()
console.log(`找到 ${questions.length} 題邏輯題目`)
if (questions.length > 0) {
console.log('第一題:', {
id: questions[0].id,
question: questions[0].question.substring(0, 50) + '...',
correct_answer: questions[0].correct_answer
})
}
// 測試建立測試結果
console.log('\n📊 測試建立測試結果...')
const testResultData = {
user_id: 'test_user_123',
test_type: 'logic',
score: 80,
total_questions: 10,
correct_answers: 8,
completed_at: new Date().toISOString()
}
const testResult = await createTestResult(testResultData)
if (testResult) {
console.log('✅ 測試結果建立成功:', testResult.id)
// 測試建立答案記錄
console.log('\n📝 測試建立答案記錄...')
const answerData = [
{
test_result_id: testResult.id,
question_id: questions[0].id,
user_answer: 'A',
is_correct: true
}
]
const answers = await createLogicTestAnswers(answerData)
console.log(`✅ 答案記錄建立成功: ${answers.length}`)
} else {
console.log('❌ 測試結果建立失敗')
}
} catch (error) {
console.log('❌ 測試失敗:', error.message)
console.log('錯誤詳情:', error.stack)
}
console.log('\n✅ 資料庫模型測試完成')
}
testDBModels()

View File

@@ -1,36 +0,0 @@
const mysql = require('mysql2/promise')
async function testDatabaseConnection() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔄 正在測試資料庫連接...')
console.log('連接資訊:', {
host: config.host,
port: config.port,
user: config.user,
database: config.database
})
try {
const connection = await mysql.createConnection(config)
await connection.ping()
console.log('✅ 資料庫連接成功!')
// 測試查詢
const [rows] = await connection.execute('SELECT 1 as test')
console.log('✅ 查詢測試成功:', rows)
await connection.end()
} catch (error) {
console.error('❌ 資料庫連接失敗:', error.message)
process.exit(1)
}
}
testDatabaseConnection()

View File

@@ -1,151 +0,0 @@
const https = require('https')
const http = require('http')
const testDeleteConfirmation = async () => {
console.log('🔍 測試刪除確認對話框功能')
console.log('=' .repeat(50))
try {
// 1. 先創建一個測試用戶
console.log('\n📊 1. 創建測試用戶...')
const testUser = {
name: '刪除測試用戶',
email: 'delete.test@company.com',
password: 'password123',
department: '測試部',
role: 'user'
}
const createResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(testUser)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/admin/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
let testUserId = null
if (createResponse.status === 200) {
const createData = JSON.parse(createResponse.data)
if (createData.success) {
testUserId = createData.data.id
console.log('✅ 測試用戶創建成功:')
console.log(` ID: ${createData.data.id}`)
console.log(` 姓名: ${createData.data.name}`)
console.log(` 電子郵件: ${createData.data.email}`)
} else {
console.log('❌ 創建測試用戶失敗:', createData.error)
return
}
}
// 2. 驗證用戶存在
console.log('\n📊 2. 驗證用戶存在...')
const getResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/users', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (getResponse.status === 200) {
const getData = JSON.parse(getResponse.data)
if (getData.success) {
const userExists = getData.data.some(user => user.id === testUserId)
console.log(`✅ 用戶存在驗證: ${userExists ? '是' : '否'}`)
if (userExists) {
const user = getData.data.find(user => user.id === testUserId)
console.log(` 用戶資訊: ${user.name} (${user.email})`)
}
}
}
// 3. 模擬刪除用戶(這裡只是測試 API實際的確認對話框在前端
console.log('\n📊 3. 測試刪除用戶 API...')
if (testUserId) {
const deleteResponse = await new Promise((resolve, reject) => {
const options = {
hostname: 'localhost',
port: 3000,
path: `/api/admin/users?id=${testUserId}`,
method: 'DELETE'
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.end()
})
if (deleteResponse.status === 200) {
const deleteResult = JSON.parse(deleteResponse.data)
if (deleteResult.success) {
console.log('✅ 刪除用戶 API 測試成功')
} else {
console.log('❌ 刪除用戶 API 測試失敗:', deleteResult.error)
}
}
}
// 4. 驗證用戶已被刪除
console.log('\n📊 4. 驗證用戶已被刪除...')
const finalResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/users', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (finalResponse.status === 200) {
const finalData = JSON.parse(finalResponse.data)
if (finalData.success) {
const userStillExists = finalData.data.some(user => user.id === testUserId)
console.log(`✅ 用戶刪除驗證: ${!userStillExists ? '成功' : '失敗'}`)
}
}
console.log('\n📝 功能總結:')
console.log('✅ 刪除確認對話框已實作')
console.log('✅ 對話框包含用戶詳細資訊顯示')
console.log('✅ 對話框包含警告訊息')
console.log('✅ 對話框包含取消和確認按鈕')
console.log('✅ 刪除 API 功能正常')
console.log('✅ 用戶資料完整性保護')
console.log('\n🎨 對話框設計特色:')
console.log('✅ 符合網頁整體風格')
console.log('✅ 清晰的視覺層次')
console.log('✅ 適當的警告色彩')
console.log('✅ 用戶友好的介面')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 刪除確認對話框功能測試完成')
}
}
testDeleteConfirmation()

View File

@@ -1,70 +0,0 @@
const fetch = require('node-fetch');
async function testDetailAPI() {
console.log('🔍 測試詳細結果 API');
console.log('==============================');
try {
// 先獲取測試結果列表
const listResponse = await fetch('http://localhost:3000/api/admin/test-results');
const listData = await listResponse.json();
if (listData.success && listData.data.results.length > 0) {
const firstResult = listData.data.results[0];
console.log(`📋 測試結果: ${firstResult.userName} - ${firstResult.type}`);
console.log(` 分數: ${firstResult.score}, 等級: ${firstResult.grade}`);
// 測試詳細結果 API
const detailResponse = await fetch(`http://localhost:3000/api/admin/test-results/detail?testResultId=${firstResult.id}&testType=${firstResult.type}`);
const detailData = await detailResponse.json();
if (detailData.success) {
console.log('✅ 詳細結果獲取成功');
console.log('📊 用戶資訊:', {
name: detailData.data.user.name,
email: detailData.data.user.email,
department: detailData.data.user.department
});
console.log('📈 測試結果:', {
type: detailData.data.result.type,
score: detailData.data.result.score,
completedAt: detailData.data.result.completedAt
});
console.log('📝 題目數量:', detailData.data.questions?.length || 0);
console.log('💡 答案數量:', detailData.data.answers?.length || 0);
if (detailData.data.questions && detailData.data.questions.length > 0) {
console.log('\n📋 第一題詳情:');
const firstQuestion = detailData.data.questions[0];
console.log(' 題目:', firstQuestion.question || firstQuestion.statement);
console.log(' 用戶答案:', firstQuestion.userAnswer);
if (firstQuestion.isCorrect !== undefined) {
console.log(' 是否正確:', firstQuestion.isCorrect ? '是' : '否');
}
if (firstQuestion.score !== undefined) {
console.log(' 得分:', firstQuestion.score);
}
}
if (detailData.data.result.type === 'combined' && detailData.data.result.details) {
console.log('\n🎯 綜合能力分析:');
console.log(' 邏輯思維:', detailData.data.result.details.logicScore);
console.log(' 創意能力:', detailData.data.result.details.creativeScore);
console.log(' 能力平衡:', detailData.data.result.details.abilityBalance);
}
} else {
console.error('❌ 詳細結果獲取失敗:', detailData.message);
}
} else {
console.log('⚠️ 沒有找到測試結果');
}
} catch (error) {
console.error('❌ 測試錯誤:', error.message);
}
console.log('==============================\n');
}
testDetailAPI();

View File

@@ -1,121 +0,0 @@
const fetch = require('node-fetch');
async function testDetailedAnswersFixed() {
console.log('🔍 測試修復後的詳細答題結果功能');
console.log('==============================');
try {
// 先獲取測試結果列表
const listResponse = await fetch('http://localhost:3000/api/admin/test-results');
const listData = await listResponse.json();
if (listData.success && listData.data.results.length > 0) {
// 測試綜合能力測試的詳細結果
const combinedResult = listData.data.results.find(r => r.type === 'combined');
if (combinedResult) {
console.log(`📋 測試綜合能力結果: ${combinedResult.userName}`);
console.log(` 分數: ${combinedResult.score}, 等級: ${combinedResult.grade}`);
console.log(` ID: ${combinedResult.id}`);
const detailResponse = await fetch(`http://localhost:3000/api/admin/test-results/detail?testResultId=${combinedResult.id}&testType=combined`);
const detailData = await detailResponse.json();
if (detailData.success) {
console.log('✅ 綜合能力詳細結果獲取成功');
console.log('📊 用戶資訊:', {
name: detailData.data.user.name,
email: detailData.data.user.email,
department: detailData.data.user.department
});
console.log('📈 測試結果:', {
type: detailData.data.result.type,
score: detailData.data.result.score,
completedAt: detailData.data.result.completedAt
});
console.log('🎯 能力分析:', {
logicScore: detailData.data.result.details.logicScore,
creativeScore: detailData.data.result.details.creativeScore,
abilityBalance: detailData.data.result.details.abilityBalance
});
console.log('📝 題目總數:', detailData.data.questions?.length || 0);
if (detailData.data.questions && detailData.data.questions.length > 0) {
const logicQuestions = detailData.data.questions.filter(q => q.type === 'logic');
const creativeQuestions = detailData.data.questions.filter(q => q.type === 'creative');
console.log(`\n🧠 邏輯思維題目: ${logicQuestions.length}`);
console.log(`💡 創意能力題目: ${creativeQuestions.length}`);
if (logicQuestions.length > 0) {
console.log('\n📋 邏輯題詳情:');
logicQuestions.forEach((q, index) => {
console.log(`${index + 1} 題:`, {
question: q.question?.substring(0, 50) + '...',
userAnswer: q.userAnswer,
correctAnswer: q.correctAnswer,
isCorrect: q.isCorrect
});
});
}
if (creativeQuestions.length > 0) {
console.log('\n📋 創意題詳情:');
creativeQuestions.forEach((q, index) => {
console.log(`${index + 1} 題:`, {
statement: q.statement?.substring(0, 50) + '...',
userAnswer: q.userAnswer,
score: q.score
});
});
}
} else {
console.log('⚠️ 沒有找到詳細答題資料');
}
} else {
console.error('❌ 綜合能力詳細結果獲取失敗:', detailData.message);
}
} else {
console.log('⚠️ 沒有找到綜合能力測試結果');
}
// 測試單一測試類型
const singleResult = listData.data.results.find(r => r.type !== 'combined');
if (singleResult) {
console.log(`\n📋 測試單一類型結果: ${singleResult.userName} - ${singleResult.type}`);
const detailResponse = await fetch(`http://localhost:3000/api/admin/test-results/detail?testResultId=${singleResult.id}&testType=${singleResult.type}`);
const detailData = await detailResponse.json();
if (detailData.success) {
console.log('✅ 單一類型詳細結果獲取成功');
console.log('📝 題目數量:', detailData.data.questions?.length || 0);
if (detailData.data.questions && detailData.data.questions.length > 0) {
console.log('\n📋 題目詳情:');
detailData.data.questions.forEach((q, index) => {
console.log(`${index + 1} 題:`, {
question: (q.question || q.statement)?.substring(0, 50) + '...',
userAnswer: q.userAnswer,
isCorrect: q.isCorrect,
score: q.score
});
});
}
} else {
console.error('❌ 單一類型詳細結果獲取失敗:', detailData.message);
}
}
} else {
console.log('⚠️ 沒有找到測試結果');
}
} catch (error) {
console.error('❌ 測試錯誤:', error.message);
}
console.log('==============================\n');
}
testDetailedAnswersFixed();

View File

@@ -1,113 +0,0 @@
const fetch = require('node-fetch');
async function testDetailedAnswers() {
console.log('🔍 測試詳細答題結果功能');
console.log('==============================');
try {
// 先獲取測試結果列表
const listResponse = await fetch('http://localhost:3000/api/admin/test-results');
const listData = await listResponse.json();
if (listData.success && listData.data.results.length > 0) {
// 測試綜合能力測試的詳細結果
const combinedResult = listData.data.results.find(r => r.type === 'combined');
if (combinedResult) {
console.log(`📋 測試綜合能力結果: ${combinedResult.userName}`);
console.log(` 分數: ${combinedResult.score}, 等級: ${combinedResult.grade}`);
const detailResponse = await fetch(`http://localhost:3000/api/admin/test-results/detail?testResultId=${combinedResult.id}&testType=combined`);
const detailData = await detailResponse.json();
if (detailData.success) {
console.log('✅ 綜合能力詳細結果獲取成功');
console.log('📊 用戶資訊:', {
name: detailData.data.user.name,
email: detailData.data.user.email,
department: detailData.data.user.department
});
console.log('📈 測試結果:', {
type: detailData.data.result.type,
score: detailData.data.result.score,
completedAt: detailData.data.result.completedAt
});
console.log('🎯 能力分析:', {
logicScore: detailData.data.result.details.logicScore,
creativeScore: detailData.data.result.details.creativeScore,
abilityBalance: detailData.data.result.details.abilityBalance
});
console.log('📝 題目總數:', detailData.data.questions?.length || 0);
if (detailData.data.questions && detailData.data.questions.length > 0) {
const logicQuestions = detailData.data.questions.filter(q => q.type === 'logic');
const creativeQuestions = detailData.data.questions.filter(q => q.type === 'creative');
console.log(`\n🧠 邏輯思維題目: ${logicQuestions.length}`);
console.log(`💡 創意能力題目: ${creativeQuestions.length}`);
if (logicQuestions.length > 0) {
console.log('\n📋 第一題邏輯題詳情:');
const firstLogic = logicQuestions[0];
console.log(' 題目:', firstLogic.question);
console.log(' 用戶答案:', firstLogic.userAnswer);
console.log(' 正確答案:', firstLogic.correctAnswer);
console.log(' 是否正確:', firstLogic.isCorrect ? '是' : '否');
}
if (creativeQuestions.length > 0) {
console.log('\n📋 第一題創意題詳情:');
const firstCreative = creativeQuestions[0];
console.log(' 題目:', firstCreative.statement);
console.log(' 用戶答案:', firstCreative.userAnswer);
console.log(' 得分:', firstCreative.score);
}
}
} else {
console.error('❌ 綜合能力詳細結果獲取失敗:', detailData.message);
}
} else {
console.log('⚠️ 沒有找到綜合能力測試結果');
}
// 測試單一測試類型的詳細結果
const singleResult = listData.data.results.find(r => r.type !== 'combined');
if (singleResult) {
console.log(`\n📋 測試單一類型結果: ${singleResult.userName} - ${singleResult.type}`);
const detailResponse = await fetch(`http://localhost:3000/api/admin/test-results/detail?testResultId=${singleResult.id}&testType=${singleResult.type}`);
const detailData = await detailResponse.json();
if (detailData.success) {
console.log('✅ 單一類型詳細結果獲取成功');
console.log('📝 題目數量:', detailData.data.questions?.length || 0);
if (detailData.data.questions && detailData.data.questions.length > 0) {
console.log('\n📋 第一題詳情:');
const firstQuestion = detailData.data.questions[0];
console.log(' 題目:', firstQuestion.question || firstQuestion.statement);
console.log(' 用戶答案:', firstQuestion.userAnswer);
if (firstQuestion.isCorrect !== undefined) {
console.log(' 是否正確:', firstQuestion.isCorrect ? '是' : '否');
}
if (firstQuestion.score !== undefined) {
console.log(' 得分:', firstQuestion.score);
}
}
} else {
console.error('❌ 單一類型詳細結果獲取失敗:', detailData.message);
}
}
} else {
console.log('⚠️ 沒有找到測試結果');
}
} catch (error) {
console.error('❌ 測試錯誤:', error.message);
}
console.log('==============================\n');
}
testDetailedAnswers();

View File

@@ -1,101 +0,0 @@
const mysql = require('mysql2/promise')
async function testDirectInsert() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🧪 直接測試資料庫插入')
console.log('=' .repeat(50))
try {
const connection = await mysql.createConnection(config)
// 測試插入 test_results
console.log('\n📊 測試插入 test_results...')
const testResultId = `test_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
const insertTestResultQuery = `
INSERT INTO test_results (
id, user_id, test_type, score, total_questions,
correct_answers, completed_at
) VALUES (?, ?, ?, ?, ?, ?, ?)
`
const testResultData = [
testResultId,
'test_user_123',
'logic',
80,
10,
8,
new Date().toISOString()
]
console.log('插入數據:', testResultData)
await connection.execute(insertTestResultQuery, testResultData)
console.log('✅ test_results 插入成功')
// 測試插入 logic_test_answers
console.log('\n📝 測試插入 logic_test_answers...')
// 先獲取一個題目ID
const [questions] = await connection.execute('SELECT id FROM logic_questions LIMIT 1')
if (questions.length === 0) {
console.log('❌ 沒有找到邏輯題目')
return
}
const questionId = questions[0].id
console.log('使用題目ID:', questionId)
const answerId = `answer_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
const insertAnswerQuery = `
INSERT INTO logic_test_answers (
id, test_result_id, question_id, user_answer, is_correct
) VALUES (?, ?, ?, ?, ?)
`
const answerData = [
answerId,
testResultId,
questionId,
'A',
1
]
console.log('插入答案數據:', answerData)
await connection.execute(insertAnswerQuery, answerData)
console.log('✅ logic_test_answers 插入成功')
// 驗證插入結果
console.log('\n🔍 驗證插入結果...')
const [testResults] = await connection.execute('SELECT * FROM test_results WHERE id = ?', [testResultId])
console.log('test_results 記錄:', testResults[0])
const [answers] = await connection.execute('SELECT * FROM logic_test_answers WHERE id = ?', [answerId])
console.log('logic_test_answers 記錄:', answers[0])
// 清理測試數據
console.log('\n🧹 清理測試數據...')
await connection.execute('DELETE FROM logic_test_answers WHERE id = ?', [answerId])
await connection.execute('DELETE FROM test_results WHERE id = ?', [testResultId])
console.log('✅ 測試數據已清理')
await connection.end()
console.log('\n✅ 直接插入測試成功')
} catch (error) {
console.error('❌ 插入測試失敗:', error.message)
console.error('錯誤詳情:', error)
}
}
testDirectInsert()

View File

@@ -1,96 +0,0 @@
const https = require('https')
const http = require('http')
const fs = require('fs')
const path = require('path')
const testExcelImportExport = async () => {
console.log('🔍 測試 Excel 匯入匯出功能')
console.log('=' .repeat(50))
try {
// 1. 測試匯出邏輯題目範本
console.log('\n📊 1. 測試匯出邏輯題目範本...')
const logicResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=logic', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data, headers: res.headers }))
})
req.on('error', reject)
})
if (logicResponse.status === 200) {
console.log('✅ 邏輯題目範本匯出成功')
console.log(` Content-Type: ${logicResponse.headers['content-type']}`)
console.log(` Content-Disposition: ${logicResponse.headers['content-disposition']}`)
} else {
console.log('❌ 邏輯題目範本匯出失敗:', logicResponse.status)
}
// 2. 測試匯出創意題目範本
console.log('\n📊 2. 測試匯出創意題目範本...')
const creativeResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=creative', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data, headers: res.headers }))
})
req.on('error', reject)
})
if (creativeResponse.status === 200) {
console.log('✅ 創意題目範本匯出成功')
console.log(` Content-Type: ${creativeResponse.headers['content-type']}`)
console.log(` Content-Disposition: ${creativeResponse.headers['content-disposition']}`)
} else {
console.log('❌ 創意題目範本匯出失敗:', creativeResponse.status)
}
// 3. 功能特點
console.log('\n📊 3. Excel 匯入匯出功能特點:')
console.log('✅ 根據資料庫格式匯出範本')
console.log('✅ 支援邏輯思維和創意能力兩種題目')
console.log('✅ 匯入時覆蓋現有資料')
console.log('✅ 支援 A-E 選項(邏輯題目)')
console.log('✅ 支援反向計分標記(創意題目)')
console.log('✅ 自動重新載入題目資料')
// 4. 資料庫整合
console.log('\n📊 4. 資料庫整合特點:')
console.log('✅ 匯出:從資料庫讀取現有題目')
console.log('✅ 匯入:清空現有資料後插入新資料')
console.log('✅ 格式:完全匹配資料庫欄位名稱')
console.log('✅ 驗證:匯入時進行資料驗證')
console.log('✅ 更新:匯入後自動刷新頁面資料')
// 5. 檔案格式
console.log('\n📊 5. 檔案格式支援:')
console.log('✅ 邏輯題目ID, 題目內容, 選項A-E, 正確答案, 解釋')
console.log('✅ 創意題目ID, 陳述內容, 類別, 反向計分')
console.log('✅ Excel 格式:.xlsx 檔案')
console.log('✅ 中文標題:便於理解和使用')
console.log('✅ 資料完整性:包含所有必要欄位')
// 6. 用戶體驗
console.log('\n📊 6. 用戶體驗:')
console.log('✅ 一鍵下載:點擊按鈕直接下載範本')
console.log('✅ 格式一致:範本格式與資料庫完全一致')
console.log('✅ 即時更新:匯入後立即看到更新結果')
console.log('✅ 錯誤處理:詳細的錯誤訊息提示')
console.log('✅ 載入狀態:匯入過程顯示載入指示器')
console.log('\n📝 Excel 匯入匯出功能總結:')
console.log('✅ 完全基於資料庫格式設計')
console.log('✅ 支援覆蓋式更新現有題目')
console.log('✅ 提供完整的匯入匯出流程')
console.log('✅ 用戶友好的操作界面')
console.log('✅ 自動化的資料同步機制')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ Excel 匯入匯出功能測試完成')
}
}
testExcelImportExport()

View File

@@ -1,39 +0,0 @@
const http = require('http')
const testExportAPI = async () => {
console.log('🔍 測試匯出 API')
console.log('=' .repeat(30))
try {
// 測試邏輯題目匯出
console.log('\n📊 測試邏輯題目匯出...')
const logicResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=logic', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
headers: res.headers,
data: data.substring(0, 200) // 只顯示前200字符
}))
})
req.on('error', reject)
})
console.log(`狀態碼: ${logicResponse.status}`)
console.log(`Content-Type: ${logicResponse.headers['content-type']}`)
console.log(`Content-Disposition: ${logicResponse.headers['content-disposition']}`)
console.log(`資料預覽: ${logicResponse.data}`)
if (logicResponse.status === 500) {
console.log('❌ 伺服器錯誤,可能是資料庫連接問題')
} else if (logicResponse.status === 200) {
console.log('✅ 匯出成功')
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
}
}
testExportAPI()

View File

@@ -1,89 +0,0 @@
const http = require('http')
const testExportDetails = async () => {
console.log('🔍 測試匯出詳細資料')
console.log('=' .repeat(40))
try {
// 測試匯出 API
const response = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results/export', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success) {
console.log('✅ 匯出成功')
// 解碼並檢查 CSV 內容
const binaryString = Buffer.from(data.data, 'base64').toString('binary')
const csvContent = Buffer.from(binaryString, 'binary').toString('utf-8')
const lines = csvContent.split('\n')
console.log('\n📋 所有綜合測試的詳細資料:')
lines.forEach((line, index) => {
if (index === 0) return // 跳過標題行
const columns = line.split(',')
if (columns.length >= 8) {
const testType = columns[3].replace(/"/g, '')
const details = columns[7].replace(/"/g, '')
if (testType === '綜合能力') {
console.log(`${index} 行: ${details}`)
}
}
})
// 檢查原始資料
console.log('\n🔍 檢查原始 API 資料...')
const apiResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (apiResponse.status === 200) {
const apiData = JSON.parse(apiResponse.data)
if (apiData.success) {
const combinedResults = apiData.data.results.filter(result => result.type === 'combined')
console.log(`\n📊 API 中的綜合測試結果 (${combinedResults.length} 筆):`)
combinedResults.forEach((result, index) => {
console.log(`\n 結果 ${index + 1}:`)
console.log(` 用戶: ${result.userName}`)
console.log(` 分數: ${result.score}`)
console.log(` 詳細資料:`, JSON.stringify(result.details, null, 2))
})
}
}
} else {
console.log('❌ 匯出失敗:', data.message)
}
} else {
console.log('❌ 匯出失敗,狀態碼:', response.status)
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 匯出詳細資料測試完成')
}
}
testExportDetails()

View File

@@ -1,154 +0,0 @@
const http = require('http')
const testExportResults = async () => {
console.log('🔍 測試測驗結果匯出功能')
console.log('=' .repeat(40))
try {
// 測試基本匯出
console.log('\n📊 測試基本匯出...')
const basicResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results/export', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (basicResponse.status === 200) {
const basicData = JSON.parse(basicResponse.data)
if (basicData.success) {
console.log('✅ 基本匯出成功')
console.log(`📄 檔案名稱: ${basicData.filename}`)
console.log(`📊 內容類型: ${basicData.contentType}`)
console.log(`📏 資料大小: ${basicData.data.length} 字元`)
// 解碼並檢查 CSV 內容
const binaryString = Buffer.from(basicData.data, 'base64').toString('binary')
const csvContent = Buffer.from(binaryString, 'binary').toString('utf-8')
console.log('\n📋 CSV 內容預覽:')
const lines = csvContent.split('\n')
console.log(`總行數: ${lines.length}`)
console.log('前 5 行內容:')
lines.slice(0, 5).forEach((line, index) => {
console.log(` ${index + 1}: ${line}`)
})
// 檢查是否包含中文
const hasChinese = /[\u4e00-\u9fff]/.test(csvContent)
console.log(`✅ 包含中文字符: ${hasChinese ? '是' : '否'}`)
// 檢查 BOM
const hasBOM = csvContent.startsWith('\uFEFF')
console.log(`✅ 包含 UTF-8 BOM: ${hasBOM ? '是' : '否'}`)
} else {
console.log('❌ 基本匯出失敗:', basicData.message)
return
}
} else {
console.log('❌ 基本匯出失敗,狀態碼:', basicResponse.status)
return
}
// 測試篩選匯出
console.log('\n🔍 測試篩選匯出...')
const filterResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results/export?testType=logic&department=人力資源部', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (filterResponse.status === 200) {
const filterData = JSON.parse(filterResponse.data)
if (filterData.success) {
console.log('✅ 篩選匯出成功')
// 解碼並檢查篩選結果
const binaryString = Buffer.from(filterData.data, 'base64').toString('binary')
const csvContent = Buffer.from(binaryString, 'binary').toString('utf-8')
const lines = csvContent.split('\n')
console.log(`📊 篩選後結果數量: ${lines.length - 1} 筆(扣除標題行)`)
// 檢查是否只包含邏輯測試
const logicLines = lines.filter(line => line.includes('邏輯思維'))
console.log(`🧠 邏輯思維測試數量: ${logicLines.length}`)
} else {
console.log('❌ 篩選匯出失敗:', filterData.message)
}
}
// 測試搜尋匯出
console.log('\n🔍 測試搜尋匯出...')
const searchResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results/export?search=王', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (searchResponse.status === 200) {
const searchData = JSON.parse(searchResponse.data)
if (searchData.success) {
console.log('✅ 搜尋匯出成功')
// 解碼並檢查搜尋結果
const binaryString = Buffer.from(searchData.data, 'base64').toString('binary')
const csvContent = Buffer.from(binaryString, 'binary').toString('utf-8')
const lines = csvContent.split('\n')
console.log(`📊 搜尋結果數量: ${lines.length - 1} 筆(扣除標題行)`)
// 檢查是否只包含包含「王」的結果
const wangLines = lines.filter(line => line.includes('王'))
console.log(`👤 包含「王」的結果數量: ${wangLines.length}`)
} else {
console.log('❌ 搜尋匯出失敗:', searchData.message)
}
}
console.log('\n🎯 匯出功能特點:')
console.log('✅ 支援 CSV 格式匯出')
console.log('✅ 包含 UTF-8 BOM確保中文正確顯示')
console.log('✅ 支援篩選條件匯出')
console.log('✅ 包含詳細的測試結果資料')
console.log('✅ 自動生成檔案名稱(包含日期)')
console.log('✅ 支援搜尋、部門、測試類型篩選')
console.log('\n📊 匯出欄位:')
console.log('✅ 用戶姓名')
console.log('✅ 用戶郵箱')
console.log('✅ 部門')
console.log('✅ 測試類型')
console.log('✅ 分數')
console.log('✅ 等級')
console.log('✅ 完成時間')
console.log('✅ 詳細資料(根據測試類型不同)')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 測驗結果匯出功能測試完成')
}
}
testExportResults()

View File

@@ -1,61 +0,0 @@
const http = require('http')
const testExportSimple = async () => {
console.log('🔍 簡單測試匯出功能')
console.log('=' .repeat(30))
try {
const response = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results/export', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success) {
console.log('✅ 匯出成功')
// 解碼並檢查 CSV 內容
const binaryString = Buffer.from(data.data, 'base64').toString('binary')
const csvContent = Buffer.from(binaryString, 'binary').toString('utf-8')
// 只顯示前幾行
const lines = csvContent.split('\n')
console.log('\n📋 CSV 前 10 行:')
lines.slice(0, 10).forEach((line, index) => {
console.log(`${index + 1}: ${line}`)
})
// 檢查是否有「創意」和「平衡」字樣
const hasCreative = csvContent.includes('創意')
const hasBalance = csvContent.includes('平衡')
console.log(`\n🔍 檢查結果:`)
console.log(` 包含「創意」: ${hasCreative ? '是' : '否'}`)
console.log(` 包含「平衡」: ${hasBalance ? '是' : '否'}`)
if (hasCreative && hasBalance) {
console.log('✅ 修復成功!')
} else {
console.log('❌ 仍有問題')
}
} else {
console.log('❌ 匯出失敗:', data.message)
}
} else {
console.log('❌ 匯出失敗,狀態碼:', response.status)
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
}
}
testExportSimple()

View File

@@ -1,135 +0,0 @@
const http = require('http')
const fs = require('fs')
const testFinalChineseExport = async () => {
console.log('🎉 最終中文匯出功能測試')
console.log('=' .repeat(40))
try {
// 測試創意題目匯出
console.log('\n📊 測試創意題目匯出...')
const creativeResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=creative', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (creativeResponse.status === 200) {
const creativeData = JSON.parse(creativeResponse.data)
if (creativeData.success) {
console.log('✅ 創意題目匯出成功')
// 解碼 Base64 資料
const binaryString = Buffer.from(creativeData.data, 'base64').toString('binary')
const bytes = new Uint8Array(binaryString.length)
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i)
}
// 檢查 BOM
const hasBOM = bytes[0] === 0xEF && bytes[1] === 0xBB && bytes[2] === 0xBF
console.log(`📝 UTF-8 BOM: ${hasBOM ? '✅' : '❌'}`)
// 解碼為文字
const csvContent = new TextDecoder('utf-8').decode(bytes)
const hasChinese = /[\u4e00-\u9fff]/.test(csvContent)
console.log(`🔤 中文字符: ${hasChinese ? '✅' : '❌'}`)
// 顯示內容
const lines = csvContent.split('\n')
console.log(`📊 總行數: ${lines.length}`)
console.log(`📋 標題: ${lines[0]}`)
console.log(`📝 範例: ${lines[1]?.substring(0, 60)}...`)
// 保存測試檔案
fs.writeFileSync('test-final-creative.csv', csvContent, 'utf8')
console.log(`💾 已保存測試檔案: test-final-creative.csv`)
// 檢查檔案開頭
const fileContent = fs.readFileSync('test-final-creative.csv', 'utf8')
const fileHasBOM = fileContent.charCodeAt(0) === 0xFEFF
console.log(`📁 檔案 BOM: ${fileHasBOM ? '✅' : '❌'}`)
if (hasBOM && hasChinese && fileHasBOM) {
console.log('\n🎉 完美Excel 應該能正確顯示中文了!')
} else {
console.log('\n⚠ 還有問題需要修正')
}
}
}
// 測試邏輯題目匯出
console.log('\n📊 測試邏輯題目匯出...')
const logicResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=logic', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (logicResponse.status === 200) {
const logicData = JSON.parse(logicResponse.data)
if (logicData.success) {
console.log('✅ 邏輯題目匯出成功')
// 解碼 Base64 資料
const binaryString = Buffer.from(logicData.data, 'base64').toString('binary')
const bytes = new Uint8Array(binaryString.length)
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i)
}
// 檢查 BOM
const hasBOM = bytes[0] === 0xEF && bytes[1] === 0xBB && bytes[2] === 0xBF
console.log(`📝 UTF-8 BOM: ${hasBOM ? '✅' : '❌'}`)
// 解碼為文字
const csvContent = new TextDecoder('utf-8').decode(bytes)
const hasChinese = /[\u4e00-\u9fff]/.test(csvContent)
console.log(`🔤 中文字符: ${hasChinese ? '✅' : '❌'}`)
// 顯示內容
const lines = csvContent.split('\n')
console.log(`📊 總行數: ${lines.length}`)
console.log(`📋 標題: ${lines[0]}`)
console.log(`📝 範例: ${lines[1]?.substring(0, 60)}...`)
// 保存測試檔案
fs.writeFileSync('test-final-logic.csv', csvContent, 'utf8')
console.log(`💾 已保存測試檔案: test-final-logic.csv`)
}
}
console.log('\n🎯 解決方案總結:')
console.log('✅ 後端:使用 Uint8Array 處理 UTF-8 BOM')
console.log('✅ 後端:使用 TextEncoder 編碼中文內容')
console.log('✅ 後端:使用 Base64 編碼避免 API 路由限制')
console.log('✅ 前端:使用 atob() 解碼 Base64')
console.log('✅ 前端:使用 Uint8Array 保留原始字節')
console.log('✅ 前端:使用 Blob 創建檔案,保留 BOM')
console.log('\n📋 使用說明:')
console.log('1. 點擊「邏輯思維範本」或「創意能力範本」按鈕')
console.log('2. 下載的 CSV 檔案包含 UTF-8 BOM')
console.log('3. 在 Excel 中打開,中文字符會正確顯示')
console.log('4. 編輯後上傳,系統會覆蓋現有資料')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 最終中文匯出功能測試完成')
}
}
testFinalChineseExport()

View File

@@ -1,94 +0,0 @@
const http = require('http')
const testFinalExcelFunctionality = async () => {
console.log('🎉 最終 Excel 匯入匯出功能測試')
console.log('=' .repeat(50))
try {
// 測試創意題目匯出
console.log('\n📊 測試創意題目匯出...')
const creativeResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=creative', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (creativeResponse.status === 200) {
const creativeData = JSON.parse(creativeResponse.data)
if (creativeData.success) {
console.log('✅ 創意題目匯出成功')
const csvContent = Buffer.from(creativeData.data, 'base64').toString('utf8')
const lines = csvContent.split('\n')
console.log(` 📁 檔案名: ${creativeData.filename}`)
console.log(` 📊 總行數: ${lines.length}`)
console.log(` 🔤 中文支援: ${/[\u4e00-\u9fff]/.test(csvContent) ? '✅' : '❌'}`)
console.log(` 📝 UTF-8 BOM: ${csvContent.charCodeAt(0) === 0xFEFF ? '✅' : '❌'}`)
console.log(` 📋 標題: ${lines[0]}`)
console.log(` 📝 範例: ${lines[1]?.substring(0, 50)}...`)
}
}
// 測試邏輯題目匯出
console.log('\n📊 測試邏輯題目匯出...')
const logicResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=logic', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (logicResponse.status === 200) {
const logicData = JSON.parse(logicResponse.data)
if (logicData.success) {
console.log('✅ 邏輯題目匯出成功')
const csvContent = Buffer.from(logicData.data, 'base64').toString('utf8')
const lines = csvContent.split('\n')
console.log(` 📁 檔案名: ${logicData.filename}`)
console.log(` 📊 總行數: ${lines.length}`)
console.log(` 🔤 中文支援: ${/[\u4e00-\u9fff]/.test(csvContent) ? '✅' : '❌'}`)
console.log(` 📝 UTF-8 BOM: ${csvContent.charCodeAt(0) === 0xFEFF ? '✅' : '❌'}`)
console.log(` 📋 標題: ${lines[0]}`)
console.log(` 📝 範例: ${lines[1]?.substring(0, 50)}...`)
}
}
console.log('\n🎯 功能特點總結:')
console.log('✅ 完全基於資料庫格式設計')
console.log('✅ 支援覆蓋式更新現有題目')
console.log('✅ 提供完整的匯入匯出流程')
console.log('✅ 用戶友好的操作界面')
console.log('✅ 自動化的資料同步機制')
console.log('✅ 解決了中文字符編碼問題')
console.log('✅ 添加 UTF-8 BOM 確保 Excel 正確顯示中文')
console.log('✅ 使用 Base64 編碼避免 API 路由限制')
console.log('\n📋 使用說明:')
console.log('1. 點擊「邏輯思維範本」或「創意能力範本」下載 CSV 檔案')
console.log('2. 在 Excel 中打開檔案,中文字符會正確顯示')
console.log('3. 編輯題目內容後保存')
console.log('4. 在網頁中選擇編輯後的檔案並點擊「開始匯入」')
console.log('5. 系統會清空舊資料並插入新資料')
console.log('\n🎉 Excel 匯入匯出功能完全正常!')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
}
}
testFinalExcelFunctionality()

View File

@@ -1,77 +0,0 @@
const http = require('http')
const testFixedDecoding = async () => {
console.log('🔍 測試修正後的解碼功能')
console.log('=' .repeat(30))
try {
// 獲取創意題目匯出資料
console.log('\n📊 獲取創意題目匯出資料...')
const creativeResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=creative', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (creativeResponse.status === 200) {
const creativeData = JSON.parse(creativeResponse.data)
if (creativeData.success) {
console.log('✅ 創意題目資料獲取成功')
// 模擬修正後的前端解碼過程
const base64Data = creativeData.data
// 模擬 atob + TextDecoder 過程
const binaryString = Buffer.from(base64Data, 'base64').toString('binary')
const bytes = new Uint8Array(binaryString.length)
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i)
}
// 使用 ignoreBOM: false 確保保留 BOM
const csvContent = new TextDecoder('utf-8', { ignoreBOM: false }).decode(bytes)
console.log('\n📋 修正後的解碼結果:')
console.log(`前100字符: ${csvContent.substring(0, 100)}`)
console.log(`包含中文: ${/[\u4e00-\u9fff]/.test(csvContent) ? '✅' : '❌'}`)
console.log(`BOM檢測: ${csvContent.charCodeAt(0) === 0xFEFF ? '✅' : '❌'}`)
// 顯示前幾行內容
const lines = csvContent.split('\n')
console.log('\n📋 匯出內容預覽:')
for (let i = 0; i < Math.min(3, lines.length); i++) {
if (lines[i].trim()) {
console.log(`${i + 1}行: ${lines[i]}`)
}
}
if (csvContent.charCodeAt(0) === 0xFEFF && /[\u4e00-\u9fff]/.test(csvContent)) {
console.log('\n🎉 修正成功!')
console.log('✅ UTF-8 BOM 保留完整')
console.log('✅ 中文字符顯示正常')
console.log('✅ Excel 應該能正確識別編碼')
} else {
console.log('\n⚠ 仍有問題需要進一步修正')
}
} else {
console.log('❌ 創意題目資料獲取失敗:', creativeData.message)
}
} else {
console.log('❌ 創意題目資料獲取失敗,狀態碼:', creativeResponse.status)
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修正後的解碼功能測試完成')
}
}
testFixedDecoding()

View File

@@ -1,156 +0,0 @@
const https = require('https')
const http = require('http')
const testFixedDimensionDisplay = async () => {
console.log('🧪 測試修正後的維度分數顯示')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
const testResultId = 'test_1759086508812_xv2pof6lk'
try {
// 1. 獲取測試結果
console.log('\n📊 1. 獲取測試結果...')
const resultResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let testResult = null
if (resultResponse.status === 200) {
const resultData = JSON.parse(resultResponse.data)
if (resultData.success && resultData.data.length > 0) {
testResult = resultData.data[0]
console.log('測試結果:', {
id: testResult.id,
score: testResult.score,
total_questions: testResult.total_questions,
correct_answers: testResult.correct_answers
})
}
}
// 2. 獲取題目資料
console.log('\n📊 2. 獲取題目資料...')
const questionsResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/creative-questions', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let questions = []
if (questionsResponse.status === 200) {
const questionsData = JSON.parse(questionsResponse.data)
if (questionsData.success) {
questions = questionsData.questions
console.log(`獲取到 ${questions.length} 個題目`)
}
}
// 3. 獲取詳細答案
console.log('\n📊 3. 獲取詳細答案...')
const answersResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/creative-test-answers?testResultId=${testResultId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (answersResponse.status === 200) {
const answersData = JSON.parse(answersResponse.data)
if (answersData.success) {
const answers = answersData.data
console.log(`獲取到 ${answers.length} 個答案`)
// 4. 模擬新的維度分數計算
console.log('\n📊 4. 模擬新的維度分數計算...')
const dimensionScores = {
innovation: { total: 0, count: 0 },
imagination: { total: 0, count: 0 },
flexibility: { total: 0, count: 0 },
originality: { total: 0, count: 0 }
}
answers.forEach((answer) => {
const question = questions.find(q => q.id === answer.question_id)
if (question && dimensionScores[question.category]) {
dimensionScores[question.category].total += answer.score
dimensionScores[question.category].count += 1
}
})
// 計算新的維度分數結構
const calculatedDimensionScores = {
innovation: { percentage: 0, rawScore: 0, maxScore: 0 },
imagination: { percentage: 0, rawScore: 0, maxScore: 0 },
flexibility: { percentage: 0, rawScore: 0, maxScore: 0 },
originality: { percentage: 0, rawScore: 0, maxScore: 0 }
}
Object.keys(dimensionScores).forEach(category => {
const { total, count } = dimensionScores[category]
const maxScore = count * 5
const percentage = count > 0 ? Math.round((total / maxScore) * 100) : 0
calculatedDimensionScores[category] = {
percentage: percentage,
rawScore: total,
maxScore: maxScore
}
})
console.log('\n📈 新的維度分數結構:')
Object.entries(calculatedDimensionScores).forEach(([category, data]) => {
console.log(`${category}:`)
console.log(` 百分比: ${data.percentage}%`)
console.log(` 原始分數: ${data.rawScore}`)
console.log(` 滿分: ${data.maxScore}`)
console.log(` 顯示: ${data.rawScore}/${data.maxScore}`)
})
// 5. 模擬 categoryResults 計算
console.log('\n📊 5. 模擬 categoryResults 計算...')
const dimensionNames = {
innovation: '創新能力',
imagination: '想像力',
flexibility: '靈活性',
originality: '原創性'
}
const categoryResults = Object.entries(calculatedDimensionScores).map(([key, data]) => ({
category: key,
name: dimensionNames[key],
score: data.percentage,
rawScore: data.rawScore,
maxRawScore: data.maxScore
}))
console.log('\n📈 categoryResults:')
categoryResults.forEach(category => {
console.log(`${category.name}:`)
console.log(` 分數: ${category.score}`)
console.log(` 顯示: ${category.rawScore}/${category.maxRawScore}`)
})
}
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修正後的維度分數顯示測試完成')
}
}
testFixedDimensionDisplay()

View File

@@ -1,158 +0,0 @@
const https = require('https')
const http = require('http')
const testFixedDimensionScoring = async () => {
console.log('🧪 測試修正後的維度分數計算')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
const testResultId = 'test_1759086508812_xv2pof6lk'
try {
// 1. 獲取測試結果
console.log('\n📊 1. 獲取測試結果...')
const resultResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let testResult = null
if (resultResponse.status === 200) {
const resultData = JSON.parse(resultResponse.data)
if (resultData.success && resultData.data.length > 0) {
testResult = resultData.data[0]
console.log('測試結果:', {
id: testResult.id,
score: testResult.score,
total_questions: testResult.total_questions,
correct_answers: testResult.correct_answers
})
}
}
// 2. 獲取題目資料
console.log('\n📊 2. 獲取題目資料...')
const questionsResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/creative-questions', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let questions = []
if (questionsResponse.status === 200) {
const questionsData = JSON.parse(questionsResponse.data)
if (questionsData.success) {
questions = questionsData.questions
console.log(`獲取到 ${questions.length} 個題目`)
}
}
// 3. 獲取詳細答案
console.log('\n📊 3. 獲取詳細答案...')
const answersResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/creative-test-answers?testResultId=${testResultId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (answersResponse.status === 200) {
const answersData = JSON.parse(answersResponse.data)
if (answersData.success) {
const answers = answersData.data
console.log(`獲取到 ${answers.length} 個答案`)
// 4. 模擬結果頁面的維度分數計算
console.log('\n📊 4. 模擬結果頁面的維度分數計算...')
// 計算各維度分數(模擬資料庫計算)
const dimensionScores = {
innovation: { total: 0, count: 0 },
imagination: { total: 0, count: 0 },
flexibility: { total: 0, count: 0 },
originality: { total: 0, count: 0 }
}
answers.forEach((answer) => {
const question = questions.find(q => q.id === answer.question_id)
if (question && dimensionScores[question.category]) {
dimensionScores[question.category].total += answer.score
dimensionScores[question.category].count += 1
}
})
// 計算百分比分數
const calculatedDimensionScores = {
innovation: 0,
imagination: 0,
flexibility: 0,
originality: 0
}
Object.keys(dimensionScores).forEach(category => {
const { total, count } = dimensionScores[category]
calculatedDimensionScores[category] =
count > 0 ? Math.round((total / (count * 5)) * 100) : 0
})
console.log('\n📈 計算結果:')
console.log('創新能力:', calculatedDimensionScores.innovation + '%')
console.log('想像力:', calculatedDimensionScores.imagination + '%')
console.log('靈活性:', calculatedDimensionScores.flexibility + '%')
console.log('原創性:', calculatedDimensionScores.originality + '%')
// 5. 模擬結果頁面的 categoryResults 計算
console.log('\n📊 5. 模擬結果頁面的 categoryResults 計算...')
const dimensionNames = {
innovation: '創新能力',
imagination: '想像力',
flexibility: '靈活性',
originality: '原創性'
}
const categoryResults = Object.entries(calculatedDimensionScores).map(([key, score]) => ({
category: key,
name: dimensionNames[key],
score: score,
rawScore: 0,
maxRawScore: 0
}))
console.log('\n📈 categoryResults:')
categoryResults.forEach(category => {
console.log(`${category.name}: ${category.score}`)
})
// 6. 驗證總分一致性
console.log('\n📊 6. 驗證總分一致性...')
const totalScore = answers.reduce((sum, answer) => sum + answer.score, 0)
const maxTotalScore = answers.length * 5
const totalPercentage = Math.round((totalScore / maxTotalScore) * 100)
console.log(`資料庫總分數: ${testResult.correct_answers}`)
console.log(`計算總分數: ${totalScore}`)
console.log(`資料庫百分比: ${testResult.score}%`)
console.log(`計算百分比: ${totalPercentage}%`)
console.log(`一致性: ${testResult.correct_answers === totalScore && testResult.score === totalPercentage ? '✅ 一致' : '❌ 不一致'}`)
}
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修正後的維度分數計算測試完成')
}
}
testFixedDimensionScoring()

View File

@@ -1,106 +0,0 @@
const http = require('http')
const testFixedExport = async () => {
console.log('🔍 測試修復後的匯出功能')
console.log('=' .repeat(40))
try {
// 測試基本匯出
console.log('\n📊 測試修復後的匯出...')
const response = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/admin/test-results/export', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success) {
console.log('✅ 匯出成功')
// 解碼並檢查 CSV 內容
const binaryString = Buffer.from(data.data, 'base64').toString('binary')
const csvContent = Buffer.from(binaryString, 'binary').toString('utf-8')
const lines = csvContent.split('\n')
console.log(`📊 總行數: ${lines.length}`)
console.log('\n📋 檢查詳細資料欄位:')
let hasUndefined = false
let combinedCount = 0
let logicCount = 0
let creativeCount = 0
lines.forEach((line, index) => {
if (index === 0) return // 跳過標題行
const columns = line.split(',')
if (columns.length >= 8) {
const testType = columns[3].replace(/"/g, '')
const details = columns[7].replace(/"/g, '')
if (testType === '綜合能力') {
combinedCount++
console.log(` 綜合能力測試 ${combinedCount}: ${details}`)
if (details.includes('undefined')) {
hasUndefined = true
console.log(` ❌ 發現 undefined: ${details}`)
} else {
console.log(` ✅ 無 undefined`)
}
} else if (testType === '邏輯思維') {
logicCount++
console.log(` 邏輯思維測試 ${logicCount}: ${details}`)
} else if (testType === '創意能力') {
creativeCount++
console.log(` 創意能力測試 ${creativeCount}: ${details}`)
}
}
})
console.log('\n📊 統計:')
console.log(` 綜合能力測試: ${combinedCount}`)
console.log(` 邏輯思維測試: ${logicCount}`)
console.log(` 創意能力測試: ${creativeCount}`)
if (hasUndefined) {
console.log('\n❌ 仍然發現 undefined 值')
} else {
console.log('\n✅ 所有詳細資料欄位都沒有 undefined 值')
}
// 檢查特定修復
console.log('\n🔧 檢查修復項目:')
const hasUndefinedInCombined = csvContent.includes('undefined')
const hasNoDataPlaceholder = csvContent.includes('無資料')
console.log(` 包含 undefined: ${hasUndefinedInCombined ? '是' : '否'}`)
console.log(` 包含「無資料」: ${hasNoDataPlaceholder ? '是' : '否'}`)
if (!hasUndefinedInCombined && hasNoDataPlaceholder) {
console.log('✅ 修復成功undefined 已被替換為「無資料」')
} else if (hasUndefinedInCombined) {
console.log('❌ 修復失敗,仍有 undefined 值')
}
} else {
console.log('❌ 匯出失敗:', data.message)
}
} else {
console.log('❌ 匯出失敗,狀態碼:', response.status)
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修復後匯出功能測試完成')
}
}
testFixedExport()

View File

@@ -1,234 +0,0 @@
const https = require('https')
const http = require('http')
const testFixedLogin = async () => {
console.log('🔍 測試修正後的登入功能')
console.log('=' .repeat(50))
try {
// 1. 測試管理員新建用戶登入
console.log('\n📊 1. 測試管理員新建用戶登入...')
const adminCreatedUser = {
name: '管理員新建用戶',
email: 'admin.created@company.com',
password: 'password123',
department: '測試部',
role: 'user'
}
const createResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(adminCreatedUser)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/admin/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
let adminCreatedUserId = null
if (createResponse.status === 200) {
const createData = JSON.parse(createResponse.data)
if (createData.success) {
adminCreatedUserId = createData.data.id
console.log('✅ 管理員新建用戶成功')
console.log(' 用戶ID:', createData.data.id)
console.log(' 電子郵件:', createData.data.email)
} else {
console.log('❌ 管理員新建用戶失敗:', createData.error)
return
}
}
// 2. 測試管理員新建用戶登入
console.log('\n📊 2. 測試管理員新建用戶登入...')
const adminLoginData = {
email: 'admin.created@company.com',
password: 'password123'
}
const adminLoginResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(adminLoginData)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/auth/login',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
if (adminLoginResponse.status === 200) {
const adminLoginResult = JSON.parse(adminLoginResponse.data)
if (adminLoginResult.success) {
console.log('✅ 管理員新建用戶登入成功!')
console.log(' 用戶ID:', adminLoginResult.user.id)
console.log(' 姓名:', adminLoginResult.user.name)
console.log(' 電子郵件:', adminLoginResult.user.email)
console.log(' 角色:', adminLoginResult.user.role)
} else {
console.log('❌ 管理員新建用戶登入失敗:', adminLoginResult.error)
}
} else {
const errorData = JSON.parse(adminLoginResponse.data)
console.log('❌ 管理員新建用戶登入 API 錯誤:', errorData.error)
}
// 3. 測試註冊用戶登入(對照組)
console.log('\n📊 3. 測試註冊用戶登入(對照組)...')
const registerUser = {
name: '註冊用戶',
email: 'register.user@company.com',
password: 'password123',
department: '測試部',
role: 'user'
}
const registerResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(registerUser)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/auth/register',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
let registerUserId = null
if (registerResponse.status === 200) {
const registerData = JSON.parse(registerResponse.data)
if (registerData.success) {
registerUserId = registerData.data.id
console.log('✅ 註冊用戶成功')
console.log(' 用戶ID:', registerData.data.id)
console.log(' 電子郵件:', registerData.data.email)
} else {
console.log('❌ 註冊用戶失敗:', registerData.error)
}
}
// 4. 測試註冊用戶登入
console.log('\n📊 4. 測試註冊用戶登入...')
const registerLoginData = {
email: 'register.user@company.com',
password: 'password123'
}
const registerLoginResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(registerLoginData)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/auth/login',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
if (registerLoginResponse.status === 200) {
const registerLoginResult = JSON.parse(registerLoginResponse.data)
if (registerLoginResult.success) {
console.log('✅ 註冊用戶登入成功!')
console.log(' 用戶ID:', registerLoginResult.user.id)
console.log(' 姓名:', registerLoginResult.user.name)
console.log(' 電子郵件:', registerLoginResult.user.email)
console.log(' 角色:', registerLoginResult.user.role)
} else {
console.log('❌ 註冊用戶登入失敗:', registerLoginResult.error)
}
} else {
const errorData = JSON.parse(registerLoginResponse.data)
console.log('❌ 註冊用戶登入 API 錯誤:', errorData.error)
}
// 5. 清理測試用戶
console.log('\n📊 5. 清理測試用戶...')
const userIdsToDelete = [adminCreatedUserId, registerUserId].filter(id => id)
for (const userId of userIdsToDelete) {
const deleteResponse = await new Promise((resolve, reject) => {
const options = {
hostname: 'localhost',
port: 3000,
path: `/api/admin/users?id=${userId}`,
method: 'DELETE'
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.end()
})
if (deleteResponse.status === 200) {
console.log(`✅ 已刪除測試用戶: ${userId}`)
}
}
console.log('\n📝 修正測試總結:')
console.log('✅ 密碼雙重加密問題已修正')
console.log('✅ 管理員新建用戶可以正常登入')
console.log('✅ 註冊用戶登入功能正常')
console.log('✅ 密碼雜湊邏輯統一')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修正後登入功能測試完成')
}
}
testFixedLogin()

View File

@@ -1,62 +0,0 @@
const https = require('https')
const http = require('http')
const testFixedTimeParsing = async () => {
console.log('🔍 測試修正後的時間解析')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 檢查創意測試結果 API
console.log('\n📊 檢查創意測試結果 API...')
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success && data.data.length > 0) {
// 按創建時間排序,取最新的
const sortedResults = data.data.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
const latestResult = sortedResults[0]
console.log('\n📋 最新創意測試結果:')
console.log(`completed_at: ${latestResult.completed_at}`)
// 測試時間解析
console.log('\n📊 測試時間解析:')
const parsedDate = new Date(latestResult.completed_at)
const isValid = !isNaN(parsedDate.getTime())
console.log(`解析結果: ${parsedDate.toISOString()}`)
console.log(`是否有效: ${isValid ? '✅' : '❌'}`)
if (isValid) {
const taiwanTime = parsedDate.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(`台灣時間: ${taiwanTime}`)
}
// 檢查所有結果的時間格式
console.log('\n📊 所有結果的時間格式:')
data.data.forEach((result, index) => {
const date = new Date(result.completed_at)
const isValid = !isNaN(date.getTime())
console.log(`${index + 1}. ${result.completed_at}${isValid ? '✅' : '❌'}`)
})
}
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修正後的時間解析測試完成')
}
}
testFixedTimeParsing()

View File

@@ -1,90 +0,0 @@
const http = require('http')
const testFrontendDecoding = async () => {
console.log('🔍 測試前端解碼功能')
console.log('=' .repeat(30))
try {
// 獲取創意題目匯出資料
console.log('\n📊 獲取創意題目匯出資料...')
const creativeResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/export?type=creative', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (creativeResponse.status === 200) {
const creativeData = JSON.parse(creativeResponse.data)
if (creativeData.success) {
console.log('✅ 創意題目資料獲取成功')
// 模擬前端解碼過程
const base64Data = creativeData.data
// 方法1: 直接使用 Buffer (Node.js 環境)
const buffer = Buffer.from(base64Data, 'base64')
const csvContent1 = buffer.toString('utf8')
// 方法2: 模擬前端 atob + TextDecoder
const binaryString = Buffer.from(base64Data, 'base64').toString('binary')
const bytes = new Uint8Array(binaryString.length)
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i)
}
const csvContent2 = new TextDecoder('utf-8').decode(bytes)
console.log('\n📋 解碼結果比較:')
console.log('方法1 (Buffer):')
console.log(` 前100字符: ${csvContent1.substring(0, 100)}`)
console.log(` 包含中文: ${/[\u4e00-\u9fff]/.test(csvContent1) ? '✅' : '❌'}`)
console.log(` BOM檢測: ${csvContent1.charCodeAt(0) === 0xFEFF ? '✅' : '❌'}`)
console.log('\n方法2 (atob + TextDecoder):')
console.log(` 前100字符: ${csvContent2.substring(0, 100)}`)
console.log(` 包含中文: ${/[\u4e00-\u9fff]/.test(csvContent2) ? '✅' : '❌'}`)
console.log(` BOM檢測: ${csvContent2.charCodeAt(0) === 0xFEFF ? '✅' : '❌'}`)
// 檢查兩種方法是否一致
const isSame = csvContent1 === csvContent2
console.log(`\n兩種方法結果一致: ${isSame ? '✅' : '❌'}`)
if (isSame) {
console.log('\n🎉 前端解碼方法正確!')
console.log('✅ Base64 解碼正常')
console.log('✅ UTF-8 編碼處理正確')
console.log('✅ UTF-8 BOM 保留完整')
console.log('✅ 中文字符顯示正常')
} else {
console.log('\n⚠ 兩種解碼方法結果不同,需要檢查')
}
// 顯示前幾行內容
const lines = csvContent1.split('\n')
console.log('\n📋 匯出內容預覽:')
for (let i = 0; i < Math.min(3, lines.length); i++) {
if (lines[i].trim()) {
console.log(`${i + 1}行: ${lines[i]}`)
}
}
} else {
console.log('❌ 創意題目資料獲取失敗:', creativeData.message)
}
} else {
console.log('❌ 創意題目資料獲取失敗,狀態碼:', creativeResponse.status)
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 前端解碼功能測試完成')
}
}
testFrontendDecoding()

View File

@@ -1,49 +0,0 @@
const https = require('https')
const http = require('http')
const testFrontendTimeFix = async () => {
console.log('🔍 測試前端時間顯示修正')
console.log('=' .repeat(50))
try {
// 測試時間格式轉換
console.log('\n📊 測試前端時間轉換:')
// 模擬資料庫中的時間格式
const dbTime = '2025-09-29 17:34:08'
console.log(`資料庫時間: ${dbTime}`)
// 舊的轉換方式(錯誤)
const oldWay = new Date(dbTime)
const oldTaiwanTime = oldWay.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(`舊方式轉換: ${oldTaiwanTime}`)
// 新的轉換方式(正確)
const newWay = new Date(dbTime + 'Z')
const newTaiwanTime = newWay.toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })
console.log(`新方式轉換: ${newTaiwanTime}`)
// 驗證轉換是否正確
const expectedTime = '2025/9/29 下午5:34:08'
const isCorrect = newTaiwanTime === expectedTime
console.log(`轉換是否正確: ${isCorrect ? '✅' : '❌'}`)
if (!isCorrect) {
console.log(`期望時間: ${expectedTime}`)
console.log(`實際時間: ${newTaiwanTime}`)
}
console.log('\n📝 修正說明:')
console.log('1. 資料庫儲存: 2025-09-29 17:34:08 (UTC 時間)')
console.log('2. 舊方式: new Date("2025-09-29 17:34:08") → 當作本地時間')
console.log('3. 新方式: new Date("2025-09-29 17:34:08Z") → 當作 UTC 時間')
console.log('4. 前端顯示: 正確轉換為台灣時間 (UTC+8)')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 前端時間顯示修正測試完成')
}
}
testFrontendTimeFix()

View File

@@ -1,102 +0,0 @@
const http = require('http')
const fs = require('fs')
const testImportFix = async () => {
console.log('🔍 測試修正後的匯入功能')
console.log('=' .repeat(30))
try {
// 創建測試 CSV 檔案
console.log('\n📊 創建測試 CSV 檔案...')
const testLogicCSV = `"題目ID","題目內容","選項A","選項B","選項C","選項D","選項E","正確答案","解釋"
"1","測試邏輯題目:如果 A > B 且 B > C那麼","A > C","A < C","A = C","無法確定","A = B","A","根據傳遞性A > C"`
const testCreativeCSV = `"題目ID","陳述內容","類別","反向計分"
"1","我喜歡嘗試新的解決方案","innovation","否"
"2","我習慣按照既定規則工作","flexibility","是"`
// 保存測試檔案
fs.writeFileSync('test-logic-import.csv', testLogicCSV, 'utf8')
fs.writeFileSync('test-creative-import.csv', testCreativeCSV, 'utf8')
console.log('✅ 測試檔案創建成功')
console.log(' test-logic-import.csv')
console.log(' test-creative-import.csv')
// 測試匯入 API 端點
console.log('\n📊 測試匯入 API 端點...')
// 模擬 FormData 請求(簡化測試)
const testData = {
type: 'logic',
test: true
}
const postData = JSON.stringify(testData)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/questions/import',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const response = await new Promise((resolve, reject) => {
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
req.write(postData)
req.end()
})
console.log(`狀態碼: ${response.status}`)
console.log(`回應: ${response.data}`)
if (response.status === 400) {
console.log('✅ API 端點正常運作(預期缺少檔案參數)')
} else if (response.status === 500) {
console.log('❌ 仍有伺服器錯誤')
} else {
console.log('⚠️ 意外的回應狀態')
}
console.log('\n🎯 修正說明:')
console.log('✅ 移除了 FileReader 依賴')
console.log('✅ 使用 XLSX 庫直接處理檔案')
console.log('✅ 在伺服器端定義解析函數')
console.log('✅ 支援 CSV 和 Excel 格式')
console.log('\n📋 使用方式:')
console.log('1. 下載範本檔案CSV 格式)')
console.log('2. 在 Excel 中編輯內容')
console.log('3. 保存為 CSV 或 Excel 格式')
console.log('4. 在網頁中選擇檔案並上傳')
console.log('5. 系統會清空舊資料並插入新資料')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
// 清理測試檔案
try {
fs.unlinkSync('test-logic-import.csv')
fs.unlinkSync('test-creative-import.csv')
console.log('\n🧹 測試檔案已清理')
} catch (e) {
// 忽略清理錯誤
}
console.log('\n✅ 匯入功能修正測試完成')
}
}
testImportFix()

View File

@@ -1,66 +0,0 @@
const testLogicAPI = async () => {
console.log('🧪 測試邏輯測驗 API')
console.log('=' .repeat(50))
// 模擬測試數據
const testData = {
userId: 'test_user_123',
answers: ['A', 'B', 'C', 'D', 'E', 'A', 'B', 'C', 'D', 'E'], // 10個答案
completedAt: new Date().toISOString()
}
console.log('\n📝 測試數據:')
console.log('用戶ID:', testData.userId)
console.log('答案數量:', testData.answers.length)
console.log('完成時間:', testData.completedAt)
try {
console.log('\n🔄 發送 POST 請求到 /api/test-results/logic...')
const response = await fetch('http://localhost:3000/api/test-results/logic', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(testData)
})
console.log('📊 響應狀態:', response.status)
console.log('📊 響應狀態文字:', response.statusText)
const result = await response.json()
console.log('📊 響應內容:', JSON.stringify(result, null, 2))
if (result.success) {
console.log('\n✅ API 測試成功!')
console.log('測試結果ID:', result.data.testResult.id)
console.log('答案記錄數量:', result.data.answerCount)
} else {
console.log('\n❌ API 測試失敗!')
console.log('錯誤訊息:', result.error)
}
} catch (error) {
console.log('\n❌ 請求失敗:')
console.log('錯誤類型:', error.name)
console.log('錯誤訊息:', error.message)
if (error.code === 'ECONNREFUSED') {
console.log('\n💡 建議:')
console.log('1. 確保開發伺服器正在運行 (npm run dev)')
console.log('2. 檢查端口 3000 是否可用')
console.log('3. 檢查防火牆設定')
}
}
console.log('\n🔍 檢查要點:')
console.log('1. 開發伺服器是否運行')
console.log('2. API 路由是否正確')
console.log('3. 資料庫連接是否正常')
console.log('4. 用戶認證是否有效')
console.log('5. 資料庫表是否存在')
console.log('\n✅ 邏輯測驗 API 測試完成')
}
testLogicAPI()

View File

@@ -1,100 +0,0 @@
const testLogicDbUpload = () => {
console.log('🧠 邏輯測驗資料庫上傳功能測試')
console.log('=' .repeat(50))
console.log('\n📊 資料庫表結構分析:')
console.log('test_results 表:')
console.log('- id: varchar(50) PRIMARY KEY')
console.log('- user_id: varchar(50) NOT NULL')
console.log('- test_type: enum("logic","creative","combined") NOT NULL')
console.log('- score: int NOT NULL')
console.log('- total_questions: int NOT NULL')
console.log('- correct_answers: int NOT NULL')
console.log('- completed_at: timestamp NOT NULL')
console.log('- created_at: timestamp DEFAULT CURRENT_TIMESTAMP')
console.log('\nlogic_test_answers 表:')
console.log('- id: varchar(50) PRIMARY KEY')
console.log('- test_result_id: varchar(50) NOT NULL (FK to test_results)')
console.log('- question_id: int NOT NULL (FK to logic_questions)')
console.log('- user_answer: enum("A","B","C","D","E") NOT NULL')
console.log('- is_correct: tinyint(1) NOT NULL')
console.log('- created_at: timestamp DEFAULT CURRENT_TIMESTAMP')
console.log('\n🔧 已實現的功能:')
console.log('1. ✅ 資料庫模型檔案:')
console.log(' - lib/database/models/test_result.ts')
console.log(' - lib/database/models/logic_test_answer.ts')
console.log(' - 包含 CRUD 操作和關聯查詢')
console.log('\n2. ✅ API 路由:')
console.log(' - app/api/test-results/logic/route.ts')
console.log(' - POST: 上傳邏輯測驗結果')
console.log(' - GET: 獲取用戶邏輯測驗結果')
console.log('\n3. ✅ 前端整合:')
console.log(' - 修改 app/tests/logic/page.tsx')
console.log(' - 添加用戶認證檢查')
console.log(' - 添加資料庫上傳功能')
console.log(' - 保持 localStorage 向後兼容')
console.log('\n📝 上傳流程:')
console.log('1. 用戶完成邏輯測驗')
console.log('2. 計算分數和正確答案數')
console.log('3. 儲存到 localStorage (向後兼容)')
console.log('4. 上傳到資料庫:')
console.log(' - 建立 test_results 記錄')
console.log(' - 建立 logic_test_answers 記錄')
console.log('5. 跳轉到結果頁面')
console.log('\n🎯 資料庫上傳內容:')
console.log('test_results 記錄:')
console.log('- user_id: 用戶ID')
console.log('- test_type: "logic"')
console.log('- score: 分數 (0-100)')
console.log('- total_questions: 總題數')
console.log('- correct_answers: 答對題數')
console.log('- completed_at: 完成時間')
console.log('\nlogic_test_answers 記錄:')
console.log('- test_result_id: 測試結果ID')
console.log('- question_id: 題目ID')
console.log('- user_answer: 用戶答案 (A-E)')
console.log('- is_correct: 是否正確 (0/1)')
console.log('\n🔍 錯誤處理:')
console.log('- 用戶未登入: 顯示提示並停止')
console.log('- 上傳失敗: 記錄錯誤但繼續顯示結果')
console.log('- 網路錯誤: 顯示錯誤訊息')
console.log('- 資料庫錯誤: 記錄到控制台')
console.log('\n📱 用戶體驗:')
console.log('- 提交按鈕顯示載入狀態')
console.log('- 防止重複提交')
console.log('- 保持原有功能不變')
console.log('- 向後兼容 localStorage')
console.log('\n🧪 測試要點:')
console.log('1. 用戶登入狀態檢查')
console.log('2. 測驗結果計算正確性')
console.log('3. 資料庫記錄建立')
console.log('4. 答案記錄關聯')
console.log('5. 錯誤處理機制')
console.log('6. 向後兼容性')
console.log('\n✅ 預期結果:')
console.log('- 用戶完成測驗後,結果自動上傳到資料庫')
console.log('- 管理員可以在後台查看所有測試結果')
console.log('- 支援詳細的答案分析')
console.log('- 保持現有功能正常運作')
console.log('\n🚀 下一步:')
console.log('1. 測試實際的資料庫上傳功能')
console.log('2. 驗證資料完整性和正確性')
console.log('3. 檢查管理員後台顯示')
console.log('4. 考慮添加創意測驗和綜合測驗上傳')
console.log('\n✅ 邏輯測驗資料庫上傳功能測試完成')
}
testLogicDbUpload()

View File

@@ -1,66 +0,0 @@
const testLogicInstructions = () => {
console.log('📝 邏輯測驗註記文字添加測試')
console.log('=' .repeat(50))
console.log('\n🎯 添加內容:')
console.log('位置: 邏輯測驗題目卡片下方')
console.log('文字: "請仔細閱讀題目,選擇最正確的答案,每題均為單選。"')
console.log('樣式: 帶有圖示和邊框的說明區塊')
console.log('\n🎨 UI設計特色:')
console.log('容器樣式:')
console.log('- 背景: bg-muted/30 (淺灰色背景)')
console.log('- 圓角: rounded-lg (圓角邊框)')
console.log('- 左邊框: border-l-4 border-primary (藍色左邊框)')
console.log('- 內邊距: p-4 (16px內邊距)')
console.log('- 上邊距: mt-6 (24px上邊距)')
console.log('\n文字樣式:')
console.log('- 大小: text-sm (14px)')
console.log('- 顏色: text-muted-foreground (次要文字顏色)')
console.log('- 行高: leading-relaxed (放鬆行高)')
console.log('- 圖示: 📝 答題說明:')
console.log('- 重點文字: font-medium text-primary (粗體藍色)')
console.log('\n📊 視覺層次:')
console.log('1. 題目內容 (主要)')
console.log('2. 選項列表 (主要)')
console.log('3. 答題說明 (次要,但醒目)')
console.log('4. 導航按鈕 (操作)')
console.log('\n💡 設計理念:')
console.log('- 使用淺色背景區分說明內容')
console.log('- 左邊框突出顯示重要性')
console.log('- 圖示增加視覺吸引力')
console.log('- 文字大小適中,不干擾主要內容')
console.log('- 位置合理,在選項下方,導航上方')
console.log('\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. 註記文字是否正確顯示')
console.log('2. 樣式是否符合設計要求')
console.log('3. 在不同螢幕尺寸下是否正常')
console.log('4. 文字是否清晰易讀')
console.log('5. 整體佈局是否協調')
console.log('\n✅ 預期效果:')
console.log('- 用戶能清楚看到答題說明')
console.log('- 視覺上與主要內容區分開來')
console.log('- 提升用戶對測驗規則的理解')
console.log('- 整體用戶體驗更加完善')
console.log('\n✅ 邏輯測驗註記文字添加測試完成')
}
testLogicInstructions()

View File

@@ -1,88 +0,0 @@
const http = require('http')
const testLogicPagination = async () => {
console.log('🔍 測試邏輯題目分頁功能')
console.log('=' .repeat(30))
try {
// 獲取邏輯題目資料
console.log('\n📊 獲取邏輯題目資料...')
const logicResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/questions/logic', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({
status: res.statusCode,
data: data
}))
})
req.on('error', reject)
})
if (logicResponse.status === 200) {
const logicData = JSON.parse(logicResponse.data)
if (logicData.success) {
const questions = logicData.data
console.log(`✅ 成功獲取 ${questions.length} 道邏輯題目`)
// 模擬分頁計算
const itemsPerPage = 10
const totalPages = Math.ceil(questions.length / itemsPerPage)
console.log(`\n📊 分頁計算結果:`)
console.log(`每頁顯示: ${itemsPerPage} 道題目`)
console.log(`總頁數: ${totalPages}`)
// 顯示每頁的題目範圍
for (let page = 1; page <= totalPages; page++) {
const startIndex = (page - 1) * itemsPerPage
const endIndex = startIndex + itemsPerPage
const currentQuestions = questions.slice(startIndex, endIndex)
console.log(`\n${page} 頁:`)
console.log(` 顯示第 ${startIndex + 1} - ${Math.min(endIndex, questions.length)}`)
console.log(` 題目數量: ${currentQuestions.length}`)
console.log(` 題目ID範圍: ${currentQuestions[0]?.id} - ${currentQuestions[currentQuestions.length - 1]?.id}`)
}
console.log('\n🎯 分頁功能特點:')
console.log('✅ 每頁顯示 10 道題目')
console.log('✅ 支援桌面版和手機版分頁')
console.log('✅ 顯示當前頁範圍和總數')
console.log('✅ 上一頁/下一頁按鈕')
console.log('✅ 頁碼按鈕桌面版顯示全部手機版顯示3個')
console.log('✅ 省略號顯示(手機版)')
console.log('\n📱 手機版分頁邏輯:')
console.log('✅ 最多顯示 3 個頁碼')
console.log('✅ 當前頁居中顯示')
console.log('✅ 首頁和末頁按需顯示')
console.log('✅ 省略號表示跳過的頁碼')
console.log('\n💻 桌面版分頁邏輯:')
console.log('✅ 顯示所有頁碼')
console.log('✅ 當前頁高亮顯示')
console.log('✅ 上一頁/下一頁按鈕')
if (questions.length > itemsPerPage) {
console.log('\n🎉 分頁功能已啟用!')
console.log(`目前有 ${questions.length} 道題目,分為 ${totalPages} 頁顯示`)
} else {
console.log('\n📝 題目數量少於一頁,分頁功能未顯示')
}
} else {
console.log('❌ 獲取邏輯題目失敗:', logicData.message)
}
} else {
console.log('❌ 獲取邏輯題目失敗,狀態碼:', logicResponse.status)
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 邏輯題目分頁功能測試完成')
}
}
testLogicPagination()

View File

@@ -1,72 +0,0 @@
const testLogicSimpleInstructions = () => {
console.log('📝 邏輯測驗簡潔註記文字測試')
console.log('=' .repeat(50))
console.log('\n🎯 修正後的設計:')
console.log('位置: 標題下方CardHeader內')
console.log('文字: "請仔細閱讀題目,選擇最正確的答案,每題均為單選。"')
console.log('樣式: 簡潔無邊框無emoji符號')
console.log('\n🎨 UI設計特色:')
console.log('文字樣式:')
console.log('- 大小: text-sm (14px)')
console.log('- 顏色: text-muted-foreground (次要文字顏色)')
console.log('- 上邊距: mt-2 (8px上邊距)')
console.log('- 無邊框、無背景、無emoji')
console.log('\n📊 視覺層次:')
console.log('1. 題目標題 (主要,大號粗體)')
console.log('2. 答題說明 (次要,小號灰色)')
console.log('3. 選項列表 (主要)')
console.log('4. 導航按鈕 (操作)')
console.log('\n💡 設計理念:')
console.log('- 簡潔明瞭,不干擾主要內容')
console.log('- 位置合理,緊貼標題下方')
console.log('- 顏色低調,作為輔助說明')
console.log('- 無多餘裝飾,保持乾淨設計')
console.log('- 符合圖二簡潔風格')
console.log('\n📱 響應式設計:')
console.log('- 手機版: 文字大小適中,易於閱讀')
console.log('- 桌面版: 保持一致的視覺效果')
console.log('- 文字換行: 自動換行,保持可讀性')
console.log('- 間距: 與標題保持適當距離')
console.log('\n🎯 用戶體驗提升:')
console.log('- 清楚說明答題規則')
console.log('- 提醒用戶仔細閱讀')
console.log('- 強調單選的重要性')
console.log('- 視覺上不突兀,融入整體設計')
console.log('- 簡潔風格符合現代UI趨勢')
console.log('\n🔍 與圖二風格對比:')
console.log('圖二特色:')
console.log('- 標題: 大號粗體黑色文字')
console.log('- 說明: 小號灰色文字')
console.log('- 無邊框、無背景、無emoji')
console.log('- 簡潔乾淨的設計')
console.log('\n我們的設計:')
console.log('- 標題: text-xl text-balance (大號粗體)')
console.log('- 說明: text-sm text-muted-foreground (小號灰色)')
console.log('- 無邊框、無背景、無emoji')
console.log('- 簡潔乾淨的設計')
console.log('\n✅ 符合要求:')
console.log('- 位置: 標題下方 ✓')
console.log('- 風格: 簡潔無邊框 ✓')
console.log('- 無emoji符號 ✓')
console.log('- 符合圖二設計風格 ✓')
console.log('\n🔍 測試要點:')
console.log('1. 註記文字是否在標題下方')
console.log('2. 樣式是否簡潔無邊框')
console.log('3. 無emoji符號')
console.log('4. 文字顏色和大小是否合適')
console.log('5. 整體設計是否協調')
console.log('\n✅ 邏輯測驗簡潔註記文字測試完成')
}
testLogicSimpleInstructions()

View File

@@ -1,143 +0,0 @@
const https = require('https')
const http = require('http')
const testLoginWithDebug = async () => {
console.log('🔍 測試登入並查看調試資訊')
console.log('=' .repeat(50))
try {
// 1. 創建一個測試用戶
console.log('\n📊 1. 創建測試用戶...')
const testUser = {
name: '調試登入用戶',
email: 'debug.login@company.com',
password: 'password123',
department: '測試部',
role: 'user'
}
const createResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(testUser)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/admin/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
let testUserId = null
if (createResponse.status === 200) {
const createData = JSON.parse(createResponse.data)
if (createData.success) {
testUserId = createData.data.id
console.log('✅ 測試用戶創建成功')
console.log(' 用戶ID:', createData.data.id)
console.log(' 電子郵件:', createData.data.email)
} else {
console.log('❌ 創建測試用戶失敗:', createData.error)
return
}
}
// 2. 等待一下讓資料庫更新
console.log('\n⏳ 等待資料庫更新...')
await new Promise(resolve => setTimeout(resolve, 1000))
// 3. 嘗試登入
console.log('\n📊 2. 嘗試登入(查看調試資訊)...')
const loginData = {
email: 'debug.login@company.com',
password: 'password123'
}
console.log(' 登入資料:', loginData)
const loginResponse = await new Promise((resolve, reject) => {
const postData = JSON.stringify(loginData)
const options = {
hostname: 'localhost',
port: 3000,
path: '/api/auth/login',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(postData)
req.end()
})
console.log(' 登入回應狀態碼:', loginResponse.status)
console.log(' 登入回應內容:', loginResponse.data)
if (loginResponse.status === 200) {
const loginResult = JSON.parse(loginResponse.data)
if (loginResult.success) {
console.log('✅ 登入成功!')
console.log(' 用戶資料:', loginResult.user)
} else {
console.log('❌ 登入失敗:', loginResult.error)
}
} else {
const errorData = JSON.parse(loginResponse.data)
console.log('❌ 登入 API 錯誤:', errorData.error)
}
// 4. 清理測試用戶
console.log('\n📊 3. 清理測試用戶...')
if (testUserId) {
const deleteResponse = await new Promise((resolve, reject) => {
const options = {
hostname: 'localhost',
port: 3000,
path: `/api/admin/users?id=${testUserId}`,
method: 'DELETE'
}
const req = http.request(options, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.end()
})
if (deleteResponse.status === 200) {
console.log(`✅ 已刪除測試用戶: ${testUserId}`)
}
}
console.log('\n📝 調試測試總結:')
console.log('🔍 請查看伺服器控制台的調試資訊')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 登入調試測試完成')
}
}
testLoginWithDebug()

View File

@@ -1,43 +0,0 @@
const fetch = require('node-fetch')
async function testLogin() {
console.log('🔄 正在測試登入功能...')
const testUsers = [
{ email: 'admin@company.com', password: 'admin123' },
{ email: 'user@company.com', password: 'user123' },
{ email: 'manager@company.com', password: 'manager123' },
{ email: 'test@company.com', password: 'test123' }
]
for (const user of testUsers) {
try {
console.log(`\n測試用戶: ${user.email}`)
const response = await fetch('http://localhost:3000/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(user),
})
const data = await response.json()
if (data.success) {
console.log(`✅ 登入成功: ${data.user.name}`)
console.log(` Role: ${data.user.role}`)
console.log(` Token: ${data.accessToken ? '已生成' : '未生成'}`)
} else {
console.log(`❌ 登入失敗: ${data.error}`)
}
} catch (error) {
console.log(`❌ 請求失敗: ${error.message}`)
}
}
}
// 如果直接執行此檔案,則執行測試
if (require.main === module) {
testLogin().catch(console.error)
}

View File

@@ -1,128 +0,0 @@
const https = require('https')
const http = require('http')
const testMobilePagination = async () => {
console.log('🔍 測試手機版分頁響應式設計')
console.log('=' .repeat(50))
try {
// 1. 測試不同頁數的分頁顯示
console.log('\n📊 1. 測試分頁顯示邏輯...')
const testPages = [1, 2, 3, 4, 5]
for (const page of testPages) {
console.log(`\n 測試第 ${page} 頁:`)
const response = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/admin/users?page=${page}&limit=5`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (response.status === 200) {
const data = JSON.parse(response.data)
if (data.success) {
const totalPages = data.data.totalPages
const currentPage = data.data.currentPage
console.log(` 總頁數: ${totalPages}`)
console.log(` 當前頁: ${currentPage}`)
// 模擬手機版分頁邏輯
const maxVisiblePages = 3
const startPage = Math.max(1, currentPage - 1)
const endPage = Math.min(totalPages, startPage + maxVisiblePages - 1)
console.log(` 手機版顯示頁碼範圍: ${startPage} - ${endPage}`)
// 顯示頁碼陣列
const pages = []
if (startPage > 1) {
pages.push('1')
if (startPage > 2) pages.push('...')
}
for (let i = startPage; i <= endPage; i++) {
pages.push(i.toString())
}
if (endPage < totalPages) {
if (endPage < totalPages - 1) pages.push('...')
pages.push(totalPages.toString())
}
console.log(` 手機版頁碼: [${pages.join(', ')}]`)
}
}
}
// 2. 測試響應式設計特點
console.log('\n📊 2. 響應式設計特點:')
console.log('✅ 桌面版 (sm:flex): 顯示完整頁碼')
console.log('✅ 手機版 (sm:hidden): 智能省略頁碼')
console.log('✅ 最多顯示 3 個頁碼按鈕')
console.log('✅ 自動顯示第一頁和最後一頁')
console.log('✅ 使用省略號 (...) 表示跳過的頁碼')
console.log('✅ 上一頁/下一頁按鈕自適應寬度')
// 3. 測試不同總頁數的情況
console.log('\n📊 3. 測試不同總頁數情況:')
const testScenarios = [
{ totalPages: 2, currentPage: 1, description: '2頁第1頁' },
{ totalPages: 3, currentPage: 2, description: '3頁第2頁' },
{ totalPages: 5, currentPage: 3, description: '5頁第3頁' },
{ totalPages: 10, currentPage: 5, description: '10頁第5頁' },
{ totalPages: 20, currentPage: 10, description: '20頁第10頁' }
]
testScenarios.forEach(scenario => {
const { totalPages, currentPage, description } = scenario
const maxVisiblePages = 3
const startPage = Math.max(1, currentPage - 1)
const endPage = Math.min(totalPages, startPage + maxVisiblePages - 1)
const pages = []
if (startPage > 1) {
pages.push('1')
if (startPage > 2) pages.push('...')
}
for (let i = startPage; i <= endPage; i++) {
pages.push(i.toString())
}
if (endPage < totalPages) {
if (endPage < totalPages - 1) pages.push('...')
pages.push(totalPages.toString())
}
console.log(` ${description}: [${pages.join(', ')}]`)
})
console.log('\n📝 手機版分頁優化總結:')
console.log('✅ 響應式佈局:桌面版和手機版分別優化')
console.log('✅ 智能省略:避免頁碼按鈕過多造成跑版')
console.log('✅ 用戶體驗:保持核心導航功能')
console.log('✅ 視覺設計:清晰的省略號和頁碼顯示')
console.log('✅ 觸控友好:按鈕大小適合手指操作')
console.log('\n🎨 設計特色:')
console.log('✅ 桌面版:完整頁碼顯示,適合滑鼠操作')
console.log('✅ 手機版:精簡頁碼顯示,適合觸控操作')
console.log('✅ 自適應按鈕:上一頁/下一頁按鈕寬度自適應')
console.log('✅ 居中對齊:手機版分頁控制居中顯示')
console.log('✅ 間距優化:適當的間距避免誤觸')
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 手機版分頁響應式設計測試完成')
}
}
testMobilePagination()

Some files were not shown because too many files have changed in this diff Show More