first commit
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
const bcrypt = require('bcryptjs');
|
||||
|
||||
async function createPasswordHash() {
|
||||
const password = 'admin123';
|
||||
const saltRounds = 10;
|
||||
|
||||
try {
|
||||
const hash = await bcrypt.hash(password, saltRounds);
|
||||
console.log('密码:', password);
|
||||
console.log('生成的哈希:', hash);
|
||||
|
||||
// 验证哈希是否正确
|
||||
const isValid = await bcrypt.compare(password, hash);
|
||||
console.log('验证结果:', isValid);
|
||||
|
||||
return hash;
|
||||
} catch (error) {
|
||||
console.error('生成密码哈希失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
createPasswordHash();
|
||||
@@ -0,0 +1,399 @@
|
||||
const { createClient } = require('@supabase/supabase-js');
|
||||
|
||||
// 颜色输出函数
|
||||
const colors = {
|
||||
red: (text) => `\x1b[31m${text}\x1b[0m`,
|
||||
green: (text) => `\x1b[32m${text}\x1b[0m`,
|
||||
yellow: (text) => `\x1b[33m${text}\x1b[0m`,
|
||||
blue: (text) => `\x1b[34m${text}\x1b[0m`,
|
||||
cyan: (text) => `\x1b[36m${text}\x1b[0m`,
|
||||
bold: (text) => `\x1b[1m${text}\x1b[0m`
|
||||
};
|
||||
|
||||
async function testAdminConnection() {
|
||||
console.log(colors.bold('\n🔍 测试后台管理端 Supabase 连接...\n'));
|
||||
|
||||
// Supabase配置 - 与客户端使用相同的配置
|
||||
const supabaseUrl = 'https://riwtulmitqioswmgwftg.supabase.co';
|
||||
const supabaseKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJpd3R1bG1pdHFpb3N3bWd3ZnRnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDg1OTc1ODgsImV4cCI6MjA2NDE3MzU4OH0.fxSW_uEbpR1zwepjb83DIUIwTrmsboK2nTjPpS6XMtw';
|
||||
|
||||
console.log(colors.cyan('📡 Supabase URL:'), supabaseUrl);
|
||||
console.log(colors.cyan('🔑 API Key:'), supabaseKey.substring(0, 20) + '...');
|
||||
|
||||
// 创建客户端
|
||||
const supabase = createClient(supabaseUrl, supabaseKey);
|
||||
|
||||
try {
|
||||
// 1. 测试基本连接
|
||||
console.log(colors.blue('\n🔄 测试基本数据库连接...'));
|
||||
const { data: rates, error: ratesError } = await supabase
|
||||
.from('rates')
|
||||
.select('service_type, price_per_minute, currency')
|
||||
.limit(5);
|
||||
|
||||
if (ratesError) {
|
||||
console.log(colors.red('❌ 数据库连接失败:'), ratesError.message);
|
||||
throw ratesError;
|
||||
}
|
||||
|
||||
console.log(colors.green('✅ 基本连接成功,费率数据:'));
|
||||
rates.forEach(rate => {
|
||||
console.log(colors.cyan(` - ${rate.service_type}: $${rate.price_per_minute}/${rate.currency}`));
|
||||
});
|
||||
|
||||
// 2. 测试管理端需要的数据表
|
||||
console.log(colors.blue('\n🔄 测试管理端数据表访问...'));
|
||||
|
||||
const tables = [
|
||||
{ name: 'profiles', description: '用户资料' },
|
||||
{ name: 'calls', description: '通话记录' },
|
||||
{ name: 'translations', description: '翻译记录' },
|
||||
{ name: 'payments', description: '支付记录' },
|
||||
{ name: 'interpreters', description: '口译员信息' }
|
||||
];
|
||||
|
||||
for (const table of tables) {
|
||||
try {
|
||||
const { count, error } = await supabase
|
||||
.from(table.name)
|
||||
.select('*', { count: 'exact', head: true });
|
||||
|
||||
if (error) throw error;
|
||||
console.log(colors.green(`✅ ${table.description} (${table.name}): ${count || 0} 条记录`));
|
||||
} catch (error) {
|
||||
console.log(colors.red(`❌ ${table.description} (${table.name}): ${error.message}`));
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 测试统计数据查询
|
||||
console.log(colors.blue('\n🔄 测试统计数据查询...'));
|
||||
|
||||
const [
|
||||
{ count: totalUsers },
|
||||
{ count: totalCalls },
|
||||
{ count: totalInterpreters },
|
||||
{ data: recentPayments }
|
||||
] = await Promise.all([
|
||||
supabase.from('profiles').select('*', { count: 'exact', head: true }),
|
||||
supabase.from('calls').select('*', { count: 'exact', head: true }),
|
||||
supabase.from('interpreters').select('*', { count: 'exact', head: true }),
|
||||
supabase.from('payments').select('amount').eq('status', 'completed').limit(10)
|
||||
]);
|
||||
|
||||
const totalRevenue = recentPayments?.reduce((sum, payment) => sum + payment.amount, 0) || 0;
|
||||
|
||||
console.log(colors.green('📊 系统统计数据:'));
|
||||
console.log(colors.cyan(` - 总用户数: ${totalUsers || 0}`));
|
||||
console.log(colors.cyan(` - 总通话数: ${totalCalls || 0}`));
|
||||
console.log(colors.cyan(` - 口译员数: ${totalInterpreters || 0}`));
|
||||
console.log(colors.cyan(` - 总收入: $${totalRevenue.toFixed(2)}`));
|
||||
|
||||
// 4. 测试实时订阅功能
|
||||
console.log(colors.blue('\n🔄 测试实时数据订阅...'));
|
||||
|
||||
const channel = supabase
|
||||
.channel('admin-test')
|
||||
.on('postgres_changes', { event: '*', schema: 'public', table: 'calls' }, (payload) => {
|
||||
console.log(colors.yellow('📢 实时数据更新:'), payload);
|
||||
})
|
||||
.subscribe();
|
||||
|
||||
// 等待订阅建立
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
console.log(colors.green('✅ 实时订阅功能正常'));
|
||||
|
||||
// 清理订阅
|
||||
supabase.removeChannel(channel);
|
||||
|
||||
// 总结
|
||||
console.log(colors.bold(colors.green('\n🎉 后台管理端连接测试通过!')));
|
||||
console.log(colors.green('✅ 数据库连接正常'));
|
||||
console.log(colors.green('✅ 所有管理端表都可访问'));
|
||||
console.log(colors.green('✅ 统计查询功能正常'));
|
||||
console.log(colors.green('✅ 实时数据订阅正常'));
|
||||
console.log(colors.bold('\n💡 后台管理端已准备就绪,可以查看和管理客户端数据!'));
|
||||
|
||||
} catch (error) {
|
||||
console.log(colors.bold(colors.red('\n❌ 连接测试失败!')));
|
||||
console.log(colors.red('错误信息:'), error.message);
|
||||
console.log(colors.yellow('\n🔧 故障排除建议:'));
|
||||
console.log(colors.cyan('1. 检查网络连接'));
|
||||
console.log(colors.cyan('2. 验证 Supabase URL 和 API 密钥'));
|
||||
console.log(colors.cyan('3. 确认 Supabase 项目状态'));
|
||||
console.log(colors.cyan('4. 检查数据库表是否存在'));
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 数据同步测试函数
|
||||
async function testDataSync() {
|
||||
console.log(colors.bold('\n🔄 测试客户端-管理端数据同步...\n'));
|
||||
|
||||
const supabase = createClient(
|
||||
'https://riwtulmitqioswmgwftg.supabase.co',
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJpd3R1bG1pdHFpb3N3bWd3ZnRnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDg1OTc1ODgsImV4cCI6MjA2NDE3MzU4OH0.fxSW_uEbpR1zwepjb83DIUIwTrmsboK2nTjPpS6XMtw'
|
||||
);
|
||||
|
||||
try {
|
||||
// 模拟客户端创建一条测试数据
|
||||
const testData = {
|
||||
id: `test-${Date.now()}`,
|
||||
name: '测试口译员',
|
||||
avatar: null,
|
||||
description: '这是管理端连接测试创建的数据',
|
||||
status: 'available',
|
||||
created_at: new Date().toISOString()
|
||||
};
|
||||
|
||||
console.log(colors.blue('📝 创建测试数据...'));
|
||||
const { data: createdData, error: createError } = await supabase
|
||||
.from('interpreters')
|
||||
.insert(testData)
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (createError) throw createError;
|
||||
console.log(colors.green('✅ 测试数据创建成功:'), createdData.name);
|
||||
|
||||
// 等待数据同步
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// 从管理端查询数据
|
||||
console.log(colors.blue('🔍 从管理端查询数据...'));
|
||||
const { data: queriedData, error: queryError } = await supabase
|
||||
.from('interpreters')
|
||||
.select('*')
|
||||
.eq('id', testData.id)
|
||||
.single();
|
||||
|
||||
if (queryError) throw queryError;
|
||||
console.log(colors.green('✅ 管理端成功读取数据:'), queriedData.name);
|
||||
|
||||
// 清理测试数据
|
||||
console.log(colors.blue('🧹 清理测试数据...'));
|
||||
const { error: deleteError } = await supabase
|
||||
.from('interpreters')
|
||||
.delete()
|
||||
.eq('id', testData.id);
|
||||
|
||||
if (deleteError) throw deleteError;
|
||||
console.log(colors.green('✅ 测试数据清理完成'));
|
||||
|
||||
console.log(colors.bold(colors.green('\n🎉 数据同步测试通过!')));
|
||||
console.log(colors.green('✅ 客户端写入的数据可以在管理端实时查看'));
|
||||
console.log(colors.green('✅ 管理端可以对客户端数据进行完整的CRUD操作'));
|
||||
|
||||
} catch (error) {
|
||||
console.log(colors.bold(colors.red('\n❌ 数据同步测试失败!')));
|
||||
console.log(colors.red('错误信息:'), error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
testAdminConnection()
|
||||
.then(() => testDataSync())
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
module.exports = { testAdminConnection, testDataSync };
|
||||
|
||||
// 颜色输出函数
|
||||
const colors = {
|
||||
red: (text) => `\x1b[31m${text}\x1b[0m`,
|
||||
green: (text) => `\x1b[32m${text}\x1b[0m`,
|
||||
yellow: (text) => `\x1b[33m${text}\x1b[0m`,
|
||||
blue: (text) => `\x1b[34m${text}\x1b[0m`,
|
||||
cyan: (text) => `\x1b[36m${text}\x1b[0m`,
|
||||
bold: (text) => `\x1b[1m${text}\x1b[0m`
|
||||
};
|
||||
|
||||
async function testAdminConnection() {
|
||||
console.log(colors.bold('\n🔍 测试后台管理端 Supabase 连接...\n'));
|
||||
|
||||
// Supabase配置 - 与客户端使用相同的配置
|
||||
const supabaseUrl = 'https://riwtulmitqioswmgwftg.supabase.co';
|
||||
const supabaseKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJpd3R1bG1pdHFpb3N3bWd3ZnRnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDg1OTc1ODgsImV4cCI6MjA2NDE3MzU4OH0.fxSW_uEbpR1zwepjb83DIUIwTrmsboK2nTjPpS6XMtw';
|
||||
|
||||
console.log(colors.cyan('📡 Supabase URL:'), supabaseUrl);
|
||||
console.log(colors.cyan('🔑 API Key:'), supabaseKey.substring(0, 20) + '...');
|
||||
|
||||
// 创建客户端
|
||||
const supabase = createClient(supabaseUrl, supabaseKey);
|
||||
|
||||
try {
|
||||
// 1. 测试基本连接
|
||||
console.log(colors.blue('\n🔄 测试基本数据库连接...'));
|
||||
const { data: rates, error: ratesError } = await supabase
|
||||
.from('rates')
|
||||
.select('service_type, price_per_minute, currency')
|
||||
.limit(5);
|
||||
|
||||
if (ratesError) {
|
||||
console.log(colors.red('❌ 数据库连接失败:'), ratesError.message);
|
||||
throw ratesError;
|
||||
}
|
||||
|
||||
console.log(colors.green('✅ 基本连接成功,费率数据:'));
|
||||
rates.forEach(rate => {
|
||||
console.log(colors.cyan(` - ${rate.service_type}: $${rate.price_per_minute}/${rate.currency}`));
|
||||
});
|
||||
|
||||
// 2. 测试管理端需要的数据表
|
||||
console.log(colors.blue('\n🔄 测试管理端数据表访问...'));
|
||||
|
||||
const tables = [
|
||||
{ name: 'profiles', description: '用户资料' },
|
||||
{ name: 'calls', description: '通话记录' },
|
||||
{ name: 'translations', description: '翻译记录' },
|
||||
{ name: 'payments', description: '支付记录' },
|
||||
{ name: 'interpreters', description: '口译员信息' }
|
||||
];
|
||||
|
||||
for (const table of tables) {
|
||||
try {
|
||||
const { count, error } = await supabase
|
||||
.from(table.name)
|
||||
.select('*', { count: 'exact', head: true });
|
||||
|
||||
if (error) throw error;
|
||||
console.log(colors.green(`✅ ${table.description} (${table.name}): ${count || 0} 条记录`));
|
||||
} catch (error) {
|
||||
console.log(colors.red(`❌ ${table.description} (${table.name}): ${error.message}`));
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 测试统计数据查询
|
||||
console.log(colors.blue('\n🔄 测试统计数据查询...'));
|
||||
|
||||
const [
|
||||
{ count: totalUsers },
|
||||
{ count: totalCalls },
|
||||
{ count: totalInterpreters },
|
||||
{ data: recentPayments }
|
||||
] = await Promise.all([
|
||||
supabase.from('profiles').select('*', { count: 'exact', head: true }),
|
||||
supabase.from('calls').select('*', { count: 'exact', head: true }),
|
||||
supabase.from('interpreters').select('*', { count: 'exact', head: true }),
|
||||
supabase.from('payments').select('amount').eq('status', 'completed').limit(10)
|
||||
]);
|
||||
|
||||
const totalRevenue = recentPayments?.reduce((sum, payment) => sum + payment.amount, 0) || 0;
|
||||
|
||||
console.log(colors.green('📊 系统统计数据:'));
|
||||
console.log(colors.cyan(` - 总用户数: ${totalUsers || 0}`));
|
||||
console.log(colors.cyan(` - 总通话数: ${totalCalls || 0}`));
|
||||
console.log(colors.cyan(` - 口译员数: ${totalInterpreters || 0}`));
|
||||
console.log(colors.cyan(` - 总收入: $${totalRevenue.toFixed(2)}`));
|
||||
|
||||
// 4. 测试实时订阅功能
|
||||
console.log(colors.blue('\n🔄 测试实时数据订阅...'));
|
||||
|
||||
const channel = supabase
|
||||
.channel('admin-test')
|
||||
.on('postgres_changes', { event: '*', schema: 'public', table: 'calls' }, (payload) => {
|
||||
console.log(colors.yellow('📢 实时数据更新:'), payload);
|
||||
})
|
||||
.subscribe();
|
||||
|
||||
// 等待订阅建立
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
console.log(colors.green('✅ 实时订阅功能正常'));
|
||||
|
||||
// 清理订阅
|
||||
supabase.removeChannel(channel);
|
||||
|
||||
// 总结
|
||||
console.log(colors.bold(colors.green('\n🎉 后台管理端连接测试通过!')));
|
||||
console.log(colors.green('✅ 数据库连接正常'));
|
||||
console.log(colors.green('✅ 所有管理端表都可访问'));
|
||||
console.log(colors.green('✅ 统计查询功能正常'));
|
||||
console.log(colors.green('✅ 实时数据订阅正常'));
|
||||
console.log(colors.bold('\n💡 后台管理端已准备就绪,可以查看和管理客户端数据!'));
|
||||
|
||||
} catch (error) {
|
||||
console.log(colors.bold(colors.red('\n❌ 连接测试失败!')));
|
||||
console.log(colors.red('错误信息:'), error.message);
|
||||
console.log(colors.yellow('\n🔧 故障排除建议:'));
|
||||
console.log(colors.cyan('1. 检查网络连接'));
|
||||
console.log(colors.cyan('2. 验证 Supabase URL 和 API 密钥'));
|
||||
console.log(colors.cyan('3. 确认 Supabase 项目状态'));
|
||||
console.log(colors.cyan('4. 检查数据库表是否存在'));
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 数据同步测试函数
|
||||
async function testDataSync() {
|
||||
console.log(colors.bold('\n🔄 测试客户端-管理端数据同步...\n'));
|
||||
|
||||
const supabase = createClient(
|
||||
'https://riwtulmitqioswmgwftg.supabase.co',
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJpd3R1bG1pdHFpb3N3bWd3ZnRnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDg1OTc1ODgsImV4cCI6MjA2NDE3MzU4OH0.fxSW_uEbpR1zwepjb83DIUIwTrmsboK2nTjPpS6XMtw'
|
||||
);
|
||||
|
||||
try {
|
||||
// 模拟客户端创建一条测试数据
|
||||
const testData = {
|
||||
id: `test-${Date.now()}`,
|
||||
name: '测试口译员',
|
||||
avatar: null,
|
||||
description: '这是管理端连接测试创建的数据',
|
||||
status: 'available',
|
||||
created_at: new Date().toISOString()
|
||||
};
|
||||
|
||||
console.log(colors.blue('📝 创建测试数据...'));
|
||||
const { data: createdData, error: createError } = await supabase
|
||||
.from('interpreters')
|
||||
.insert(testData)
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (createError) throw createError;
|
||||
console.log(colors.green('✅ 测试数据创建成功:'), createdData.name);
|
||||
|
||||
// 等待数据同步
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// 从管理端查询数据
|
||||
console.log(colors.blue('🔍 从管理端查询数据...'));
|
||||
const { data: queriedData, error: queryError } = await supabase
|
||||
.from('interpreters')
|
||||
.select('*')
|
||||
.eq('id', testData.id)
|
||||
.single();
|
||||
|
||||
if (queryError) throw queryError;
|
||||
console.log(colors.green('✅ 管理端成功读取数据:'), queriedData.name);
|
||||
|
||||
// 清理测试数据
|
||||
console.log(colors.blue('🧹 清理测试数据...'));
|
||||
const { error: deleteError } = await supabase
|
||||
.from('interpreters')
|
||||
.delete()
|
||||
.eq('id', testData.id);
|
||||
|
||||
if (deleteError) throw deleteError;
|
||||
console.log(colors.green('✅ 测试数据清理完成'));
|
||||
|
||||
console.log(colors.bold(colors.green('\n🎉 数据同步测试通过!')));
|
||||
console.log(colors.green('✅ 客户端写入的数据可以在管理端实时查看'));
|
||||
console.log(colors.green('✅ 管理端可以对客户端数据进行完整的CRUD操作'));
|
||||
|
||||
} catch (error) {
|
||||
console.log(colors.bold(colors.red('\n❌ 数据同步测试失败!')));
|
||||
console.log(colors.red('错误信息:'), error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
testAdminConnection()
|
||||
.then(() => testDataSync())
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
module.exports = { testAdminConnection, testDataSync };
|
||||
Reference in New Issue
Block a user