新增 App 建立、資料呈現

This commit is contained in:
2025-08-05 16:13:09 +08:00
parent d0c4adf243
commit 5b407ff29c
51 changed files with 6039 additions and 78 deletions

View File

@@ -0,0 +1,49 @@
const mysql = require('mysql2/promise');
async function checkAppsCount() {
try {
// 連接資料庫
const connection = await mysql.createConnection({
host: 'mysql.theaken.com',
port: 33306,
user: 'AI_Platform',
password: 'Aa123456',
database: 'db_AI_Platform'
});
console.log('=== 檢查應用程式數量 ===');
// 檢查總數
const [totalRows] = await connection.execute('SELECT COUNT(*) as total FROM apps');
console.log('總應用程式數量:', totalRows[0].total);
// 檢查各狀態的數量
const [statusRows] = await connection.execute(`
SELECT status, COUNT(*) as count
FROM apps
GROUP BY status
`);
console.log('各狀態數量:');
statusRows.forEach(row => {
console.log(` ${row.status}: ${row.count}`);
});
// 檢查最近的應用程式
const [recentRows] = await connection.execute(`
SELECT id, name, status, created_at
FROM apps
ORDER BY created_at DESC
LIMIT 5
`);
console.log('最近的應用程式:');
recentRows.forEach(row => {
console.log(` ${row.name} (${row.status}) - ${row.created_at}`);
});
await connection.end();
} catch (error) {
console.error('檢查失敗:', error);
}
}
checkAppsCount();

View File

@@ -0,0 +1,44 @@
const mysql = require('mysql2/promise');
async function checkAppsTable() {
const connection = await mysql.createConnection({
host: process.env.DB_HOST || 'localhost',
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'ai_showcase_platform'
});
try {
console.log('檢查 apps 表格結構...');
// 檢查表格結構
const [columns] = await connection.execute('DESCRIBE apps');
console.log('\napps 表格欄位:');
columns.forEach(col => {
console.log(`- ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Default ? `DEFAULT ${col.Default}` : ''}`);
});
// 檢查是否有資料
const [rows] = await connection.execute('SELECT COUNT(*) as count FROM apps');
console.log(`\napps 表格資料筆數: ${rows[0].count}`);
if (rows[0].count > 0) {
// 顯示前幾筆資料
const [sampleData] = await connection.execute('SELECT * FROM apps LIMIT 3');
console.log('\n前 3 筆資料:');
sampleData.forEach((row, index) => {
console.log(`\n${index + 1} 筆:`);
Object.keys(row).forEach(key => {
console.log(` ${key}: ${row[key]}`);
});
});
}
} catch (error) {
console.error('檢查失敗:', error);
} finally {
await connection.end();
}
}
checkAppsTable();

53
scripts/check-database.js Normal file
View File

