C内核流量计算方法优化,前端文件名称读取优化

This commit is contained in:
lujingze committed 2026-09-11 08:48:56 +00:00
1 parent 5d5a2e1843
commit 808c484f5b
94 files changed
+20163 -4418

No files matched your search

@@ -0,0 +1,89 @@
// Real browser/HTTP/native execution. No API routes or result data are mocked.
import { chromium } from '../../frontend/node_modules/playwright/index.mjs';
import fs from 'node:fs/promises';
import path from 'node:path';
import { performance } from 'node:perf_hooks';
import assert from 'node:assert/strict';
import { createHash } from 'node:crypto';
const [input, output, baseURL = 'http://127.0.0.1:8011', runCount = '3'] = process.argv.slice(2);
if (!input || !output) throw new Error('Usage: node browser_native_simulation.mjs MODEL.json OUTPUT_DIR [URL] [RUNS]');
await fs.mkdir(output, { recursive: true });
const inputText = await fs.readFile(input, 'utf8');
const project = JSON.parse(inputText);
const curveNodeId = project.nodes.find(node => node.id === 'amesim_pnl0002_10')?.id
?? project.nodes.find(node => node.data.modelType === 'amesim_pnl0002')?.id;
if (!curveNodeId) throw new Error('Curve verification requires a PNL0002 component.');
await fs.writeFile(path.join(output, 'input.json'), inputText);
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({ viewport: { width: 1600, height: 1000 }, acceptDownloads: true });
const page = await context.newPage();
page.setDefaultTimeout(30000);
const errors = [];
page.on('pageerror', error => errors.push(String(error)));
const rows = [];
try {
await page.goto(baseURL);
await page.locator('input[type="file"][accept*=".json"]').setInputFiles(path.resolve(input));
await page.getByRole('textbox', { name: '工程', exact: true }).waitFor();
await page.waitForFunction(name => document.querySelector('input[aria-label="工程"]')?.value === name || [...document.querySelectorAll('input')].some(input => input.value === name), path.basename(input, path.extname(input)));
await page.screenshot({ path: path.join(output, 'model.png'), fullPage: true });
for (let i = 0; i <= Number(runCount); i++) {
const oldMarker = await page.evaluate(() => sessionStorage.getItem('system-simulation-flow:latest-result'));
const responsePromise = page.waitForResponse(response => response.url().endsWith('/api/system-xml/simulate-stream'), { timeout: 180000 });
const started = performance.now();
await page.getByRole('button', { name: '运行仿真', exact: true }).click();
const response = await responsePromise;
await response.finished();
if (!response.ok()) throw new Error(`Simulation HTTP ${response.status()}`);
const receivedMs = performance.now() - started;
await page.waitForFunction(old => {
const marker = sessionStorage.getItem('system-simulation-flow:latest-result');
return marker && marker !== old && JSON.parse(marker).storage === 'indexeddb';
}, oldMarker, { timeout: 180000 });
await page.getByRole('button', { name: '运行仿真', exact: true }).waitFor({ state: 'visible' });
await page.waitForFunction(() => !document.querySelector('button[aria-label="运行仿真"]')?.disabled);
await page.getByRole('tab', { name: /^结果/ }).click();
await page.getByRole('button', { name: '下载结果文件', exact: true }).waitFor();
const readyMs = performance.now() - started;
await page.waitForFunction(old => {
const marker = sessionStorage.getItem('system-simulation-flow:latest-result');
return marker && marker !== old && JSON.parse(marker).storage === 'indexeddb';
}, oldMarker);
const downloadPromise = page.waitForEvent('download');
await page.getByRole('button', { name: '下载结果文件', exact: true }).click();
await (await downloadPromise).saveAs(path.join(output, `run-${i}.simresult`));
const exported = JSON.parse(await fs.readFile(path.join(output, `run-${i}.simresult`), 'utf8'));
const result = exported.snapshot.result;
if (!result.success) throw new Error(result.message);
assert.equal(result.diagnostics.integration.rtol, 1e-8);
assert.equal(result.simulatedUntil, project.simulation.t_stop);
const row = { run: i, receivedMs, readyMs, sampleCount: result.series.time.length,
...result.diagnostics.native };
rows.push(row);
console.log(JSON.stringify(row));
if (i < Number(runCount)) await page.getByRole('tab', { name: '建模', exact: true }).click();
}
await page.getByRole('button', { name: '适应系统图窗口', exact: true }).click();
await page.locator(`.results-system-panel .react-flow__node[data-id=${JSON.stringify(curveNodeId)}]`).click();
await page.locator('.results-variable-list button').filter({ has: page.locator('small', { hasText: /^K$/ }) }).first().click();
await page.locator('.results-chart-panel .result-chart-window svg').first().waitFor();
const csvDownload = page.waitForEvent('download');
await page.getByRole('button', { name: '下载结果 CSV', exact: true }).click();
await (await csvDownload).saveAs(path.join(output, 'result.csv'));
await page.screenshot({ path: path.join(output, 'result.png'), fullPage: true });
await page.reload();
await page.getByRole('tab', { name: /^结果/ }).click();
await page.getByRole('button', { name: '下载结果文件', exact: true }).waitFor();
const restored = page.waitForEvent('download');
await page.getByRole('button', { name: '下载结果文件', exact: true }).click();
await (await restored).saveAs(path.join(output, 'restored.simresult'));
const restoredData = JSON.parse(await fs.readFile(path.join(output, 'restored.simresult'), 'utf8'));
const lastData = JSON.parse(await fs.readFile(path.join(output, `run-${runCount}.simresult`), 'utf8'));
assert.deepEqual(restoredData.snapshot.result, lastData.snapshot.result);
await fs.writeFile(path.join(output, 'summary.json'), JSON.stringify({ input: path.resolve(input), inputSha256: createHash('sha256').update(inputText).digest('hex'), baseURL, browser: browser.version(), rows, errors, restored: true, restoredResultIdentical: true, csvExported: true }, null, 2));
if (errors.length) throw new Error(`Browser errors: ${errors.join('\n')}`);
} catch (error) {
await page.screenshot({ path: path.join(output, 'failure.png'), fullPage: true });
await fs.writeFile(path.join(output, 'failure.txt'), `${error.stack}\nPage errors: ${JSON.stringify(errors)}\n${await page.locator('body').innerText()}`);
throw error;
} finally { await context.close(); await browser.close(); }