feat(workbench): expand SCADA monitoring and investigation presentation

This commit is contained in:
2026-11-07 19:50:14 +08:00
parent 0801e161ec
commit ba71e2d529
133 changed files with 6754 additions and 1438 deletions
@@ -1,4 +1,4 @@
import { AlertTriangle, CheckCircle2, Info, Loader2, X, XCircle } from "lucide-react";
import { AlertTriangle, ArrowUpRight, CheckCircle2, Info, Loader2, X, XCircle } from "lucide-react";
import type { ReactNode } from "react";
import { cn } from "@/shared/ui/cn";
import { Button } from "@/shared/ui/button";
@@ -32,16 +32,16 @@ export function MapNoticeContent({
return (
<MapNoticeFrame tone={tone}>
<MapNoticeIcon tone={tone} icon={Icon} />
<MapNoticeBody
title={title}
message={message}
action={
actionLabel && onAction ? (
<MapNoticeAction label={actionLabel} onClick={onAction} />
) : null
}
/>
<div data-slot="map-notice-summary" className="flex items-start gap-3 py-3.5 pl-4 pr-12">
<MapNoticeIcon tone={tone} icon={Icon} />
<MapNoticeBody title={title} message={message} />
</div>
{actionLabel && onAction ? (
<div data-slot="map-notice-actions" className="flex flex-wrap items-center justify-between gap-x-3 gap-y-1 pb-3 pl-14 pr-3">
<span className="text-xs leading-5 text-[var(--ink-muted)]">保留至手动关闭</span>
<MapNoticeAction label={actionLabel} onClick={onAction} />
</div>
) : null}
</MapNoticeFrame>
);
}
@@ -59,8 +59,11 @@ function MapNoticeFrame({ tone, children }: { tone: MapNoticeTone; children: Rea
return (
<div
role={tone === "error" || tone === "warning" ? "alert" : "status"}
// Sonner restores its saved focus on blur. Persistent action buttons must
// let the user move directly to another workbench control instead.
onFocus={(event) => event.stopPropagation()}
className={cn(
"glass-transient relative flex w-full items-start gap-2.5 overflow-hidden border py-2.5 pl-3 pr-10 text-sm text-slate-900",
"glass-transient relative w-full overflow-hidden border text-sm text-slate-900",
MAP_READABLE_RADIUS_CLASS_NAME,
)}
>
@@ -90,23 +93,20 @@ function MapNoticeIcon({
function MapNoticeBody({
title,
message,
action
message
}: {
title?: string;
message: string;
action?: ReactNode;
}) {
return (
<span className="min-w-0 flex-1">
<div className="min-w-0 flex-1">
{title ? (
<span className="block text-sm font-semibold leading-5 text-slate-950">{title}</span>
<span className="block break-words text-sm font-semibold leading-5 text-slate-950">{title}</span>
) : null}
<span className={cn("block text-sm leading-5 text-slate-600", title && "mt-0.5")}>
<span className={cn("block break-words text-sm leading-6 text-slate-600", title && "mt-1")}>
{message}
</span>
{action}
</span>
</div>
);
}
@@ -118,11 +118,12 @@ function MapNoticeAction({ label, onClick }: { label: string; onClick: () => voi
size="sm"
variant="outline"
className={cn(
"pointer-events-auto mt-2 border-[var(--surface-border)] bg-[var(--action-soft)] text-[var(--action-blue-hover)]",
"pointer-events-auto h-9 max-w-full gap-1.5 whitespace-normal border-[var(--surface-border)] bg-[var(--action-soft)] px-2.5 text-xs text-[var(--action-blue-hover)]",
MAP_COMPACT_RADIUS_CLASS_NAME
)}
>
{label}
<ArrowUpRight size={14} aria-hidden="true" />
</Button>
);
}