import type { FaultDashboardFilters } from '../../../shared/assets/faults'; import { useCallback, useEffect, useRef, useState } from 'react'; import { ClipboardList, RefreshCw } from 'lucide-react'; import { CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; import { fetchJson } from '../../../auth/api-client'; import { FAULT_WEEKLY_METRICS, type FaultWeeklyMetric, type FaultWeeklyResponse } from '../../../shared/assets/faults'; import { AnalysisExportButton } from '../components/analysis/AnalysisExportButton'; import { downloadFaultReport } from './report-export'; import { FlowDateRangePicker } from '../components/overview/FlowDateRangePicker'; import { getWeeklyFlowRange } from '../model'; import { FaultAnalysisModal, type FaultAnalysisSource } from './FaultAnalysisModal'; const metrics: FaultWeeklyMetric[] = ['reported', 'closed']; const definition = '新增故障按提报时间统计,解决故障按解决时间统计;同一故障可在不同日期分别计入两个指标。'; export function FaultWeeklyReport({ refresh, scope = {}, scopeLabel = '', period }: { refresh: number; scope?: FaultDashboardFilters; scopeLabel?: string; period?: { start: string; end: string } }) { const [range, setRange] = useState(() => period || getWeeklyFlowRange()); const scopeKey = new URLSearchParams(scope).toString(); useEffect(() => { if (period) setRange(period); }, [period?.start, period?.end]); const [data, setData] = useState(null); const [error, setError] = useState(''); const [loading, setLoading] = useState(true); const [revision, setRevision] = useState(0); const [source, setSource] = useState(null); const chartRef = useRef(null); const close = useCallback(() => setSource(null), []); const today = new Date(Date.now() + 8 * 3600000).toISOString().slice(0, 10); useEffect(() => { const controller = new AbortController(); setLoading(true); setData(null); setError(''); fetchJson(`/api/asset-faults/weekly-report?${new URLSearchParams({ start: range.start, end: range.end, ...scope })}`, { signal: controller.signal }) .then(result => { if (!controller.signal.aborted) setData(result); }) .catch(e => { if (!controller.signal.aborted) setError(e instanceof Error ? e.message : '加载失败'); }) .finally(() => { if (!controller.signal.aborted) setLoading(false); }); return () => controller.abort(); }, [range.start, range.end, revision, refresh, scopeKey]); const drill = (metric: FaultWeeklyMetric, day?: string) => { if (!data || loading) return; const params = new URLSearchParams({ start: data.start, end: data.end, metric, ...scope }); if (day) params.set('day', day); setSource({ url: `/api/asset-faults/weekly-report-analysis?${params}`, title: `故障运维周报 · ${FAULT_WEEKLY_METRICS[metric]}`, periodLabel: `${day || `${data.start} 至 ${data.end}`} · 按事件发生时间`, definition }); }; return

故障运维周报

单位:单 data ? downloadFaultReport({ kind: 'weekly', data, filterLabel: scopeLabel }, chartRef.current?.querySelector('svg.recharts-surface[role=application]') || undefined) : undefined} />

按日展示新增故障和解决故障。{period ? '统计周期沿用查询范围,可在下方单独调整。' : '默认业务周为周六至周五,可自选日期。'}

{error ?
故障运维周报加载失败,请稍后重试。
: loading || !data ?
正在加载故障运维周报…
: <>
{metrics.map(metric => )}
每日变化单位:单
新增故障解决故障
v.slice(5)} minTickGap={32} tickMargin={12} padding={{ left: 12, right: 12 }} axisLine={false} tickLine={false} /> [`${value} 单`, name]} />
{metrics.map(metric => )}{[...data.days].reverse().map(row => {metrics.map(metric => )})}{metrics.map(metric => )}
日期{FAULT_WEEKLY_METRICS[metric]}
{row.date}{row.date === today && 今天}{new Date(`${row.date}T12:00:00+08:00`).toLocaleDateString('zh-CN', { weekday: 'short', timeZone: 'Asia/Shanghai' })}
合计
{!metrics.some(metric => data.totals[metric]) &&

所选日期范围暂无新增或解决故障。

}

新增故障按提报日期,解决故障按解决日期统计,不受提报日期限制。数据时间:{new Date(data.updatedAt).toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', hour12: false })}。

} {source && }
; }