| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- // 测试:默认识别规则(红框)识别用户户型图内红框柜子并报价
- // 运行:node debug_redbox_recognition.js
- const { chromium } = require('playwright-core');
- const fs = require('fs');
- const IMG = 'd:/AI文件夹/预算报价/test_redbox_input.png';
- const URL = 'http://127.0.0.1:8931/AI%E5%BF%AB%E9%80%9F%E6%8A%A5%E4%BB%B7_Demo2.optimizing.html?v=redbox-test';
- const log = o => { fs.writeFileSync('debug_redbox_result.json', JSON.stringify(o, null, 1)); console.log(JSON.stringify(o, null, 1)); };
- (async () => {
- const stage = s => fs.writeFileSync('debug_redbox_stage.txt', s + ' @ ' + new Date().toISOString());
- process.on('exit', code => { try { fs.appendFileSync('debug_redbox_stage.txt', '\nexit:' + code); } catch (e) {} });
- process.on('uncaughtException', e => { try { fs.appendFileSync('debug_redbox_stage.txt', '\nuncaught:' + e.message); } catch (e2) {} });
- process.on('unhandledRejection', e => { try { fs.appendFileSync('debug_redbox_stage.txt', '\nrejection:' + String(e && e.message || e).slice(0, 300)); } catch (e2) {} });
- stage('launching');
- const b = await chromium.launchPersistentContext('d:/AI文件夹/预算报价/.edge-profile-' + Date.now(), { headless: true, executablePath: 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe', args: ['--no-first-run', '--no-default-browser-check', '--no-sandbox', '--disable-gpu', '--disable-breakpad', '--disable-crash-reporter'] });
- b.on('close', () => { try { fs.appendFileSync('debug_redbox_stage.txt', '\nbrowser-close @ ' + new Date().toISOString()); } catch (e) {} });
- stage('launched');
- const p = await b.newPage({ viewport: { width: 1400, height: 950 } });
- // 只放行本地服务与 data/blob,阻断外部网络(qwen 等调用按设计静默回退本地识别)
- await p.route('**/*', r => { const u = r.request().url(); if (u.startsWith('http://127.0.0.1') || u.startsWith('data:') || u.startsWith('blob:')) return r.continue(); return r.abort(); });
- const errors = [];
- const consoleLog = [];
- p.on('pageerror', e => errors.push('pageerror: ' + e.message));
- p.on('console', m => { consoleLog.push(m.type() + ': ' + m.text().slice(0, 200)); if (consoleLog.length > 150) consoleLog.shift(); });
- await p.goto(URL, { waitUntil: 'load' });
- await p.evaluate(() => { try { localStorage.clear(); } catch (e) {} });
- await p.reload({ waitUntil: 'load' });
- await p.waitForTimeout(1000);
- stage('loaded');
- // 1) 默认识别规则应为红框
- stage('pre-rule');
- const rule = await p.evaluate(() => ({ color: window.qCadRuleColor, name: window.qCadRuleColorName, mode: state.quoteMode }));
- stage('rule:' + rule.color);
- // 2) 上传户型图(统一上传入口,图片自动路由到图纸处理)
- await p.setInputFiles('#q-file-unified', IMG);
- stage('uploaded');
- // 3) 轮询等待识别完成(每10秒记录进度,最长300秒)
- let done = false, diag = null;
- for (let i = 0; i < 30; i++) {
- await p.waitForTimeout(10000);
- diag = await p.evaluate(() => ({
- hasRecog: !!(window.state && state.qRecogResult),
- boxes: (state.qRecogResult && state.qRecogResult.boxes) ? state.qRecogResult.boxes.length : -1,
- qwen: state.qRecogResult ? state.qRecogResult.qwen : null,
- cabs: window.qAIPlacedCabinets ? qAIPlacedCabinets.length : -1
- })).catch(e => ({ pollErr: String(e.message).slice(0, 120) }));
- fs.appendFileSync('debug_redbox_stage.txt', '\npoll' + i + ': ' + JSON.stringify(diag));
- if (diag && diag.cabs > 0) { done = true; break; }
- }
- if (!done) {
- const tail = await p.evaluate(() => { const el = document.getElementById('q-ai-log'); return el ? el.innerText.slice(-1500) : null; }).catch(() => null);
- log({ fail: 'recognition not done in 300s', diag, logTail: tail, consoleTail: consoleLog.slice(-40), errors });
- await b.close();
- process.exit(1);
- }
- await p.waitForTimeout(800);
- stage('recognized');
- const recog = await p.evaluate(() => ({
- ratio: state.qRecogResult.ratio,
- ratioSource: state.qRecogResult.source,
- dimCount: state.qRecogResult.dimCount,
- labelCount: state.qRecogResult.labelCount,
- qwen: state.qRecogResult.qwen,
- qwenNamed: state.qRecogResult.qwenNamed,
- applied: state.qRecogResult.applied,
- boxes: state.qRecogResult.boxes.map(b => ({ x: b.x, y: b.y, w: b.w, h: b.h, wm: b.wm, hm: b.hm })),
- cabinets: qAIPlacedCabinets.map(c => ({ name: c.type, width: c.width, height: c.height, source: c.source, pos: c.posLabel || '', kitchenWalls: c.kitchenWalls || null })),
- rooms: qRooms.map(r => ({ room: r.roomName, cab: r.cabinetType, w: r.cabinetWidth, h: r.cabinetHeight, area: +(+r.projectArea).toFixed(2) }))
- }));
- await p.screenshot({ path: 'debug_redbox_step1.png' });
- // 4) 进入计价与报价单
- await p.evaluate(() => goToStep(3));
- await p.waitForTimeout(800);
- await p.evaluate(() => goToStep(4));
- await p.waitForTimeout(1500);
- stage('step4');
- const quote = await p.evaluate(() => {
- const t = id => { const el = document.getElementById(id); return el ? el.textContent.trim() : null; };
- const s4 = document.getElementById('step-4');
- return {
- grandTotal: t('q-grand-total-value'),
- grandArea: t('q-grand-total-area'),
- grandNote: t('q-grand-total-note'),
- step4Text: s4 ? s4.innerText.replace(/\n{2,}/g, '\n').slice(0, 2500) : null
- };
- });
- await p.screenshot({ path: 'debug_redbox_step4.png', fullPage: true });
- log({ rule, recog, quote, errors });
- await b.close();
- })().catch(e => { log({ fail: String(e && e.message || e), stack: String(e && e.stack || '').slice(0, 500) }); process.exit(1); });
|