feat(workbench): integrate runtime data and map tooling

This commit is contained in:
2026-09-22 10:45:46 +08:00
parent bf44cc0f25
commit bebcf2a06c
163 changed files with 15642 additions and 1312 deletions
+26 -33
View File
@@ -17,6 +17,7 @@ test.describe("Main Frame workbench", () => {
test("desktop light basemap keeps the Main Frame workspace legible", async ({ page }) => {
await page.setViewportSize({ width: 1440, height: 900 });
await openWorkbench(page);
await openDesktopAgent(page);
await expectDesktopMainFrameGeometry(page);
await expectSolidMainFrameMaterials(page);
@@ -31,6 +32,7 @@ test.describe("Main Frame workbench", () => {
test("desktop satellite basemap preserves the solid Main Frame hierarchy", async ({ page }) => {
await page.setViewportSize({ width: 1440, height: 900 });
await openWorkbench(page);
await openDesktopAgent(page);
await selectBasemap(page, "影像");
await expect(page.locator("main")).toHaveAttribute("data-basemap-tone", "satellite");
@@ -42,20 +44,21 @@ test.describe("Main Frame workbench", () => {
});
});
test("wide desktop expands the map document when navigation is collapsed", async ({ page }) => {
test("wide desktop expands the map document when Agent is collapsed", async ({ page }) => {
await page.setViewportSize({ width: 1920, height: 1080 });
await openWorkbench(page);
await openDesktopAgent(page);
const navigation = page.getByRole("complementary", { name: "工作台导航" });
const agentPanel = page.getByRole("complementary", { name: "Agent 命令面板" });
const workspace = page.locator("#main-workspace");
const expandedWorkspace = await workspace.boundingBox();
expect(expandedWorkspace).not.toBeNull();
await expect(navigation).toHaveCSS("width", "368px");
await expect(agentPanel).toHaveCSS("width", "540px");
await page.getByRole("button", { name: "折叠工作台导航" }).click();
await expect(navigation).toHaveCSS("width", "48px");
await expect.poll(async () => Math.round((await workspace.boundingBox())?.x ?? 0)).toBe(48);
await expect.poll(async () => Math.round((await workspace.boundingBox())?.width ?? 0)).toBe(1872);
await page.getByRole("button", { name: "折叠 Agent 面板" }).click();
await expect(page.getByLabel("Agent 折叠栏")).toBeVisible();
await expect.poll(async () => Math.round((await workspace.boundingBox())?.x ?? 0)).toBe(0);
await expect.poll(async () => Math.round((await workspace.boundingBox())?.width ?? 0)).toBe(1920);
expect((await workspace.boundingBox())!.width).toBeGreaterThan(expandedWorkspace!.width);
await expect(page).toHaveScreenshot("workbench-desktop-wide-max-agent.png", {
animations: "disabled",
@@ -179,7 +182,7 @@ async function openWorkbench(page: Page) {
await page.evaluate(async () => {
await document.fonts.ready;
});
await page.waitForFunction(() => Boolean(window.__waterNetworkMap?.getLayer("scada-hit")));
await page.waitForFunction(() => Boolean(window.__waterNetworkMap?.getLayer("scada-pressure-hit")));
}
async function selectBasemap(page: Page, label: "浅色" | "影像") {
@@ -192,54 +195,44 @@ async function selectBasemap(page: Page, label: "浅色" | "影像") {
);
}
async function openDesktopAgent(page: Page) {
await page.getByRole("button", { name: /展开 Agent 助手面板/ }).click();
await expect(page.getByRole("complementary", { name: "Agent 命令面板" })).toBeVisible();
}
async function expectDesktopMainFrameGeometry(page: Page) {
const navigation = page.getByRole("complementary", { name: "工作台导航" });
const workspace = page.locator("#main-workspace");
const mapWindow = page.locator("#workspace-map");
const agentPanel = page.locator('aside[aria-label="Agent 命令面板"]');
await expect(navigation).toHaveCSS("width", "368px");
await expect(agentPanel).toHaveCSS("border-radius", "0px");
const agentPanel = page.getByRole("complementary", { name: "Agent 命令面板" });
await expect(agentPanel).toHaveCSS("width", "500px");
await expect(agentPanel).toHaveCSS("border-top-right-radius", "16px");
await expect(mapWindow).toHaveCSS("border-radius", "0px");
const navigationBox = await navigation.boundingBox();
const workspaceBox = await workspace.boundingBox();
const mapBox = await mapWindow.boundingBox();
const agentBox = await agentPanel.boundingBox();
expect(navigationBox).not.toBeNull();
expect(workspaceBox).not.toBeNull();
expect(mapBox).not.toBeNull();
expect(agentBox).not.toBeNull();
expect(navigationBox!.x).toBe(0);
expect(navigationBox!.y).toBe(56);
expect(workspaceBox!.x).toBe(navigationBox!.x + navigationBox!.width);
expect(workspaceBox!.y).toBe(navigationBox!.y);
expect(agentBox!.x).toBe(0);
expect(agentBox!.y).toBe(56);
expect(workspaceBox!.x).toBe(agentBox!.x + agentBox!.width);
expect(workspaceBox!.y).toBe(agentBox!.y);
expect(mapBox).toEqual(workspaceBox);
expect(agentBox!.x).toBeGreaterThanOrEqual(48);
expect(agentBox!.x).toBeLessThanOrEqual(49);
expect(
Math.abs(agentBox!.x + agentBox!.width - (navigationBox!.x + navigationBox!.width))
).toBeLessThanOrEqual(1);
}
async function expectSolidMainFrameMaterials(page: Page) {
const materials = await page.evaluate(() => {
const navigation = getComputedStyle(document.querySelector('[aria-label="工作台导航"]')!);
const agent = getComputedStyle(document.querySelector('aside[aria-label="Agent 命令面板"]')!);
return {
navigationBackdrop: navigation.backdropFilter,
navigationBackground: navigation.backgroundColor,
agentBackdrop: agent.backdropFilter,
agentBackground: agent.backgroundColor,
agentShadow: agent.boxShadow
};
});
expect(materials).toEqual({
navigationBackdrop: "none",
navigationBackground: "rgb(237, 241, 245)",
agentBackdrop: "none",
agentBackground: "rgb(247, 249, 251)",
agentShadow: "none"
});
expect(materials.agentBackdrop).toBe("none");
expect(materials.agentBackground).toBe("oklch(0.965 0.012 248)");
expect(materials.agentShadow).not.toBe("none");
}
async function expectLoadedChineseFont(page: Page) {