import { chromium } from 'playwright'; const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' }); const p = await (await b.newContext({ viewport: { width: 1280, height: 1000 } })).newPage(); const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove())); await p.goto('http://localhost:4200/login', { waitUntil:'networkidle' }); await clear(); await p.waitForTimeout(700); const ins = await p.locator('ui-input input').all(); await ins[0].fill('13800138000'); await ins[1].fill('123456'); await p.getByText('登 录', { exact:false }).first().click(); await p.waitForTimeout(2800); await p.goto('http://localhost:4200/desktop/contacts', { waitUntil:'networkidle' }); await clear(); await p.waitForTimeout(1800); // 直接看 tabs-row / search-row 及其子元素的盒子 const r = await p.evaluate(() => { const pick = (sel) => { const el = document.querySelector(sel); if (!el) return `${sel}: 不存在`; const b = el.getBoundingClientRect(); return `${sel}: ${Math.round(b.width)}x${Math.round(b.height)} @y=${Math.round(b.y)}`; }; const tabs = document.querySelector('ui-tabs'); const tabsBox = tabs ? tabs.getBoundingClientRect() : null; // ui-tabs 内部结构 const inner = tabs ? [...tabs.querySelectorAll('*')].map(e => { const b = e.getBoundingClientRect(); return `${e.tagName}.${String(e.className).slice(0,40)} ${Math.round(b.width)}x${Math.round(b.height)}`; }).slice(0,6) : []; return { tabsRow: pick('.tabs-row'), searchRow: pick('.search-row'), searchBox: pick('.search-box'), tabsInternal: inner, }; }); console.log(JSON.stringify(r, null, 2)); await b.close();