#!/usr/bin/env node /** * 新姓名管理系统功能演示脚本 * 逐个展示所有新开发的功能 */ const { chromium } = require('playwright'); async function demoNewFeatures() { console.log('🎭 开始演示新开发的姓名管理系统功能...\n'); let browser; let page; try { browser = await chromium.launch({ headless: false, slowMo: 1500, // 慢一点,便于观察 devtools: false }); const context = await browser.newContext({ viewport: { width: 1400, height: 900 } }); page = await context.newPage(); // 监听所有姓名相关的API调用 page.on('request', request => { const url = request.url(); if (url.includes('/nameTemplate/') || url.includes('/firstname/') || url.includes('/lastname/')) { console.log(`🔗 API请求: ${request.method()} ${url}`); } }); page.on('response', response => { const url = response.url(); if (url.includes('/nameTemplate/') || url.includes('/firstname/') || url.includes('/lastname/')) { console.log(`📡 API响应: ${response.status()} ${url}`); if (response.status() !== 200) { console.log(` ⚠️ 状态码: ${response.status()} ${response.statusText()}`); } } }); // ==================== 第1步:登录系统 ==================== console.log('🚀 第1步:访问系统并登录...'); 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('✅ 登录成功!'); await page.screenshot({ path: '01_logged_in.png', fullPage: true }); console.log('📸 保存截图: 01_logged_in.png'); // ==================== 第2步:找到姓名管理菜单 ==================== console.log('\n🔍 第2步:找到并点击姓名管理菜单...'); // 等待菜单加载 await page.waitForTimeout(2000); // 查找姓名管理菜单 const nameMenu = await page.locator('text=名字管理').first(); if (await nameMenu.isVisible()) { console.log('✅ 找到"名字管理"菜单'); await nameMenu.click(); await page.waitForLoadState('networkidle'); console.log('🖱️ 点击进入姓名管理'); } else { // 尝试其他可能的菜单名称 const alternatives = ['text=姓名管理', 'text=姓名', 'text=名字', '[href*="firstname"]']; for (const alt of alternatives) { try { const menu = await page.locator(alt).first(); if (await menu.isVisible({ timeout: 1000 })) { console.log(`✅ 找到菜单: ${alt}`); await menu.click(); await page.waitForLoadState('networkidle'); break; } } catch (e) { // 继续尝试 } } } await page.screenshot({ path: '02_name_management_page.png', fullPage: true }); console.log('📸 保存截图: 02_name_management_page.png'); // ==================== 第3步:演示新API的调用 ==================== console.log('\n🔧 第3步:演示新开发的API接口...'); // 在浏览器控制台中调用新的API console.log('📡 调用新的supportedOptions API...'); const supportedOptions = await page.evaluate(async () => { try { const response = await fetch('http://localhost:3000/nameTemplate/supportedOptions'); const data = await response.json(); return { status: response.status, data }; } catch (error) { return { error: error.message }; } }); console.log('✅ supportedOptions API响应:'); console.log(' - 支持的平台:', supportedOptions.data?.data?.platforms?.length || 0, '个'); console.log(' - 支持的文化:', supportedOptions.data?.data?.cultures?.length || 0, '个'); console.log(' - 数据源类型:', supportedOptions.data?.data?.sources?.length || 0, '个'); // 调用生成器状态API console.log('\n📡 调用新的generatorStatus API...'); const generatorStatus = await page.evaluate(async () => { try { const response = await fetch('http://localhost:3000/nameTemplate/generatorStatus'); const data = await response.json(); return { status: response.status, data }; } catch (error) { return { error: error.message }; } }); console.log('✅ generatorStatus API响应:'); if (generatorStatus.data?.data) { Object.keys(generatorStatus.data.data).forEach(generator => { const info = generatorStatus.data.data[generator]; console.log(` - ${generator}: ${info.available ? '✅可用' : '❌不可用'} (优先级: ${info.priority})`); }); } // ==================== 第4步:测试页面功能 ==================== console.log('\n🧪 第4步:测试页面功能...'); // 检查页面元素 const hasTable = await page.locator('table').isVisible(); const hasAddButton = await page.locator('button:has-text("添加")').isVisible(); const hasSearchBox = await page.locator('input[placeholder*="搜索"], input[placeholder*="姓"]').isVisible(); console.log('📊 页面功能检查:'); console.log(` - 数据表格: ${hasTable ? '✅存在' : '❌缺失'}`); console.log(` - 添加按钮: ${hasAddButton ? '✅存在' : '❌缺失'}`); console.log(` - 搜索框: ${hasSearchBox ? '✅存在' : '❌缺失'}`); // ==================== 第5步:尝试添加新姓名模板 ==================== if (hasAddButton) { console.log('\n➕ 第5步:演示添加新姓名模板功能...'); try { await page.click('button:has-text("添加")'); await page.waitForTimeout(2000); // 检查是否有弹窗 const hasModal = await page.locator('.modal, .dialog, [class*="modal"]').isVisible(); console.log(` - 添加弹窗: ${hasModal ? '✅打开' : '❌未找到'}`); if (hasModal) { await page.screenshot({ path: '03_add_modal.png', fullPage: true }); console.log('📸 保存截图: 03_add_modal.png'); // 尝试填写测试数据 const nameInput = await page.locator('input[placeholder*="姓"], input[v-model*="name"]').first(); if (await nameInput.isVisible()) { await nameInput.fill('测试姓氏'); console.log('✏️ 填写测试姓氏'); await page.waitForTimeout(1000); await page.screenshot({ path: '04_filled_form.png', fullPage: true }); console.log('📸 保存截图: 04_filled_form.png'); // 取消或关闭弹窗(不实际提交) const cancelButton = await page.locator('button:has-text("取消"), button:has-text("关闭")').first(); if (await cancelButton.isVisible()) { await cancelButton.click(); console.log('❌ 取消添加操作(演示完成)'); } } } } catch (error) { console.log(` ⚠️ 添加功能测试失败: ${error.message}`); } } // ==================== 第6步:检查数据列表 ==================== console.log('\n📋 第6步:检查现有数据列表...'); if (hasTable) { // 统计表格行数 const tableRows = await page.locator('table tbody tr').count(); console.log(` - 数据行数: ${tableRows}`); if (tableRows > 0) { // 获取表头信息 const headers = await page.locator('table thead th').allTextContents(); console.log(' - 表格列:', headers.filter(h => h.trim()).join(', ')); await page.screenshot({ path: '05_data_table.png', fullPage: true }); console.log('📸 保存截图: 05_data_table.png'); } else { console.log(' ℹ️ 表格为空,可能需要先添加数据'); } } // ==================== 第7步:测试搜索功能 ==================== if (hasSearchBox) { console.log('\n🔍 第7步:测试搜索功能...'); try { const searchInput = await page.locator('input[placeholder*="搜索"], input[placeholder*="姓"]').first(); await searchInput.fill('测试'); console.log('🔍 输入搜索关键词: 测试'); // 触发搜索 const searchButton = await page.locator('button:has-text("搜索")').first(); if (await searchButton.isVisible()) { await searchButton.click(); console.log('🔍 点击搜索按钮'); await page.waitForTimeout(2000); await page.screenshot({ path: '06_search_result.png', fullPage: true }); console.log('📸 保存截图: 06_search_result.png'); } // 清空搜索 await searchInput.clear(); console.log('🧹 清空搜索条件'); } catch (error) { console.log(` ⚠️ 搜索功能测试失败: ${error.message}`); } } // ==================== 第8步:检查控制台错误 ==================== console.log('\n🔍 第8步:检查页面控制台错误...'); // 收集控制台错误 const consoleErrors = []; page.on('console', msg => { if (msg.type() === 'error') { consoleErrors.push(msg.text()); } }); await page.waitForTimeout(2000); if (consoleErrors.length > 0) { console.log('⚠️ 发现控制台错误:'); consoleErrors.slice(-3).forEach((error, index) => { console.log(` ${index + 1}. ${error}`); }); } else { console.log('✅ 无控制台错误'); } // ==================== 第9步:最终总结截图 ==================== console.log('\n📸 第9步:生成最终演示截图...'); await page.screenshot({ path: '07_final_demo.png', fullPage: true }); console.log('📸 保存截图: 07_final_demo.png'); // ==================== 演示完成 ==================== console.log('\n🎉 新功能演示完成!'); console.log('📁 生成的截图文件:'); console.log(' 01_logged_in.png - 登录后页面'); console.log(' 02_name_management_page.png - 姓名管理页面'); console.log(' 03_add_modal.png - 添加模态窗口'); console.log(' 04_filled_form.png - 填写表单'); console.log(' 05_data_table.png - 数据表格'); console.log(' 06_search_result.png - 搜索结果'); console.log(' 07_final_demo.png - 最终演示'); console.log('\n⏰ 浏览器将保持打开10秒供最后观察...'); await page.waitForTimeout(10000); } catch (error) { console.error('❌ 演示失败:', error.message); if (page) { await page.screenshot({ path: 'demo_error.png', fullPage: true }); console.log('📸 错误截图: demo_error.png'); } } finally { if (browser) { await browser.close(); } console.log('🏁 演示结束'); } } if (require.main === module) { demoNewFeatures().catch(console.error); } module.exports = demoNewFeatures;