// 验证「账号设定」内容区左右 20px 间隔(persona-wrap padding 0 20px) const list = await fetch('http://localhost:9223/json').then((r) => r.json()); let page = list.find((t) => t.type === 'page' && t.url.includes('localhost:8899')); if (!page) { console.log('ERR: no workbuddy page open'); process.exit(1); } const ws = new WebSocket(page.webSocketDebuggerUrl); let id = 0; const pending = new Map(); const send = (method, params = {}) => new Promise((res, rej) => { const i = ++id; pending.set(i, { res, rej }); ws.send(JSON.stringify({ id: i, method, params })); }); ws.onmessage = (e) => { const m = JSON.parse(e.data); if (m.id && pending.has(m.id)) { const p = pending.get(m.id); pending.delete(m.id); m.error ? p.rej(new Error(m.error.message)) : p.res(m.result); } }; await new Promise((r) => (ws.onopen = r)); const ev = async (expr) => { const r = await send('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise: true }); if (r.exceptionDetails) return { __err: (r.exceptionDetails.exception?.description || r.exceptionDetails.text).slice(0, 300) }; return r.result.value; }; const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); await send('Page.enable'); await send('Runtime.enable'); const goto = async (url) => { await send('Page.navigate', { url }); await sleep(2500); await send('Page.reload', { ignoreCache: true }); await sleep(3000); }; console.log('=== 旧梦留声机 1629(有卡片)==='); await goto('http://localhost:8899/#/account/1629'); const tabClick = await ev(`(() => { const b = document.querySelector('[data-tab="persona"]'); if (!b) return { err: 'no persona tab' }; b.click(); return 'clicked persona tab'; })()`); console.log('切tab:', JSON.stringify(tabClick)); await sleep(1800); const s1 = await ev(`(() => { const wrap = document.querySelector('.persona-wrap'); const card = document.querySelector('.card-view'); const img = card && card.querySelector('img'); if (!wrap) return { err: 'no .persona-wrap' }; const cs = getComputedStyle(wrap); const dbody = document.querySelector('.detail-body'); const dw = dbody ? dbody.getBoundingClientRect().width : null; const ww = wrap.getBoundingClientRect().width; const iw = img ? img.getBoundingClientRect().width : null; return { paddingLeft: cs.paddingLeft, paddingRight: cs.paddingRight, detailBodyW: dw, wrapW: ww, imgW: iw, imgInset: iw !== null && dw !== null ? (dw - iw).toFixed(1) : null, // 卡片比内容区窄多少(两侧总和) }; })()`); console.log('persona padding 检查:', JSON.stringify(s1, null, 2)); // 切文字版后再看文字容器 const s2 = await ev(`(() => { const btn = document.querySelector('.persona-vs-icons [data-vs="text"]'); if (btn) btn.click(); return 'switched to text'; })()`); await sleep(600); const s3 = await ev(`(() => { const md = document.querySelector('.persona-text'); if (!md) return { err: 'no .persona-text' }; const dbody = document.querySelector('.detail-body'); const dw = dbody ? dbody.getBoundingClientRect().width : null; const mw = md.getBoundingClientRect().width; return { mdW: mw, inset: dw !== null ? (dw - mw).toFixed(1) : null }; })()`); console.log('文字版检查:', JSON.stringify(s3, null, 2)); ws.close(); console.log('DONE');