import { useLayoutEffect, useRef, useState, type ReactNode } from "react"; import { Check, FileText, X } from "lucide-react"; import { AgentChartView } from "@/features/agent"; import { DeferredRender } from "@/shared/ui/deferred-render"; import { formatChartDisplayText } from "@/shared/utils/date-time-text"; import { Button } from "@/shared/ui/button"; import { Card, CardContent, CardHeader } from "@/shared/ui/card"; import { FloatingWindow } from "@/shared/ui/floating-window"; import { Popover, PopoverContent, PopoverTrigger } from "@/shared/ui/popover"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/shared/ui/select"; import type { InvestigationChartGroup as ChartGroup } from "../utils/investigation-chart-groups"; export function InvestigationChartGroup({ group, reviewing, onCloseChart, references, tracked = true, tile = false }: { group: ChartGroup; tracked?: boolean; tile?: boolean; reviewing: boolean; onCloseChart: (id: string) => void; references: (ids: string[]) => ReactNode; }) { const card = useRef(null); const [plotHeight, setPlotHeight] = useState(220); useLayoutEffect(() => { if (tile) return; const viewport = card.current?.closest("[data-investigation-content]"); if (!viewport || typeof ResizeObserver === "undefined") return; const resize = () => setPlotHeight(Math.max(120, Math.min(220, viewport.clientHeight - 24))); resize(); const observer = new ResizeObserver(resize); observer.observe(viewport); return () => observer.disconnect(); }, [tile]); const [selectedId, setSelectedId] = useState(group.items[0].command.chart_id); const selected = group.items.find((item) => item.command.chart_id === selectedId) ?? group.items[0]; const multiple = group.items.length > 1; const title = formatChartDisplayText(multiple ? group.title : selected.command.chart.title); const gaps = selected.command.chart.scada?.gaps ?? []; const missingCurrent = gaps.filter((gap) => gap.day_offset === 0 && gap.reason !== "no_scheduled_samples").reduce((sum, gap) => sum + gap.missing_count, 0); const missingHistory = gaps.filter((gap) => gap.day_offset > 0 && gap.reason !== "no_scheduled_samples").reduce((sum, gap) => sum + gap.missing_count, 0); const gapNotice = gaps.length ?

{[missingCurrent ? `当前缺测 ${missingCurrent} 点` : "", missingHistory ? `历史缺测 ${missingHistory} 点` : "", gaps.some((gap) => gap.reason.startsWith("outside_frozen_")) ? "部分数据不在冻结范围内" : "", gaps.some((gap) => gap.reason === "no_scheduled_samples") ? "窗口内无计划采样点" : ""].filter(Boolean).join(";")},已保留空槽。

: null; const objectButtons = (compact = false) => ; const content = (expanded: boolean, compact = false) => compact ?
{gapNotice} {multiple ?
: null}
{multiple ? objectButtons(true) : null}
:
{gapNotice}
{multiple ?

{selected.label}{selected.command.chart.x_data[0]} 至 {selected.command.chart.x_data.at(-1)}

: null}
{multiple ? objectButtons() : null}
{selected.command.evidence_refs.length ?
{references(selected.command.evidence_refs)}
: null}
; return {tracked ? group.items.slice(1).map((item) => ) : null}

{title}

{!tile ?

{multiple ? `${group.items.length} 个对象 · 点击切换 · ` : ""}{selected.command.chart.series.some((series) => series.type === "scatter") ? "折线与历史散点" : selected.command.chart.chart_type === "bar" ? "柱状图" : "折线图"} · {selected.command.chart.x_data.length} 个{selected.command.chart.chart_type === "bar" ? "类别" : "时间点"}

: null}
button]:size-6" : ""}`}> {tile && selected.command.evidence_refs.length ? {references(selected.command.evidence_refs)} : null} {() => {content(true)}}
{content(tile, tile)}
; }