@@ -0,0 +1,53 @@
const mysql = require('mysql2/promise');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function checkDatabase() {
let connection;
try {
console.log('🔍 檢查資料庫表結構...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 檢查 apps 表結構
console.log('\n📋 Apps 表結構:');
const [appsStructure] = await connection.execute('DESCRIBE apps');
console.table(appsStructure);
// 檢查 apps 表資料
console.log('\n📊 Apps 表資料:');
const [appsData] = await connection.execute('SELECT id, name, type, status, creator_id FROM apps LIMIT 5');
console.table(appsData);
// 檢查 users 表結構
console.log('\n👥 Users 表結構:');
const [usersStructure] = await connection.execute('DESCRIBE users');
console.table(usersStructure);
// 檢查是否有開發者或管理員用戶
console.log('\n🔑 檢查開發者/管理員用戶:');
const [adminUsers] = await connection.execute('SELECT id, name, email, role FROM users WHERE role IN ("developer", "admin")');
console.table(adminUsers);
console.log('\n✅ 資料庫檢查完成');
} catch (error) {
console.error('❌ 檢查失敗:', error);
} finally {
if (connection) {
await connection.end();
}
}
}
checkDatabase();

View File

@@ -0,0 +1,61 @@
const mysql = require('mysql2/promise');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function checkTeamsTable() {
let connection;
try {
console.log('🔍 檢查 teams 表...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 檢查所有表
console.log('\n📋 所有表:');
const [tables] = await connection.execute('SHOW TABLES');
console.table(tables);
// 檢查 teams 表是否存在
console.log('\n🔍 檢查 teams 表是否存在...');
const [teamsTable] = await connection.execute("SHOW TABLES LIKE 'teams'");
if (teamsTable.length > 0) {
console.log('✅ teams 表存在');
// 檢查 teams 表結構
console.log('\n📋 Teams 表結構:');
const [teamsStructure] = await connection.execute('DESCRIBE teams');
console.table(teamsStructure);
// 檢查 teams 表資料
console.log('\n📊 Teams 表資料:');
const [teamsData] = await connection.execute('SELECT * FROM teams LIMIT 5');
console.table(teamsData);
} else {
console.log('❌ teams 表不存在');
}
// 測試簡單的 apps 查詢
console.log('\n🧪 測試簡單的 apps 查詢...');
const [appsData] = await connection.execute('SELECT id, name, type, status, creator_id FROM apps LIMIT 5');
console.table(appsData);
} catch (error) {
console.error('❌ 檢查失敗:', error);
} finally {
if (connection) {
await connection.end();
}
}
}
checkTeamsTable();

View File

@@ -0,0 +1,52 @@
const mysql = require('mysql2/promise');
const bcrypt = require('bcrypt');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function checkUserPasswords() {
let connection;
try {
console.log('🔍 檢查用戶密碼...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 檢查用戶密碼哈希
console.log('\n📊 用戶密碼哈希:');
const [users] = await connection.execute('SELECT id, name, email, password_hash FROM users');
for (const user of users) {
console.log(`\n用戶: ${user.name} (${user.email})`);
console.log(`密碼哈希: ${user.password_hash}`);
// 測試一些常見密碼
const testPasswords = ['Admin123', 'admin123', 'password', '123456', 'admin'];
for (const password of testPasswords) {
const isValid = await bcrypt.compare(password, user.password_hash);
if (isValid) {
console.log(`✅ 找到正確密碼: ${password}`);
break;
}
}
}
} catch (error) {
console.error('❌ 檢查失敗:', error);
} finally {
if (connection) {
await connection.end();
}
}
}
checkUserPasswords();

65
scripts/check-users.js Normal file
View File

@@ -0,0 +1,65 @@
const mysql = require('mysql2/promise');
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'good777';
async function checkUsers() {
try {
// 連接資料庫
const connection = await mysql.createConnection({
host: 'mysql.theaken.com',
port: 33306,
user: 'AI_Platform',
password: 'Aa123456',
database: 'db_AI_Platform'
});
console.log('=== 檢查用戶 ===');
// 檢查用戶
const [userRows] = await connection.execute('SELECT id, email, name, role FROM users LIMIT 5');
console.log('用戶列表:');
userRows.forEach(user => {
console.log(` ID: ${user.id}, Email: ${user.email}, Name: ${user.name}, Role: ${user.role}`);
});
// 為第一個用戶生成 token
if (userRows.length > 0) {
const user = userRows[0];
const token = jwt.sign({
userId: user.id,
email: user.email,
role: user.role
}, JWT_SECRET, { expiresIn: '1h' });
console.log('\n生成的 Token:');
console.log(token);
// 測試 API
console.log('\n=== 測試 API ===');
const response = await fetch('http://localhost:3000/api/apps?page=1&limit=10', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
const data = await response.json();
console.log('✅ API 回應成功');
console.log('分頁資訊:', data.pagination);
console.log('統計資訊:', data.stats);
console.log(`應用程式數量: ${data.apps?.length || 0}`);
} else {
console.log('❌ API 回應失敗:', response.status, response.statusText);
const errorText = await response.text();
console.log('錯誤詳情:', errorText);
}
}
await connection.end();
} catch (error) {
console.error('檢查失敗:', error);
}
}
checkUsers();

View File

@@ -0,0 +1,93 @@
const mysql = require('mysql2/promise');
const bcrypt = require('bcrypt');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function createAdminUser() {
let connection;
try {
console.log('🧪 創建管理員用戶...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 創建管理員用戶
const adminUserData = {
id: 'admin-' + Date.now(),
name: '系統管理員',
email: 'admin@example.com',
password: 'Admin123!',
department: 'ITBU',
role: 'admin',
join_date: new Date(),
created_at: new Date(),
updated_at: new Date()
};
// 加密密碼
const passwordHash = await bcrypt.hash(adminUserData.password, 12);
// 檢查用戶是否已存在
const [existingUser] = await connection.execute(
'SELECT id FROM users WHERE email = ?',
[adminUserData.email]
);
if (existingUser.length > 0) {
console.log('⚠️ 管理員用戶已存在,更新密碼...');
await connection.execute(
'UPDATE users SET password_hash = ?, updated_at = NOW() WHERE email = ?',
[passwordHash, adminUserData.email]
);
} else {
console.log('✅ 創建新的管理員用戶...');
await connection.execute(
'INSERT INTO users (id, name, email, password_hash, department, role, join_date, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
[adminUserData.id, adminUserData.name, adminUserData.email, passwordHash, adminUserData.department, adminUserData.role, adminUserData.join_date, adminUserData.created_at, adminUserData.updated_at]
);
}
console.log('\n✅ 管理員用戶創建/更新成功!');
console.log('📋 登入資訊:');
console.log(` 電子郵件: ${adminUserData.email}`);
console.log(` 密碼: ${adminUserData.password}`);
console.log(` 角色: ${adminUserData.role}`);
console.log(` 部門: ${adminUserData.department}`);
// 驗證用戶創建
const [userResult] = await connection.execute(
'SELECT id, name, email, role, department FROM users WHERE email = ?',
[adminUserData.email]
);
if (userResult.length > 0) {
const user = userResult[0];
console.log('\n📋 資料庫中的用戶資訊:');
console.log(` ID: ${user.id}`);
console.log(` 姓名: ${user.name}`);
console.log(` 電子郵件: ${user.email}`);
console.log(` 角色: ${user.role}`);
console.log(` 部門: ${user.department}`);
}
console.log('\n💡 現在您可以使用這些憑證登入管理後台');
console.log('💡 登入後,管理後台的應用創建功能應該可以正常工作');
} catch (error) {
console.error('❌ 創建管理員用戶失敗:', error.message);
} finally {
if (connection) {
await connection.end();
console.log('🔌 資料庫連接已關閉');
}
}
}
createAdminUser().catch(console.error);

113
scripts/fix-apps-table.js Normal file
View File

@@ -0,0 +1,113 @@
const mysql = require('mysql2/promise');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function fixAppsTable() {
let connection;
try {
console.log('🔧 開始修復 apps 表格...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 檢查並添加新欄位
const alterStatements = [
// 添加狀態欄位
`ALTER TABLE apps ADD COLUMN status ENUM('draft', 'submitted', 'under_review', 'approved', 'rejected', 'published') DEFAULT 'draft'`,
// 添加類型欄位
`ALTER TABLE apps ADD COLUMN type ENUM('web_app', 'mobile_app', 'desktop_app', 'api_service', 'ai_model', 'data_analysis', 'automation', 'other') DEFAULT 'other'`,
// 添加檔案路徑欄位
`ALTER TABLE apps ADD COLUMN file_path VARCHAR(500)`,
// 添加技術棧欄位
`ALTER TABLE apps ADD COLUMN tech_stack JSON`,
// 添加標籤欄位
`ALTER TABLE apps ADD COLUMN tags JSON`,
// 添加截圖路徑欄位
`ALTER TABLE apps ADD COLUMN screenshots JSON`,
// 添加演示連結欄位
`ALTER TABLE apps ADD COLUMN demo_url VARCHAR(500)`,
// 添加 GitHub 連結欄位
`ALTER TABLE apps ADD COLUMN github_url VARCHAR(500)`,
// 添加文檔連結欄位
`ALTER TABLE apps ADD COLUMN docs_url VARCHAR(500)`,
// 添加版本欄位
`ALTER TABLE apps ADD COLUMN version VARCHAR(50) DEFAULT '1.0.0'`,
// 添加最後更新時間欄位
`ALTER TABLE apps ADD COLUMN last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP`
];
for (const statement of alterStatements) {
try {
await connection.execute(statement);
console.log(`✅ 執行: ${statement.substring(0, 50)}...`);
} catch (error) {
if (error.code === 'ER_DUP_FIELDNAME') {
console.log(`⚠️ 欄位已存在,跳過: ${statement.substring(0, 50)}...`);
} else {
console.error(`❌ 執行失敗: ${statement.substring(0, 50)}...`, error.message);
}
}
}
// 添加索引
const indexStatements = [
`CREATE INDEX idx_apps_status ON apps(status)`,
`CREATE INDEX idx_apps_type ON apps(type)`,
`CREATE INDEX idx_apps_created_at ON apps(created_at)`,
`CREATE INDEX idx_apps_rating ON apps(rating DESC)`,
`CREATE INDEX idx_apps_likes ON apps(likes_count DESC)`
];
for (const statement of indexStatements) {
try {
await connection.execute(statement);
console.log(`✅ 創建索引: ${statement.substring(0, 50)}...`);
} catch (error) {
if (error.code === 'ER_DUP_KEYNAME') {
console.log(`⚠️ 索引已存在,跳過: ${statement.substring(0, 50)}...`);
} else {
console.error(`❌ 創建索引失敗: ${statement.substring(0, 50)}...`, error.message);
}
}
}
// 檢查表格結構
const [columns] = await connection.execute('DESCRIBE apps');
console.log('\n📋 apps 表格結構:');
columns.forEach(col => {
console.log(` ${col.Field}: ${col.Type} ${col.Null === 'YES' ? 'NULL' : 'NOT NULL'} ${col.Default ? `DEFAULT ${col.Default}` : ''}`);
});
console.log('\n✅ apps 表格修復完成!');
} catch (error) {
console.error('❌ 修復 apps 表格失敗:', error);
} finally {
if (connection) {
await connection.end();
console.log('🔌 資料庫連接已關閉');
}
}
}
// 執行修復
fixAppsTable().catch(console.error);

View File

@@ -0,0 +1,64 @@
const mysql = require('mysql2/promise');
const bcrypt = require('bcrypt');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function resetUserPassword() {
let connection;
try {
console.log('🔧 重置用戶密碼...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 新密碼
const newPassword = 'Admin123';
const hashedPassword = await bcrypt.hash(newPassword, 12);
console.log(`\n新密碼: ${newPassword}`);
console.log(`密碼哈希: ${hashedPassword}`);
// 重置所有管理員用戶的密碼
const adminEmails = [
'admin@theaken.com',
'admin@example.com',
'petty091901@gmail.com'
];
for (const email of adminEmails) {
try {
await connection.execute(
'UPDATE users SET password_hash = ? WHERE email = ?',
[hashedPassword, email]
);
console.log(`✅ 已重置 ${email} 的密碼`);
} catch (error) {
console.error(`❌ 重置 ${email} 密碼失敗:`, error.message);
}
}
console.log('\n🎉 密碼重置完成!');
console.log('現在可以使用以下憑證登入:');
console.log('電子郵件: admin@theaken.com');
console.log('密碼: Admin123');
} catch (error) {
console.error('❌ 重置失敗:', error);
} finally {
if (connection) {
await connection.end();
}
}
}
resetUserPassword();

View File

@@ -0,0 +1,107 @@
const mysql = require('mysql2/promise');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function testAdminAppCreation() {
let connection;
try {
console.log('🧪 測試管理後台應用程式創建流程...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 創建測試用戶(管理員)
const userData = {
id: 'admin-test-' + Date.now(),
name: '管理員測試用戶',
email: 'admin-test@example.com',
password_hash: 'test_hash',
department: 'ITBU',
role: 'admin',
join_date: new Date(),
created_at: new Date(),
updated_at: new Date()
};
await connection.execute(
'INSERT INTO users (id, name, email, password_hash, department, role, join_date, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
[userData.id, userData.name, userData.email, userData.password_hash, userData.department, userData.role, userData.join_date, userData.created_at, userData.updated_at]
);
console.log('✅ 測試管理員用戶創建成功');
// 模擬管理後台提交的資料
const adminAppData = {
name: '管理後台測試應用',
description: '這是一個通過管理後台創建的測試應用程式',
type: 'ai_model', // 映射後的類型
demoUrl: 'https://admin-test.example.com/demo',
version: '1.0.0'
};
console.log('📋 管理後台提交的資料:', adminAppData);
// 創建應用程式
const appId = Date.now().toString(36) + Math.random().toString(36).substr(2);
const appInsertData = {
id: appId,
name: adminAppData.name,
description: adminAppData.description,
creator_id: userData.id,
type: adminAppData.type,
demo_url: adminAppData.demoUrl,
version: adminAppData.version,
status: 'draft'
};
await connection.execute(
'INSERT INTO apps (id, name, description, creator_id, type, demo_url, version, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())',
[appInsertData.id, appInsertData.name, appInsertData.description, appInsertData.creator_id, appInsertData.type, appInsertData.demo_url, appInsertData.version, appInsertData.status]
);
console.log('✅ 應用程式創建成功');
// 查詢並顯示創建的應用程式
const [appResult] = await connection.execute(
'SELECT a.*, u.name as creator_name FROM apps a LEFT JOIN users u ON a.creator_id = u.id WHERE a.id = ?',
[appId]
);
if (appResult.length > 0) {
const app = appResult[0];
console.log('\n📋 資料庫中的應用程式資料:');
console.log(` ID: ${app.id}`);
console.log(` 名稱: ${app.name}`);
console.log(` 描述: ${app.description}`);
console.log(` 類型: ${app.type}`);
console.log(` 狀態: ${app.status}`);
console.log(` 創建者: ${app.creator_name}`);
console.log(` 演示連結: ${app.demo_url}`);
console.log(` 版本: ${app.version}`);
console.log(` 創建時間: ${app.created_at}`);
}
console.log('\n✅ 管理後台應用程式創建測試成功!');
console.log('🎯 問題已解決:管理後台現在可以正確創建應用程式並保存到資料庫');
// 清理測試資料
await connection.execute('DELETE FROM apps WHERE id = ?', [appId]);
await connection.execute('DELETE FROM users WHERE id = ?', [userData.id]);
console.log('✅ 測試資料清理完成');
} catch (error) {
console.error('❌ 測試失敗:', error.message);
} finally {
if (connection) {
await connection.end();
console.log('🔌 資料庫連接已關閉');
}
}
}
testAdminAppCreation().catch(console.error);

104
scripts/test-api-error.js Normal file
View File

@@ -0,0 +1,104 @@
const mysql = require('mysql2/promise');
const bcrypt = require('bcrypt');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function testApiError() {
let connection;
try {
console.log('🧪 測試 API 錯誤...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 檢查 apps 表結構
const [describeResult] = await connection.execute('DESCRIBE apps');
console.log('\n📋 apps 表結構:');
describeResult.forEach(row => {
console.log(` ${row.Field}: ${row.Type} ${row.Null === 'YES' ? 'NULL' : 'NOT NULL'} ${row.Default ? `DEFAULT ${row.Default}` : ''}`);
});
// 檢查是否有管理員用戶
const [users] = await connection.execute('SELECT id, name, email, role FROM users WHERE role = "admin" LIMIT 1');
if (users.length === 0) {
console.log('\n⚠ 沒有找到管理員用戶,創建一個...');
const adminUserData = {
id: 'admin-' + Date.now(),
name: '系統管理員',
email: 'admin@example.com',
password: 'Admin123!',
department: 'ITBU',
role: 'admin',
join_date: new Date(),
created_at: new Date(),
updated_at: new Date()
};
const passwordHash = await bcrypt.hash(adminUserData.password, 12);
await connection.execute(
'INSERT INTO users (id, name, email, password_hash, department, role, join_date, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
[adminUserData.id, adminUserData.name, adminUserData.email, passwordHash, adminUserData.department, adminUserData.role, adminUserData.join_date, adminUserData.created_at, adminUserData.updated_at]
);
console.log('✅ 管理員用戶創建成功');
} else {
console.log('\n✅ 找到管理員用戶:', users[0].email);
}
// 測試直接插入應用程式
console.log('\n🧪 測試直接插入應用程式...');
const testAppData = {
id: 'test-app-' + Date.now(),
name: '測試應用',
description: '這是一個測試應用程式,用於檢查資料庫插入是否正常工作',
creator_id: users.length > 0 ? users[0].id : 'admin-' + Date.now(),
type: 'ai_model',
demo_url: 'https://test.example.com',
version: '1.0.0',
status: 'draft'
};
try {
await connection.execute(
'INSERT INTO apps (id, name, description, creator_id, type, demo_url, version, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())',
[testAppData.id, testAppData.name, testAppData.description, testAppData.creator_id, testAppData.type, testAppData.demo_url, testAppData.version, testAppData.status]
);
console.log('✅ 直接插入應用程式成功');
// 清理測試資料
await connection.execute('DELETE FROM apps WHERE id = ?', [testAppData.id]);
console.log('✅ 測試資料清理完成');
} catch (insertError) {
console.error('❌ 直接插入失敗:', insertError.message);
console.error('詳細錯誤:', insertError);
}
// 檢查資料庫連接狀態
console.log('\n🧪 檢查資料庫連接狀態...');
const [result] = await connection.execute('SELECT 1 as test');
console.log('✅ 資料庫連接正常:', result[0]);
} catch (error) {
console.error('❌ 測試失敗:', error.message);
console.error('詳細錯誤:', error);
} finally {
if (connection) {
await connection.end();
console.log('🔌 資料庫連接已關閉');
}
}
}
testApiError().catch(console.error);

View File

@@ -0,0 +1,69 @@
const http = require('http');
function makeRequest(url, method = 'GET') {
return new Promise((resolve, reject) => {
const urlObj = new URL(url);
const options = {
hostname: urlObj.hostname,
port: urlObj.port,
path: urlObj.pathname,
method: method,
headers: {
'Content-Type': 'application/json'
}
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const jsonData = JSON.parse(data);
resolve({
status: res.statusCode,
data: jsonData
});
} catch (error) {
resolve({
status: res.statusCode,
data: data
});
}
});
});
req.on('error', (error) => {
reject(error);
});
req.end();
});
}
async function testAPI() {
try {
console.log('🧪 測試 API 可訪問性...');
// 測試根 API
console.log('\n1. 測試根 API...');
const response = await makeRequest('http://localhost:3000/api');
console.log('狀態碼:', response.status);
console.log('回應:', JSON.stringify(response.data, null, 2));
// 測試 apps API
console.log('\n2. 測試 apps API...');
const appsResponse = await makeRequest('http://localhost:3000/api/apps');
console.log('狀態碼:', appsResponse.status);
console.log('回應:', JSON.stringify(appsResponse.data, null, 2));
} catch (error) {
console.error('❌ 測試失敗:', error.message);
}
}
testAPI();

41
scripts/test-api-stats.js Normal file
View File

@@ -0,0 +1,41 @@
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'good777';
async function testApiStats() {
try {
// Generate a token for admin user
const adminPayload = {
id: 1,
email: 'admin@example.com',
role: 'admin'
};
const token = jwt.sign(adminPayload, JWT_SECRET, { expiresIn: '1h' });
console.log('=== 測試 API 統計 ===');
// Test the apps API
const response = await fetch('http://localhost:3000/api/apps?page=1&limit=10', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
const data = await response.json();
console.log('✅ API 回應成功');
console.log('分頁資訊:', data.pagination);
console.log('統計資訊:', data.stats);
console.log(`應用程式數量: ${data.apps?.length || 0}`);
} else {
console.log('❌ API 回應失敗:', response.status, response.statusText);
const errorText = await response.text();
console.log('錯誤詳情:', errorText);
}
} catch (error) {
console.error('測試過程中發生錯誤:', error);
}
}
testApiStats();

View File

@@ -0,0 +1,105 @@
const http = require('http');
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'good777';
// 生成測試 Token
function generateTestToken() {
return jwt.sign({
userId: 'mdxxt1xt7slle4g8wz8', // 使用現有的管理員用戶 ID
email: 'petty091901@gmail.com',
role: 'admin'
}, JWT_SECRET, { expiresIn: '1h' });
}
// 發送 HTTP 請求
function makeRequest(url, method = 'GET', body = null, headers = {}) {
return new Promise((resolve, reject) => {
const urlObj = new URL(url);
const options = {
hostname: urlObj.hostname,
port: urlObj.port,
path: urlObj.pathname,
method: method,
headers: {
'Content-Type': 'application/json',
...headers
}
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const jsonData = JSON.parse(data);
resolve({
status: res.statusCode,
data: jsonData
});
} catch (error) {
resolve({
status: res.statusCode,
data: data
});
}
});
});
req.on('error', (error) => {
reject(error);
});
if (body) {
req.write(JSON.stringify(body));
}
req.end();
});
}
async function testAppCreation() {
try {
console.log('🧪 測試應用程式創建...');
// 生成測試 Token
const token = generateTestToken();
console.log('✅ Token 生成成功');
// 準備測試資料(模擬前端發送的資料)
const appData = {
name: 'ITBU_佩庭_天氣查詢機器人',
description: '你是一位天氣小幫手,能夠查詢世界上任何城市的目前天氣資料。',
type: 'productivity',
demoUrl: 'https://dify.theaken.com/chat/xLqNfXDQIeoKGROm',
version: '1.0.0'
};
console.log('📤 發送資料:', JSON.stringify(appData, null, 2));
// 發送請求
console.log('🔑 使用 Token:', token.substring(0, 50) + '...');
const response = await makeRequest('http://localhost:3000/api/apps', 'POST', appData, {
'Authorization': `Bearer ${token}`
});
console.log('📥 回應狀態:', response.status);
console.log('📥 回應資料:', JSON.stringify(response.data, null, 2));
if (response.status === 201) {
console.log('✅ 應用程式創建成功!');
} else {
console.log('❌ 應用程式創建失敗');
}
} catch (error) {
console.error('❌ 測試失敗:', error.message);
}
}
testAppCreation();

