u
This commit is contained in:
1 parent
b4498e5350
commit
bf9dca19de
47 files changed
+8592
-313
No files matched your search
@@ -0,0 +1,81 @@
|
||||
import { chromium } from '@playwright/test'
|
||||
|
||||
/**
|
||||
* 方案验证:外框底边若改用 inset box-shadow(画在 padding box 内侧、覆盖在上层),
|
||||
* 是否能"永远赢"——即无论最后一行是否贴近,视觉上只有一条线。
|
||||
*
|
||||
* 先做纯 CSS 实验:在页面上注入覆盖样式,然后逐像素扫描底边,
|
||||
* 数出「深色像素的数量」,1 条 = 正确,2 条 = 双线,0 条 = 缺线。
|
||||
*/
|
||||
const BASE = process.env.PROBE_URL || 'http://localhost:5200'
|
||||
const browser = await chromium.launch()
|
||||
const page = await browser.newPage({ viewport: { width: 1400, height: 1200 } })
|
||||
await page.goto(BASE, { waitUntil: 'networkidle' })
|
||||
|
||||
const clipSample = async (x, y, w, h) => {
|
||||
const shot = await page.screenshot({ clip: { x, y, width: w, height: h } })
|
||||
return page.evaluate(async (dataUrl) => {
|
||||
const img = new Image()
|
||||
await new Promise((res) => {
|
||||
img.onload = res
|
||||
img.src = dataUrl
|
||||
})
|
||||
const cv = document.createElement('canvas')
|
||||
cv.width = img.width
|
||||
cv.height = img.height
|
||||
const ctx = cv.getContext('2d')
|
||||
ctx.drawImage(img, 0, 0)
|
||||
const d = ctx.getImageData(0, 0, img.width, img.height).data
|
||||
const out = []
|
||||
for (let i = 0; i < d.length; i += 4) out.push([d[i], d[i + 1], d[i + 2]])
|
||||
return out
|
||||
}, `data:image/png;base64,${shot.toString('base64')}`)
|
||||
}
|
||||
|
||||
const scan = async (label, h) => {
|
||||
await page.evaluate((hh) => {
|
||||
const wrap = document.querySelector('[data-testid="table-wrap"]')
|
||||
wrap.style.height = `${hh}px`
|
||||
}, h)
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// 必须先把表格滚进视口:page.screenshot 的 clip 用视口坐标,页面下方的元素会落空
|
||||
const wrapLoc = page.locator('[data-testid="table-wrap"]')
|
||||
await wrapLoc.scrollIntoViewIfNeeded()
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
const geo = await page.evaluate(() => {
|
||||
const wrap = document.querySelector('[data-testid="table-wrap"]')
|
||||
const root = wrap.querySelector('.g3-table')
|
||||
const r = root.getBoundingClientRect()
|
||||
return {
|
||||
left: Math.round(r.left),
|
||||
// getBoundingClientRect 已是视口坐标,直接可用
|
||||
bottom: Math.round(r.bottom),
|
||||
isBodyFill: root.classList.contains('is-body-fill'),
|
||||
}
|
||||
})
|
||||
|
||||
// 采样窗口必须完整落在视口内
|
||||
const y0 = Math.max(0, geo.bottom - 4)
|
||||
const available = 1200 - y0
|
||||
if (available < 8) {
|
||||
console.log(`${label} h=${h} 跳过(采样窗口超出视口)`)
|
||||
return null
|
||||
}
|
||||
|
||||
const px = await clipSample(geo.left + 300, y0, 1, 8)
|
||||
const dark = px.map(([r, g, b]) => (r < 246 || g < 246 || b < 246 ? 1 : 0))
|
||||
const count = dark.reduce((a, b) => a + b, 0)
|
||||
console.log(
|
||||
`${label} h=${String(h).padStart(3)} bodyFill=${String(geo.isBodyFill).padStart(5)} 底边纵向像素: ${dark.join('')} → ${count === 1 ? '一条线 ✅' : count === 0 ? '缺线 ❌' : count + ' 条 ❌'}`,
|
||||
)
|
||||
return count
|
||||
}
|
||||
|
||||
console.log('========== 修复前(当前实现)==========')
|
||||
for (const h of [400, 200, 140, 130, 128, 127, 126, 125, 124, 120, 100, 80, 60]) {
|
||||
await scan('before', h)
|
||||
}
|
||||
|
||||
await browser.close()
|
||||
Reference in new issue
Block a user