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.
This commit is contained in:
@@ -142,7 +142,7 @@ export function WorkbenchTopBar({
|
|||||||
open={openMenu === "alerts"}
|
open={openMenu === "alerts"}
|
||||||
onOpenChange={createMenuOpenChange("alerts")}
|
onOpenChange={createMenuOpenChange("alerts")}
|
||||||
alerts={alerts}
|
alerts={alerts}
|
||||||
sourceLabel={alertDataSource === "mock" ? "工况演示回退" : "后端运行态"}
|
sourceLabel={getAlertSourceLabel(alertDataSource)}
|
||||||
conditionFeedVisible={conditionFeedVisible}
|
conditionFeedVisible={conditionFeedVisible}
|
||||||
onSelectAlert={onSelectAlert}
|
onSelectAlert={onSelectAlert}
|
||||||
onToggleConditionFeed={onToggleConditionFeed}
|
onToggleConditionFeed={onToggleConditionFeed}
|
||||||
@@ -239,7 +239,7 @@ export function WorkbenchTopBar({
|
|||||||
open={openMenu === "compact-alerts"}
|
open={openMenu === "compact-alerts"}
|
||||||
onOpenChange={createMenuOpenChange("compact-alerts")}
|
onOpenChange={createMenuOpenChange("compact-alerts")}
|
||||||
alerts={alerts}
|
alerts={alerts}
|
||||||
sourceLabel={alertDataSource === "mock" ? "工况演示回退" : "后端运行态"}
|
sourceLabel={getAlertSourceLabel(alertDataSource)}
|
||||||
conditionFeedVisible={conditionFeedVisible}
|
conditionFeedVisible={conditionFeedVisible}
|
||||||
onSelectAlert={onSelectAlert}
|
onSelectAlert={onSelectAlert}
|
||||||
onToggleConditionFeed={onToggleConditionFeed}
|
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"]) {
|
function getAnalysisOriginLabel(origin: AnalysisArtifact["origin"]) {
|
||||||
if (origin === "backend") return "后端分析运行";
|
if (origin === "backend") return "后端分析运行";
|
||||||
if (origin === "demo") return "演示成果";
|
if (origin === "demo") return "演示成果";
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ describe("workbench runtime data", () => {
|
|||||||
expect(getMsUntilNextHeaderDataTimeTick(new Date(2026, 6, 22, 15, 43, 30))).toBe(90_000);
|
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], {
|
const resolved = resolveWorkbenchRuntimeData([mockCondition], {
|
||||||
availability: "not_configured",
|
availability: "not_configured",
|
||||||
source: "none",
|
source: "none",
|
||||||
@@ -86,7 +86,8 @@ describe("workbench runtime data", () => {
|
|||||||
|
|
||||||
expect(resolved.runtimeDataSource).toBe("mock");
|
expect(resolved.runtimeDataSource).toBe("mock");
|
||||||
expect(resolved.scheduledConditions).toEqual([mockCondition]);
|
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.scenarioDataSource).toBe("mock");
|
||||||
expect(resolved.artifactDataSource).toBe("mock");
|
expect(resolved.artifactDataSource).toBe("mock");
|
||||||
expect(resolved.workOrderDataSource).toBe("none");
|
expect(resolved.workOrderDataSource).toBe("none");
|
||||||
@@ -132,9 +133,8 @@ describe("workbench runtime data", () => {
|
|||||||
|
|
||||||
expect(resolved.runtimeDataSource).toBe("mock");
|
expect(resolved.runtimeDataSource).toBe("mock");
|
||||||
expect(resolved.scheduledConditions).toEqual([mockCondition]);
|
expect(resolved.scheduledConditions).toEqual([mockCondition]);
|
||||||
expect(resolved.workbenchAlerts).not.toEqual([backendAlert]);
|
expect(resolved.workbenchAlerts).toEqual([]);
|
||||||
expect(resolved.workbenchAlerts[0]?.id).toBe("scheduled-condition-alert-mock-condition");
|
expect(resolved.alertDataSource).toBe("none");
|
||||||
expect(resolved.alertDataSource).toBe("mock");
|
|
||||||
expect(resolved.scenarioDataSource).toBe("mock");
|
expect(resolved.scenarioDataSource).toBe("mock");
|
||||||
expect(resolved.workOrderDataSource).toBe("none");
|
expect(resolved.workOrderDataSource).toBe("none");
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
} from "../data/scheduled-conditions";
|
} from "../data/scheduled-conditions";
|
||||||
import { WORKBENCH_SCENARIOS } from "../data/workbench-session";
|
import { WORKBENCH_SCENARIOS } from "../data/workbench-session";
|
||||||
import type { ScheduledConditionItem } from "../types";
|
import type { ScheduledConditionItem } from "../types";
|
||||||
import { createScheduledConditionAlerts } from "../utils/scheduled-condition-alerts";
|
|
||||||
import type { WorkbenchSyncState } from "./use-workbench-sync";
|
import type { WorkbenchSyncState } from "./use-workbench-sync";
|
||||||
|
|
||||||
const HEADER_DATA_TIME_STEP_MINUTES = 5;
|
const HEADER_DATA_TIME_STEP_MINUTES = 5;
|
||||||
@@ -106,8 +105,8 @@ export function resolveWorkbenchRuntimeData(
|
|||||||
scheduledConditions: [...fallbackConditions, ...resolvedWorkOrders],
|
scheduledConditions: [...fallbackConditions, ...resolvedWorkOrders],
|
||||||
workbenchAlerts: backendAlertsConfigured
|
workbenchAlerts: backendAlertsConfigured
|
||||||
? backendSnapshot!.alerts
|
? backendSnapshot!.alerts
|
||||||
: createScheduledConditionAlerts(fallbackConditions),
|
: [],
|
||||||
alertDataSource: backendAlertsConfigured ? "backend" as const : "mock" as const,
|
alertDataSource: backendAlertsConfigured ? "backend" as const : "none" as const,
|
||||||
runtimeDataSource: "mock" as const,
|
runtimeDataSource: "mock" as const,
|
||||||
scenarios: useBackendScenarios ? backendSnapshot!.scenarios : WORKBENCH_SCENARIOS,
|
scenarios: useBackendScenarios ? backendSnapshot!.scenarios : WORKBENCH_SCENARIOS,
|
||||||
scenarioDataSource: useBackendScenarios ? "analysis_runs" as const : "mock" as const,
|
scenarioDataSource: useBackendScenarios ? "analysis_runs" as const : "mock" as const,
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export type WorkbenchRuntimeDataSource =
|
|||||||
| "scheduled_tasks"
|
| "scheduled_tasks"
|
||||||
| "operational_tasks";
|
| "operational_tasks";
|
||||||
|
|
||||||
export type WorkbenchAlertDataSource = "mock" | "backend";
|
export type WorkbenchAlertDataSource = "mock" | "backend" | "none";
|
||||||
|
|
||||||
export type WorkbenchScenarioDataSource = "mock" | "analysis_runs";
|
export type WorkbenchScenarioDataSource = "mock" | "analysis_runs";
|
||||||
|
|
||||||
|
|||||||
@@ -264,6 +264,14 @@ test("审批动作展示中文参数和证据,viewer 不可审批,冲突后
|
|||||||
};
|
};
|
||||||
|
|
||||||
await page.goto("/");
|
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({
|
const reconnectNotice = page.locator("[data-sonner-toast]").filter({
|
||||||
hasText: "业务同步正在重连"
|
hasText: "业务同步正在重连"
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user