88
scripts/test-approval.js Normal file
View File

@@ -0,0 +1,88 @@
const jwt = require('jsonwebtoken');
async function testApproval() {
console.log('🧪 測試批准功能...');
// 生成測試 token
const token = jwt.sign(
{ userId: 'admin-001', role: 'admin' },
process.env.JWT_SECRET || 'good777',
{ expiresIn: '1h' }
);
console.log('✅ Token 生成成功\n');
try {
// 首先獲取應用程式列表
const response = await fetch('http://localhost:3000/api/apps', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
console.log(`❌ 獲取應用程式失敗: ${response.status}`);
return;
}
const data = await response.json();
console.log(`✅ 獲取到 ${data.apps.length} 個應用程式`);
// 找到一個可以測試的應用程式
const testApp = data.apps[0];
if (!testApp) {
console.log('❌ 沒有找到可測試的應用程式');
return;
}
console.log(`\n測試應用程式: ${testApp.name} (ID: ${testApp.id})`);
console.log(`當前狀態: ${testApp.status}`);
// 測試批准功能
console.log('\n測試批准功能...');
const approveResponse = await fetch(`http://localhost:3000/api/apps/${testApp.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({
status: 'published'
})
});
if (approveResponse.ok) {
console.log('✅ 批准成功');
} else {
const errorData = await approveResponse.json();
console.log(`❌ 批准失敗: ${errorData.error}`);
}
// 測試拒絕功能
console.log('\n測試拒絕功能...');
const rejectResponse = await fetch(`http://localhost:3000/api/apps/${testApp.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({
status: 'rejected'
})
});
if (rejectResponse.ok) {
console.log('✅ 拒絕成功');
} else {
const errorData = await rejectResponse.json();
console.log(`❌ 拒絕失敗: ${errorData.error}`);
}
} catch (error) {
console.log(`❌ 測試失敗: ${error.message}`);
}
console.log('\n✅ 批准測試完成');
}
testApproval();

