Files
workspace/code/fms/.playwright-cli/inspect-fmsfile2.mjs
T
2026-08-20 22:38:37 +08:00

192 lines
6.9 KiB
JavaScript

import { chromium } from 'playwright-core'
const BASE = 'http://localhost:5082'
const browser = await chromium.launch({
headless: true,
executablePath: `${process.env.LOCALAPPDATA}\\ms-playwright\\chromium-1232\\chrome-win64\\chrome.exe`,
})
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } })
const out = { logs: [] }
page.on('console', (m) => {
if (m.type() === 'error' || m.type() === 'warning') out.logs.push(`[${m.type()}] ${m.text()}`)
})
page.on('pageerror', (e) => out.logs.push(`[pageerror] ${e.message}`))
// 1) inject fake auth before app boot
await page.addInitScript(() => {
sessionStorage.setItem(
'fms-login',
JSON.stringify({ loginInfo: { token: 'dev-token', user: { id: 1, name: 'dev', account: 'g3soft' } } }),
)
localStorage.setItem('fms-user', JSON.stringify({ userInfo: { orgId: 'G3HD', account: 'g3soft' } }))
})
// 2) mock every /api call so the fake token is never validated by the real backend
const mockData = {
s_module: [
{ b_id: 1, b_code: 'b_port', b_name: '港口管理', b_module_type: 'data', b_canuse: 1, b_parent_id: null },
{ b_id: 2, b_code: 'b_file', b_name: '附件管理', b_module_type: 'data', b_canuse: 1, b_parent_id: null },
],
bf_files_cateid: [
{ b_id: '10', b_name: '合同文件', b_code: 'cate_contract', b_xh: 1, b_canuse: 1 },
{ b_id: '11', b_name: '验收资料', b_code: 'cate_accept', b_xh: 2, b_canuse: 1 },
{ b_id: '12', b_name: '日常管理文件(长名称分类测试)', b_code: 'cate_daily', b_xh: 3, b_canuse: 1 },
],
}
const files = Array.from({ length: 12 }, (_, i) => ({
subid: String(1000 + i),
father: '1001',
mx_moduleid: '1',
mx_cate_id: i % 3 === 0 ? '10' : i % 3 === 1 ? '11' : '12',
mx_filename: `项目文件-${i + 1}-合同附件扫描件.pdf`,
mx_filesize: (i + 1) * 1024 * 1024,
mx_fileext: 'pdf',
mx_mapfilename: '',
}))
await page.route('**/api/**', async (route) => {
const req = route.request()
const url = req.url()
let body = {}
try {
body = req.postDataJSON() || {}
} catch {}
if (url.includes('/auth/login')) {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
code: 0,
data: { token: 'dev-token', orgid: 'G3HD', user: { id: 1, account: 'g3soft', name: 'dev' } },
}),
})
}
if (url.includes('/data/loaddata')) {
const rows = mockData[body.view_name] || []
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ code: 0, data: rows }),
})
}
if (url.includes('/data/page')) {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ code: 0, data: { rows: files, total: files.length } }),
})
}
if (url.includes('/file/config')) {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ code: 0, data: { storageType: 'local' } }),
})
}
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ code: 0, data: null }),
})
})
try {
await page.goto(`${BASE}/file-demo`, { waitUntil: 'networkidle', timeout: 30000 })
await page.waitForTimeout(3000)
out.url = page.url()
await page.screenshot({ path: '.playwright-cli/fmsfile-1.png' })
// splitter panels
out.panels = await page.evaluate(() => {
const els = Array.from(document.querySelectorAll('.fms-splitter-panel'))
return els.map((el, i) => ({
i,
w: Math.round(el.getBoundingClientRect().width),
h: Math.round(el.getBoundingClientRect().height),
text: (el.textContent || '').slice(0, 40).replace(/\s+/g, ' '),
}))
})
out.bars = await page.evaluate(() => {
const els = Array.from(document.querySelectorAll('.fms-splitter-bar'))
return els.map((el, i) => {
const r = el.getBoundingClientRect()
return { i, x: Math.round(r.x), w: Math.round(r.width), y: Math.round(r.y), h: Math.round(r.height) }
})
})
// tree info
out.treeInfo = await page.evaluate(() => {
const tree = document.querySelector('.tree')
const panel = document.querySelector('.fc-panel')
const nodes = document.querySelectorAll('.tree-node')
return {
tree: !!tree,
treeW: tree ? Math.round(tree.getBoundingClientRect().width) : null,
treeMinW: tree ? getComputedStyle(tree).minWidth : null,
panelW: panel ? Math.round(panel.getBoundingClientRect().width) : null,
nodeCount: nodes.length,
}
})
// drag test: bar 0 → right +120
if (out.bars.length) {
const b = out.bars[0]
const cx = b.x + b.w / 2
const cy = b.y + b.h / 2
await page.mouse.move(cx, cy)
await page.mouse.down()
await page.mouse.move(cx + 120, cy, { steps: 10 })
await page.mouse.up()
await page.waitForTimeout(500)
out.afterDragRight = await page.evaluate(() => {
const els = Array.from(document.querySelectorAll('.fms-splitter-panel'))
return els.map((el, i) => ({ i, w: Math.round(el.getBoundingClientRect().width) }))
})
await page.screenshot({ path: '.playwright-cli/fmsfile-2-dragged.png' })
}
// switch to list view
const listBtn = page.locator('.fl-header__modes .button', { hasText: '' }).nth(1)
try {
await listBtn.click({ timeout: 3000 })
await page.waitForTimeout(800)
out.listMode = await page.evaluate(() => {
const table = document.querySelector('.fl-table')
if (!table) return { exists: false }
const ths = Array.from(table.querySelectorAll('thead th')).map((th) => ({
text: (th.textContent || '').trim(),
w: Math.round(th.getBoundingClientRect().width),
}))
const rows = Array.from(table.querySelectorAll('tbody tr')).slice(0, 4)
const rowCells = rows.map((tr) =>
Array.from(tr.querySelectorAll('td')).map((td) => Math.round(td.getBoundingClientRect().width)),
)
const actions = Array.from(table.querySelectorAll('.fl-actions')).slice(0, 4).map((el) => ({
w: Math.round(el.getBoundingClientRect().width),
btnCount: el.querySelectorAll('.button').length,
}))
return { exists: true, ths, rowCells, actions }
})
await page.screenshot({ path: '.playwright-cli/fmsfile-3-list.png' })
} catch (e) {
out.listModeError = String(e)
}
// grid card footer check
out.cardFooter = await page.evaluate(() => {
const cards = Array.from(document.querySelectorAll('.fcard'))
if (!cards.length) return { count: 0 }
const footers = Array.from(document.querySelectorAll('.fcard__footer')).slice(0, 4).map((el) => {
const btns = Array.from(el.querySelectorAll('.button')).map((b) => Math.round(b.getBoundingClientRect().width))
return { w: Math.round(el.getBoundingClientRect().width), btns }
})
return { count: cards.length, footers }
})
} catch (e) {
out.error = String(e)
}
console.log(JSON.stringify(out, null, 2))
await browser.close()