Files
kefu/deploy/customer-picker-20260918/audit_assistant_render.py
T
2026-09-21 10:34:06 +08:00

52 lines
3.3 KiB
Python

"""Read-only production asset rendering; synthetic state and blocked networking."""
import os
os.environ['QT_QPA_PLATFORM'] = 'offscreen'
import json, sys
from pathlib import Path
from PySide6.QtCore import QEventLoop, QTimer, QUrl
from PySide6.QtWidgets import QApplication
from PySide6.QtWebEngineWidgets import QWebEngineView
from PySide6.QtWebEngineCore import QWebEnginePage, QWebEngineUrlRequestInterceptor
DEST = Path(__file__).parent
class DenyNetwork(QWebEngineUrlRequestInterceptor):
def interceptRequest(self, info):
if info.requestUrl().scheme() in ('http','https','ws','wss'):
info.block(True)
class Page(QWebEnginePage):
def javaScriptConsoleMessage(self, level, message, line, source):
print('JS:', str(message), flush=True)
app=QApplication([])
view=QWebEngineView(); page=Page(view); view.setPage(page)
blocker=DenyNetwork(page); page.profile().setUrlRequestInterceptor(blocker)
view.resize(1440,1000);view.show()
def wait(ms):
loop=QEventLoop();QTimer.singleShot(ms,loop.quit);loop.exec()
def js(code):
values=[];loop=QEventLoop()
def done(value): values.append(value);loop.quit()
page.runJavaScript(code,done);QTimer.singleShot(10000,loop.quit);loop.exec()
if not values: raise RuntimeError('JS callback timeout')
return values[0]
loop=QEventLoop();loaded=[]
view.loadFinished.connect(lambda ok:(loaded.append(ok),loop.quit()))
view.load(QUrl.fromLocalFile(r'C:\wechat_rpa\assets\ui\zhenyang-ai-console.html'))
QTimer.singleShot(15000,loop.quit);loop.exec()
assert loaded==[True],loaded
state={'view':'automation','ready':True,'demo':False,'automation':{'transport':'protocol','reviewAssistant':{
'supported':True,'ready':True,'enabled':False,'busy':False,'accountId':'168800000000001','accountName':'合成账号',
'recipient':{'id':'S:168800000000001_10001','name':'合成医疗助理','label':'企业微信客户 · 联系编号10001','kind':'企业微信客户','peerId':'10001'},
'notification':{'message':'等待人工直接回复客户'},'preview':'【合成审核提醒内容】仅渲染测试,不发送消息'}}}
js('window.applyState('+json.dumps(state)+');render("automation");fit();')
metrics=[]
for ms in (50,700,2000):
wait(ms)
dom=json.loads(js('JSON.stringify({visibility:document.visibilityState,view:STATE.view,mainText:document.querySelector("#main").textContent.length,mainRect:document.querySelector("#main").getBoundingClientRect().toJSON(),screenRect:document.querySelector(".screen").getBoundingClientRect().toJSON(),opacity:getComputedStyle(document.querySelector(".screen")).opacity,transform:getComputedStyle(document.querySelector("#stage")).transform,window:[innerWidth,innerHeight],toggleRect:document.querySelector("[data-action=review-assistant-toggle]").getBoundingClientRect().toJSON()})'))
shot=view.grab();path=DEST/f'assistant-settings-independent-{ms}.png';assert shot.save(str(path))
image=shot.toImage();pixels=set(image.pixelColor(x,y).name() for x in range(240,1350,9) for y in range(30,970,9))
dom.update(wait_ms=ms,pixel_colors_main=len(pixels),path=str(path));metrics.append(dom)
(DEST/'assistant-render-metrics.json').write_text(json.dumps(metrics,ensure_ascii=False,indent=2),encoding='utf-8')
print(json.dumps(metrics,ensure_ascii=False,indent=2),flush=True)
view.close();app.processEvents()
os._exit(0)