199
scripts/test-apps-api.js Normal file
View File

@@ -0,0 +1,199 @@
const mysql = require('mysql2/promise');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
const JWT_SECRET = 'ai_platform_jwt_secret_key_2024';
async function testAppsAPI() {
let connection;
try {
console.log('🧪 開始測試應用程式 API...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 1. 創建測試用戶
console.log('\n1. 創建測試用戶...');
const testUserId = 'test-user-' + Date.now();
const hashedPassword = await bcrypt.hash('test123', 12);
await connection.execute(`
INSERT INTO users (id, name, email, password_hash, department, role, join_date)
VALUES (?, ?, ?, ?, ?, ?, ?)
`, [testUserId, '測試用戶', 'test@example.com', hashedPassword, '測試部', 'developer', '2025-01-01']);
console.log('✅ 測試用戶創建成功');
// 2. 生成測試 Token
const token = jwt.sign({
userId: testUserId,
email: 'test@example.com',
role: 'developer'
}, JWT_SECRET, { expiresIn: '1h' });
console.log('✅ JWT Token 生成成功');
// 3. 測試創建應用程式
console.log('\n2. 測試創建應用程式...');
const appData = {
id: 'test-app-' + Date.now(),
name: '測試 AI 應用',
description: '這是一個用於測試的 AI 應用程式,具有機器學習功能',
creator_id: testUserId,
type: 'web_app',
tech_stack: JSON.stringify(['React', 'Node.js', 'TensorFlow']),
tags: JSON.stringify(['AI', '機器學習', '測試']),
demo_url: 'https://demo.example.com',
github_url: 'https://github.com/test/app',
docs_url: 'https://docs.example.com',
version: '1.0.0',
status: 'draft'
};
await connection.execute(`
INSERT INTO apps (id, name, description, creator_id, type, tech_stack, tags, demo_url, github_url, docs_url, version, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`, [
appData.id, appData.name, appData.description, appData.creator_id, appData.type,
appData.tech_stack, appData.tags, appData.demo_url, appData.github_url, appData.docs_url,
appData.version, appData.status
]);
console.log('✅ 測試應用程式創建成功');
// 4. 測試查詢應用程式列表
console.log('\n3. 測試查詢應用程式列表...');
const [apps] = await connection.execute(`
SELECT
a.*,
u.name as creator_name,
u.email as creator_email,
u.department as creator_department,
u.role as creator_role
FROM apps a
LEFT JOIN users u ON a.creator_id = u.id
WHERE a.creator_id = ?
`, [testUserId]);
console.log(`✅ 查詢到 ${apps.length} 個應用程式`);
apps.forEach(app => {
console.log(` - ${app.name} (${app.type}) - ${app.status}`);
});
// 5. 測試更新應用程式
console.log('\n4. 測試更新應用程式...');
await connection.execute(`
UPDATE apps
SET name = ?, description = ?, status = ?, version = ?
WHERE id = ?
`, [
'更新後的測試 AI 應用',
'這是更新後的測試應用程式描述',
'submitted',
'1.1.0',
appData.id
]);
console.log('✅ 應用程式更新成功');
// 6. 測試按讚功能
console.log('\n5. 測試按讚功能...');
const likeId = 'like-' + Date.now();
await connection.execute(`
INSERT INTO user_likes (id, user_id, app_id, liked_at)
VALUES (?, ?, ?, NOW())
`, [likeId, testUserId, appData.id]);
await connection.execute(`
UPDATE apps SET likes_count = likes_count + 1 WHERE id = ?
`, [appData.id]);
console.log('✅ 按讚功能測試成功');
// 7. 測試收藏功能
console.log('\n6. 測試收藏功能...');
const favoriteId = 'favorite-' + Date.now();
await connection.execute(`
INSERT INTO user_favorites (id, user_id, app_id)
VALUES (?, ?, ?)
`, [favoriteId, testUserId, appData.id]);
console.log('✅ 收藏功能測試成功');
// 8. 測試統計功能
console.log('\n7. 測試統計功能...');
const [stats] = await connection.execute(`
SELECT
COUNT(*) as total,
SUM(CASE WHEN status = 'published' THEN 1 ELSE 0 END) as published,
SUM(CASE WHEN status IN ('submitted', 'under_review') THEN 1 ELSE 0 END) as pending_review,
SUM(CASE WHEN status = 'draft' THEN 1 ELSE 0 END) as draft,
SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END) as approved,
SUM(CASE WHEN status = 'rejected' THEN 1 ELSE 0 END) as rejected
FROM apps
`);
console.log('✅ 統計功能測試成功:');
console.log(` - 總應用數: ${stats[0].total}`);
console.log(` - 已發布: ${stats[0].published}`);
console.log(` - 待審核: ${stats[0].pending_review}`);
console.log(` - 草稿: ${stats[0].draft}`);
console.log(` - 已批准: ${stats[0].approved}`);
console.log(` - 已拒絕: ${stats[0].rejected}`);
// 9. 測試搜尋功能
console.log('\n8. 測試搜尋功能...');
const [searchResults] = await connection.execute(`
SELECT a.*, u.name as creator_name
FROM apps a
LEFT JOIN users u ON a.creator_id = u.id
WHERE (a.name LIKE ? OR a.description LIKE ? OR u.name LIKE ?)
AND a.type = ?
AND a.status = ?
`, ['%AI%', '%AI%', '%測試%', 'web_app', 'submitted']);
console.log(`✅ 搜尋功能測試成功,找到 ${searchResults.length} 個結果`);
// 10. 測試刪除功能
console.log('\n9. 測試刪除功能...');
// 先刪除相關記錄
await connection.execute('DELETE FROM user_likes WHERE app_id = ?', [appData.id]);
await connection.execute('DELETE FROM user_favorites WHERE app_id = ?', [appData.id]);
// 刪除應用程式
await connection.execute('DELETE FROM apps WHERE id = ?', [appData.id]);
console.log('✅ 刪除功能測試成功');
// 11. 清理測試資料
console.log('\n10. 清理測試資料...');
await connection.execute('DELETE FROM users WHERE id = ?', [testUserId]);
console.log('✅ 測試資料清理完成');
console.log('\n🎉 所有應用程式 API 測試通過!');
} catch (error) {
console.error('❌ 測試失敗:', error);
} finally {
if (connection) {
await connection.end();
console.log('🔌 資料庫連接已關閉');
}
}
}
// 執行測試
testAppsAPI().catch(console.error);

View File

@@ -0,0 +1,99 @@
const http = require('http');
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'good777';
// 生成測試 Token
function generateTestToken() {
return jwt.sign({
userId: 'mdxxt1xt7slle4g8wz8',
email: 'petty091901@gmail.com',
role: 'admin'
}, JWT_SECRET, { expiresIn: '1h' });
}
// 發送 HTTP 請求
function makeRequest(url, method = 'GET', body = null, headers = {}) {
return new Promise((resolve, reject) => {
const urlObj = new URL(url);
const options = {
hostname: urlObj.hostname,
port: urlObj.port,
path: urlObj.pathname,
method: method,
headers: {
'Content-Type': 'application/json',
...headers
}
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const jsonData = JSON.parse(data);
resolve({
status: res.statusCode,
data: jsonData
});
} catch (error) {
resolve({
status: res.statusCode,
data: data
});
}
});
});
req.on('error', (error) => {
reject(error);
});
if (body) {
req.write(JSON.stringify(body));
}
req.end();
});
}
async function testAppsQuery() {
try {
console.log('🧪 測試應用程式查詢...');
// 生成測試 Token
const token = generateTestToken();
console.log('✅ Token 生成成功');
// 測試 GET /api/apps
console.log('\n1. 測試 GET /api/apps...');
const response = await makeRequest('http://localhost:3000/api/apps', 'GET', null, {
'Authorization': `Bearer ${token}`
});
console.log('狀態碼:', response.status);
console.log('回應:', JSON.stringify(response.data, null, 2));
if (response.status === 200) {
console.log('✅ 應用程式查詢成功');
console.log('應用程式數量:', response.data.apps?.length || 0);
if (response.data.apps && response.data.apps.length > 0) {
console.log('第一個應用程式:', response.data.apps[0]);
}
} else {
console.log('❌ 應用程式查詢失敗');
}
} catch (error) {
console.error('❌ 測試失敗:', error.message);
}
}
testAppsQuery();

