const fs = require('fs'); const path = require('path'); const { chromium } = require('playwright'); const ROOT = path.resolve(__dirname, '..'); const PROFILE = path.join(ROOT, 'diagnostics', 'erp-playwright-profile'); const RUN_ID = new Date().toISOString().replace(/[-:T.Z]/g, '').slice(0, 14); const RUN_DIR = path.join(ROOT, 'diagnostics', 'split-child-inspect', `run-${RUN_ID}`); const PARENT_GROUP = 'LW-260704A-A'; const DATE = '2026-07-04'; fs.mkdirSync(RUN_DIR, { recursive: true }); async function setField(page, selector, value) { const locator = page.locator(selector).first(); await locator.fill(String(value)); await locator.evaluate((el) => { el.dispatchEvent(new Event('input', { bubbles: true })); el.dispatchEvent(new Event('change', { bubbles: true })); el.dispatchEvent(new Event('blur', { bubbles: true })); }); } async function dump(page, name) { const frames = []; for (const frame of page.frames()) { const data = await frame.evaluate(() => { const controls = Array.from(document.querySelectorAll('input, button, a, select, textarea')).map((el, index) => { const attrs = {}; for (const attr of ['id', 'name', 'type', 'value', 'title', 'class', 'onclick', 'href']) { const value = el.getAttribute(attr); if (value != null) attrs[attr] = value; } const rect = el.getBoundingClientRect(); return { index, tag: el.tagName.toLowerCase(), text: (el.innerText || el.value || '').replace(/\s+/g, ' ').trim().slice(0, 240), attrs, rect: { x: Math.round(rect.x), y: Math.round(rect.y), w: Math.round(rect.width), h: Math.round(rect.height) }, }; }); return { url: location.href, title: document.title, bodyText: document.body.innerText.replace(/\s+/g, ' ').slice(0, 3500), controls }; }).catch((error) => ({ url: frame.url(), title: '', bodyText: `ERROR:${error.message}`, controls: [] })); frames.push({ frameUrl: frame.url(), frameName: frame.name(), ...data }); } fs.writeFileSync(path.join(RUN_DIR, `${name}.json`), JSON.stringify(frames, null, 2), 'utf8'); await page.screenshot({ path: path.join(RUN_DIR, `${name}.png`), fullPage: false }); console.log(JSON.stringify({ name, RUN_DIR, frames: frames.map((f) => ({ url: f.url, controls: f.controls.length, body: f.bodyText.slice(0, 220) })) }, null, 2)); } async function main() { const context = await chromium.launchPersistentContext(PROFILE, { headless: false, viewport: { width: 1920, height: 1000 }, acceptDownloads: true, }); const page = context.pages()[0] || await context.newPage(); page.setDefaultTimeout(15000); try { await page.goto('https://ltjt.yunzhi.run/System/Business/plan.asp', { waitUntil: 'domcontentloaded', timeout: 30000 }); await page.waitForTimeout(900); await setField(page, '#S_chufariqi', DATE); await setField(page, '#S_chufarizhi', DATE); await setField(page, '#S_tuanxuhao', PARENT_GROUP); await page.locator('#SearchButton').click(); await page.waitForTimeout(2500); await dump(page, '01-search-result'); await page.locator(`a:has-text("拼单")`).first().click(); await page.waitForTimeout(2500); await dump(page, '02-child-form'); } finally { await context.close(); } } main().catch((error) => { console.error(error); process.exit(1); });