From fe174535b7232ad2af935b4e685ed9f9d1a97172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8C=D1=8F=D1=81=20=D0=A1=D1=83=D0=BB=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Tue, 22 Sep 2026 21:15:31 +0300 Subject: [PATCH] =?UTF-8?q?feat(gps):=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA?= =?UTF-8?q?=D0=B0=20=C2=AB=D0=9D=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=C2=BB=20=D0=B4=D0=BB=D1=8F=20=D1=81=D0=BB=D0=BE=D1=8F=20=D0=BE?= =?UTF-8?q?=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=BE=D0=B2=20(=D0=BF=D0=BE=20?= =?UTF-8?q?=D1=83=D0=BC=D0=BE=D0=BB=D1=87=D0=B0=D0=BD=D0=B8=D1=8E=20=D1=81?= =?UTF-8?q?=D0=BA=D1=80=D1=8B=D1=82=D1=8B);=20=D0=BF=D0=BE=D0=B4=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B8=20=D1=81=D0=BE=D0=BA=D1=80=D0=B0=D1=89=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B4=D0=BE=20=C2=AB=D0=BE=D0=B1=D1=8A=D0=B5?= =?UTF-8?q?=D0=BA=D1=82=20=C2=B7=20=D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D1=87?= =?UTF-8?q?=D0=B8=D0=BA=C2=BB=20(=E2=89=A440=20=D1=81=D0=B8=D0=BC=D0=B2?= =?UTF-8?q?=D0=BE=D0=BB=D0=BE=D0=B2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pages/gps/MapTab.tsx | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/client/src/pages/gps/MapTab.tsx b/client/src/pages/gps/MapTab.tsx index 03524ff..1fc5359 100644 --- a/client/src/pages/gps/MapTab.tsx +++ b/client/src/pages/gps/MapTab.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from 'react'; import { Card } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; -import { X, Route, Ruler, MapPinPlus } from 'lucide-react'; +import { X, Route, Ruler, MapPinPlus, Tag } from 'lucide-react'; import { useQuery } from '@tanstack/react-query'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { useLocation } from 'wouter'; @@ -132,6 +132,9 @@ export function GpsMapTab({ onShowRoute }: { onShowRoute: (assetId: number) => v // === Слой задач формы: выбранная форма + её geo-поле → задачи на карте === const [, setLocation] = useLocation(); const [tasksLayer, setTasksLayer] = useState(false); + // Отображение названий объектов на карте (по умолчанию скрыты — длинные + // заголовки перекрывают друг друга; включаем кнопкой «Названия») + const [showLabels, setShowLabels] = useState(false); const [mapFormId, setMapFormId] = useState(null); const [mapFieldId, setMapFieldId] = useState(null); const [createAt, setCreateAt] = useState<{ lat: number; lng: number } | null>(null); @@ -183,6 +186,15 @@ export function GpsMapTab({ onShowRoute }: { onShowRoute: (assetId: number) => v return { lat, lng }; }; + // Короткое название для подписи: «объект · заказчик» (первая и последняя + // части заголовка через «;»), длину ограничиваем, иначе подписи перекрывают карту + const shortTitle = (title: string): string => { + const parts = title.split(';').map((x) => x.trim()).filter(Boolean); + let text = parts.length > 1 ? `${parts[0]} · ${parts[parts.length - 1]}` : (parts[0] ?? title); + if (text.length > 40) text = `${text.slice(0, 39)}…`; + return text; + }; + const taskMarkers: GpsMapMarker[] = useMemo(() => { if (!tasksLayer || mapFieldId === null) return []; const markers: GpsMapMarker[] = []; @@ -195,14 +207,15 @@ export function GpsMapTab({ onShowRoute }: { onShowRoute: (assetId: number) => v lng: geo.lng, kind: 'dot', color: '#8b5cf6', - label: t.title, + // Подпись — только при включённом режиме «Названия» + label: showLabels ? shortTitle(t.title) : undefined, noCluster: true, zIndex: 40, onClick: rulerMode ? undefined : () => setLocation(`/forms/${mapFormId}/tasks/${t.id}`), }); } return markers; - }, [tasksLayer, mapFieldId, tasksData, rulerMode, setLocation, mapFormId]); + }, [tasksLayer, mapFieldId, tasksData, rulerMode, setLocation, mapFormId, showLabels]); // Правый клик по карте — создать объект выбранной формы с этими координатами const handleMapContextMenu = (lat: number, lng: number) => { @@ -339,6 +352,15 @@ export function GpsMapTab({ onShowRoute }: { onShowRoute: (assetId: number) => v )} + Правый клик по карте — новый объект здесь