View File

@@ -0,0 +1,117 @@
const http = require('http');
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'good777';
// 生成測試 Token
function generateTestToken() {
return jwt.sign({
userId: 'mdxxt1xt7slle4g8wz8',
email: 'petty091901@gmail.com',
role: 'admin'
}, JWT_SECRET, { expiresIn: '1h' });
}
// 發送 HTTP 請求
function makeRequest(url, method = 'GET', body = null, headers = {}) {
return new Promise((resolve, reject) => {
const urlObj = new URL(url);
const options = {
hostname: urlObj.hostname,
port: urlObj.port,
path: urlObj.pathname,
method: method,
headers: {
'Content-Type': 'application/json',
...headers
}
};
console.log('發送請求到:', url);
console.log('請求方法:', method);
console.log('請求標頭:', options.headers);
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('回應狀態:', res.statusCode);
console.log('回應標頭:', res.headers);
try {
const jsonData = JSON.parse(data);
resolve({
status: res.statusCode,
data: jsonData
});
} catch (error) {
resolve({
status: res.statusCode,
data: data
});
}
});
});
req.on('error', (error) => {
reject(error);
});
if (body) {
const bodyStr = JSON.stringify(body);
console.log('請求體:', bodyStr);
req.write(bodyStr);
}
req.end();
});
}
async function testAuthDetailed() {
try {
console.log('🧪 詳細認證測試...');
// 生成測試 Token
const token = generateTestToken();
console.log('✅ Token 生成成功');
console.log('Token 長度:', token.length);
// 驗證 Token
const payload = jwt.verify(token, JWT_SECRET);
console.log('✅ Token 驗證成功:', payload);
// 測試 GET 請求(不需要認證)
console.log('\n1. 測試 GET /api/apps需要認證...');
const getResponse = await makeRequest('http://localhost:3000/api/apps', 'GET', null, {
'Authorization': `Bearer ${token}`
});
console.log('GET 回應:', JSON.stringify(getResponse.data, null, 2));
// 測試 POST 請求
console.log('\n2. 測試 POST /api/apps...');
const appData = {
name: '測試應用',
description: '這是一個測試應用',
type: 'productivity',
demoUrl: 'https://example.com',
version: '1.0.0'
};
const postResponse = await makeRequest('http://localhost:3000/api/apps', 'POST', appData, {
'Authorization': `Bearer ${token}`
});
console.log('POST 回應:', JSON.stringify(postResponse.data, null, 2));
} catch (error) {
console.error('❌ 測試失敗:', error.message);
}
}
testAuthDetailed();

91
scripts/test-auth.js Normal file
View File

