Files
LWLT-AI/archive/handoff/2026-07-12/legacy-erp-handoff/tools/erp_single_team_test.js
2026-07-13 19:57:46 +08:00

106 lines
3.6 KiB
JavaScript

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', 'single-team-test', `run-${RUN_ID}`);
const LOG_FILE = path.join(RUN_DIR, 'run.log');
const ORDER = {
product: '遇见老挝',
departureDate: '2026-07-12',
pax: { adult: 2, childBed: 1, childNoBed: 1, infant: 0, leader: 0 },
rooms: { SGL: 0, TWN: 0, TRP: 0, DBL: 2, HNM: 0, TL: 0 },
prices: { adult: 500, childBed: 200, childNoBed: 100, infant: 0, leader: 0 },
op: '测试',
sales: '琳琳',
};
fs.mkdirSync(RUN_DIR, { recursive: true });
function log(message, data) {
const line = `[${new Date().toISOString()}] ${message}${data === undefined ? '' : ` ${JSON.stringify(data)}`}`;
fs.appendFileSync(LOG_FILE, `${line}\n`, 'utf8');
console.log(line);
}
async function saveShot(page, name) {
const file = path.join(RUN_DIR, `${name}.png`);
await page.screenshot({ path: file, fullPage: false });
log('screenshot', { file });
}
async function getText(page) {
return await page.locator('body').innerText({ timeout: 5000 }).catch(() => '');
}
async function waitForLogin(page) {
await page.goto('https://ltjt.yunzhi.run/System/Mainlt.asp', { waitUntil: 'domcontentloaded', timeout: 30000 });
for (;;) {
const url = page.url().toLowerCase();
const body = await getText(page);
if (!url.includes('login') && (body.includes('业务操作') || body.includes('独立团计划表') || body.includes('首页'))) {
log('login-ok', { url: page.url(), title: await page.title() });
return;
}
log('waiting-login', { url: page.url(), title: await page.title() });
await saveShot(page, 'waiting-login');
await page.waitForTimeout(3000);
}
}
async function countAndClick(page, selector, label) {
const locator = page.locator(selector);
const count = await locator.count();
log('locator-count', { label, selector, count });
if (count !== 1) throw new Error(`${label} locator count ${count}: ${selector}`);
await locator.click({ timeout: 10000 });
}
async function main() {
log('run-start', { runDir: RUN_DIR, order: ORDER });
const context = await chromium.launchPersistentContext(PROFILE, {
headless: false,
viewport: { width: 1920, height: 1000 },
acceptDownloads: true,
downloadsPath: path.join(RUN_DIR, 'downloads'),
});
const page = context.pages()[0] || await context.newPage();
page.setDefaultTimeout(12000);
try {
await waitForLogin(page);
await page.goto('https://ltjt.yunzhi.run/System/Business/orders.asp', {
waitUntil: 'domcontentloaded',
timeout: 30000,
});
await page.waitForTimeout(1500);
await saveShot(page, 'orders-list');
await countAndClick(page, 'input[type="button"][value="下单"]', 'single-order-button');
await page.waitForTimeout(1500);
await saveShot(page, 'after-click-single-order');
const body = await getText(page);
log('after-click-body-snippet', body.slice(0, 1000));
log('manual-checkpoint', {
message: 'Single-order form opened. Automation paused here until field selectors are confirmed.',
runDir: RUN_DIR,
});
} catch (error) {
log('error', { message: error.message, stack: error.stack });
await saveShot(page, 'error');
throw error;
} finally {
log('leaving-browser-open', { runDir: RUN_DIR });
await new Promise(() => {});
}
}
main().catch((error) => {
console.error(error);
process.exit(1);
});