166 lines
6.4 KiB
JavaScript
166 lines
6.4 KiB
JavaScript
const mysql = require('mysql2/promise');
|
||
|
||
// Simulate the detailed API response structure
|
||
const simulateDetailedApiResponse = async () => {
|
||
try {
|
||
const connection = await mysql.createConnection({
|
||
host: 'localhost',
|
||
user: 'root',
|
||
password: '123456',
|
||
database: 'ai_showcase_platform'
|
||
});
|
||
|
||
console.log('=== Testing Detail View Edit Flow ===\n');
|
||
|
||
// 1. First, get the actual detailed API response
|
||
const [apps] = await connection.execute(`
|
||
SELECT
|
||
a.id, a.name, a.description, a.type, a.department as app_department,
|
||
a.creator_name as app_creator_name, a.creator_email as app_creator_email,
|
||
a.icon, a.icon_color, a.status, a.created_at,
|
||
u.id as user_id, u.name as user_name, u.email as user_email, u.department as user_department
|
||
FROM apps a LEFT JOIN users u ON a.creator_id = u.id
|
||
ORDER BY a.created_at DESC LIMIT 1
|
||
`);
|
||
|
||
if (apps.length === 0) {
|
||
console.log('No apps found in database');
|
||
return;
|
||
}
|
||
|
||
const app = apps[0];
|
||
console.log('Raw database data:');
|
||
console.log('app_department:', app.app_department);
|
||
console.log('app_creator_name:', app.app_creator_name);
|
||
console.log('user_department:', app.user_department);
|
||
console.log('user_name:', app.user_name);
|
||
console.log('type:', app.type);
|
||
console.log('icon:', app.icon);
|
||
console.log('icon_color:', app.icon_color);
|
||
console.log('');
|
||
|
||
// 2. Simulate the detailed API response structure (like /api/apps/[id])
|
||
const detailedAppData = {
|
||
id: app.id,
|
||
name: app.name,
|
||
description: app.description,
|
||
type: app.type, // This is the API type (English)
|
||
department: app.app_department, // This should be the app's department
|
||
icon: app.icon,
|
||
iconColor: app.icon_color,
|
||
status: app.status,
|
||
createdAt: app.created_at,
|
||
creator: {
|
||
id: app.user_id,
|
||
name: app.app_creator_name || app.user_name, // Prioritize app.creator_name
|
||
email: app.app_creator_email || app.user_email,
|
||
department: app.app_department || app.user_department, // Prioritize app.department
|
||
role: 'developer'
|
||
}
|
||
};
|
||
|
||
console.log('Simulated detailed API response:');
|
||
console.log('detailedAppData:', JSON.stringify(detailedAppData, null, 2));
|
||
console.log('');
|
||
|
||
// 3. Simulate the handleEditApp function processing
|
||
const handleEditApp = (app) => {
|
||
console.log('=== handleEditApp Debug ===');
|
||
console.log('Input app:', app);
|
||
console.log('app.type:', app.type);
|
||
console.log('app.department:', app.department);
|
||
console.log('app.creator:', app.creator);
|
||
console.log('app.icon:', app.icon);
|
||
console.log('app.iconColor:', app.iconColor);
|
||
|
||
// 處理類型轉換:如果類型是英文的,轉換為中文
|
||
let displayType = app.type;
|
||
if (app.type && !['文字處理', '圖像生成', '程式開發', '數據分析', '教育工具', '健康醫療', '金融科技', '物聯網', '區塊鏈', 'AR/VR', '機器學習', '電腦視覺', '自然語言處理', '機器人', '網路安全', '雲端服務', '其他'].includes(app.type)) {
|
||
displayType = mapApiTypeToDisplayType(app.type);
|
||
}
|
||
|
||
// 處理部門和創建者資料
|
||
let department = app.department;
|
||
let creator = app.creator;
|
||
|
||
// 如果 app.creator 是物件(來自詳細 API),提取名稱
|
||
if (app.creator && typeof app.creator === 'object') {
|
||
creator = app.creator.name || "";
|
||
// 優先使用應用程式的部門,而不是創建者的部門
|
||
department = app.department || app.creator.department || "";
|
||
}
|
||
|
||
const newAppData = {
|
||
name: app.name || "",
|
||
type: displayType || "文字處理",
|
||
department: department || "",
|
||
creator: creator || "",
|
||
description: app.description || "",
|
||
appUrl: app.appUrl || app.demoUrl || "",
|
||
icon: app.icon || "",
|
||
iconColor: app.iconColor || "",
|
||
}
|
||
|
||
console.log('newAppData:', newAppData);
|
||
return newAppData;
|
||
};
|
||
|
||
// 4. Test the type conversion function
|
||
const mapApiTypeToDisplayType = (apiType) => {
|
||
const typeMap = {
|
||
'productivity': '文字處理',
|
||
'ai_model': '圖像生成',
|
||
'automation': '程式開發',
|
||
'data_analysis': '數據分析',
|
||
'educational': '教育工具',
|
||
'healthcare': '健康醫療',
|
||
'finance': '金融科技',
|
||
'iot_device': '物聯網',
|
||
'blockchain': '區塊鏈',
|
||
'ar_vr': 'AR/VR',
|
||
'machine_learning': '機器學習',
|
||
'computer_vision': '電腦視覺',
|
||
'nlp': '自然語言處理',
|
||
'robotics': '機器人',
|
||
'cybersecurity': '網路安全',
|
||
'cloud_service': '雲端服務',
|
||
'other': '其他',
|
||
// Old English types
|
||
'web_app': '文字處理',
|
||
'mobile_app': '文字處理',
|
||
'desktop_app': '文字處理',
|
||
'api_service': '程式開發'
|
||
};
|
||
return typeMap[apiType] || '其他';
|
||
};
|
||
|
||
// 5. Process the detailed app data
|
||
const result = handleEditApp(detailedAppData);
|
||
|
||
console.log('\n=== Final Result ===');
|
||
console.log('Expected creator name:', app.app_creator_name || app.user_name);
|
||
console.log('Expected department:', app.app_department);
|
||
console.log('Actual result creator:', result.creator);
|
||
console.log('Actual result department:', result.department);
|
||
console.log('Actual result type:', result.type);
|
||
console.log('Actual result icon:', result.icon);
|
||
console.log('Actual result iconColor:', result.iconColor);
|
||
|
||
// 6. Verify the results
|
||
const expectedCreator = app.app_creator_name || app.user_name;
|
||
const expectedDepartment = app.app_department;
|
||
|
||
console.log('\n=== Verification ===');
|
||
console.log('Creator match:', result.creator === expectedCreator ? '✅ PASS' : '❌ FAIL');
|
||
console.log('Department match:', result.department === expectedDepartment ? '✅ PASS' : '❌ FAIL');
|
||
console.log('Type conversion:', result.type !== app.type ? '✅ PASS (converted)' : '⚠️ No conversion needed');
|
||
console.log('Icon preserved:', result.icon === app.icon ? '✅ PASS' : '❌ FAIL');
|
||
console.log('IconColor preserved:', result.iconColor === app.icon_color ? '✅ PASS' : '❌ FAIL');
|
||
|
||
await connection.end();
|
||
} catch (error) {
|
||
console.error('Test failed:', error);
|
||
}
|
||
};
|
||
|
||
simulateDetailedApiResponse();
|