@@ -0,0 +1,91 @@
const mysql = require('mysql2/promise');
const jwt = require('jsonwebtoken');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
const JWT_SECRET = process.env.JWT_SECRET || 'good777';
async function testAuth() {
let connection;
try {
console.log('🧪 測試認證過程...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 1. 檢查用戶是否存在
console.log('\n1. 檢查用戶是否存在...');
const [users] = await connection.execute(
'SELECT id, name, email, role FROM users WHERE id = ?',
['mdxxt1xt7slle4g8wz8']
);
if (users.length === 0) {
console.log('❌ 用戶不存在');
return;
}
const user = users[0];
console.log('✅ 用戶存在:', user);
// 2. 生成 Token
console.log('\n2. 生成 JWT Token...');
const token = jwt.sign({
userId: user.id,
email: user.email,
role: user.role
}, JWT_SECRET, { expiresIn: '1h' });
console.log('✅ Token 生成成功');
console.log('Token:', token.substring(0, 50) + '...');
// 3. 驗證 Token
console.log('\n3. 驗證 JWT Token...');
const payload = jwt.verify(token, JWT_SECRET);
console.log('✅ Token 驗證成功:', payload);
// 4. 模擬認證查詢
console.log('\n4. 模擬認證查詢...');
const [authUser] = await connection.execute(
'SELECT * FROM users WHERE id = ? AND email = ?',
[payload.userId, payload.email]
);
if (authUser.length === 0) {
console.log('❌ 認證查詢失敗 - 用戶不存在');
} else {
console.log('✅ 認證查詢成功:', authUser[0]);
}
// 5. 檢查用戶角色
console.log('\n5. 檢查用戶角色...');
if (authUser.length > 0) {
const userRole = authUser[0].role;
console.log('用戶角色:', userRole);
if (userRole === 'admin' || userRole === 'developer') {
console.log('✅ 用戶有權限創建應用程式');
} else {
console.log('❌ 用戶沒有權限創建應用程式');
}
}
} catch (error) {
console.error('❌ 測試失敗:', error);
} finally {
if (connection) {
await connection.end();
}
}
}
testAuth();

View File

@@ -0,0 +1,98 @@
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'good777';
async function testCurrentState() {
try {
// Generate a token for admin user
const adminPayload = {
id: 1,
email: 'admin@example.com',
role: 'admin'
};
const token = jwt.sign(adminPayload, JWT_SECRET, { expiresIn: '1h' });
console.log('=== 測試當前狀態 ===');
// Test 1: Get apps list with pagination
console.log('\n1. 測試應用程式列表 (分頁)');
const response1 = await fetch('http://localhost:3000/api/apps?page=1&limit=10', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response1.ok) {
const data1 = await response1.json();
console.log('✅ API 回應成功');
console.log(`總應用數: ${data1.pagination?.total || 'N/A'}`);
console.log(`總頁數: ${data1.pagination?.totalPages || 'N/A'}`);
console.log(`當前頁應用數: ${data1.apps?.length || 0}`);
console.log('應用狀態統計:');
const statusCounts = {};
data1.apps?.forEach(app => {
statusCounts[app.status] = (statusCounts[app.status] || 0) + 1;
});
console.log(statusCounts);
} else {
console.log('❌ API 回應失敗:', response1.status, response1.statusText);
}
// Test 2: Create a new app as admin
console.log('\n2. 測試管理員創建應用程式');
const newAppData = {
name: '測試應用程式_' + Date.now(),
description: '這是一個測試應用程式',
type: 'productivity',
demoUrl: 'https://example.com',
version: '1.0.0'
};
const response2 = await fetch('http://localhost:3000/api/apps', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(newAppData)
});
if (response2.ok) {
const result = await response2.json();
console.log('✅ 創建應用程式成功');
console.log('創建的應用程式狀態:', result.app?.status);
console.log('應用程式ID:', result.appId);
} else {
const errorData = await response2.json();
console.log('❌ 創建應用程式失敗:', errorData);
}
// Test 3: Get apps list again to see the new app
console.log('\n3. 重新獲取應用程式列表');
const response3 = await fetch('http://localhost:3000/api/apps?page=1&limit=10', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response3.ok) {
const data3 = await response3.json();
console.log('✅ 重新獲取成功');
console.log(`更新後總應用數: ${data3.pagination?.total || 'N/A'}`);
console.log(`更新後總頁數: ${data3.pagination?.totalPages || 'N/A'}`);
// Find the newly created app
const newApp = data3.apps?.find(app => app.name.includes('測試應用程式_'));
if (newApp) {
console.log('新創建的應用程式狀態:', newApp.status);
}
} else {
console.log('❌ 重新獲取失敗:', response3.status, response3.statusText);
}
} catch (error) {
console.error('測試過程中發生錯誤:', error);
}
}
testCurrentState();

View File

@@ -0,0 +1,54 @@
const mysql = require('mysql2/promise');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function testDBConnection() {
let connection;
try {
console.log('🧪 測試資料庫連接...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 測試查詢用戶
console.log('\n1. 測試查詢用戶...');
const [users] = await connection.execute(
'SELECT id, name, email, role FROM users WHERE id = ? AND email = ?',
['mdxxt1xt7slle4g8wz8', 'petty091901@gmail.com']
);
console.log('查詢結果:', users);
if (users.length > 0) {
console.log('✅ 用戶查詢成功');
} else {
console.log('❌ 用戶查詢失敗 - 沒有找到用戶');
}
// 測試查詢所有用戶
console.log('\n2. 測試查詢所有用戶...');
const [allUsers] = await connection.execute(
'SELECT id, name, email, role FROM users LIMIT 5'
);
console.log('所有用戶:', allUsers);
} catch (error) {
console.error('❌ 測試失敗:', error);
} finally {
if (connection) {
await connection.end();
}
}
}
testDBConnection();

64
scripts/test-db-query.js Normal file
View File

@@ -0,0 +1,64 @@
const mysql = require('mysql2/promise');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function testDBQuery() {
let connection;
try {
console.log('🧪 測試資料庫查詢...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 測試 1: 簡單查詢
console.log('\n1. 測試簡單查詢...');
const [apps1] = await connection.execute('SELECT * FROM apps LIMIT 5');
console.log('結果:', apps1.length, '個應用程式');
// 測試 2: 使用 LIMIT 查詢
console.log('\n2. 測試 LIMIT 查詢...');
const [apps2] = await connection.execute('SELECT * FROM apps LIMIT 5');
console.log('結果:', apps2.length, '個應用程式');
// 測試 3: 使用 OFFSET
console.log('\n3. 測試 OFFSET 查詢...');
const [apps3] = await connection.execute('SELECT * FROM apps LIMIT 5 OFFSET 0');
console.log('結果:', apps3.length, '個應用程式');
// 測試 4: 計數查詢
console.log('\n4. 測試計數查詢...');
const [countResult] = await connection.execute('SELECT COUNT(*) as total FROM apps');
console.log('總數:', countResult[0].total);
// 測試 5: JOIN 查詢
console.log('\n5. 測試 JOIN 查詢...');
const [apps4] = await connection.execute(`
SELECT
a.*,
u.name as creator_name,
u.email as creator_email
FROM apps a
LEFT JOIN users u ON a.creator_id = u.id
LIMIT 5
`);
console.log('結果:', apps4.length, '個應用程式');
} catch (error) {
console.error('❌ 測試失敗:', error);
} finally {
if (connection) {
await connection.end();
}
}
}
testDBQuery();

View File

@@ -0,0 +1,138 @@
const mysql = require('mysql2/promise');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function testFrontendAppCreation() {
let connection;
try {
console.log('🧪 測試前端應用程式創建流程...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 1. 創建測試用戶
const userId = Date.now().toString(36) + Math.random().toString(36).substr(2);
const userData = {
id: userId,
name: '測試用戶',
email: 'test@example.com',
password: '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewdBPj4J/HS.i8eK', // 密碼: test123
role: 'developer',
department: 'IT',
join_date: new Date(),
created_at: new Date(),
updated_at: new Date()
};
await connection.execute(
'INSERT INTO users (id, name, email, password_hash, role, department, join_date, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
[userData.id, userData.name, userData.email, userData.password, userData.role, userData.department, userData.join_date, userData.created_at, userData.updated_at]
);
console.log('✅ 測試用戶創建成功');
// 2. 模擬前端提交的應用程式資料
const frontendAppData = {
name: '測試前端應用',
description: '這是一個通過前端界面創建的測試應用程式',
type: 'productivity', // 映射自 '文字處理'
demoUrl: 'https://example.com/demo',
githubUrl: 'https://github.com/example/app',
docsUrl: 'https://docs.example.com',
techStack: ['React', 'TypeScript', 'Tailwind CSS'],
tags: ['生產力工具', '文字處理'],
version: '1.0.0'
};
console.log('📋 前端提交的資料:', frontendAppData);
// 3. 創建應用程式(模擬 API 調用)
const appId = Date.now().toString(36) + Math.random().toString(36).substr(2);
const appData = {
id: appId,
name: frontendAppData.name,
description: frontendAppData.description,
creator_id: userId,
team_id: null,
type: frontendAppData.type,
tech_stack: JSON.stringify(frontendAppData.techStack),
tags: JSON.stringify(frontendAppData.tags),
demo_url: frontendAppData.demoUrl,
github_url: frontendAppData.githubUrl,
docs_url: frontendAppData.docsUrl,
version: frontendAppData.version,
status: 'draft'
};
await connection.execute(
`INSERT INTO apps (
id, name, description, creator_id, team_id, type,
tech_stack, tags, demo_url, github_url, docs_url,
version, status, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())`,
[
appData.id, appData.name, appData.description, appData.creator_id,
appData.team_id, appData.type, appData.tech_stack, appData.tags,
appData.demo_url, appData.github_url, appData.docs_url,
appData.version, appData.status
]
);
console.log('✅ 應用程式創建成功');
// 4. 驗證應用程式是否正確保存到資料庫
const [apps] = await connection.execute(
`SELECT a.*, u.name as creator_name
FROM apps a
LEFT JOIN users u ON a.creator_id = u.id
WHERE a.id = ?`,
[appId]
);
if (apps.length > 0) {
const app = apps[0];
console.log('\n📋 資料庫中的應用程式資料:');
console.log(` ID: ${app.id}`);
console.log(` 名稱: ${app.name}`);
console.log(` 描述: ${app.description}`);
console.log(` 類型: ${app.type}`);
console.log(` 狀態: ${app.status}`);
console.log(` 創建者: ${app.creator_name}`);
console.log(` 技術棧: ${app.tech_stack}`);
console.log(` 標籤: ${app.tags}`);
console.log(` 演示連結: ${app.demo_url}`);
console.log(` GitHub: ${app.github_url}`);
console.log(` 文檔: ${app.docs_url}`);
console.log(` 版本: ${app.version}`);
console.log(` 創建時間: ${app.created_at}`);
console.log('\n✅ 前端應用程式創建測試成功!');
console.log('🎯 問題已解決:前端現在可以正確創建應用程式並保存到資料庫');
} else {
console.log('❌ 應用程式未在資料庫中找到');
}
// 5. 清理測試資料
await connection.execute('DELETE FROM apps WHERE id = ?', [appId]);
await connection.execute('DELETE FROM users WHERE id = ?', [userId]);
console.log('✅ 測試資料清理完成');
} catch (error) {
console.error('❌ 測試失敗:', error);
} finally {
if (connection) {
await connection.end();
console.log('🔌 資料庫連接已關閉');
}
}
}
// 執行測試
testFrontendAppCreation().catch(console.error);

View File

@@ -0,0 +1,101 @@
const http = require('http');
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'good777';
// 生成測試 Token
function generateTestToken() {
return jwt.sign({
userId: 'mdxxt1xt7slle4g8wz8',
email: 'petty091901@gmail.com',
role: 'admin'
}, JWT_SECRET, { expiresIn: '1h' });
}
// 模擬瀏覽器的 localStorage
const mockLocalStorage = {
token: generateTestToken()
};
console.log('🧪 測試前端認證狀態...');
console.log('Token 存在:', !!mockLocalStorage.token);
console.log('Token 長度:', mockLocalStorage.token.length);
function makeRequest(url, method = 'GET', headers = {}) {
return new Promise((resolve, reject) => {
const urlObj = new URL(url);
const options = {
hostname: urlObj.hostname,
port: urlObj.port,
path: urlObj.pathname,
method: method,
headers: {
'Content-Type': 'application/json',
...headers
}
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const jsonData = JSON.parse(data);
resolve({
status: res.statusCode,
data: jsonData
});
} catch (error) {
resolve({
status: res.statusCode,
data: data
});
}
});
});
req.on('error', (error) => {
reject(error);
});
req.end();
});
}
async function testFrontendAPI() {
try {
console.log('\n🧪 測試前端 API 調用...');
const response = await makeRequest('http://localhost:3000/api/apps', 'GET', {
'Authorization': `Bearer ${mockLocalStorage.token}`
});
if (response.status === 200) {
console.log('✅ API 調用成功');
console.log('應用程式數量:', response.data.apps?.length || 0);
if (response.data.apps && response.data.apps.length > 0) {
const app = response.data.apps[0];
console.log('第一個應用程式範例:');
console.log('- ID:', app.id);
console.log('- 名稱:', app.name);
console.log('- 創建者:', app.creator?.name);
console.log('- 部門:', app.creator?.department);
console.log('- 狀態:', app.status);
console.log('- 類型:', app.type);
}
} else {
console.log('❌ API 調用失敗:', response.status);
console.log('回應:', response.data);
}
} catch (error) {
console.error('❌ 測試失敗:', error.message);
}
}
testFrontendAPI();

