Files
telegram-management-system/check-vben-menus.js
你的用户名 237c7802e5
Some checks failed
Deploy / deploy (push) Has been cancelled
Initial commit: Telegram Management System
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>
2025-11-04 15:37:50 +08:00

375 lines
14 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 };