import { useEffect, useRef, useState, type ReactNode } from 'react' import { AlertTriangle, ClipboardList, Gauge, Radar, RefreshCw, RadioTower, } from 'lucide-react' import type { OrderSummary } from '@/types' import type { DashboardConnectionState } from '@/lib/dashboard-api' import { getConnectionPresentation } from '@/lib/dashboard-status' import { flattenTree } from '@/lib/production' import { formatPercent, formatQuantity } from '@/lib/utils' const DASHBOARD_TITLE = '东方水利制造进度驾驶舱' interface TopMetricsProps { orders: OrderSummary[] lastUpdated: string connectionState: DashboardConnectionState onRefresh: () => void } export function TopMetrics({ orders, lastUpdated, connectionState, onRefresh, }: TopMetricsProps) { const totalOrders = orders.length const totalRequired = orders.reduce((total, order) => total + order.requiredQty, 0) const totalCompleted = orders.reduce((total, order) => total + order.completedQty, 0) const overallProgress = totalRequired === 0 ? 0 : (totalCompleted / totalRequired) * 100 const delayedCount = orders.filter((order) => order.delayDays > 0 || order.status === 'delayed' || order.status === 'blocked' ).length const riskCount = orders.filter((order) => order.riskLevel === 'critical').length const warningCount = orders.filter((order) => order.riskLevel === 'warning').length const planAchievement = orders.length === 0 ? 0 : orders.reduce((total, order) => total + order.planAchievement, 0) / orders.length const averageDelta = orders.length === 0 ? 0 : orders.reduce((total, order) => total + order.dailyDelta, 0) / orders.length const activeNodes = orders .flatMap((order) => flattenTree(order.root)) .filter((node) => node.status === 'in_progress').length const connection = getConnectionPresentation(connectionState) return (
} label="订单总数" value={formatQuantity(totalOrders)} detail={`较昨日 +${Math.max(1, Math.round(activeNodes / 25))}`} /> } label="总完成率" value={formatPercent(overallProgress)} detail={`${formatQuantity(totalCompleted)} / ${formatQuantity(totalRequired)}`} tone="success" /> } label="延期订单" value={formatQuantity(delayedCount)} detail="较昨日 +3" tone="critical" /> } label="高风险订单" value={formatQuantity(riskCount)} detail={`较昨日 +${warningCount}`} tone="warning" /> } label="计划达成率" value={formatPercent(planAchievement)} detail={`较昨日 ${averageDelta >= 0 ? '+' : ''}${averageDelta.toFixed(1)}%`} tone="info" />
{connection.label} DATA LINK
) } function DashboardTitle() { const frameRef = useRef(null) const textRef = useRef(null) const [isOverflowing, setIsOverflowing] = useState(false) useEffect(() => { const measure = () => { const frame = frameRef.current const text = textRef.current if (!frame || !text) { return } setIsOverflowing(text.scrollWidth > frame.clientWidth + 2) } measure() window.addEventListener('resize', measure) if (typeof ResizeObserver === 'undefined') { return () => window.removeEventListener('resize', measure) } const observer = new ResizeObserver(measure) if (frameRef.current) { observer.observe(frameRef.current) } if (textRef.current) { observer.observe(textRef.current) } return () => { observer.disconnect() window.removeEventListener('resize', measure) } }, []) return (
DONGFANG HYDRO · CONTROL 01

东方水利制造进度驾驶舱

) } function MetricItem({ icon, label, value, detail, tone = 'info', }: { icon: ReactNode label: string value: string detail: string tone?: 'info' | 'success' | 'warning' | 'critical' }) { return (
{label} {value} {detail}
) }