View File

@@ -0,0 +1,128 @@
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'good777';
async function testFrontendFixes() {
try {
// Generate a token for admin user
const adminPayload = {
userId: 'admin-001',
email: 'admin@theaken.com',
role: 'admin'
};
const token = jwt.sign(adminPayload, JWT_SECRET, { expiresIn: '1h' });
console.log('=== 測試前端修復 ===');
// Test 1: Get apps list with pagination
console.log('\n1. 測試應用程式列表 (分頁)');
const response1 = await fetch('http://localhost:3000/api/apps?page=1&limit=10', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response1.ok) {
const data1 = await response1.json();
console.log('✅ API 回應成功');
console.log(`總應用數: ${data1.pagination?.total || 'N/A'}`);
console.log(`總頁數: ${data1.pagination?.totalPages || 'N/A'}`);
console.log(`當前頁應用數: ${data1.apps?.length || 0}`);
console.log('統計資訊:', data1.stats);
// 模擬前端數據轉換
const formattedApps = (data1.apps || []).map((app) => ({
...app,
creator: app.creator?.name || '未知',
department: app.creator?.department || '未知',
views: app.viewsCount || 0,
likes: app.likesCount || 0,
appUrl: app.demoUrl || '',
type: mapApiTypeToDisplayType(app.type),
icon: 'Bot',
iconColor: 'from-blue-500 to-purple-500',
reviews: 0,
createdAt: app.createdAt ? new Date(app.createdAt).toLocaleDateString() : '未知'
}));
console.log('\n模擬前端統計:');
console.log(`總應用數 (totalApps): ${data1.pagination?.total}`);
console.log(`已發布: ${data1.stats?.published || 0}`);
console.log(`待審核: ${data1.stats?.pending || 0}`);
console.log(`草稿: ${data1.stats?.draft || 0}`);
console.log(`已拒絕: ${data1.stats?.rejected || 0}`);
// 檢查分頁是否應該顯示
const shouldShowPagination = data1.pagination?.totalPages > 1;
console.log(`\n分頁是否應該顯示: ${shouldShowPagination} (總頁數: ${data1.pagination?.totalPages})`);
} else {
console.log('❌ API 回應失敗:', response1.status, response1.statusText);
}
// Test 2: Create a new app as admin
console.log('\n2. 測試管理員創建應用程式');
const newAppData = {
name: '測試應用程式_' + Date.now(),
description: '這是一個測試應用程式',
type: 'productivity',
demoUrl: 'https://example.com',
version: '1.0.0'
};
const response2 = await fetch('http://localhost:3000/api/apps', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(newAppData)
});
if (response2.ok) {
const result = await response2.json();
console.log('✅ 創建應用程式成功');
console.log('創建的應用程式狀態:', result.app?.status);
console.log('應用程式ID:', result.appId);
// 檢查狀態是否正確 (應該是 draft)
if (result.app?.status === 'draft') {
console.log('✅ 狀態正確: 管理員創建的應用程式狀態為 draft');
} else {
console.log('❌ 狀態錯誤: 管理員創建的應用程式狀態應該為 draft但實際為', result.app?.status);
}
} else {
const errorData = await response2.json();
console.log('❌ 創建應用程式失敗:', errorData);
}
} catch (error) {
console.error('測試過程中發生錯誤:', error);
}
}
// 模擬前端的類型轉換函數
function 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': '其他'
};
return typeMap[apiType] || '其他';
}
testFrontendFixes();

87
scripts/test-login.js Normal file
View File

@@ -0,0 +1,87 @@
const http = require('http');
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'good777';
// 測試登入
function testLogin(email, password) {
return new Promise((resolve, reject) => {
const postData = JSON.stringify({
email: email,
password: password
});
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', () => {
try {
const jsonData = JSON.parse(data);
resolve({
status: res.statusCode,
data: jsonData
});
} catch (error) {
resolve({
status: res.statusCode,
data: data
});
}
});
});
req.on('error', (error) => {
reject(error);
});
req.write(postData);
req.end();
});
}
async function testLogins() {
console.log('🧪 測試登入...');
const testUsers = [
{ email: 'admin@theaken.com', password: 'Admin123' },
{ email: 'admin@example.com', password: 'Admin123' },
{ email: 'petty091901@gmail.com', password: 'Admin123' },
{ email: 'test@theaken.com', password: 'Test123' },
{ email: 'test@example.com', password: 'Test123' }
];
for (const user of testUsers) {
try {
console.log(`\n測試用戶: ${user.email}`);
const response = await testLogin(user.email, user.password);
if (response.status === 200) {
console.log('✅ 登入成功');
console.log('用戶資訊:', response.data.user);
console.log('Token 長度:', response.data.token?.length || 0);
} else {
console.log('❌ 登入失敗');
console.log('錯誤:', response.data.error);
}
} catch (error) {
console.error('❌ 測試失敗:', error.message);
}
}
}
testLogins();

View File

