'use strict'; /* 临时验收脚本:走 CDP 打开首页 → 填表 → 分析 → 选目的地 → 生成方案 → 截图 */ const { spawn } = require('child_process'); const fs = require('fs'); const path = require('path'); const os = require('os'); const OUT = path.join(__dirname, '..', 'preview'); const BASE = process.env.BASE || 'http://127.0.0.1:8788'; const CHROME = 'C:/Program Files/Google/Chrome/Application/chrome.exe'; function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); } async function getWsUrl() { const port = 9333; const res = await fetch(`http://127.0.0.1:${port}/json/version`); const j = await res.json(); return j.webSocketDebuggerUrl; } class CDP { constructor(ws) { this.ws = ws; this.id = 0; this.waits = new Map(); this.events = []; } static async connect(url) { const ws = new WebSocket(url); await new Promise((res, rej) => { ws.onopen = res; ws.onerror = rej; }); const c = new CDP(ws); ws.onmessage = (e) => { const m = JSON.parse(e.data); if (m.id && c.waits.has(m.id)) { c.waits.get(m.id)(m); c.waits.delete(m.id); } else if (m.method) c.events.push(m); }; return c; } send(method, params = {}, sessionId) { const id = ++this.id; return new Promise((res) => { this.waits.set(id, res); this.ws.send(JSON.stringify({ id, method, params, sessionId })); }); } } (async () => { const wsUrl = await getWsUrl(); const browser = await CDP.connect(wsUrl); const { result: { targetId } } = await browser.send('Target.createTarget', { url: 'about:blank' }); const { result: { sessionId } } = await browser.send('Target.attachToTarget', { targetId, flatten: true }); const S = (m, p) => browser.send(m, p, sessionId); await S('Page.enable'); await S('Runtime.enable'); await S('Emulation.setDeviceMetricsOverride', { width: 1280, height: 1600, deviceScaleFactor: 1, mobile: false }); await S('Page.navigate', { url: BASE }); await sleep(2500); const evalJs = async (expr) => { const r = await S('Runtime.evaluate', { expression: expr, awaitPromise: true, returnByValue: true }); if (r.result?.exceptionDetails) throw new Error(JSON.stringify(r.result.exceptionDetails)); return r.result?.result?.value; }; // 填出发地 await evalJs(`(() => { const el = document.querySelector('#originInput'); el.value = '柳州'; el.dispatchEvent(new Event('input', { bubbles: true })); return true; })()`); // 等联想(网络有波动,最多等 20s) let picked = false; for (let i = 0; i < 20; i += 1) { await sleep(1000); picked = await evalJs(`(() => { const it = document.querySelector('#suggestBox .suggest-item'); if (it && !document.querySelector('#suggestBox').classList.contains('hidden')) { it.click(); return true; } return false; })()`); if (picked) break; } console.log('suggest picked =', picked, '| box =', await evalJs(`document.querySelector('#suggestBox')?.textContent?.slice(0,60)`)); await sleep(1500); const originName = await evalJs(`document.querySelector('#originInput')?.value`); console.log('origin =', originName); // 点击分析 await evalJs(`document.querySelector('#analyzeBtn')?.click()`); await sleep(12000); const candCount = await evalJs(`document.querySelectorAll('.dest-card').length`); console.log('candidates =', candCount); // 选前 3 个 await evalJs(`(() => { const btns = [...document.querySelectorAll('.dest-card .pick-btn')].slice(0,3); btns.forEach(b => b.click()); return btns.length; })()`); await sleep(2000); console.log('selected =', await evalJs(`document.querySelector('#selectedCount')?.textContent`)); // 生成方案 await evalJs(`document.querySelector('#planBtn')?.click()`); await sleep(12000); const meta = await evalJs(`document.querySelector('#outputMeta')?.textContent`); console.log('outputMeta =', meta); console.log('plan head =', await evalJs(`(document.querySelector('#planOutput')?.innerText||'').slice(0,80)`)); await evalJs(`document.querySelector('#panel3')?.scrollIntoView()`); await sleep(800); const shot = await S('Page.captureScreenshot', { format: 'png', captureBeyondViewport: false }); if (!shot.result || !shot.result.data) throw new Error('no screenshot data: ' + JSON.stringify(shot).slice(0, 300)); fs.writeFileSync(path.join(OUT, 'preview-ctx-token.png'), Buffer.from(shot.result.data, 'base64')); console.log('screenshot saved'); browser.ws.close(); process.exit(0); })().catch((e) => { console.error('FAIL', e.message); process.exit(1); });