Files
test-x6/frontend/src/features/schema/edges/edgeGrouping.ts
Alina ef816cdcf4 feat: frontend MVP — детальная схема связей устройств (AntV X6)
- 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>
2026-02-17 22:02:25 +03:00

77 lines
2.1 KiB
TypeScript

import type { Line, Port, Device, SchemaData } from '../../../types/index.ts';
import { STATUS_COLORS, STATUS_LABELS } from '../../../constants/statusColors.ts';
export interface LineGroup {
key: string;
deviceAId: string;
deviceZId: string;
lines: Line[];
representativeLine: Line;
count: number;
}
function getDeviceIdForPort(
portId: string,
data: SchemaData,
): string | null {
const port = data.ports.find((p: Port) => p.id === portId);
return port ? port.deviceId : null;
}
export function groupLinesByDevicePair(data: SchemaData): LineGroup[] {
const groupMap = new Map<string, Line[]>();
for (const line of data.lines) {
const devA = getDeviceIdForPort(line.portAId, data);
const devZ = getDeviceIdForPort(line.portZId, data);
if (!devA || !devZ) continue;
const key = [devA, devZ].sort().join('::');
const existing = groupMap.get(key);
if (existing) {
existing.push(line);
} else {
groupMap.set(key, [line]);
}
}
const groups: LineGroup[] = [];
for (const [key, lines] of groupMap.entries()) {
const [deviceAId, deviceZId] = key.split('::');
groups.push({
key,
deviceAId,
deviceZId,
lines,
representativeLine: lines[0],
count: lines.length,
});
}
return groups;
}
export function getGroupTooltip(
group: LineGroup,
devices: Device[],
): string {
const devA = devices.find((d) => d.id === group.deviceAId);
const devZ = devices.find((d) => d.id === group.deviceZId);
const statusCounts = new Map<string, number>();
for (const line of group.lines) {
const current = statusCounts.get(line.status) ?? 0;
statusCounts.set(line.status, current + 1);
}
let tooltip = `${devA?.name ?? '?'}${devZ?.name ?? '?'}\n`;
tooltip += `Линий: ${group.count}\n`;
for (const [status, count] of statusCounts.entries()) {
const color = STATUS_COLORS[status as keyof typeof STATUS_COLORS];
const label = STATUS_LABELS[status as keyof typeof STATUS_LABELS];
tooltip += ` ${label}: ${count} (${color.border})\n`;
}
return tooltip;
}