feat: 同步全部系统改动与文档
This commit is contained in:
168
work/system-manual/capture-system-pages.js
Normal file
168
work/system-manual/capture-system-pages.js
Normal file
@@ -0,0 +1,168 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const WebSocket = require('ws')
|
||||
|
||||
const outputDir = path.resolve(__dirname, 'screenshots')
|
||||
fs.mkdirSync(outputDir, { recursive: true })
|
||||
const loginUser = process.env.MES_MANUAL_USER
|
||||
const loginPassword = process.env.MES_MANUAL_PASSWORD
|
||||
|
||||
const wait = ms => new Promise(resolve => setTimeout(resolve, ms))
|
||||
|
||||
async function connect() {
|
||||
const targets = await fetch('http://127.0.0.1:9222/json').then(res => res.json())
|
||||
const target = targets.find(item => item.type === 'page')
|
||||
if (!target) throw new Error('No Chrome page target found')
|
||||
|
||||
const ws = new WebSocket(target.webSocketDebuggerUrl)
|
||||
let id = 0
|
||||
const pending = new Map()
|
||||
ws.on('message', raw => {
|
||||
const message = JSON.parse(raw.toString())
|
||||
if (message.id && pending.has(message.id)) {
|
||||
const { resolve, reject } = pending.get(message.id)
|
||||
pending.delete(message.id)
|
||||
message.error ? reject(new Error(message.error.message)) : resolve(message.result)
|
||||
}
|
||||
})
|
||||
await new Promise((resolve, reject) => {
|
||||
ws.once('open', resolve)
|
||||
ws.once('error', reject)
|
||||
})
|
||||
|
||||
const send = (method, params = {}) => new Promise((resolve, reject) => {
|
||||
const requestId = ++id
|
||||
pending.set(requestId, { resolve, reject })
|
||||
ws.send(JSON.stringify({ id: requestId, method, params }))
|
||||
})
|
||||
return { ws, send }
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { ws, send } = await connect()
|
||||
await send('Page.enable')
|
||||
await send('Runtime.enable')
|
||||
await send('Emulation.setDeviceMetricsOverride', {
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
deviceScaleFactor: 1,
|
||||
mobile: false
|
||||
})
|
||||
|
||||
const evaluate = expression => send('Runtime.evaluate', {
|
||||
expression,
|
||||
awaitPromise: true,
|
||||
returnByValue: true
|
||||
}).then(result => result.result.value)
|
||||
|
||||
async function waitFor(expression, timeout = 30000) {
|
||||
const started = Date.now()
|
||||
while (Date.now() - started < timeout) {
|
||||
if (await evaluate(`Boolean(${expression})`)) return
|
||||
await wait(300)
|
||||
}
|
||||
throw new Error(`Timed out waiting for: ${expression}`)
|
||||
}
|
||||
|
||||
async function screenshot(name) {
|
||||
await wait(700)
|
||||
const result = await send('Page.captureScreenshot', {
|
||||
format: 'png',
|
||||
captureBeyondViewport: false,
|
||||
fromSurface: true
|
||||
})
|
||||
fs.writeFileSync(path.join(outputDir, `${name}.png`), Buffer.from(result.data, 'base64'))
|
||||
console.log(`Captured ${name}`)
|
||||
}
|
||||
|
||||
async function navigate(hashPath) {
|
||||
await send('Page.navigate', { url: `https://127.0.0.1:1997/#${hashPath}` })
|
||||
await waitFor("document.readyState === 'complete'")
|
||||
await waitFor("document.querySelector('.app-main') || document.querySelector('.el-card')", 40000)
|
||||
await wait(1800)
|
||||
}
|
||||
|
||||
async function clickByText(text, selector = 'button') {
|
||||
return evaluate(`(() => {
|
||||
const nodes = [...document.querySelectorAll(${JSON.stringify(selector)})]
|
||||
const node = nodes.find(item => item.innerText && item.innerText.replace(/\\s+/g, '').includes(${JSON.stringify(text.replace(/\s+/g, ''))}))
|
||||
if (!node) return false
|
||||
node.click()
|
||||
return true
|
||||
})()`)
|
||||
}
|
||||
|
||||
await send('Page.navigate', { url: 'https://127.0.0.1:1997/#/login' })
|
||||
await waitFor("document.querySelector('input[name=username]') || document.querySelector('.sidebar-container')", 40000)
|
||||
if (await evaluate("Boolean(document.querySelector('input[name=username]'))")) {
|
||||
if (!loginUser || !loginPassword) {
|
||||
throw new Error('Set MES_MANUAL_USER and MES_MANUAL_PASSWORD before capturing pages')
|
||||
}
|
||||
await evaluate(`(() => {
|
||||
const setValue = (el, value) => {
|
||||
const setter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value').set
|
||||
setter.call(el, value)
|
||||
el.dispatchEvent(new Event('input', { bubbles: true }))
|
||||
el.dispatchEvent(new Event('change', { bubbles: true }))
|
||||
}
|
||||
setValue(document.querySelector('input[name=username]'), ${JSON.stringify(loginUser)})
|
||||
setValue(document.querySelector('input[name=password]'), ${JSON.stringify(loginPassword)})
|
||||
})()`)
|
||||
await clickByText('登录')
|
||||
}
|
||||
await waitFor("document.querySelector('.sidebar-container')", 40000)
|
||||
await wait(1500)
|
||||
|
||||
const pages = [
|
||||
['01-personnel-list', '/SystemMaintenance/PersonnelManagement/index'],
|
||||
['02-role-list', '/SystemMaintenance/SystemRrolemaintenance/index'],
|
||||
['03-menu-list', '/SystemMaintenance/MenuManagement/index'],
|
||||
['04-workstation-list', '/SystemMaintenance/WorkstationManagement/index'],
|
||||
['05-operation-log', '/SystemMaintenance/OperationLog/index']
|
||||
]
|
||||
|
||||
for (const [name, route] of pages) {
|
||||
await navigate(route)
|
||||
await screenshot(name)
|
||||
|
||||
if (name === '01-personnel-list') {
|
||||
if (await clickByText('新增')) {
|
||||
await waitFor("document.querySelector('.el-dialog__wrapper:not([style*=\"display: none\"])')")
|
||||
await screenshot('01-personnel-add-dialog')
|
||||
await clickByText('取消', '.el-dialog__wrapper:not([style*=\"display: none\"]) button')
|
||||
}
|
||||
}
|
||||
if (name === '02-role-list') {
|
||||
if (await clickByText('新增')) {
|
||||
await waitFor("document.querySelector('.el-dialog__wrapper:not([style*=\"display: none\"])')")
|
||||
await screenshot('02-role-add-dialog')
|
||||
await clickByText('取消', '.el-dialog__wrapper:not([style*=\"display: none\"]) button')
|
||||
}
|
||||
}
|
||||
if (name === '03-menu-list') {
|
||||
await evaluate(`document.querySelector('#selectRoleName').click()`)
|
||||
await waitFor("[...document.querySelectorAll('.el-select-dropdown__item')].some(item => item.innerText.trim() === '管理员')")
|
||||
await evaluate(`(() => {
|
||||
const option = [...document.querySelectorAll('.el-select-dropdown__item')]
|
||||
.find(item => item.innerText.trim() === '管理员')
|
||||
option.click()
|
||||
})()`)
|
||||
await waitFor("document.querySelectorAll('.moduleTree .el-tree-node').length > 0")
|
||||
await screenshot('03-menu-permission-panel')
|
||||
}
|
||||
if (name === '04-workstation-list') {
|
||||
if (await clickByText('新增')) {
|
||||
await waitFor("document.querySelector('.el-dialog__wrapper:not([style*=\"display: none\"])')")
|
||||
await screenshot('04-workstation-add-dialog')
|
||||
await clickByText('取消', '.el-dialog__wrapper:not([style*=\"display: none\"]) button')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ws.close()
|
||||
}
|
||||
|
||||
main().catch(error => {
|
||||
console.error(error)
|
||||
process.exitCode = 1
|
||||
})
|
||||
Reference in New Issue
Block a user