优化参数表样式与科学计数法支持

This commit is contained in:
ljz committed 2026-08-03 23:51:27 +08:00
1 parent 046aa49814
commit 32f21f08ff
6 files changed
+547 -64

No files matched your search

+250
View File
@@ -41,6 +41,7 @@ test("组件参数和仿真设置使用共享的三列表格", async ({ page })
"节点 ID",
"介质物性索引",
"参考压力",
"参考温度",
]);
await expect(simulationTable.getByRole("rowheader")).toHaveText([
"起始时间",
@@ -64,6 +65,173 @@ test("组件参数和仿真设置使用共享的三列表格", async ({ page })
.locator("thead .parameter-table-name-cell")
.evaluate((element) => element.getBoundingClientRect().width);
expect(Math.abs(componentNameWidth - simulationNameWidth)).toBeLessThanOrEqual(1);
const panelTitleHeights = await page
.locator(".properties .panel-title")
.evaluateAll((elements) =>
elements.map((element) => element.getBoundingClientRect().height),
);
expect(panelTitleHeights).toHaveLength(2);
panelTitleHeights.forEach((height) => expect(height).toBeLessThanOrEqual(32));
const compactTableMetrics = await page
.locator(".properties .parameter-table")
.evaluateAll((tables) =>
tables.map((table) => {
const content = table.closest<HTMLElement>(".properties-subpane-content");
const headerCell = table.querySelector<HTMLElement>("thead th");
const bodyRows = Array.from(
table.querySelectorAll<HTMLElement>("tbody .parameter-table-row"),
);
const control = table.querySelector<HTMLElement>("input, select");
if (!content || !headerCell || !control) {
throw new Error("参数表缺少布局测量所需的元素");
}
const tableBounds = table.getBoundingClientRect();
const contentBounds = content.getBoundingClientRect();
const tableStyle = getComputedStyle(table);
const contentLeft = contentBounds.left + content.clientLeft;
const contentRight = contentLeft + content.clientWidth;
const controlBounds = control.getBoundingClientRect();
const controlCell = control.closest<HTMLElement>("td");
if (!controlCell) {
throw new Error("参数控件不在数据单元格中");
}
const controlCellBounds = controlCell.getBoundingClientRect();
return {
leftInset: tableBounds.left - contentLeft,
rightInset: contentRight - tableBounds.right,
borderRadius: tableStyle.borderRadius,
borderTopWidth: tableStyle.borderTopWidth,
headerHeight: headerCell.getBoundingClientRect().height,
headerPosition: getComputedStyle(headerCell).position,
maximumRowHeight: Math.max(
...bodyRows.map((row) => row.getBoundingClientRect().height),
),
controlHeight: controlBounds.height,
controlContained:
controlBounds.left >= controlCellBounds.left - 0.5 &&
controlBounds.right <= controlCellBounds.right + 0.5 &&
controlBounds.top >= controlCellBounds.top - 0.5 &&
controlBounds.bottom <= controlCellBounds.bottom + 0.5,
};
}),
);
expect(compactTableMetrics).toHaveLength(2);
compactTableMetrics.forEach((metrics) => {
expect(Math.abs(metrics.leftInset)).toBeLessThanOrEqual(1);
expect(Math.abs(metrics.rightInset)).toBeLessThanOrEqual(1);
expect(metrics.borderRadius).toBe("0px");
expect(metrics.borderTopWidth).toBe("0px");
expect(metrics.headerHeight).toBeLessThanOrEqual(28);
expect(metrics.headerPosition).toBe("sticky");
expect(metrics.maximumRowHeight).toBeLessThanOrEqual(32);
expect(metrics.controlHeight).toBeGreaterThanOrEqual(22);
expect(metrics.controlHeight).toBeLessThanOrEqual(28);
expect(metrics.controlContained).toBe(true);
});
await expect(
componentTable.getByRole("rowheader", {
name: "组件名称",
exact: true,
}),
).toHaveCSS("text-align", "left");
await expect(page.getByLabel("参考压力", { exact: true })).toHaveCSS(
"text-align",
"right",
);
const valueColumnAlignment = await page
.locator(".properties .parameter-table tbody .parameter-table-value-cell")
.evaluateAll((cells) =>
cells.every((cell) => {
const controls = Array.from(
cell.querySelectorAll<HTMLElement>("input, select"),
);
return (
getComputedStyle(cell).textAlign === "right" &&
controls.every(
(control) => getComputedStyle(control).textAlign === "right",
)
);
}),
);
expect(valueColumnAlignment).toBe(true);
await expect(
componentTable.locator(".parameter-table-read-only-value").first(),
).toHaveCSS("justify-content", "flex-end");
await expect(page.getByLabel("介质物性索引", { exact: true })).toHaveCSS(
"text-align-last",
"right",
);
const solver = page.getByLabel("求解器", { exact: true });
await expect(solver).toHaveCSS("text-align", "right");
await expect(solver).toHaveCSS("text-align-last", "right");
await solver.selectOption("Radau");
await expect(solver).toHaveValue("Radau");
});
test("最窄参数面板滚动时表头固定且值列保持可用宽度", async ({ page }) => {
await page.goto("/");
await addPneumaticTestComponent(page);
const widthSeparator = page.getByRole("separator", {
name: "调整参数面板宽度",
exact: true,
});
await widthSeparator.focus();
await page.keyboard.press("ArrowRight");
await page.keyboard.press("ArrowRight");
await page.keyboard.press("ArrowRight");
await expect(widthSeparator).toHaveAttribute("aria-valuenow", "280");
const heightSeparator = page.getByRole("separator", {
name: "调整组件参数和仿真设置区域高度",
exact: true,
});
await heightSeparator.focus();
for (let step = 0; step < 11; step += 1) {
await page.keyboard.press("ArrowUp");
}
await expect(heightSeparator).toHaveAttribute("aria-valuenow", "120");
const componentContent = page
.getByRole("region", { name: "组件参数子栏", exact: true })
.locator(".properties-subpane-content");
await expect
.poll(() =>
componentContent.evaluate(
(element) => element.scrollHeight - element.clientHeight,
),
)
.toBeGreaterThan(0);
await componentContent.evaluate((element) => {
element.scrollTop = 48;
});
await expect
.poll(() => componentContent.evaluate((element) => element.scrollTop))
.toBeGreaterThan(0);
const narrowLayout = await componentContent.evaluate((content) => {
const header = content.querySelector<HTMLElement>(
"thead .parameter-table-name-cell",
);
const valueHeader = content.querySelector<HTMLElement>(
"thead .parameter-table-value-cell",
);
const wrap = content.querySelector<HTMLElement>(".parameter-table-wrap");
if (!header || !valueHeader || !wrap) {
throw new Error("无法测量最窄参数表布局");
}
return {
stickyTopDelta:
header.getBoundingClientRect().top - content.getBoundingClientRect().top,
valueWidth: valueHeader.getBoundingClientRect().width,
horizontalOverflow: wrap.scrollWidth - wrap.clientWidth,
};
});
expect(Math.abs(narrowLayout.stickyTopDelta)).toBeLessThanOrEqual(1);
expect(narrowLayout.valueWidth).toBeGreaterThanOrEqual(95);
expect(narrowLayout.horizontalOverflow).toBeLessThanOrEqual(1);
});
test("参数说明延迟显示,单位切换不改变 XML 基础值", async ({ page }) => {
@@ -140,6 +308,63 @@ test("参数说明延迟显示,单位切换不改变 XML 基础值", async ({
);
});
test("科学计数法在提交、单位换算和工程加载后保持", async ({ page }) => {
await page.goto("/");
await addPneumaticTestComponent(page);
const pressureInput = page.getByLabel("参考压力", { exact: true });
const pressureUnit = page.getByLabel("参考压力单位", { exact: true });
await pressureInput.fill("1e-5");
await pressureInput.press("Enter");
await pressureUnit.selectOption("kPa");
await expect(pressureInput).toHaveValue("1e-8");
await pressureUnit.selectOption("Pa");
await expect(pressureInput).toHaveValue("1e-5");
await pressureUnit.selectOption("kPa");
await pressureInput.fill("1.234567890123E+3");
await pressureInput.press("Enter");
await pressureUnit.selectOption("Pa");
await expect(pressureInput).toHaveValue("1.234567890123E+6");
await pressureUnit.selectOption("kPa");
await expect(pressureInput).toHaveValue("1.234567890123E+3");
await pressureInput.fill("1.20E+3");
await pressureInput.press("Enter");
await pressureUnit.selectOption("Pa");
await expect(pressureInput).toHaveValue("1.20E+6");
await pressureUnit.selectOption("kPa");
await expect(pressureInput).toHaveValue("1.20E+3");
const temperatureInput = page.getByLabel("参考温度", { exact: true });
const temperatureUnit = page.getByLabel("参考温度单位", { exact: true });
await temperatureUnit.selectOption("degC");
await temperatureInput.fill("1e-10");
await temperatureInput.press("Enter");
await temperatureUnit.selectOption("K");
await expect(temperatureInput).toHaveValue("2.731500000001e2");
await temperatureUnit.selectOption("degC");
await expect(temperatureInput).toHaveValue("1e-10");
await page.getByRole("button", { name: "保存工程", exact: true }).click();
await pressureInput.fill("2");
await pressureInput.press("Enter");
await page.getByRole("button", { name: "加载工程", exact: true }).click();
await page
.locator('.flow-canvas .react-flow__node[data-id="amesim_pneumatic_test_1"]')
.click();
await expect(pressureUnit).toHaveValue("kPa");
await expect(pressureInput).toHaveValue("1.20E+3");
await expect(temperatureUnit).toHaveValue("degC");
await expect(temperatureInput).toHaveValue("1e-10");
await page.getByRole("button", { name: "生成系统 XML", exact: true }).click();
await expect(page.getByLabel("生成的系统 XML")).toContainText(
'<Parameter name="reference_pressure" value="1200000"',
);
});
test("参数表列宽可调整并在刷新后保留", async ({ page }) => {
await page.goto("/");
@@ -388,3 +613,28 @@ test("仿真数值设置同样保留公式,并在执行协议中使用计算
await expect(xmlBlock).toContainText('tStop="7"');
await expect(xmlBlock).not.toContainText(expression);
});
test("仿真数值设置中的科学计数法在保存加载后保持", async ({ page }) => {
await page.goto("/");
const stepInput = page.getByLabel("采样步长", { exact: true });
const maxStepInput = page.getByLabel("最大积分步长", { exact: true });
await stepInput.fill("1e-5");
await stepInput.press("Enter");
await maxStepInput.fill("1.20E-4");
await maxStepInput.press("Enter");
await page.getByRole("button", { name: "保存工程", exact: true }).click();
await stepInput.fill("0.1");
await stepInput.press("Enter");
await maxStepInput.fill("0.01");
await maxStepInput.press("Enter");
await page.getByRole("button", { name: "加载工程", exact: true }).click();
await expect(stepInput).toHaveValue("1e-5");
await expect(maxStepInput).toHaveValue("1.20E-4");
await page.getByRole("button", { name: "生成系统 XML", exact: true }).click();
const xmlBlock = page.getByLabel("生成的系统 XML");
await expect(xmlBlock).toContainText('step="0.00001"');
await expect(xmlBlock).toContainText('maxStep="0.00012"');
});