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>
228 lines
8.7 KiB
JavaScript
228 lines
8.7 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
/**
|
||
* 调试前端页面,查看具体的页面内容和问题
|
||
*/
|
||
|
||
const { chromium } = require('playwright');
|
||
|
||
async function debugFrontend() {
|
||
console.log('🔍 开始调试前端页面...\n');
|
||
|
||
let browser;
|
||
let page;
|
||
|
||
try {
|
||
browser = await chromium.launch({
|
||
headless: false,
|
||
slowMo: 1000
|
||
});
|
||
|
||
const context = await browser.newContext({
|
||
viewport: { width: 1400, height: 900 }
|
||
});
|
||
|
||
page = await context.newPage();
|
||
|
||
// 登录
|
||
console.log('🚀 登录系统...');
|
||
await page.goto('http://localhost:8891');
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
await page.fill('input[type="text"]', 'admin');
|
||
await page.fill('input[type="password"]', '111111');
|
||
await page.click('button:has-text("登录")');
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
// 进入姓名管理
|
||
console.log('🔍 进入姓名管理页面...');
|
||
const nameMenu = await page.locator('text=名字管理').first();
|
||
await nameMenu.click();
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
// 检查当前URL
|
||
const currentUrl = page.url();
|
||
console.log(`📍 当前URL: ${currentUrl}`);
|
||
|
||
// 获取页面HTML内容
|
||
console.log('\n📄 页面HTML结构分析...');
|
||
const pageContent = await page.evaluate(() => {
|
||
// 获取主要内容区域
|
||
const mainContent = document.querySelector('main, .main-content, .content, #app > div');
|
||
if (mainContent) {
|
||
return {
|
||
hasContent: true,
|
||
innerHTML: mainContent.innerHTML.substring(0, 1000), // 前1000字符
|
||
classes: mainContent.className,
|
||
children: Array.from(mainContent.children).map(child => ({
|
||
tagName: child.tagName,
|
||
className: child.className,
|
||
id: child.id,
|
||
textContent: child.textContent ? child.textContent.substring(0, 100) : ''
|
||
}))
|
||
};
|
||
} else {
|
||
return {
|
||
hasContent: false,
|
||
bodyHTML: document.body.innerHTML.substring(0, 1000)
|
||
};
|
||
}
|
||
});
|
||
|
||
console.log('📋 页面内容分析结果:');
|
||
if (pageContent.hasContent) {
|
||
console.log(` ✅ 找到主内容区域`);
|
||
console.log(` 📦 容器类名: ${pageContent.classes}`);
|
||
console.log(` 🔢 子元素数量: ${pageContent.children.length}`);
|
||
|
||
pageContent.children.forEach((child, index) => {
|
||
console.log(` ${index + 1}. <${child.tagName}> class="${child.className}" - ${child.textContent.substring(0, 50)}...`);
|
||
});
|
||
} else {
|
||
console.log(` ❌ 未找到主内容区域`);
|
||
console.log(` 📄 Body内容预览: ${pageContent.bodyHTML}...`);
|
||
}
|
||
|
||
// 检查是否有Vue组件
|
||
console.log('\n🔍 Vue组件检查...');
|
||
const vueInfo = await page.evaluate(() => {
|
||
// 检查Vue实例
|
||
const app = document.getElementById('app');
|
||
if (app && app.__vue__) {
|
||
return {
|
||
hasVue: true,
|
||
vueVersion: 'Vue 2',
|
||
componentName: app.__vue__.$options.name || 'unknown'
|
||
};
|
||
} else if (app && app._vnode) {
|
||
return {
|
||
hasVue: true,
|
||
vueVersion: 'Vue 3',
|
||
componentData: 'Vue 3 detected'
|
||
};
|
||
} else {
|
||
return { hasVue: false };
|
||
}
|
||
});
|
||
|
||
console.log('🔧 Vue状态:');
|
||
if (vueInfo.hasVue) {
|
||
console.log(` ✅ Vue检测成功: ${vueInfo.vueVersion}`);
|
||
if (vueInfo.componentName) {
|
||
console.log(` 📦 组件名称: ${vueInfo.componentName}`);
|
||
}
|
||
} else {
|
||
console.log(` ❌ 未检测到Vue实例`);
|
||
}
|
||
|
||
// 检查网络请求
|
||
console.log('\n🌐 检查网络请求...');
|
||
|
||
// 手动触发一些API调用来看看数据
|
||
const apiTest = await page.evaluate(async () => {
|
||
try {
|
||
// 测试姓名模板列表API(需要认证)
|
||
const listResponse = await fetch('http://localhost:3000/nameTemplate/list', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
// 这里需要token,但我们先看看是否会返回401
|
||
},
|
||
body: JSON.stringify({})
|
||
});
|
||
|
||
return {
|
||
listAPI: {
|
||
status: listResponse.status,
|
||
statusText: listResponse.statusText,
|
||
needsAuth: listResponse.status === 401
|
||
}
|
||
};
|
||
} catch (error) {
|
||
return { error: error.message };
|
||
}
|
||
});
|
||
|
||
console.log('📡 API测试结果:');
|
||
if (apiTest.listAPI) {
|
||
console.log(` - 列表API状态: ${apiTest.listAPI.status} ${apiTest.listAPI.statusText}`);
|
||
console.log(` - 需要认证: ${apiTest.listAPI.needsAuth ? '是' : '否'}`);
|
||
}
|
||
|
||
// 查找所有可能的页面路由
|
||
console.log('\n🗺️ 检查路由结构...');
|
||
const routeInfo = await page.evaluate(() => {
|
||
// 检查Vue Router
|
||
const links = Array.from(document.querySelectorAll('a[href*="#"]')).map(a => ({
|
||
href: a.href,
|
||
text: a.textContent?.trim()
|
||
}));
|
||
|
||
return {
|
||
hashLinks: links.slice(0, 10), // 前10个
|
||
currentHash: window.location.hash
|
||
};
|
||
});
|
||
|
||
console.log('🔗 路由信息:');
|
||
console.log(` 📍 当前Hash: ${routeInfo.currentHash}`);
|
||
console.log(' 🔗 可用路由:');
|
||
routeInfo.hashLinks.forEach((link, index) => {
|
||
if (link.text) {
|
||
console.log(` ${index + 1}. ${link.text} -> ${link.href}`);
|
||
}
|
||
});
|
||
|
||
// 尝试直接访问firstName页面
|
||
console.log('\n🎯 尝试直接访问firstName页面...');
|
||
try {
|
||
await page.goto('http://localhost:8891/#/nameManage/firstnameList');
|
||
await page.waitForTimeout(3000);
|
||
|
||
await page.screenshot({ path: 'firstname_page_debug.png', fullPage: true });
|
||
console.log('📸 截图保存: firstname_page_debug.png');
|
||
|
||
// 再次检查页面内容
|
||
const firstnamePageContent = await page.evaluate(() => {
|
||
const tables = document.querySelectorAll('table');
|
||
const buttons = document.querySelectorAll('button');
|
||
const inputs = document.querySelectorAll('input');
|
||
|
||
return {
|
||
tables: tables.length,
|
||
buttons: Array.from(buttons).map(b => b.textContent?.trim()).filter(t => t),
|
||
inputs: Array.from(inputs).map(i => i.placeholder || i.type).filter(t => t),
|
||
hasViewCard: !!document.querySelector('.view-card, view-card'),
|
||
hasTableList: !!document.querySelector('.table-list, table-list')
|
||
};
|
||
});
|
||
|
||
console.log('📊 firstName页面内容:');
|
||
console.log(` - 表格数量: ${firstnamePageContent.tables}`);
|
||
console.log(` - 按钮: ${firstnamePageContent.buttons.join(', ')}`);
|
||
console.log(` - 输入框: ${firstnamePageContent.inputs.join(', ')}`);
|
||
console.log(` - view-card组件: ${firstnamePageContent.hasViewCard ? '存在' : '不存在'}`);
|
||
console.log(` - table-list组件: ${firstnamePageContent.hasTableList ? '存在' : '不存在'}`);
|
||
|
||
} catch (error) {
|
||
console.log(`❌ 访问firstName页面失败: ${error.message}`);
|
||
}
|
||
|
||
console.log('\n⏰ 浏览器将保持打开10秒供观察...');
|
||
await page.waitForTimeout(10000);
|
||
|
||
} catch (error) {
|
||
console.error('❌ 调试失败:', error.message);
|
||
} finally {
|
||
if (browser) {
|
||
await browser.close();
|
||
}
|
||
console.log('🏁 调试结束');
|
||
}
|
||
}
|
||
|
||
if (require.main === module) {
|
||
debugFrontend().catch(console.error);
|
||
}
|
||
|
||
module.exports = debugFrontend; |