From a5e5acb03b4b470d49abf6f00d6b3be4729a1139 Mon Sep 17 00:00:00 2001 From: Huarch Date: Thu, 24 Sep 2026 15:13:14 +0800 Subject: [PATCH] fix(workbench): suppress unconfigured demo alerts The not_configured branch previously promoted mock task failures into critical alerts. Return an explicit empty alert source so the exception badge reflects only actionable backend state. --- .../workbench/components/workbench-top-bar.tsx | 10 ++++++++-- .../workbench/hooks/use-workbench-runtime-data.test.ts | 10 +++++----- .../workbench/hooks/use-workbench-runtime-data.ts | 5 ++--- src/features/workbench/types.ts | 2 +- tests/browser/operational-task-approval.e2e.ts | 8 ++++++++ 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/features/workbench/components/workbench-top-bar.tsx b/src/features/workbench/components/workbench-top-bar.tsx index 860fc5a..ca675f4 100644 --- a/src/features/workbench/components/workbench-top-bar.tsx +++ b/src/features/workbench/components/workbench-top-bar.tsx @@ -142,7 +142,7 @@ export function WorkbenchTopBar({ open={openMenu === "alerts"} onOpenChange={createMenuOpenChange("alerts")} alerts={alerts} - sourceLabel={alertDataSource === "mock" ? "工况演示回退" : "后端运行态"} + sourceLabel={getAlertSourceLabel(alertDataSource)} conditionFeedVisible={conditionFeedVisible} onSelectAlert={onSelectAlert} onToggleConditionFeed={onToggleConditionFeed} @@ -239,7 +239,7 @@ export function WorkbenchTopBar({ open={openMenu === "compact-alerts"} onOpenChange={createMenuOpenChange("compact-alerts")} alerts={alerts} - sourceLabel={alertDataSource === "mock" ? "工况演示回退" : "后端运行态"} + sourceLabel={getAlertSourceLabel(alertDataSource)} conditionFeedVisible={conditionFeedVisible} onSelectAlert={onSelectAlert} onToggleConditionFeed={onToggleConditionFeed} @@ -261,6 +261,12 @@ export function WorkbenchTopBar({ ); } +function getAlertSourceLabel(source: WorkbenchAlertDataSource) { + if (source === "backend") return "后端运行态"; + if (source === "mock") return "工况演示回退"; + return "未配置告警源"; +} + function getAnalysisOriginLabel(origin: AnalysisArtifact["origin"]) { if (origin === "backend") return "后端分析运行"; if (origin === "demo") return "演示成果"; diff --git a/src/features/workbench/hooks/use-workbench-runtime-data.test.ts b/src/features/workbench/hooks/use-workbench-runtime-data.test.ts index 15cec86..edde2b4 100644 --- a/src/features/workbench/hooks/use-workbench-runtime-data.test.ts +++ b/src/features/workbench/hooks/use-workbench-runtime-data.test.ts @@ -66,7 +66,7 @@ describe("workbench runtime data", () => { expect(getMsUntilNextHeaderDataTimeTick(new Date(2026, 6, 22, 15, 43, 30))).toBe(90_000); }); - it("keeps mock conditions and shows no work orders when backend storage is not configured", () => { + it("keeps mock conditions without inventing alerts when backend storage is not configured", () => { const resolved = resolveWorkbenchRuntimeData([mockCondition], { availability: "not_configured", source: "none", @@ -86,7 +86,8 @@ describe("workbench runtime data", () => { expect(resolved.runtimeDataSource).toBe("mock"); expect(resolved.scheduledConditions).toEqual([mockCondition]); - expect(resolved.workbenchAlerts).toHaveLength(1); + expect(resolved.workbenchAlerts).toEqual([]); + expect(resolved.alertDataSource).toBe("none"); expect(resolved.scenarioDataSource).toBe("mock"); expect(resolved.artifactDataSource).toBe("mock"); expect(resolved.workOrderDataSource).toBe("none"); @@ -132,9 +133,8 @@ describe("workbench runtime data", () => { expect(resolved.runtimeDataSource).toBe("mock"); expect(resolved.scheduledConditions).toEqual([mockCondition]); - expect(resolved.workbenchAlerts).not.toEqual([backendAlert]); - expect(resolved.workbenchAlerts[0]?.id).toBe("scheduled-condition-alert-mock-condition"); - expect(resolved.alertDataSource).toBe("mock"); + expect(resolved.workbenchAlerts).toEqual([]); + expect(resolved.alertDataSource).toBe("none"); expect(resolved.scenarioDataSource).toBe("mock"); expect(resolved.workOrderDataSource).toBe("none"); diff --git a/src/features/workbench/hooks/use-workbench-runtime-data.ts b/src/features/workbench/hooks/use-workbench-runtime-data.ts index b5bb729..f350b03 100644 --- a/src/features/workbench/hooks/use-workbench-runtime-data.ts +++ b/src/features/workbench/hooks/use-workbench-runtime-data.ts @@ -11,7 +11,6 @@ import { } from "../data/scheduled-conditions"; import { WORKBENCH_SCENARIOS } from "../data/workbench-session"; import type { ScheduledConditionItem } from "../types"; -import { createScheduledConditionAlerts } from "../utils/scheduled-condition-alerts"; import type { WorkbenchSyncState } from "./use-workbench-sync"; const HEADER_DATA_TIME_STEP_MINUTES = 5; @@ -106,8 +105,8 @@ export function resolveWorkbenchRuntimeData( scheduledConditions: [...fallbackConditions, ...resolvedWorkOrders], workbenchAlerts: backendAlertsConfigured ? backendSnapshot!.alerts - : createScheduledConditionAlerts(fallbackConditions), - alertDataSource: backendAlertsConfigured ? "backend" as const : "mock" as const, + : [], + alertDataSource: backendAlertsConfigured ? "backend" as const : "none" as const, runtimeDataSource: "mock" as const, scenarios: useBackendScenarios ? backendSnapshot!.scenarios : WORKBENCH_SCENARIOS, scenarioDataSource: useBackendScenarios ? "analysis_runs" as const : "mock" as const, diff --git a/src/features/workbench/types.ts b/src/features/workbench/types.ts index d14b538..d585a3a 100644 --- a/src/features/workbench/types.ts +++ b/src/features/workbench/types.ts @@ -44,7 +44,7 @@ export type WorkbenchRuntimeDataSource = | "scheduled_tasks" | "operational_tasks"; -export type WorkbenchAlertDataSource = "mock" | "backend"; +export type WorkbenchAlertDataSource = "mock" | "backend" | "none"; export type WorkbenchScenarioDataSource = "mock" | "analysis_runs"; diff --git a/tests/browser/operational-task-approval.e2e.ts b/tests/browser/operational-task-approval.e2e.ts index 4237f5b..35dc4c4 100644 --- a/tests/browser/operational-task-approval.e2e.ts +++ b/tests/browser/operational-task-approval.e2e.ts @@ -264,6 +264,14 @@ test("审批动作展示中文参数和证据,viewer 不可审批,冲突后 }; await page.goto("/"); + const alertTrigger = page.getByRole("button", { + name: "查看异常处置面板,当前 0 条待复核工况" + }).first(); + await expect(alertTrigger).toBeVisible(); + await alertTrigger.click(); + await expect(page.getByText("当前无待复核工况", { exact: true }).first()).toBeVisible(); + await expect(page.getByText("来源:未配置告警源", { exact: true })).toBeVisible(); + await page.keyboard.press("Escape"); const reconnectNotice = page.locator("[data-sonner-toast]").filter({ hasText: "业务同步正在重连" });