节点移出地图不消失
This commit is contained in:
@@ -19,7 +19,7 @@ import MeshMap from './components/MeshMap.vue'
|
|||||||
import NodeDetailedPage from './components/NodeDetailedPage.vue'
|
import NodeDetailedPage from './components/NodeDetailedPage.vue'
|
||||||
import NodeListPanel from './components/NodeListPanel.vue'
|
import NodeListPanel from './components/NodeListPanel.vue'
|
||||||
import { fallbackMapSource, loadEnabledMapSources } from './mapSource'
|
import { fallbackMapSource, loadEnabledMapSources } from './mapSource'
|
||||||
import type { AdminUser, HealthStatus, MapBoundsChangePayload, MapBoundsQuery, MapRenderable, MapViewportItem, NodeInfo, NodeInfoById, PositionRecord, PublicMapTileSource, TextMessage } from './types'
|
import type { AdminUser, HealthStatus, MapBoundsChangePayload, MapBoundsQuery, MapRenderable, MapViewportItem, MapViewportPoint, NodeInfo, NodeInfoById, PositionRecord, PublicMapTileSource, TextMessage } from './types'
|
||||||
|
|
||||||
const currentPath = window.location.pathname
|
const currentPath = window.location.pathname
|
||||||
const adminPath = currentPath
|
const adminPath = currentPath
|
||||||
@@ -41,6 +41,7 @@ const selectedNodeId = ref<string | null>(null)
|
|||||||
const health = ref<HealthStatus | null>(null)
|
const health = ref<HealthStatus | null>(null)
|
||||||
const nodeInfoSource = ref<NodeInfo[]>([])
|
const nodeInfoSource = ref<NodeInfo[]>([])
|
||||||
const mapViewportItems = ref<MapViewportItem[]>([])
|
const mapViewportItems = ref<MapViewportItem[]>([])
|
||||||
|
const selectedMapPoint = ref<MapViewportPoint | null>(null)
|
||||||
const mapViewportMode = ref<'points' | 'clusters'>('points')
|
const mapViewportMode = ref<'points' | 'clusters'>('points')
|
||||||
const pagedNodeInfo = ref<NodeInfo[]>([])
|
const pagedNodeInfo = ref<NodeInfo[]>([])
|
||||||
const nodePage = ref(1)
|
const nodePage = ref(1)
|
||||||
@@ -82,7 +83,13 @@ const nodesById = computed<NodeInfoById>(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const mapItems = computed<MapRenderable[]>(() => {
|
const mapItems = computed<MapRenderable[]>(() => {
|
||||||
return mapViewportItems.value
|
const items = mapViewportItems.value
|
||||||
|
const selectedItem = selectedMapPoint.value
|
||||||
|
const renderItems = selectedItem && selectedItem.type === 'point' && !items.some((item) => item.type === 'point' && item.node_id === selectedItem.node_id)
|
||||||
|
? [...items, selectedItem]
|
||||||
|
: items
|
||||||
|
|
||||||
|
return renderItems
|
||||||
.filter((item) => item.type === 'cluster' || (item.latitude != null && item.longitude != null))
|
.filter((item) => item.type === 'cluster' || (item.latitude != null && item.longitude != null))
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
if (item.type === 'cluster') {
|
if (item.type === 'cluster') {
|
||||||
@@ -187,6 +194,21 @@ function isSameJSON(left: unknown, right: unknown): boolean {
|
|||||||
return JSON.stringify(left) === JSON.stringify(right)
|
return JSON.stringify(left) === JSON.stringify(right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isMapViewportPoint(item: MapViewportItem): item is MapViewportPoint {
|
||||||
|
return item.type === 'point'
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectNode(nodeId: string) {
|
||||||
|
selectedNodeId.value = nodeId
|
||||||
|
const item = mapViewportItems.value.find((item): item is MapViewportPoint => isMapViewportPoint(item) && item.node_id === nodeId)
|
||||||
|
selectedMapPoint.value = item ?? (selectedMapPoint.value?.node_id === nodeId ? selectedMapPoint.value : null)
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearSelectedNode() {
|
||||||
|
selectedNodeId.value = null
|
||||||
|
selectedMapPoint.value = null
|
||||||
|
}
|
||||||
|
|
||||||
async function loadInitialChatMessages() {
|
async function loadInitialChatMessages() {
|
||||||
const response = await getTextMessages(chatPageSize, 0)
|
const response = await getTextMessages(chatPageSize, 0)
|
||||||
messages.value = toChronological(response.items)
|
messages.value = toChronological(response.items)
|
||||||
@@ -248,6 +270,12 @@ async function loadMapReportsForBounds(bounds: MapBoundsQuery, zoom: number, sho
|
|||||||
if (!isSameJSON(mapViewportItems.value, response.items)) {
|
if (!isSameJSON(mapViewportItems.value, response.items)) {
|
||||||
mapViewportItems.value = response.items
|
mapViewportItems.value = response.items
|
||||||
}
|
}
|
||||||
|
const selectedItem = selectedNodeId.value
|
||||||
|
? response.items.find((item): item is MapViewportPoint => isMapViewportPoint(item) && item.node_id === selectedNodeId.value)
|
||||||
|
: null
|
||||||
|
if (selectedItem) {
|
||||||
|
selectedMapPoint.value = selectedItem
|
||||||
|
}
|
||||||
mapViewportMode.value = response.mode
|
mapViewportMode.value = response.mode
|
||||||
mapReportTotal.value = response.total
|
mapReportTotal.value = response.total
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -391,7 +419,7 @@ async function removeNodeFromLocalState(nodeId: string) {
|
|||||||
pagedNodeInfo.value = pagedNodeInfo.value.filter((node) => node.node_id !== nodeId)
|
pagedNodeInfo.value = pagedNodeInfo.value.filter((node) => node.node_id !== nodeId)
|
||||||
mapViewportItems.value = mapViewportItems.value.filter((item) => item.type === 'cluster' || item.node_id !== nodeId)
|
mapViewportItems.value = mapViewportItems.value.filter((item) => item.type === 'cluster' || item.node_id !== nodeId)
|
||||||
if (selectedNodeId.value === nodeId) {
|
if (selectedNodeId.value === nodeId) {
|
||||||
selectedNodeId.value = null
|
clearSelectedNode()
|
||||||
}
|
}
|
||||||
await loadNodePage(nodePage.value, false)
|
await loadNodePage(nodePage.value, false)
|
||||||
}
|
}
|
||||||
@@ -587,7 +615,7 @@ onBeforeUnmount(() => {
|
|||||||
:loading-older="chatLoadingOlder"
|
:loading-older="chatLoadingOlder"
|
||||||
:has-more-messages="chatHasMore"
|
:has-more-messages="chatHasMore"
|
||||||
:is-admin="!!adminUser"
|
:is-admin="!!adminUser"
|
||||||
@select-node="selectedNodeId = $event"
|
@select-node="selectNode"
|
||||||
@load-older="loadOlderMessages"
|
@load-older="loadOlderMessages"
|
||||||
@delete-message="requestDeleteMessage"
|
@delete-message="requestDeleteMessage"
|
||||||
@delete-and-block-node="requestDeleteAndBlockNode"
|
@delete-and-block-node="requestDeleteAndBlockNode"
|
||||||
@@ -602,8 +630,8 @@ onBeforeUnmount(() => {
|
|||||||
:map-sources="mapSources"
|
:map-sources="mapSources"
|
||||||
@map-source-change="selectMapSource"
|
@map-source-change="selectMapSource"
|
||||||
@bounds-change="handleMapBoundsChange"
|
@bounds-change="handleMapBoundsChange"
|
||||||
@select-node="selectedNodeId = $event"
|
@select-node="selectNode"
|
||||||
@clear-node="selectedNodeId = null"
|
@clear-node="clearSelectedNode"
|
||||||
@delete-node="requestDeleteNode"
|
@delete-node="requestDeleteNode"
|
||||||
@delete-and-block-node="requestDeleteAndBlockNode"
|
@delete-and-block-node="requestDeleteAndBlockNode"
|
||||||
/>
|
/>
|
||||||
@@ -617,7 +645,7 @@ onBeforeUnmount(() => {
|
|||||||
:total="nodeTotal"
|
:total="nodeTotal"
|
||||||
:loading="nodePageLoading || loading"
|
:loading="nodePageLoading || loading"
|
||||||
:is-admin="!!adminUser"
|
:is-admin="!!adminUser"
|
||||||
@select-node="selectedNodeId = $event"
|
@select-node="selectNode"
|
||||||
@page-change="loadNodePage"
|
@page-change="loadNodePage"
|
||||||
@delete-node="requestDeleteNode"
|
@delete-node="requestDeleteNode"
|
||||||
@delete-and-block-node="requestDeleteAndBlockNode"
|
@delete-and-block-node="requestDeleteAndBlockNode"
|
||||||
|
|||||||
Reference in New Issue
Block a user