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

66 lines
4.4 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, QMainWindow
from unittest.mock import Mock
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([])
sys.path.insert(0, r'C:\kefu\wechat_rpa')
import wechat_gui_qt as qt
qt.CONSOLE_HTML=Path(r'C:\wechat_rpa\assets\ui\zhenyang-ai-console.html')
owner=QMainWindow();owner._push_console_state=Mock()
view=qt.ConsoleShell(owner);owner.setCentralWidget(view);owner.resize(1440,1000);owner.show()
page=view.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':'【合成审核提醒内容】仅渲染测试,不发送消息'}}}
unsupported={'view':'automation','ready':True,'demo':False,'automation':{'transport':'visual','reviewAssistant':{'supported':False,'ready':False,'enabled':False,'reason':'当前版本不支持协议审核提醒'}}}
js('window.applyState('+json.dumps(unsupported)+');render("automation");')
assert js('document.querySelector("[data-action=review-assistant-toggle]").disabled')
assert js('document.querySelector("[data-action=review-assistant-choose]").disabled')
assert '当前版本不支持' in js('document.body.textContent')
js('window.applyState('+json.dumps(state)+');render("automation");')
assert not js('document.querySelector("[data-action=review-assistant-toggle]").disabled')
js('window.qtBridge={setReviewAssistantEnabled:(payload,cb)=>cb(JSON.stringify({ok:true,message:"synthetic"}))};document.querySelector("[data-action=review-assistant-toggle]").click();')
js('window.fit(); document.querySelector("details").open=true;')
metrics=[]
for ms in (700,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-shell-{len(metrics)}-{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-shell-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)