Initial commit: Telegram Management System
Some checks failed
Deploy / deploy (push) Has been cancelled

Full-stack web application for Telegram management
- Frontend: Vue 3 + Vben Admin
- Backend: NestJS
- Features: User management, group broadcast, statistics

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
你的用户名
2025-11-04 15:37:50 +08:00
commit 237c7802e5
3674 changed files with 525172 additions and 0 deletions

375
check-vben-menus.js Normal file
View File

@@ -0,0 +1,375 @@
const { chromium } = require('playwright');
const fs = require('fs').promises;
const path = require('path');
// 菜单项配置
const MENU_CONFIG = [
// 仪表板
{ name: '仪表板', path: '/dashboard/home', selector: 'text=仪表板' },
// 账号管理
{ name: 'TG账号列表', path: '/account-manage/list', selector: 'text=TG账号列表' },
{ name: 'TG账号用途', path: '/account-manage/usage', selector: 'text=TG账号用途' },
{ name: 'Telegram用户列表', path: '/account-manage/telegram-users', selector: 'text=Telegram用户列表' },
{ name: '统一注册系统', path: '/account-manage/unified-register', selector: 'text=统一注册系统' },
{ name: 'Telegram指南', path: '/account-manage/guide', selector: 'text=Telegram指南' },
{ name: 'Telegram快速访问', path: '/account-manage/quick-access', selector: 'text=Telegram快速访问' },
{ name: 'Telegram聊天', path: '/account-manage/telegram-chat', selector: 'text=Telegram聊天' },
{ name: 'Telegram网页版', path: '/account-manage/telegram-web', selector: 'text=Telegram网页版' },
{ name: 'Telegram网页版全屏', path: '/account-manage/telegram-full', selector: 'text=Telegram网页版全屏' },
// 名称管理
{ name: '名字列表', path: '/name-management/firstname', selector: 'text=名字列表' },
{ name: '姓氏列表', path: '/name-management/lastname', selector: 'text=姓氏列表' },
{ name: '统一名称管理', path: '/name-management/unified', selector: 'text=统一名称管理' },
// 群组管理
{ name: '群组列表', path: '/group-config/list', selector: 'text=群组列表' },
{ name: '群组成员', path: '/group-config/members', selector: 'text=群组成员' },
{ name: '群组设置', path: '/group-config/sets', selector: 'text=群组设置' },
// 消息管理
{ name: '消息列表', path: '/message-management/list', selector: 'text=消息列表' },
// 营销中心
{ name: '营销控制台', path: '/marketing-center/dashboard', selector: 'text=营销控制台' },
{ name: '智能群发', path: '/marketing-center/smart-campaign', selector: 'text=智能群发' },
{ name: '统一账号管理', path: '/marketing-center/integrated-account', selector: 'text=统一账号管理' },
{ name: '账号池管理', path: '/marketing-center/account-pool', selector: 'text=账号池管理' },
{ name: '风控中心', path: '/marketing-center/risk-control', selector: 'text=风控中心' },
{ name: '监控中心', path: '/marketing-center/monitoring', selector: 'text=监控中心' },
// 私信群发
{ name: '任务列表', path: '/direct-message/task-list', selector: 'text=任务列表' },
{ name: '创建任务', path: '/direct-message/create-task', selector: 'text=创建任务' },
{ name: '模板列表', path: '/direct-message/template-list', selector: 'text=模板列表' },
{ name: '创建模板', path: '/direct-message/create-template', selector: 'text=创建模板' },
{ name: '引擎控制', path: '/direct-message/engine-control', selector: 'text=引擎控制' },
{ name: '统计分析', path: '/direct-message/statistics', selector: 'text=统计分析' },
// 群发广播
{ name: '广播任务', path: '/group-broadcast/task', selector: 'text=广播任务' },
{ name: '广播日志', path: '/group-broadcast/log', selector: 'text=广播日志' },
// 炒群营销
{ name: '剧本列表', path: '/group-marketing/script', selector: 'text=剧本列表' },
{ name: '营销项目', path: '/group-marketing/project', selector: 'text=营销项目' },
// 短信平台
{ name: '短信仪表板', path: '/sms-platform/dashboard', selector: 'text=短信仪表板' },
{ name: '平台管理', path: '/sms-platform/platform-list', selector: 'text=平台管理' },
{ name: '发送记录', path: '/sms-platform/records', selector: 'text=发送记录' },
{ name: '统计分析', path: '/sms-platform/statistics', selector: 'text=统计分析' },
{ name: '价格对比', path: '/sms-platform/price-compare', selector: 'text=价格对比' },
{ name: '快速操作', path: '/sms-platform/quick-actions', selector: 'text=快速操作' },
{ name: '余额报警', path: '/sms-platform/balance-alert', selector: 'text=余额报警' },
// 日志管理
{ name: '注册日志', path: '/log-manage/register', selector: 'text=注册日志' },
{ name: '用户登录', path: '/log-manage/user-login', selector: 'text=用户登录' },
{ name: '用户注册', path: '/log-manage/user-register', selector: 'text=用户注册' },
{ name: '群发日志', path: '/log-manage/group-send', selector: 'text=群发日志' },
{ name: '群组加入', path: '/log-manage/group-join', selector: 'text=群组加入' },
{ name: 'TG登录验证码', path: '/log-manage/login-code', selector: 'text=TG登录验证码' },
{ name: '拉群成员', path: '/log-manage/pull-member', selector: 'text=拉群成员' },
{ name: '拉群统计', path: '/log-manage/pull-member-statistic', selector: 'text=拉群统计' },
{ name: '拉群项目统计', path: '/log-manage/pull-member-project-statistic', selector: 'text=拉群项目统计' },
// 系统配置
{ name: '系统参数', path: '/system-config/params', selector: 'text=系统参数' },
{ name: '通用设置', path: '/system-config/base-config', selector: 'text=通用设置' },
{ name: '数据中心', path: '/system-config/dc-list', selector: 'text=数据中心' }
];
class VbenMenuChecker {
constructor() {
this.baseUrl = 'http://localhost:5173';
this.results = [];
this.screenshots = [];
this.browser = null;
this.context = null;
this.page = null;
}
async init() {
console.log('🚀 启动浏览器...');
this.browser = await chromium.launch({
headless: false,
slowMo: 500
});
this.context = await this.browser.newContext({
viewport: { width: 1920, height: 1080 }
});
this.page = await this.context.newPage();
// 监听网络请求
this.page.on('response', (response) => {
const url = response.url();
if (url.includes('/api/') && !response.ok()) {
console.log(`⚠️ API 请求失败: ${url} - ${response.status()}`);
}
});
}
async login() {
console.log('🔑 开始登录...');
try {
await this.page.goto(this.baseUrl);
await this.page.waitForLoadState('networkidle');
// 检查是否已经登录
try {
if (await this.page.locator('text=仪表板').first().isVisible({ timeout: 2000 })) {
console.log('✅ 已经登录');
return true;
}
} catch (e) {
// 继续登录流程
}
// 填写登录信息
await this.page.fill('input[placeholder*="用户名"]', 'admin');
await this.page.fill('input[placeholder*="密码"]', '111111');
// 点击登录按钮
await this.page.click('button:has-text("登录")');
await this.page.waitForLoadState('networkidle');
// 等待登录成功 - 等待页面跳转
await this.page.waitForTimeout(3000);
// 检查是否登录成功URL改变或出现菜单
const currentUrl = this.page.url();
const hasMenu = await this.page.locator('.ant-menu, .vben-menu, [role="menu"]').count() > 0;
const hasDashboard = await this.page.locator('text=仪表板').count() > 0;
if (!currentUrl.includes('/login') || hasMenu || hasDashboard) {
console.log('✅ 登录成功,当前页面包含菜单组件');
} else {
throw new Error('登录后未找到预期的页面元素');
}
console.log('✅ 登录成功');
// 截图保存登录后状态
await this.page.screenshot({
path: `/Users/hahaha/telegram-management-system/test-screenshots/vben-after-login.png`,
fullPage: true
});
return true;
} catch (error) {
console.error('❌ 登录失败:', error.message);
await this.page.screenshot({
path: `/Users/hahaha/telegram-management-system/test-screenshots/vben-login-error.png`,
fullPage: true
});
return false;
}
}
async checkMenu(menuItem) {
console.log(`\n📋 检查菜单: ${menuItem.name}`);
const result = {
name: menuItem.name,
path: menuItem.path,
success: false,
loadTime: 0,
hasData: false,
error: null,
dataElements: 0,
apiCalls: 0,
screenshot: null
};
try {
const startTime = Date.now();
// 监听 API 调用
let apiCallCount = 0;
const apiListener = (response) => {
if (response.url().includes('/api/')) {
apiCallCount++;
console.log(`🔄 API 调用: ${response.url()} - ${response.status()}`);
}
};
this.page.on('response', apiListener);
// 导航到菜单页面
await this.page.goto(`${this.baseUrl}${menuItem.path}`);
await this.page.waitForLoadState('networkidle');
// 等待页面内容加载
await this.page.waitForTimeout(2000);
const loadTime = Date.now() - startTime;
result.loadTime = loadTime;
result.apiCalls = apiCallCount;
// 检查页面是否有错误
const hasError = await this.page.locator('.ant-result-error, .error, .ant-empty').count() > 0;
// 检查是否有数据表格或列表
const tableCount = await this.page.locator('table, .ant-table, .ant-list, .card-list').count();
const dataElements = await this.page.locator('td, li, .card-item').count();
result.dataElements = dataElements;
result.hasData = dataElements > 0;
result.success = !hasError && loadTime < 10000;
// 截图
const screenshotPath = `/Users/hahaha/telegram-management-system/test-screenshots/vben-${menuItem.name.replace(/[\/\\]/g, '-')}.png`;
await this.page.screenshot({
path: screenshotPath,
fullPage: true
});
result.screenshot = screenshotPath;
console.log(` ✅ 加载时间: ${loadTime}ms`);
console.log(` 📊 数据元素: ${dataElements}`);
console.log(` 🌐 API调用: ${apiCallCount}`);
console.log(` 📷 截图: ${screenshotPath}`);
// 移除事件监听器
this.page.off('response', apiListener);
} catch (error) {
result.error = error.message;
console.error(` ❌ 错误: ${error.message}`);
// 错误截图
const errorScreenshotPath = `/Users/hahaha/telegram-management-system/test-screenshots/vben-error-${menuItem.name.replace(/[\/\\]/g, '-')}.png`;
await this.page.screenshot({
path: errorScreenshotPath,
fullPage: true
});
result.screenshot = errorScreenshotPath;
}
return result;
}
async checkAllMenus() {
console.log(`\n🎯 开始检查 ${MENU_CONFIG.length} 个菜单...\n`);
for (let i = 0; i < MENU_CONFIG.length; i++) {
const menuItem = MENU_CONFIG[i];
console.log(`[${i + 1}/${MENU_CONFIG.length}] 检查菜单: ${menuItem.name}`);
const result = await this.checkMenu(menuItem);
this.results.push(result);
// 每检查5个菜单暂停一下
if ((i + 1) % 5 === 0) {
console.log(`⏸️ 已检查 ${i + 1} 个菜单暂停2秒...`);
await this.page.waitForTimeout(2000);
}
}
}
async generateReport() {
console.log('\n📊 生成测试报告...');
const successCount = this.results.filter(r => r.success).length;
const errorCount = this.results.filter(r => r.error).length;
const dataCount = this.results.filter(r => r.hasData).length;
const avgLoadTime = this.results.reduce((sum, r) => sum + r.loadTime, 0) / this.results.length;
const totalApiCalls = this.results.reduce((sum, r) => sum + r.apiCalls, 0);
const report = {
timestamp: new Date().toISOString(),
summary: {
total: this.results.length,
success: successCount,
errors: errorCount,
hasData: dataCount,
successRate: `${((successCount / this.results.length) * 100).toFixed(1)}%`,
avgLoadTime: `${avgLoadTime.toFixed(0)}ms`,
totalApiCalls
},
details: this.results.map(r => ({
name: r.name,
path: r.path,
success: r.success,
loadTime: `${r.loadTime}ms`,
hasData: r.hasData,
dataElements: r.dataElements,
apiCalls: r.apiCalls,
error: r.error,
screenshot: r.screenshot
}))
};
// 保存报告
await fs.writeFile(
'/Users/hahaha/telegram-management-system/vben-menu-test-report.json',
JSON.stringify(report, null, 2)
);
// 打印摘要
console.log('\n📈 测试摘要:');
console.log(` 总菜单数: ${report.summary.total}`);
console.log(` 成功加载: ${report.summary.success} (${report.summary.successRate})`);
console.log(` 加载错误: ${report.summary.errors}`);
console.log(` 有数据显示: ${report.summary.hasData}`);
console.log(` 平均加载时间: ${report.summary.avgLoadTime}`);
console.log(` API调用总数: ${report.summary.totalApiCalls}`);
// 打印有问题的菜单
const problemMenus = this.results.filter(r => !r.success || r.error);
if (problemMenus.length > 0) {
console.log('\n⚠ 有问题的菜单:');
problemMenus.forEach(menu => {
console.log(` - ${menu.name}: ${menu.error || '加载失败'}`);
});
}
// 打印无数据的菜单
const noDataMenus = this.results.filter(r => r.success && !r.hasData);
if (noDataMenus.length > 0) {
console.log('\n📭 无数据显示的菜单:');
noDataMenus.forEach(menu => {
console.log(` - ${menu.name} (${menu.loadTime}ms)`);
});
}
console.log(`\n📁 完整报告已保存到: vben-menu-test-report.json`);
return report;
}
async close() {
if (this.browser) {
await this.browser.close();
}
}
}
async function main() {
const checker = new VbenMenuChecker();
try {
await checker.init();
const loginSuccess = await checker.login();
if (!loginSuccess) {
console.error('❌ 登录失败,无法继续测试');
return;
}
await checker.checkAllMenus();
await checker.generateReport();
console.log('\n🎉 菜单检查完成!');
} catch (error) {
console.error('❌ 测试过程中发生错误:', error);
} finally {
await checker.close();
}
}
// 运行测试
if (require.main === module) {
main().catch(console.error);
}
module.exports = { VbenMenuChecker, MENU_CONFIG };