vue-asset-map
v1.0.8
Published
Interactive infrastructure asset map for Vue 3, built on Vue Flow
Downloads
55
Maintainers
Readme
vue-asset-map
Интерактивная карта инфраструктурных активов для Vue 3 на базе Vue Flow.
Документация · Живое демо · Changelog
Возможности
- Проекции одного графа. Сущности и связи объявляются один раз; вид оставляет связи, у которых в
layersесть его id, поэтому одни и те же данные рисуются и как физическая топология, и как VPN-оверлей. - Свёртка групп. Однотипные соседи по родителю схлопываются в один узел при превышении порога: их рёбра переносятся на групповой узел, параллельные агрегируются со счётчиком. Клик раскрывает группу обратно.
- Свёртка поддерева. Кнопка на самом узле прячет его потомков и переносит их рёбра на него.
- Поиск по имени, IPv4-маске и CIDR.
10.38.24.*и10.38.24.0/24сравниваются с адресами внутри подписей; всё остальное — регистронезависимая подстрока. - Фасетные фильтры. Группы вроде «Подсеть» или «Критичность» задаёт потребитель через
valuesOf. Счётчики считаются по текущей проекции, поэтому выбор одного значения не обнуляет остальные. - Маркеры принадлежности. Кружки под подписью показывают, к каким узлам-центрам подключён актив; состав считается по самому графу. Наведение подсвечивает всех с тем же кружком, остальных гасит.
- Подробности в перетаскиваемых окнах. Несколько окон одновременно, лимит задаётся пропсом, содержимое — через слот
#details. Заголовок, заголовочный блок и табы подменяются или убираются по отдельности, так что от дефолтного оформления не обязано остаться ничего, кроме шапки.<MapWindow>экспортируется: из него собираются свои окна. - Автоматическая трассировка пути. С
autoPathи двумя выделенными узлами маршрут между ними находится и подсвечивается сам, а приходит событиемpath-change. Shift+клик набирает пару и окон при этом не открывает. - Оформление узла разбирается на части. Плашка состояния, кнопка свёртки, плашка с подписями и сами подписи по
отдельности выключаются пропом или подменяются слотом;
nodeTypesзаменяет узел целиком. - Виды соединений и легенда.
linkTypesодин раз объявляет цвет, штрих и название; это же управляет цветом связи, легендой и выбором типа при правке, так что разойтись они не могут. - Правка, не владея данными. Кнопка превращает окно подробностей в форму, меню по правому клику удаляет через
собственное подтверждение пакета, а связи рисуются перетаскиванием от узла к узлу. Карта никогда не пишет в
entitiesиlinks— она сообщает событиями, а решает приложение. - Расстановку можно сохранить. Перетащенные позиции уходят через
v-model:positions— обычный сериализуемый объект только из осознанных перемещений, поэтому сохранённая расстановка переживает изменение данных.getPositions()снимает позиции всех узлов, когда нужна вся картина. - Подключаемые раскладки.
manualиradialвстроены,dagre— отдельным подпутём. Можно передать любой объект с методомrun(graph, options, signal). - Ядро без фреймворка.
vue-asset-map/coreне импортирует ни Vue, ни Vue Flow, поэтому проекцию, фильтрацию и радиус связей можно посчитать на сервере.
Установка
npm install vue-asset-map vue @vue-flow/corevue и @vue-flow/core — peer-зависимости. Vue Flow должен быть в дереве ровно один раз: он работает через
provide/inject, и вторая копия ломает контекст провайдера.
Раскладка на dagre опциональна и нужна только если вы ей пользуетесь:
npm install @dagrejs/dagreОба стиля подключает приложение — структурный CSS Vue Flow и токены пакета:
import '@vue-flow/core/dist/style.css'
import 'vue-asset-map/style.css'Минимальный пример
<script setup lang="ts">
import { ref } from 'vue'
import { AssetMap } from 'vue-asset-map'
import type { AssetEntity, AssetLink, AssetView } from 'vue-asset-map'
const entities: AssetEntity[] = [
{ id: 'internet', type: 'cloud', label: 'Интернет' },
{ id: 'router', type: 'router', label: 'Роутер офиса', parentId: 'internet', sublabels: ['10.0.0.1'] },
{ id: 'vpn', type: 'vps', label: 'Координатор VPN', parentId: 'internet', status: 'online' },
{ id: 'laptop', type: 'host', label: 'Ноутбук', parentId: 'router', sublabels: ['10.0.0.14'] },
]
const links: AssetLink[] = [
{ id: 'l1', source: 'internet', target: 'router', layers: ['physical'] },
{ id: 'l2', source: 'internet', target: 'vpn', layers: ['physical'] },
{ id: 'l3', source: 'router', target: 'laptop', layers: ['physical'] },
{ id: 'l4', source: 'vpn', target: 'laptop', layers: ['logical'] },
]
const views: AssetView[] = [
{ id: 'physical', label: 'Физическая', hideIsolated: true },
{ id: 'logical', label: 'VPN-оверлей', hideIsolated: true },
]
const view = ref('physical')
const selection = ref<string[]>([])
</script>
<template>
<AssetMap
v-model:view="view"
v-model:selection="selection"
:entities="entities"
:links="links"
:views="views"
style="height: 100vh"
/>
</template>Связь попадает в вид, если её layers содержат id вида, поэтому l4 виден только в оверлее. С hideIsolated узлы,
оставшиеся в виде без связей, из него убираются.
Props
Самое частое; полный список — в справочнике API.
| Prop | Тип | По умолчанию | Что делает |
| ------------------- | --------------------------------- | ------------ | -------------------------------------------------------- |
| entities | AssetEntity<E>[] | — | Узлы. Карта их не мутирует. |
| links | AssetLink<L>[] | — | Связи. Карта их не мутирует. |
| views | AssetView[] | — | Проекции. Без них рисуется всё. |
| layout | AssetMapLayoutSpec | manual | Движок по имени или объектом, плюс его опции. |
| collapse | CollapseRule \| false | порог 10 | false выключает свёртку групп. |
| themeConfig | ThemeConfig | — | statusColors и kindIcons по вашим значениям. |
| theme | 'light' \| 'dark' \| 'auto' | 'light' | 'auto' читает системную настройку один раз. |
| markers | NodeMarkerDef[] | — | Кружки принадлежности под подписями. |
| maxDetailsWindows | number | 2 | 0 полностью выключает окна подробностей. |
| detailsTabs | DetailsTabDef[] \| false | встроенные | Табы окна подробностей; false убирает полосу. |
| showNodeStatus | boolean | true | false убирает плашку состояния со всех узлов. |
| maxSublabels | number | без предела | Ограничивает число подписей; 0 убирает их. |
| autoPath | boolean | false | Сам строит путь между двумя выделенными узлами. |
| linkTypes | LinkTypeDef[] | — | Виды соединений: цвет, штрих, название. |
| showLegend | boolean | false | Легенда соединений слева снизу. |
| showContextMenu | boolean | false | Меню по правому клику на узлах и связях. |
| editable | boolean | false | Кнопка правки, удаление, рисование связей. |
| detailsMode | 'replace' | 'stack' | 'replace' | Что обычный клик делает с открытыми окнами. |
| locale | string \| PartialLocaleMessages | ru | Код локали или словарь переопределений. |
| autoFitView | boolean | false | Подгонять полотно под содержимое после каждой раскладки. |
Двусторонние привязки: view, selection, expanded, filters, viewport, positions, openDetails,
openLinks, collapsedNodes, openFilterGroups. Каждая работает и без v-model — тогда состоянием управляет сам компонент.
События
| Событие | Полезная нагрузка | Когда |
| ------------------------------- | ------------------------------ | ----------------------------------------------------------- |
| node-click | { id, entity, group, event } | Клик по узлу или групповому узлу. |
| selection-change | EntityId[] | Изменилось выделение, в порядке выбора. |
| path-change | EntityId[] | Изменился путь; пустой, когда подсветку сняли. |
| entity-update / link-update | { id, entity | link } | Правку сохранили. В нагрузке — новый объект. |
| entity-delete / link-delete | { id, entity | link } | Удаление подтвердили. |
| link-create | { link, source, target } | Связь нарисовали между узлами и сохранили. |
| expand / collapse | { groupId, group } | Группа раскрыта или свёрнута. |
| layout-done | { engine, positions } | Раскладка досчитана и применена. |
| error | unknown | Движок раскладки упал или запрошено неизвестное имя движка. |
Слоты
| Слот | Параметры | Зачем |
| -------------------------------- | -------------------------------- | ---------------------------------------- |
| details | { entity, close, tab } | Тело окна подробностей. |
| details-title / details-tabs | { entity, … } | Подпись и полоса табов окна. |
| node-{type} | { entity, nodeId, simplified } | Подменяет содержимое круга узла. |
| node-label / node-status | { entity, nodeId, simplified } | Подменяет плашку подписей или состояния. |
| toolbar-left / toolbar-right | — | Свои контролы в шапке карты. |
| windows | — | Свои плавающие окна поверх полотна. |
| edge-label | { link, aggregated, count } | Подменяет подпись связи. |
Требования
| | Версия |
| ------------------------------ | --------- |
| Vue | ^3.4.0 |
| Vue Flow (@vue-flow/core) | ^1.42.0 |
| Node, для сборки из исходников | >=20 |
Пакет только ESM, а его декларации рассчитаны на moduleResolution: "bundler" — значение по умолчанию в проекте на
Vite или webpack.
Лицензия
MIT © Dmitriy Korolev
