SNAPSHOT W7 已部署稳定态 — 凯迪ERP+OA一体化平台 (MET 73.3%)
恢复点(restore point)。别人改崩后可 git reset --hard 回到此提交。 == 此快照内容 == - 后端 oa-backend: 734 控制器 / 711 实体 (Spring Boot 3.2.5 + SQLite, 端口8091) - 前端 modern-ui/app: Vue3+Vite, 约700页 (构建产物已在 oa-backend/src/main/resources/static) - 数据库 oa-backend/data/oa.db: 含全部演示数据 (强制入库, 6.6MB) - 交接文档 go.md + go-code-reference/endpoints/entities/database.md - 多代理建设脚本 .claude/wf-*.js == 状态 == - 对 凯迪科技ERP_20260507.xlsx 合规 MET ~73.3% (PARTIAL 75: 34可建+6种子/bug+35外部硬天花板) - 安全: 5轮红队+5轮复检, default-deny分级鉴权, 连续零可利用 - W3~W7 累计补完436缺口; W8末轮(40缺口)为半成品(源码树可编译但未集成) - 运行: cd oa-backend; java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091; admin/123456 == 排除(gitignore, 可再生) == node_modules / oa-backend/build / .jdks / *.log / Backup-ERP-* / 弃用的OFBiz核心(只保留modern-ui) 完整文件夹备份见同目录 Backup-ERP-20260615-191517/ (含上述全部, 仅缺 node_modules) 时间戳: 20260615-191517 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
// Capture screenshots of the OA replica for manual review (saved as PNGs).
|
||||
import { spawn } from 'node:child_process'
|
||||
import { mkdtemp, readFile, rm, writeFile, mkdir } from 'node:fs/promises'
|
||||
import os from 'node:os'
|
||||
import path from 'node:path'
|
||||
import { setTimeout as delay } from 'node:timers/promises'
|
||||
|
||||
const CHROME = process.env.CHROME_BIN || '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
|
||||
const BASE = process.env.OA_BASE || 'http://localhost:8080/modern/app/'
|
||||
const OUTDIR = '/Users/qiu/Desktop/ERP/ofbiz-framework/plugins/modern-ui/verification/oa-shots'
|
||||
const SHOTS = [
|
||||
['portal', '#/oa'],
|
||||
['collab-todo', '#/oa/collab/todo'],
|
||||
['collab-create', '#/oa/collab/create'],
|
||||
['collab-center', '#/oa/collab/center'],
|
||||
['meeting-mine', '#/oa/meeting/mine'],
|
||||
['meeting-room', '#/oa/meeting/room'],
|
||||
['goal-project', '#/oa/goal/project'],
|
||||
['knowledge-doccenter', '#/oa/knowledge/doccenter'],
|
||||
['hr-staff', '#/oa/hr/staff'],
|
||||
['hr-org', '#/oa/hr/org'],
|
||||
['culture-notice', '#/oa/culture/notice'],
|
||||
['report-analysis', '#/oa/report/analysis'],
|
||||
['contacts', '#/oa/contacts']
|
||||
]
|
||||
|
||||
await mkdir(OUTDIR, { recursive: true })
|
||||
const profile = await mkdtemp(path.join(os.tmpdir(), 'oashots.'))
|
||||
const chrome = spawn(CHROME, ['--headless=new', '--disable-gpu', '--no-first-run', '--remote-debugging-port=0', '--window-size=1440,900', `--user-data-dir=${profile}`, 'about:blank'], { stdio: ['ignore', 'ignore', 'pipe'] })
|
||||
let port = ''
|
||||
const dl = Date.now() + 15000
|
||||
while (Date.now() < dl && !port) { try { port = (await readFile(path.join(profile, 'DevToolsActivePort'), 'utf8')).trim().split('\n')[0] } catch { await delay(150) } }
|
||||
const targets = await fetch(`http://127.0.0.1:${port}/json/list`).then((r) => r.json())
|
||||
const ws = new WebSocket(targets.find((t) => t.type === 'page' && t.webSocketDebuggerUrl).webSocketDebuggerUrl)
|
||||
await new Promise((res) => ws.addEventListener('open', res, { once: true }))
|
||||
let id = 0
|
||||
const pending = new Map()
|
||||
ws.addEventListener('message', (e) => { const m = JSON.parse(e.data); if (m.id && pending.has(m.id)) { pending.get(m.id)(m.result); pending.delete(m.id) } })
|
||||
const cmd = (method, params = {}) => new Promise((res) => { const i = ++id; pending.set(i, res); ws.send(JSON.stringify({ id: i, method, params })) })
|
||||
await cmd('Page.enable')
|
||||
await cmd('Emulation.setDeviceMetricsOverride', { width: 1440, height: 900, deviceScaleFactor: 1, mobile: false })
|
||||
|
||||
for (const [name, route] of SHOTS) {
|
||||
await cmd('Page.navigate', { url: BASE + route })
|
||||
await delay(1900)
|
||||
const shot = await cmd('Page.captureScreenshot', { format: 'png' })
|
||||
if (shot?.data) { await writeFile(path.join(OUTDIR, `${name}.png`), Buffer.from(shot.data, 'base64')); console.log('saved', name) }
|
||||
else console.log('FAILED', name)
|
||||
}
|
||||
ws.close(); chrome.kill('SIGTERM'); await delay(300); await rm(profile, { recursive: true, force: true })
|
||||
console.log('OUTDIR', OUTDIR)
|
||||
process.exit(0)
|
||||
Reference in New Issue
Block a user