diff --git a/client/src/components/gps/OsmMap.tsx b/client/src/components/gps/OsmMap.tsx index 9db4caa..9ff1a3e 100644 --- a/client/src/components/gps/OsmMap.tsx +++ b/client/src/components/gps/OsmMap.tsx @@ -84,7 +84,8 @@ export function OsmMap({ iconCreateFunction: (cluster) => L.divIcon({ html: gpsClusterHtml(cluster.getChildCount()), className: '', iconSize: [0, 0] }), zoomToBoundsOnClick: false, - spiderfyOnMaxZoom: false, + // Точки в одной координате («3») на max zoom раскрываются «паучком» + spiderfyOnMaxZoom: true, showCoverageOnHover: false, }).addTo(map); clusterLayerRef.current = clusterLayer; @@ -113,9 +114,11 @@ export function OsmMap({ // Делегированный клик по пункту списка кластера в popup // (контент popup рендерится внутри контейнера карты) map.getContainer().addEventListener('click', (ev) => { - const el = (ev.target as HTMLElement | null)?.closest?.('[data-gps-marker-id]') as HTMLElement | null; + const el = (ev.target as HTMLElement | null)?.closest?.('[data-gps-action]') as HTMLElement | null; if (!el) return; - const marker = markersByIdRef.current.get(el.dataset.gpsMarkerId || ''); + const action = el.dataset.gpsAction || ''; + if (!action.startsWith('open:')) return; + const marker = markersByIdRef.current.get(action.slice(5)); if (marker?.onClick) { marker.onClick(); map.closePopup(); diff --git a/client/src/components/gps/Yandex21Map.tsx b/client/src/components/gps/Yandex21Map.tsx index eb9324c..1e73ab8 100644 --- a/client/src/components/gps/Yandex21Map.tsx +++ b/client/src/components/gps/Yandex21Map.tsx @@ -170,9 +170,11 @@ export function Yandex21Map({ const container = containerRef.current; if (!mapReady || !container) return; const handler = (ev: MouseEvent) => { - const el = (ev.target as HTMLElement | null)?.closest?.('[data-gps-marker-id]') as HTMLElement | null; + const el = (ev.target as HTMLElement | null)?.closest?.('[data-gps-action]') as HTMLElement | null; if (!el) return; - const marker = markersByIdRef.current.get(el.dataset.gpsMarkerId || ''); + const action = el.dataset.gpsAction || ''; + if (!action.startsWith('open:')) return; + const marker = markersByIdRef.current.get(action.slice(5)); if (marker?.onClick) { marker.onClick(); mapRef.current?.balloon.close(); diff --git a/client/src/components/gps/marker-html.ts b/client/src/components/gps/marker-html.ts index 58bc1b4..84fee0c 100644 --- a/client/src/components/gps/marker-html.ts +++ b/client/src/components/gps/marker-html.ts @@ -94,9 +94,10 @@ export function gpsMarkerHtml(marker: GpsMapMarker): string { } } - // data-gps-marker-id: делегированный обработчик контейнера карты ловит клики - // по любому маркеру (надёжнее нативных событий placemark/divIcon) - return `
${body}${label}
`; + // data-* атрибута на корне НЕТ намеренно: делегированный обработчик ловит + // только кнопки с data-gps-action (список кластера, «Открыть задачу» в попапе), + // иначе клик по точке сразу вызывал onClick и глушил открытие попапа + return `
${body}${label}
`; } /** @@ -119,7 +120,7 @@ export function gpsClusterHtml(count: number | string): string { export function gpsClusterListHtml(markers: GpsMapMarker[]): string { const rows = markers .map( - (m) => `` diff --git a/client/src/pages/gps/MapTab.tsx b/client/src/pages/gps/MapTab.tsx index 332d9d9..2e83b35 100644 --- a/client/src/pages/gps/MapTab.tsx +++ b/client/src/pages/gps/MapTab.tsx @@ -236,7 +236,7 @@ export function GpsMapTab({ onShowRoute }: { onShowRoute: (assetId: number) => v const st = shortTitle(t.title); // Попап по клику: название (две строки) + кнопка «Открыть задачу». // Работает и при выключенных подписях — название видно по клику. - const popup = `
${esc(st.line1)}${st.line2 ? `
${esc(st.line2)}
` : ''}
`; + const popup = `
${esc(st.line1)}${st.line2 ? `
${esc(st.line2)}
` : ''}
`; markers.push({ id: `task-${t.id}`, lat: geo.lat,