Files
ycode/scripts/wb-home-parts.mjs

141 lines
5.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import './wb-legacy-disabled.mjs'
/**
* 首页补充探测:大标题、输入框下方行、建议列表。
*
* 用法:node scripts/wb-home-parts.mjs <port>
*/
const port = Number(process.argv[2] ?? 9223)
async function main() {
const list = await (await fetch(`http://127.0.0.1:${port}/json/list`)).json()
const page = list.filter((t) => t.type === 'page')[0]
const ws = new WebSocket(page.webSocketDebuggerUrl)
await new Promise((r, j) => {
const t = setTimeout(() => j(new Error('连接超时')), 8000)
ws.addEventListener('open', () => {
clearTimeout(t)
r()
})
ws.addEventListener('error', () => {
clearTimeout(t)
j(new Error('连接失败'))
})
})
const send = (method, params = {}) =>
new Promise((res, rej) => {
const id = Math.floor(Math.random() * 1e9)
const timer = setTimeout(() => rej(new Error(`超时 ${method}`)), 25000)
const h = (ev) => {
const m = JSON.parse(ev.data)
if (m.id === id) {
clearTimeout(timer)
ws.removeEventListener('message', h)
res(m.result)
}
}
ws.addEventListener('message', h)
ws.send(JSON.stringify({ id, method, params }))
})
const expr = `(() => {
const clean = (v) => (v == null ? '' : String(v).replace(/\\s+/g, ' ').trim());
const R = (el) => { const r = el.getBoundingClientRect(); return [Math.round(r.x), Math.round(r.y), Math.round(r.width), Math.round(r.height)]; };
const info = (el) => {
if (!el) return null;
const cs = getComputedStyle(el);
return {
tag: el.tagName.toLowerCase(),
cls: clean(el.className).slice(0, 80),
rect: R(el),
fontSize: cs.fontSize,
fontWeight: cs.fontWeight,
lineHeight: cs.lineHeight,
color: cs.color,
display: cs.display,
flexDirection: cs.flexDirection,
alignItems: cs.alignItems,
justifyContent: cs.justifyContent,
gap: cs.gap,
padding: cs.padding,
margin: cs.margin,
radius: cs.borderRadius,
bg: cs.backgroundColor,
border: cs.borderTopWidth + ' ' + cs.borderTopColor
};
};
// 1) 最大字号元素(标题)
let heading = null, maxFs = 0;
document.querySelectorAll('body *').forEach((el) => {
const r = el.getBoundingClientRect();
if (r.y < 30 || r.y > 350 || r.width < 40 || r.height < 10) return;
if (el.children.length > 2) return;
const cs = getComputedStyle(el);
const fs = parseFloat(cs.fontSize);
if (fs > maxFs) { maxFs = fs; heading = el; }
});
// 2) 输入框外层容器的全部子元素(含下方那行)
const box = document.querySelector('[class*="home-route__input-box"]') || document.querySelector('.cr-input-box');
const boxKids = box ? [...box.children].map((c) => ({ ...info(c), text: clean(c.textContent).slice(0, 50) })) : [];
// 3) 建议列表:找 y > 520 且高度 32 左右的成组元素
const suggCandidates = [];
document.querySelectorAll('button, [role="button"], div, li').forEach((el) => {
const r = el.getBoundingClientRect();
if (r.y < 500 || r.y > 800 || r.height < 24 || r.height > 44 || r.width < 120 || r.width > 700) return;
const cs = getComputedStyle(el);
if (cs.borderRadius === '0px' && cs.backgroundColor === 'rgba(0, 0, 0, 0)') return;
const t = clean(el.textContent);
if (!t || t.length > 50) return;
suggCandidates.push({ ...info(el), text: t });
});
return JSON.stringify({
viewport: { w: innerWidth, h: innerHeight },
heading: info(heading),
box: info(box),
boxKids,
sugg: suggCandidates.slice(0, 12),
suggParent: suggCandidates[0] ? info(suggCandidates[0].parentElement) : null,
suggGrand: suggCandidates[0] ? info(suggCandidates[0].parentElement?.parentElement) : null
});
})()`
const r = await send('Runtime.evaluate', { expression: expr, returnByValue: true })
const d = JSON.parse(r.result.value)
console.log(`viewport ${d.viewport.w}x${d.viewport.h}`)
const show = (label, o) => {
if (!o) return console.log(`\n### ${label}\n (无)`)
console.log(`\n### ${label}`)
console.log(` ${o.tag}.${o.cls} rect ${JSON.stringify(o.rect)}`)
console.log(` fs=${o.fontSize}/${o.fontWeight} lh=${o.lineHeight} color=${o.color}`)
console.log(` display=${o.display}/${o.flexDirection} align=${o.alignItems} justify=${o.justifyContent} gap=${o.gap}`)
console.log(` pad=${o.padding} margin=${o.margin} radius=${o.radius} bg=${o.bg} border=${o.border}`)
if (o.text) console.log(` text="${o.text}"`)
}
show('大标题', d.heading)
show('输入框外层 .cr-input-box', d.box)
console.log(`\n### 输入框外层的子元素(${d.boxKids.length})`)
for (const k of d.boxKids) {
console.log(` ${k.tag}.${k.cls} ${JSON.stringify(k.rect)} gap=${k.gap} pad=${k.padding} radius=${k.radius} bg=${k.bg}`)
if (k.text) console.log(` "${k.text}"`)
}
show('建议项父级', d.suggParent)
show('建议项祖父', d.suggGrand)
console.log(`\n### 建议项候选(${d.sugg.length})`)
for (const s of d.sugg) {
console.log(` ${s.tag}.${s.cls} ${JSON.stringify(s.rect)} radius=${s.radius} bg=${s.bg} border=${s.border} fs=${s.fontSize} "${s.text}"`)
}
ws.close()
}
main().catch((e) => {
console.error('失败:', e.message)
process.exit(1)
})