Files
20260324-42433647/debug-export.mjs
2026-04-25 21:50:03 +08:00

175 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 调试导出:点击导出按钮后,监控网络请求、页面变化、弹窗等
*/
import { chromium } from 'playwright';
import { readFileSync, existsSync, mkdirSync } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const COOKIE_FILE = path.join(__dirname, 'cookies.json');
const SS = path.join(__dirname, 'screenshots');
const BASE = 'https://www.dianxiaomi.com';
mkdirSync(SS, { recursive: true });
const browser = await chromium.launch({ headless: true, args: ['--no-sandbox'] });
const ctx = await browser.newContext({
viewport: { width: 1920, height: 1080 }, locale: 'zh-CN',
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
acceptDownloads: true,
});
const page = await ctx.newPage();
// Cookie
await ctx.addCookies(JSON.parse(readFileSync(COOKIE_FILE, 'utf-8')));
// 监听所有网络请求
page.on('request', req => {
const url = req.url();
if (url.includes('export') || url.includes('Export') || url.includes('download') ||
url.includes('Download') || url.includes('导出') || url.includes('.xls') ||
url.includes('.csv') || url.includes('.xlsx')) {
console.log(` [REQ] ${req.method()} ${url}`);
if (req.postData()) console.log(` [POST] ${req.postData().substring(0, 200)}`);
}
});
page.on('response', async resp => {
const url = resp.url();
if (url.includes('export') || url.includes('Export') || url.includes('download') ||
url.includes('Download') || url.includes('.xls') || url.includes('.csv')) {
const ct = resp.headers()['content-type'] || '';
const cd = resp.headers()['content-disposition'] || '';
console.log(` [RESP] ${resp.status()} ${url.substring(0, 100)}`);
console.log(` [CT] ${ct} [CD] ${cd}`);
if (ct.includes('json') || ct.includes('text')) {
try {
const body = await resp.text();
console.log(` [BODY] ${body.substring(0, 500)}`);
} catch {}
}
}
});
page.on('download', d => {
console.log(` [DOWNLOAD] ${d.suggestedFilename()} url=${d.url()}`);
});
page.on('dialog', async d => {
console.log(` [DIALOG] ${d.type()}: ${d.message()}`);
await d.accept();
});
// 监听新页面/标签
ctx.on('page', p => {
console.log(` [NEW PAGE] ${p.url()}`);
});
// === 测试采购建议的导出 ===
console.log('\n=== 采购建议页面 ===');
await page.goto(`${BASE}/purchasingProposal/index.htm?state=3`, { waitUntil: 'load', timeout: 30000 });
await page.waitForTimeout(5000);
// 点击"导出建议"下拉
const dropdown = await page.locator('text=导出建议').first();
await dropdown.click();
await page.waitForTimeout(1000);
// 点击"导出全部"
console.log('>> 点击"导出全部"...');
const exportAll = await page.locator('text=导出全部').first();
await exportAll.click();
// 等待并观察
console.log('>> 等待 15 秒观察反应...');
await page.waitForTimeout(15000);
// 截图
await page.screenshot({ path: path.join(SS, 'debug-after-export-click.png'), fullPage: true });
// 检查页面变化
const alerts = await page.evaluate(() => {
// 检查是否有弹窗/提示
const modals = document.querySelectorAll('.el-dialog, .modal, [class*="dialog"], [class*="modal"], [class*="popup"], [class*="toast"], [class*="message"], [class*="notify"]');
return Array.from(modals).map(m => ({
visible: m.offsetHeight > 0,
text: m.textContent?.substring(0, 200),
cls: m.className?.substring(0, 80),
})).filter(m => m.visible);
});
if (alerts.length) {
console.log('\n>> 弹窗/提示:');
alerts.forEach(a => console.log(` ${a.cls}: "${a.text}"`));
}
// 检查是否有 iframe
const iframes = await page.$$('iframe');
console.log(`\n>> iframe 数量: ${iframes.length}`);
// 查看页面当前状态
const pageText = await page.evaluate(() => document.body?.innerText?.substring(0, 3000));
console.log('\n>> 页面当前文本前1500字:\n', pageText?.substring(0, 1500));
await page.screenshot({ path: path.join(SS, 'debug-final.png') });
// === 同样测试仓库 ===
console.log('\n\n=== 仓库页面 ===');
await page.goto(`${BASE}/warehouseProduct/index.htm`, { waitUntil: 'load', timeout: 30000 });
await page.waitForTimeout(5000);
// 导入/导出 → 按所有页导出
const impExpBtn = await page.locator('text=导入/导出').first();
await impExpBtn.click();
await page.waitForTimeout(1500);
console.log('>> 点击"按所有页导出"...');
const allPages = await page.locator('text=按所有页导出').first();
await allPages.click();
await page.waitForTimeout(3000);
// 看看弹窗
await page.screenshot({ path: path.join(SS, 'debug-warehouse-dialog.png') });
// 找到并点击对话框的导出按钮
console.log('>> 查找对话框中的导出按钮...');
const dialogBtns = await page.$$eval('button', els =>
els.filter(el => el.offsetHeight > 0)
.map(el => ({
text: el.textContent.trim(), id: el.id,
cls: (el.className || '').substring(0, 60),
rect: el.getBoundingClientRect(),
})).filter(e => e.text.includes('导出') || e.text.includes('确认') || e.text.includes('确定'))
);
console.log(' 可见导出/确认按钮:', JSON.stringify(dialogBtns, null, 2));
if (dialogBtns.length) {
// 点击最后一个"导出"按钮(通常是对话框内的)
const targetText = dialogBtns.find(b => b.text === '导出')?.text || dialogBtns[0].text;
console.log(`>> 点击按钮: "${targetText}"`);
const btn = await page.locator(`button:visible:has-text("${targetText}")`).last();
await btn.click();
console.log('>> 等待 15 秒...');
await page.waitForTimeout(15000);
await page.screenshot({ path: path.join(SS, 'debug-warehouse-after-confirm.png') });
// 再次检查弹窗
const alerts2 = await page.evaluate(() => {
const modals = document.querySelectorAll('.el-dialog, .modal, [class*="dialog"], [class*="message"], [class*="notify"], [class*="toast"]');
return Array.from(modals).map(m => ({
visible: m.offsetHeight > 0,
text: m.textContent?.substring(0, 300),
})).filter(m => m.visible);
});
if (alerts2.length) {
console.log('\n>> 点击后弹窗:');
alerts2.forEach(a => console.log(` "${a.text}"`));
}
}
await browser.close();
console.log('\n>> 完成');