# -*- coding: utf-8 -*- """票 12 快验:联系人顶级菜单 + 商机侧三入口(UI 层 + 登录链路尽力)""" import io, json, sys sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') from playwright.sync_api import sync_playwright URL = 'file:///E:/code/crm-backend-matt/.scratch/customer-demo-ref/demo/index.html' errors = [] out = {} with sync_playwright() as p: b = p.chromium.launch() pg = b.new_page(viewport={'width': 1720, 'height': 1080}) pg.on('pageerror', lambda e: errors.append(str(e))) pg.goto(URL) pg.wait_for_timeout(800) # 1) nav tabs = 6,联系人按钮存在 out['tabs'] = pg.eval_on_selector_all('nav.tabs button', 'els => els.map(e => e.dataset.tab)') # 2) 切联系人 tab pg.click('nav.tabs button[data-tab="contacts"]') pg.wait_for_timeout(300) out['contacts_section_visible'] = pg.eval_on_selector('#tab-contacts', 'e => e.style.display !== "none"') out['g5_badge'] = pg.eval_on_selector_all('#tab-contacts [data-defect="G5"]', 'els => els.length') out['cform_options'] = pg.eval_on_selector('#cForm', 'e => e.options.length') # 3) 未登录 hint(尽力;登录后此值会被覆盖) out['ct_hint_before_login'] = pg.eval_on_selector('#ctPageInfo', 'e => e.textContent') # 4) 登录链路(远程 debug token;失败不阻塞 UI 断言) try: pg.fill('#uidInput', '739564171091247104') pg.evaluate('loginByUid()') pg.wait_for_timeout(2500) out['token_set'] = pg.evaluate('!!localStorage.getItem("e2c_token")') if out['token_set']: pg.click('nav.tabs button[data-tab="contacts"]') pg.evaluate('loadContactPage()') pg.wait_for_timeout(2000) out['ct_rows'] = pg.eval_on_selector_all('#ctPageBody tr', 'els => els.length') out['ct_head'] = pg.eval_on_selector('#ctPageHead', 'e => e.textContent.slice(0, 120)') out['ct_info'] = pg.eval_on_selector('#ctPageInfo', 'e => e.textContent') out['phone_masked'] = pg.evaluate('''() => { const tds = [...document.querySelectorAll('#ctPageBody td')]; const phone = tds.map(t => t.textContent).find(t => /^\\d{3}\\*{4}\\d{4}$/.test(t)); return phone || null; }''') # 行点开详情弹窗(contact/detail 回显 + G6 空态) has_row = pg.eval_on_selector_all('#ctPageBody tr td.row', 'els => els.length') if has_row: pg.click('#ctPageBody tr td.row') pg.wait_for_timeout(1200) out['detail_dlg'] = pg.eval_on_selector('dialog#dlg[open]', 'e => !!e') out['ct_info_kv'] = pg.eval_on_selector_all('#ctPaneInfo .kv', 'els => els.length') pg.click('#ctTabBtn1') pg.wait_for_timeout(200) out['g6_log'] = pg.eval_on_selector_all('#ctPaneLog[data-defect="G6"]', 'els => els.length') pg.keyboard.press('Escape') pg.wait_for_timeout(200) except Exception as e: out['login_error'] = str(e)[:200] # 5) 商机侧三入口 UI pg.click('nav.tabs button[data-tab="list"]') pg.wait_for_timeout(200) out['opp_entry_buttons'] = pg.evaluate('''() => ({ quick: [...document.querySelectorAll('button')].some(b => b.textContent.includes('快建客户')), search3d: [...document.querySelectorAll('button')].some(b => b.textContent.includes('三维搜索')), })''') # 快建弹窗打开(7 必填控件) pg.evaluate('dlgQuickCreate()') pg.wait_for_timeout(200) out['quick_fields'] = pg.evaluate('''() => ['qName','qType','qProv','qCity','qInd','qStar','qRStar'].filter(id => !!document.getElementById(id)).length''') pg.keyboard.press('Escape') pg.wait_for_timeout(200) # 全局搜索弹窗 pg.click('nav.tabs button[data-tab="contacts"]') pg.evaluate('dlgContactSearch()') pg.wait_for_timeout(200) out['search_dlg'] = pg.eval_on_selector('dialog#dlg[open]', 'e => !!e') pg.keyboard.press('Escape') pg.screenshot(path='E:/code/crm-backend-matt/.scratch/customer-demo-ref/demo/shots/t12-quick-contacts.png', full_page=False) b.close() out['pageerror'] = errors print(json.dumps(out, ensure_ascii=False, indent=1))