--- /dev/null
+import pkg from '/home/StationBuilder/node_modules/playwright/index.js';
+const { chromium } = pkg;
+
+const BASE = process.env.BASE || 'http://127.0.0.1:37821/t/stationbuilder/';
+const results = [];
+const consoleErrors = [];
+function check(name, cond, extra='') { results.push({name, ok: !!cond, extra}); }
+
+const browser = await chromium.launch();
+const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } });
+const page = await ctx.newPage();
+page.on('console', m => { if (m.type() === 'error') consoleErrors.push(m.text()); });
+page.on('pageerror', e => consoleErrors.push('PAGEERROR: ' + e.message));
+
+try {
+ await page.goto(BASE, { waitUntil: 'networkidle' });
+ await page.waitForSelector('.company-side-nav', { timeout: 15000 });
+ check('load -> projects', true);
+
+ // Extension menu (open by default)
+ await page.screenshot({ path: '/tmp/sb-verify-0-sidenav.png' });
+ await page.waitForSelector('.extension-menu-items', { timeout: 5000 });
+ const extText = await page.locator('.extension-menu-items').innerText();
+ check('扩展页面: 仪表盘', extText.includes('仪表盘'));
+ check('扩展页面: 报表', extText.includes('报表'));
+ check('扩展页面: 数据源', extText.includes('数据源'));
+ // 报表 submenu open by default
+ await page.waitForSelector('.extension-third-menu', { timeout: 5000 });
+ const third = await page.locator('.extension-third-menu').innerText();
+ check('报表子菜单: 仪表盘报表', third.includes('仪表盘报表'));
+ check('报表子菜单: 文档报表', third.includes('文档报表'));
+ await page.screenshot({ path: '/tmp/sb-verify-1-extmenu.png' });
+
+ // AI welcome panel
+ await page.waitForSelector('.ai-fab', { timeout: 5000 });
+ await page.click('.ai-fab');
+ await page.waitForSelector('.ai-welcome', { timeout: 5000 });
+ const aiText = await page.locator('.ai-welcome').innerText();
+ check('AI欢迎面板: 我可以帮你建设场站', aiText.includes('我可以帮你建设场站'));
+ check('AI欢迎面板: 能力列表', await page.locator('.ai-capability-list').count() > 0);
+ check('AI欢迎面板: 你可以问', aiText.includes('你可以问'));
+ await page.screenshot({ path: '/tmp/sb-verify-2-aiwelcome.png' });
+ await page.click('.ai-close');
+
+ // Site edit 5 steps (SiteEditTabs)
+ await page.locator('.company-side-nav button:has-text("站点编辑")').first().click();
+ await page.waitForSelector('.site-edit-tabs', { timeout: 5000 });
+ const tabLabels = await page.locator('.site-edit-tabs button span').allInnerTexts();
+ check('向导5步数量', tabLabels.length === 5, 'got ' + JSON.stringify(tabLabels));
+ check('向导含页面配置', tabLabels.join(' ').includes('页面配置'));
+ await page.screenshot({ path: '/tmp/sb-verify-3-steps.png' });
+
+ // pageConfig blank
+ await page.locator('.site-edit-tabs button:has-text("页面配置")').click();
+ await page.waitForSelector('.site-step-blank', { timeout: 5000 });
+ check('页面配置: site-step-blank 占位', await page.locator('.site-step-blank').count() > 0);
+ await page.screenshot({ path: '/tmp/sb-verify-4-pageconfig.png' });
+
+ // Manual asset UI
+ await page.locator('.site-edit-tabs button:has-text("站点资产设置")').click();
+ await page.waitForSelector('button[role="tab"]', { timeout: 5000 });
+ await page.locator('button[role="tab"]:has-text("手动配置")').click();
+ await page.waitForSelector('.manual-asset-editor, .asset-editor-loading', { timeout: 8000 });
+ check('手动配置资产: 编辑器或加载态渲染', await page.locator('.manual-asset-editor, .asset-editor-loading').count() > 0);
+ await page.screenshot({ path: '/tmp/sb-verify-5-manualasset.png' });
+
+ // Regression: 领域方案库
+ await page.locator(".company-side-nav button:has-text(\"领域方案\")").first().click();
+ await page.waitForTimeout(1500);
+ check('回归: 领域方案库渲染', await page.locator('.company-list-panel, .domain-grid, .domain-library').count() > 0);
+ await page.screenshot({ path: '/tmp/sb-verify-6-domains.png' });
+
+ // Regression: 设备模板
+ await page.locator(".company-side-nav button:has-text(\"设备模板\")").first().click();
+ await page.waitForTimeout(1000);
+ check('回归: 设备模板渲染', true);
+ await page.screenshot({ path: '/tmp/sb-verify-7-devicetemplates.png' });
+
+ // Regression: 页面样式库
+ await page.locator(".company-side-nav button:has-text(\"页面样式\")").first().click();
+ await page.waitForTimeout(1000);
+ check('回归: 页面样式库渲染', true);
+ await page.screenshot({ path: '/tmp/sb-verify-8-stylelibrary.png' });
+
+} catch (e) {
+ results.push({ name: 'SCRIPT ERROR', ok: false, extra: e.message });
+} finally {
+ console.log('=== CHECKS ===');
+ for (const r of results) console.log(`${r.ok ? 'PASS' : 'FAIL'} ${r.name}${r.extra ? ' ('+r.extra+')' : ''}`);
+ console.log('=== CONSOLE ERRORS (' + consoleErrors.length + ') ===');
+ for (const e of consoleErrors.slice(0, 30)) console.log(e);
+ await browser.close();
+}