Migrate maps to @geoscene/core, polish monitoring/alerts UX, fix timeline basemap flicker and district alert regions, and ship compose/nginx Docker deploy assets with CBPOA_ROOT data mounts. Co-authored-by: Cursor <cursoragent@cursor.com>
83 lines
2.4 KiB
TypeScript
83 lines
2.4 KiB
TypeScript
import { memo } from 'react';
|
|
import { PieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer } from 'recharts';
|
|
import { EmptyState } from '@/components/ui';
|
|
import { CHART_COLORS } from './chartColors';
|
|
|
|
export interface AlertSlice {
|
|
name: string;
|
|
value: number;
|
|
color: string;
|
|
}
|
|
|
|
interface AlertSeverityDonutProps {
|
|
data: AlertSlice[];
|
|
embed?: boolean;
|
|
}
|
|
|
|
const tooltipStyle = {
|
|
backgroundColor: '#FFFFFF',
|
|
border: `1px solid ${CHART_COLORS.tooltipBorder}`,
|
|
borderRadius: '10px',
|
|
fontSize: '12px',
|
|
};
|
|
|
|
function AlertSeverityDonutComponent({ data, embed }: AlertSeverityDonutProps) {
|
|
const hasData = data.some((d) => d.value > 0);
|
|
|
|
const body = (
|
|
<>
|
|
{embed ? (
|
|
<div className="workbench-panel__head">
|
|
<div>
|
|
<h3 className="workbench-panel__title">预警严重度分布</h3>
|
|
<p className="workbench-panel__sub">P1 紧急 / P2 关注</p>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="text-[11px] font-medium text-text-secondary uppercase tracking-wide mb-4">
|
|
预警严重度分布
|
|
</div>
|
|
)}
|
|
<div className={embed ? 'workbench-panel__body' : undefined}>
|
|
{hasData ? (
|
|
<div className="flex items-center justify-center">
|
|
<ResponsiveContainer width="100%" height={240}>
|
|
<PieChart>
|
|
<Pie
|
|
data={data}
|
|
cx="50%"
|
|
cy="50%"
|
|
innerRadius={50}
|
|
outerRadius={80}
|
|
paddingAngle={4}
|
|
dataKey="value"
|
|
nameKey="name"
|
|
>
|
|
{data.map((entry) => (
|
|
<Cell key={entry.name} fill={entry.color} />
|
|
))}
|
|
</Pie>
|
|
<Tooltip
|
|
contentStyle={tooltipStyle}
|
|
formatter={(value: number, name: string) => [value, name]}
|
|
/>
|
|
<Legend
|
|
wrapperStyle={{ fontSize: '12px' }}
|
|
formatter={(value: string) => <span className="text-text-primary">{value}</span>}
|
|
/>
|
|
</PieChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
) : (
|
|
<EmptyState title="暂无预警数据" />
|
|
)}
|
|
</div>
|
|
</>
|
|
);
|
|
|
|
if (embed) return <>{body}</>;
|
|
return <div className="card p-4">{body}</div>;
|
|
}
|
|
|
|
export const AlertSeverityDonut = memo(AlertSeverityDonutComponent);
|