- React 18 + TypeScript strict + AntV X6 2.x + AntD 5 + Zustand - Custom nodes: SiteNode, CrossDeviceNode, SpliceNode, DeviceNode, CardNode - 8-слойный автолейаут, порты (left/right), линии с цветами по статусу - Toolbar, дерево навигации, карточка объекта, таблица соединений - Контекстные меню, легенда, drag линий/нод, создание линий из портов - Моковые данные: 3 сайта, 10 устройств, 15 линий Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
87 lines
2.9 KiB
TypeScript
87 lines
2.9 KiB
TypeScript
import { Modal, Space, Tag } from 'antd';
|
||
import { useSchemaStore } from '../../store/schemaStore.ts';
|
||
import { STATUS_COLORS, STATUS_LABELS } from '../../constants/statusColors.ts';
|
||
import { EntityStatus, LineStyle, Medium } from '../../types/index.ts';
|
||
|
||
export function LegendModal() {
|
||
const visible = useSchemaStore((s) => s.legendVisible);
|
||
const setVisible = useSchemaStore((s) => s.setLegendVisible);
|
||
|
||
return (
|
||
<Modal
|
||
title="Легенда"
|
||
open={visible}
|
||
onCancel={() => setVisible(false)}
|
||
footer={null}
|
||
width={480}
|
||
>
|
||
<div style={{ marginBottom: 20 }}>
|
||
<h4 style={{ marginBottom: 8 }}>Цвета статусов</h4>
|
||
<Space wrap>
|
||
{Object.values(EntityStatus).map((status) => {
|
||
const colors = STATUS_COLORS[status];
|
||
const label = STATUS_LABELS[status];
|
||
return (
|
||
<Tag
|
||
key={status}
|
||
style={{
|
||
borderColor: colors.border,
|
||
backgroundColor: colors.fill,
|
||
color: colors.text,
|
||
}}
|
||
>
|
||
{label}
|
||
</Tag>
|
||
);
|
||
})}
|
||
</Space>
|
||
</div>
|
||
|
||
<div style={{ marginBottom: 20 }}>
|
||
<h4 style={{ marginBottom: 8 }}>Типы линий</h4>
|
||
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||
{Object.values(LineStyle).map((style) => {
|
||
const dasharray =
|
||
style === LineStyle.Solid
|
||
? ''
|
||
: style === LineStyle.Dashed
|
||
? '8 4'
|
||
: '2 4';
|
||
return (
|
||
<div key={style} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||
<svg width={60} height={20}>
|
||
<line
|
||
x1={0}
|
||
y1={10}
|
||
x2={60}
|
||
y2={10}
|
||
stroke="#333"
|
||
strokeWidth={2}
|
||
strokeDasharray={dasharray}
|
||
/>
|
||
</svg>
|
||
<span style={{ fontSize: 12 }}>{style}</span>
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<h4 style={{ marginBottom: 8 }}>Среда передачи</h4>
|
||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||
{Object.values(Medium).map((medium) => (
|
||
<div key={medium} style={{ fontSize: 12 }}>
|
||
<strong>{medium}</strong>
|
||
{medium === Medium.Optical && ' — оптическое волокно'}
|
||
{medium === Medium.Copper && ' — медный кабель'}
|
||
{medium === Medium.Wireless && ' — беспроводная связь'}
|
||
{medium === Medium.Unknown && ' — неизвестная среда'}
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</Modal>
|
||
);
|
||
}
|