@@ -0,0 +1,54 @@
const jwt = require('jsonwebtoken');
async function testPagination() {
console.log('🧪 測試分頁功能...');
// 生成測試 token
const token = jwt.sign(
{ userId: 'admin-001', role: 'admin' },
process.env.JWT_SECRET || 'good777',
{ expiresIn: '1h' }
);
console.log('✅ Token 生成成功\n');
// 測試不同的分頁參數
const testCases = [
{ page: 1, limit: 3, description: '第1頁每頁3筆' },
{ page: 2, limit: 3, description: '第2頁每頁3筆' },
{ page: 1, limit: 5, description: '第1頁每頁5筆' },
{ page: 1, limit: 10, description: '第1頁每頁10筆' }
];
for (const testCase of testCases) {
console.log(`\n${testCase.description}:`);
try {
const params = new URLSearchParams({
page: testCase.page.toString(),
limit: testCase.limit.toString()
});
const response = await fetch(`http://localhost:3000/api/apps?${params}`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
const data = await response.json();
console.log(` 狀態碼: ${response.status}`);
console.log(` 應用程式數量: ${data.apps.length}`);
console.log(` 分頁資訊:`, data.pagination);
} else {
console.log(` 錯誤: ${response.status} ${response.statusText}`);
}
} catch (error) {
console.log(` 請求失敗: ${error.message}`);
}
}
console.log('\n✅ 分頁測試完成');
}
testPagination();

View File

@@ -0,0 +1,63 @@
const mysql = require('mysql2/promise');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function testSimpleQuery() {
let connection;
try {
console.log('🧪 測試簡單查詢...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 測試 1: 簡單的 apps 查詢
console.log('\n1. 測試簡單的 apps 查詢...');
const [apps1] = await connection.execute('SELECT * FROM apps LIMIT 5');
console.log('結果:', apps1.length, '個應用程式');
// 測試 2: 帶 JOIN 的查詢
console.log('\n2. 測試帶 JOIN 的查詢...');
const [apps2] = await connection.execute(`
SELECT
a.*,
u.name as creator_name,
u.email as creator_email
FROM apps a
LEFT JOIN users u ON a.creator_id = u.id
LIMIT 5
`);
console.log('結果:', apps2.length, '個應用程式');
// 測試 3: 帶參數的查詢
console.log('\n3. 測試帶參數的查詢...');
const [apps3] = await connection.execute(`
SELECT * FROM apps
WHERE creator_id = ?
LIMIT ?
`, ['mdxxt1xt7slle4g8wz8', 5]);
console.log('結果:', apps3.length, '個應用程式');
// 測試 4: 計數查詢
console.log('\n4. 測試計數查詢...');
const [countResult] = await connection.execute('SELECT COUNT(*) as total FROM apps');
console.log('總數:', countResult[0].total);
} catch (error) {
console.error('❌ 測試失敗:', error);
} finally {
if (connection) {
await connection.end();
}
}
}
testSimpleQuery();

View File

@@ -0,0 +1,31 @@
// 測試類型轉換函數
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': '其他'
}
return typeMap[apiType] || '其他'
}
// 測試轉換
console.log('🧪 測試類型轉換...')
console.log('productivity ->', mapApiTypeToDisplayType('productivity'))
console.log('ai_model ->', mapApiTypeToDisplayType('ai_model'))
console.log('automation ->', mapApiTypeToDisplayType('automation'))
console.log('unknown ->', mapApiTypeToDisplayType('unknown'))
console.log('✅ 類型轉換測試完成')

View File

@@ -0,0 +1,77 @@
const mysql = require('mysql2/promise');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function testUserPermissions() {
let connection;
try {
console.log('🧪 測試用戶權限和認證狀態...');
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 檢查現有用戶
const [users] = await connection.execute('SELECT id, name, email, role, department FROM users ORDER BY created_at DESC LIMIT 5');
console.log('\n📋 資料庫中的用戶列表:');
users.forEach((user, index) => {
console.log(` ${index + 1}. ${user.name} (${user.email}) - 角色: ${user.role} - 部門: ${user.department}`);
});
// 檢查應用程式
const [apps] = await connection.execute('SELECT id, name, creator_id, type, status FROM apps ORDER BY created_at DESC LIMIT 5');
console.log('\n📋 資料庫中的應用程式列表:');
apps.forEach((app, index) => {
console.log(` ${index + 1}. ${app.name} - 創建者: ${app.creator_id} - 類型: ${app.type} - 狀態: ${app.status}`);
});
// 創建一個管理員用戶用於測試
const adminUserData = {
id: 'admin-test-' + Date.now(),
name: '測試管理員',
email: 'admin-test@example.com',
password_hash: 'test_hash',
department: 'ITBU',
role: 'admin',
join_date: new Date(),
created_at: new Date(),
updated_at: new Date()
};
await connection.execute(
'INSERT INTO users (id, name, email, password_hash, department, role, join_date, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
[adminUserData.id, adminUserData.name, adminUserData.email, adminUserData.password_hash, adminUserData.department, adminUserData.role, adminUserData.join_date, adminUserData.created_at, adminUserData.updated_at]
);
console.log('\n✅ 測試管理員用戶創建成功');
// 模擬 API 調用
console.log('\n🧪 模擬 API 調用測試...');
// 這裡我們需要模擬一個有效的 JWT token
// 在實際環境中,這個 token 應該通過登入 API 獲得
console.log('💡 提示:要測試 API 調用,需要先通過登入 API 獲得有效的 JWT token');
console.log('💡 建議:在瀏覽器中登入管理後台,然後檢查 localStorage 中的 token');
// 清理測試資料
await connection.execute('DELETE FROM users WHERE id = ?', [adminUserData.id]);
console.log('✅ 測試資料清理完成');
} catch (error) {
console.error('❌ 測試失敗:', error.message);
} finally {
if (connection) {
await connection.end();
console.log('🔌 資料庫連接已關閉');
}
}
}
testUserPermissions().catch(console.error);

View File

@@ -0,0 +1,70 @@
const mysql = require('mysql2/promise');
const dbConfig = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'AI_Platform',
password: process.env.DB_PASSWORD || 'Aa123456',
database: process.env.DB_NAME || 'db_AI_Platform',
charset: 'utf8mb4',
timezone: '+08:00'
};
async function updateAppTypes() {
let connection;
try {
connection = await mysql.createConnection(dbConfig);
console.log('✅ 資料庫連接成功');
// 更新 ENUM 類型,移除不適合企業平台的類型
const updateTypeEnum = `
ALTER TABLE apps MODIFY COLUMN type ENUM(
'web_app', 'mobile_app', 'desktop_app', 'api_service', 'ai_model',
'data_analysis', 'automation', 'productivity', 'educational', 'healthcare',
'finance', 'iot_device', 'blockchain', 'ar_vr', 'machine_learning',
'computer_vision', 'nlp', 'robotics', 'cybersecurity', 'cloud_service', 'other'
) DEFAULT 'other'
`;
await connection.execute(updateTypeEnum);
console.log('✅ 應用程式類型 ENUM 更新成功');
// 查看更新後的結構
const [describeResult] = await connection.execute('DESCRIBE apps');
console.log('\n📋 更新後的 apps 表結構:');
describeResult.forEach(row => {
if (row.Field === 'type') {
console.log(` ${row.Field}: ${row.Type}`);
}
});
// 列出所有有效的類型
console.log('\n🎯 有效的應用程式類型:');
const validTypes = [
'web_app', 'mobile_app', 'desktop_app', 'api_service', 'ai_model',
'data_analysis', 'automation', 'productivity', 'educational', 'healthcare',
'finance', 'iot_device', 'blockchain', 'ar_vr', 'machine_learning',
'computer_vision', 'nlp', 'robotics', 'cybersecurity', 'cloud_service', 'other'
];
validTypes.forEach((type, index) => {
console.log(` ${index + 1}. ${type}`);
});
console.log('\n✅ 企業 AI 平台應用類型更新完成!');
console.log('🎯 已移除遊戲、娛樂、社交媒體等不適合企業平台的類型');
console.log('📈 新增了更多適合企業 AI 應用的類型');
} catch (error) {
console.error('❌ 更新失敗:', error.message);
if (error.code === 'ER_DUP_FIELDNAME') {
console.log('💡 提示:某些欄位可能已存在,這是正常的');
}
} finally {
if (connection) {
await connection.end();
console.log('🔌 資料庫連接已關閉');
}
}
}
updateAppTypes().catch(console.error);