import {createRequire} from 'node:module'; import {mkdirSync,writeFileSync} from 'node:fs'; const require=createRequire('C:/kefu/admin-web/package.json');const{chromium}=require('playwright'); const folder='C:/kefu/deploy/loading-performance-20260917';mkdirSync(folder,{recursive:true}); const browser=await chromium.launch({executablePath:'C:/Program Files/Google/Chrome/Application/chrome.exe',headless:true}); const results=[]; for(const [label,root] of [['protocol','C:/wechat_rpa'],['original','C:/kefu/wechat_rpa']]){ const context=await browser.newContext({viewport:{width:1440,height:900}}); await context.route('**/*',route=>route.request().url().startsWith('file:')?route.continue():route.abort()); const p=await context.newPage();const errors=[];p.on('pageerror',e=>errors.push(e.message)); await p.goto(`file:///${root}/assets/ui/zhenyang-ai-console.html`);await p.waitForTimeout(200); await p.evaluate(()=>{ window.calls=[];window.qtBridge=new Proxy({}, {get:(_,method)=>(...args)=>calls.push({method,args})}); window.db={loading:false,query:'',selectedAccount:'test-account',selectedConversation:'test-conv-0',accounts:[{id:'test-account',name:'模拟账号'}],files:[],conversations:Array.from({length:500},(_,i)=>({id:`test-conv-${i}`,name:`模拟客户 ${i}`,preview:'合成预览',messageCount:100,lastTime:'10:00'})),messages:Array.from({length:200},(_,i)=>({id:i,content:`合成消息 ${i}`,direction:'inbound',time:'10:00'}))}; applyState({view:'wechatdb',ready:true,demo:false,wechatDb:db,system:{scale:'自动'}}); }); const repeat=await p.evaluate(()=>{ const click=(sel)=>{calls=[];const el=document.querySelector(sel);for(let i=0;i<5;i++)el.click();return calls.map(c=>c.method)}; return {refresh:click('[data-action="wechat-db-refresh"]'),sameAccount:click('[data-action="wechat-db-account"]'),sameConversation:click('[data-action="wechat-db-conversation"]')}; }); await p.evaluate(()=>{calls=[];const input=document.querySelector('#wechat-db-search');for(const text of ['s','se','sea','sear','search']){input.value=text;input.dispatchEvent(new Event('input',{bubbles:true}))}}); await p.waitForTimeout(350);const quickSearch=await p.evaluate(()=>calls.filter(c=>c.method==='setWeChatDatabaseQuery').map(c=>c.args[0])); await p.evaluate(()=>{calls=[];const input=document.querySelector('#wechat-db-search');input.dispatchEvent(new CompositionEvent('compositionstart',{bubbles:true}));}); for(const text of ['ni','nihao','你好']){ await p.locator('#wechat-db-search').evaluate((input,text)=>{input.value=text;input.dispatchEvent(new InputEvent('input',{bubbles:true,isComposing:true}));},text);await p.waitForTimeout(330); } const compositionEarly=await p.evaluate(()=>calls.filter(c=>c.method==='setWeChatDatabaseQuery').map(c=>c.args[0])); await p.locator('#wechat-db-search').evaluate(input=>input.dispatchEvent(new CompositionEvent('compositionend',{bubbles:true})));await p.waitForTimeout(330); const compositionFinal=await p.evaluate(()=>calls.filter(c=>c.method==='setWeChatDatabaseQuery').map(c=>c.args[0])); const render=await p.evaluate(()=>{ const search=document.getElementById('wechat-db-search');search.focus();search.value='正在输入';search.setSelectionRange(2,2); const list=document.querySelector('.db-conversation-list');const started=performance.now(); applyState({view:'wechatdb',wechatDb:{...db,loading:true}}); const loadingMs=performance.now()-started; const focusKept=document.activeElement===search,valueKept=document.getElementById('wechat-db-search').value==='正在输入'; const listReplaced=list!==document.querySelector('.db-conversation-list');document.activeElement.blur(); applyState({view:'wechatdb',wechatDb:db}); const stableList=document.querySelector('.db-conversation-list');const t=performance.now(); for(let i=0;i<100;i++)applyState({view:'wechatdb',wechatDb:db,runtime:String(i)}); return {loadingMs,focusKept,valueKept,listReplaced,unchanged100Ms:performance.now()-t,unchangedListPreserved:stableList===document.querySelector('.db-conversation-list'),renderedConversations:document.querySelectorAll('.db-conversation').length,renderedMessages:document.querySelectorAll('.db-message').length}; }); let repeatProbe=null; if(label==='protocol')repeatProbe=await p.evaluate(()=>{ applyState({view:'automation',automation:{transport:'protocol',protocol:{status:'idle'}}});calls=[];const el=document.querySelector('[data-action="probe-protocol"]');for(let i=0;i<5;i++)el.click();return calls.filter(c=>c.method==='probeProtocol').length; }); results.push({label,repeat,quickSearch,compositionEarly,compositionFinal,render,repeatProbe,errors});await context.close(); } await browser.close();writeFileSync(`${folder}/frontend-audit-before.json`,JSON.stringify(results,null,2));console.log(JSON.stringify(results));