Демка · 7 сентября 2026
Settlements UI
React, MobX, карта на MapLibre. Можно править вершины, загружать пачку полигонов и выгружать GeoJSON. В наборе 54 территории РФ: 19 городов, 27 районов и округов, 8 областей. Контуры из OpenStreetMap. Бэк замокан, правки живут в памяти вкладки.
01 / Задача
Редактор полигонов с импортом GeoJSON
У объекта есть карточка и геометрия на карте. Они должны обновляться вместе. При массовом импорте нужно проверить геометрию, показать ошибки и применить только подходящие полигоны.
Сценарий: Редактирование границ городов, районов и других территорий.
Что делал
- Карточки объектов, слои карты и редактирование геометрии.
- Связка React/MobX с MapLibre и Mapbox Draw. Импорт и экспорт геометрии.
- Для демки сделал адаптер вместо корпоративного API. Убрал рабочие данные и закрытые registry-зависимости.
- Деплой, правки вёрстки, проверка массового импорта и набор границ из OpenStreetMap.
Скриншоты
Экраны, формы, ошибкиСкриншоты, схемы и исходные материалы сохранены на языке оригинала; подписи и описание переведены.
02 / Технологии
Что использовано
React / MobX
Исходные экраны, состояние и импорт
MapLibre / Mapbox Draw
Подложка карты, слои и редактирование геометрии
GeoJSON / WKB
Валидация, загрузка и экспорт
03 / Решения
Как устроен проект
- Исходная тема sppi-dark: тёмный фон, жёлтые элементы управления и исходные цвета статусов.
- MapLibre получает обычные тайлы OpenStreetMap. Указана атрибуция; массовая загрузка карт и офлайн-кеширование не реализованы.
- Штатные экраны FilesScreen → PolygonsScreen → PolygonEditScreen работают через локальный адаптер контрактов OData и geo-import.
- Импорт сначала проходит проверку и просмотр. Применение переносит только валидные полигоны в основной редактор; повторное применение не создаёт новых копий с тем же importId.
- Standalone-стили собраны в единую область .sppi-dark: исходные цвета, единые SVG-иконки, размер действий 40 px, адаптивные карточки файлов. ResizeObserver синхронизирует MapLibre с изменениями панелей и экрана.
- Контуры OpenStreetMap упрощены с сохранением топологии: 54 территории, 21 421 вершина, 7 MultiPolygon. Области, районы и города имеют разную прозрачность; исходные цвета управления и статусов сохранены.
04 / Проверка
Сценарии демки
- Найти Владимир, Суздаль, Нижний Новгород, Суздальский район или Владимирскую область; открыть карточку и приблизить контур.
- Скачать набор из 54 территорий, загрузить его через массовый импорт и проверить все геометрии.
- Открыть файл: список полигонов, статусы, фильтры и карта с общими границами.
- Открыть полигон: редактирование, сброс исходной геометрии, явный пропуск и сохранение.
- Исправить или пропустить ошибки, нажать «Применить импорт», закрыть модуль и экспортировать результат из основного редактора.
- Сбросить пример; проверить, что другая вкладка не получила импортированные файлы.
Результаты проверок
- Статическая сборка обслуживается общим Nginx; отдельного backend-процесса GIS на VPS нет.
- 54 объекта; 21 421 вершина после упрощения, 76–926 на объект, до 480 на кольцо. Это характеристика набора, а не оценка точности границ.
- В одном контрольном запуске Chromium на опубликованной версии: первый список 1.80 с, импорт 54 территорий 0.66 с. Измерен интерфейс на тестовой машине; это не нагрузочный тест или SLA.
Ограничения
- Только backend заменён памятью вкладки. Серверный OData/PostGIS-сервис не подключён; закрытый исходный репозиторий остаётся приватным.
- Пределы адаптера: 20 файлов, 500 полигонов в файле, 1000 в сессии; текст файла до 5 MB. Поддержаны Polygon/MultiPolygon и EPSG:4326/3857.
- После перезагрузки импортированные данные исчезают. Экспорт GeoJSON позволяет сохранить результат у себя.
- Тайлы OpenStreetMap загружаются с внешнего сервера. Без него подложка не загрузится.
- Границы OSM упрощены для редактора, не являются кадастровыми данными. Города — контуры place=city/town, районы и области — boundary=administrative; коды ОКТМО учебные. Источник и ODbL указаны в демо и скачиваемом GeoJSON.
Технические заметки
Модули, API, схема данных, запуск и результаты проверок.
Документация →Материалы ↓