175 lines
6.2 KiB
JavaScript
175 lines
6.2 KiB
JavaScript
/**
|
||
* 调试导出:点击导出按钮后,监控网络请求、页面变化、弹窗等
|
||
*/
|
||
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>> 完成');
|