diff --git a/index.html b/index.html index 2e173de..8db8a1b 100644 --- a/index.html +++ b/index.html @@ -31,6 +31,6 @@ - + diff --git a/src/pathInfo.json b/src/pathInfo.json index 4736c63..73bcd64 100644 --- a/src/pathInfo.json +++ b/src/pathInfo.json @@ -19,16 +19,6 @@ "/src/view/energyMonitor/carbonAnalysis.vue": "CarbonAnalysis", "/src/view/energyMonitor/index.vue": "EnergyMonitor", "/src/view/energyMonitor/targetConfig.vue": "EnergyTargetConfig", - "/src/view/equipment/gateway/index.vue": "Index", - "/src/view/equipment/index.vue": "Equipment", - "/src/view/equipment/list/components/detail/components/alarm/index.vue": "Index", - "/src/view/equipment/list/components/detail/components/config/index.vue": "Index", - "/src/view/equipment/list/components/detail/components/info/index.vue": "Index", - "/src/view/equipment/list/components/detail/components/line/index.vue": "Index", - "/src/view/equipment/list/components/detail/components/trend/index.vue": "Index", - "/src/view/equipment/list/components/detail/index.vue": "Index", - "/src/view/equipment/list/components/list/index.vue": "Index", - "/src/view/equipment/list/index.vue": "Index", "/src/view/error/index.vue": "Error", "/src/view/error/reload.vue": "Reload", "/src/view/largeScreen/index.vue": "Index", diff --git a/src/view/equipment/gateway/index.vue b/src/view/equipment/gateway/index.vue deleted file mode 100644 index c5de08b..0000000 --- a/src/view/equipment/gateway/index.vue +++ /dev/null @@ -1,115 +0,0 @@ - - - - - diff --git a/src/view/equipment/index.vue b/src/view/equipment/index.vue deleted file mode 100644 index 8d528c9..0000000 --- a/src/view/equipment/index.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/view/equipment/list/components/detail/components/alarm/index.vue b/src/view/equipment/list/components/detail/components/alarm/index.vue deleted file mode 100644 index 2503af6..0000000 --- a/src/view/equipment/list/components/detail/components/alarm/index.vue +++ /dev/null @@ -1,173 +0,0 @@ - - - - - diff --git a/src/view/equipment/list/components/detail/components/config/index.vue b/src/view/equipment/list/components/detail/components/config/index.vue deleted file mode 100644 index 8b769b4..0000000 --- a/src/view/equipment/list/components/detail/components/config/index.vue +++ /dev/null @@ -1,281 +0,0 @@ - - - - - diff --git a/src/view/equipment/list/components/detail/components/info/index.vue b/src/view/equipment/list/components/detail/components/info/index.vue deleted file mode 100644 index d242890..0000000 --- a/src/view/equipment/list/components/detail/components/info/index.vue +++ /dev/null @@ -1,299 +0,0 @@ - - - - - diff --git a/src/view/equipment/list/components/detail/components/line/index.vue b/src/view/equipment/list/components/detail/components/line/index.vue deleted file mode 100644 index b2d7bbb..0000000 --- a/src/view/equipment/list/components/detail/components/line/index.vue +++ /dev/null @@ -1,177 +0,0 @@ - - - - - diff --git a/src/view/equipment/list/components/detail/components/trend/index.vue b/src/view/equipment/list/components/detail/components/trend/index.vue deleted file mode 100644 index 092cfec..0000000 --- a/src/view/equipment/list/components/detail/components/trend/index.vue +++ /dev/null @@ -1,837 +0,0 @@ - - - - - diff --git a/src/view/equipment/list/components/detail/index.vue b/src/view/equipment/list/components/detail/index.vue deleted file mode 100644 index d11b339..0000000 --- a/src/view/equipment/list/components/detail/index.vue +++ /dev/null @@ -1,129 +0,0 @@ - - - - - diff --git a/src/view/equipment/list/components/list/index.vue b/src/view/equipment/list/components/list/index.vue deleted file mode 100644 index c7e3e0e..0000000 --- a/src/view/equipment/list/components/list/index.vue +++ /dev/null @@ -1,409 +0,0 @@ - - - - - diff --git a/src/view/equipment/list/index.vue b/src/view/equipment/list/index.vue deleted file mode 100644 index 37536dc..0000000 --- a/src/view/equipment/list/index.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/src/view/largeScreen2/index.vue b/src/view/largeScreen2/index.vue index 27afda6..fa98a74 100644 --- a/src/view/largeScreen2/index.vue +++ b/src/view/largeScreen2/index.vue @@ -19,7 +19,7 @@
- +
@@ -79,7 +79,7 @@
- +
@@ -214,7 +214,7 @@
- +
@@ -234,7 +234,7 @@
- +
@@ -261,7 +261,7 @@
- +
@@ -276,7 +276,7 @@ import { onMounted, onBeforeUnmount, ref, nextTick, computed } from 'vue' import { useRouter } from 'vue-router' - import ECharts from 'vue-echarts' + import VChart from 'vue-echarts' import { getAlarmPendingOption, getAlertDistributionOption, @@ -295,7 +295,8 @@ const tableHeight = ref(180) let resizeObserver = null const mapInstance = ref(null) - const markers = ref([]) + let markerCluster = null + let deviceInfoWindow = null const mapDisplayMode = ref('3D') const mapModeOptions = [ { label: '3D', value: '3D' }, @@ -417,7 +418,6 @@ const calculateTableHeight = () => { nextTick(() => { - console.log('bottomRef.value', bottomRef.value.offsetHeight) if (bottomRef.value) { tableHeight.value = bottomRef.value.offsetHeight } @@ -433,11 +433,11 @@ getDeviceChangeList() getProjectCategoryGroup() - getDeviceGatewayList().finally(() => { - nextTick(() => { - initMap() - }) + nextTick(() => { + initMap() }) + + getDeviceGatewayList() }) const getDeviceWarningList = () => { @@ -491,7 +491,8 @@ nextTick(() => { if (mapInstance.value) { mapInstance.value.setZoomAndCenter(getCurrentMapZoom(), getValidDeviceCenter(), true) - addMarkers() + mapInstance.value.resize?.() + initMarkerCluster() } }) } @@ -654,64 +655,135 @@ } mapInstance.value.on('complete', () => { - console.log('地图加载完成') - if (devices.value && devices.value.length > 0) { - addMarkers() - } + mapInstance.value?.resize?.() + initMarkerCluster() }) bindMapInfoWindowClick() } - const addMarkers = () => { - console.log('addMarkers 被调用') - console.log('mapInstance.value:', mapInstance.value) - console.log('devices.value:', devices.value) + const clearMarkerCluster = () => { + if (!markerCluster) return - if (!mapInstance.value || !devices.value || devices.value.length === 0) { - console.log('条件不满足,返回') + try { + if (typeof markerCluster.setMap === 'function') { + markerCluster.setMap(null) + } else if (typeof markerCluster.destroy === 'function') { + markerCluster.destroy() + } + } catch (err) { + console.warn('[largeScreen2] 清理点聚合失败', err) + } + + markerCluster = null + } + + const getClusterPointData = (context) => { + if (Array.isArray(context.data)) return context.data[0] + return context.data + } + + const openDeviceInfoWindow = (device, position) => { + if (!mapInstance.value || !device) return + + if (!deviceInfoWindow) { + deviceInfoWindow = new AMap.InfoWindow({ + offset: new AMap.Pixel(0, -16) + }) + } + + deviceInfoWindow.setContent(createInfoWindowContent(device)) + deviceInfoWindow.open(mapInstance.value, position) + } + + const buildClusterPoints = () => { + return devices.value + .map((device) => { + const longitude = Number(device.gatewayLong) + const latitude = Number(device.gatewayLat) + if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) return null + return { + lnglat: [longitude, latitude], + extData: device + } + }) + .filter(Boolean) + } + + const renderClusterMarker = (context) => { + const count = context.count + const size = Math.min(56, Math.max(36, 30 + Math.log10(count + 1) * 10)) + const half = size / 2 + + context.marker.setContent(` +
+ + ${count} +
+ `) + context.marker.setOffset(new AMap.Pixel(-half, -half)) + } + + const renderSingleMarker = (context) => { + const pointData = getClusterPointData(context) + const device = pointData?.extData + if (!device || !context.marker) return + + const markerStatus = getDeviceMarkerClass(device.status) + + context.marker.setContent( + `
` + ) + context.marker.setOffset(new AMap.Pixel(-12, -12)) + context.marker.setTitle(getDeviceLocationName(device)) + context.marker.setExtData?.(device) + context.marker.off?.('click') + context.marker.on('click', () => { + openDeviceInfoWindow(device, context.marker.getPosition()) + }) + } + + const createMarkerCluster = () => { + const points = buildClusterPoints() + if (!mapInstance.value || !points.length) return + + clearMarkerCluster() + + try { + markerCluster = new AMap.MarkerCluster(mapInstance.value, points, { + gridSize: 72, + maxZoom: 17, + renderClusterMarker, + renderMarker: renderSingleMarker + }) + } catch (err) { + console.error('[largeScreen2] 点聚合创建失败', err) + markerCluster = null + } + } + + const initMarkerCluster = () => { + if (!mapInstance.value || !devices.value?.length) return + + const run = () => { + if (typeof AMap.MarkerCluster !== 'function') { + console.warn('[largeScreen2] MarkerCluster 插件未加载') + return + } + createMarkerCluster() + } + + if (typeof mapInstance.value.plugin === 'function') { + mapInstance.value.plugin(['AMap.MarkerCluster'], run) return } - // 清除之前的标记 - markers.value.forEach((marker) => { - mapInstance.value.remove(marker) - }) - markers.value = [] + if (typeof AMap.plugin === 'function') { + AMap.plugin(['AMap.MarkerCluster'], run) + return + } - console.log('开始渲染标记,数量:', devices.value.length) - - // 先只渲染前20个点测试 - const testData = devices.value.slice(0, 20) - - testData.forEach((device) => { - // console.log(`渲染第 ${index} 个点:`, device) - - const longitude = Number(device.gatewayLong) - const latitude = Number(device.gatewayLat) - if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) return - - const markerStatus = getDeviceMarkerClass(device.status) - const marker = new AMap.Marker({ - position: [longitude, latitude], - title: getDeviceLocationName(device), - content: `
`, - offset: new AMap.Pixel(-12, -12) - }) - - const infoWindow = new AMap.InfoWindow({ - content: createInfoWindowContent(device) - }) - - marker.on('click', () => { - infoWindow.open(mapInstance.value, marker.getPosition()) - }) - - mapInstance.value.add(marker) - markers.value.push(marker) - }) - - console.log('渲染完成,标记数量:', markers.value.length) + run() } const getDeviceLocationName = (device) => { @@ -752,10 +824,8 @@ } if (mapInstance.value) { - markers.value.forEach((marker) => { - mapInstance.value.remove(marker) - }) - markers.value = [] + clearMarkerCluster() + deviceInfoWindow = null hideBuildingLayer() hideSatelliteLayers() buildingLayer = null @@ -799,7 +869,7 @@ display: flex; flex-direction: column; padding: px2vw(90) 0; - width: px2vw(563); + width: px2vw(460); height: 100%; background: url('@/assets/img/largeScreen2/background-left.png') no-repeat; background-size: 100% 100%; @@ -995,6 +1065,7 @@ } .center { flex: 1; + min-height: 0; display: flex; flex-direction: column; padding-bottom: px2vh(30); @@ -1137,7 +1208,7 @@ } } .right { - width: px2vw(563); + width: px2vw(460); height: 100%; background: url('@/assets/img/largeScreen2/background-right.png') no-repeat; background-size: 100% 100%; @@ -1350,6 +1421,7 @@ .map-card { flex: 1; + min-height: 0; padding: 0; overflow: hidden; } @@ -1375,6 +1447,9 @@ .map-container-full { position: relative; flex: 1; + min-height: 0; + width: 100%; + height: 100%; display: flex; flex-direction: column; padding: 0; @@ -2215,6 +2290,61 @@ color: rgba(220, 243, 255, 0.58); } + .tech-map-cluster-marker { + position: relative; + display: flex; + align-items: center; + justify-content: center; + pointer-events: auto; + } + + .tech-map-cluster-pulse { + position: absolute; + inset: 0; + border-radius: 50%; + border: 1px solid rgba(0, 212, 255, 0.72); + background: rgba(0, 212, 255, 0.12); + box-shadow: 0 0 18px rgba(0, 212, 255, 0.35); + animation: techMapClusterPulse 2.4s ease-out infinite; + } + + .tech-map-cluster-core { + position: relative; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + min-width: 62%; + min-height: 62%; + padding: 0 4px; + border-radius: 50%; + color: #031424; + font-size: 13px; + font-weight: 700; + line-height: 1; + background: linear-gradient(135deg, #67e8f9, var(--tech-primary)); + box-shadow: + 0 0 16px rgba(0, 212, 255, 0.45), + inset 0 1px 0 rgba(255, 255, 255, 0.34); + } + + @keyframes techMapClusterPulse { + 0% { + transform: scale(0.92); + opacity: 0.95; + } + + 70% { + transform: scale(1.18); + opacity: 0.2; + } + + 100% { + transform: scale(1.24); + opacity: 0; + } + } + .tech-map-info-window { min-width: 180px; padding: 10px 12px; @@ -2278,6 +2408,7 @@ .top2 { flex: 1; + min-height: 0; display: flex; flex-direction: column; } @@ -2374,11 +2505,11 @@ } .container .left::before { - right: px2vw(18); + right: 0; } .container .right::before { - left: px2vw(18); + left: 0; } .container .left .module-card, @@ -2500,6 +2631,8 @@ .container .center .top2 { position: relative; + flex: 1; + min-height: 0; margin: 0 px2vw(16); border: 1px solid rgba(0, 212, 255, 0.18); border-radius: px2vw(16); @@ -2544,10 +2677,11 @@ &::before { content: 'ALARM MONITOR'; position: absolute; - top: px2vh(13); - left: px2vw(32); - color: rgba(0, 212, 255, 0.58); - font-size: px2vw(12); + top: px2vh(20); + left: 50%; + transform: translateX(-50%); + color: rgba(0, 212, 255); + font-size: px2vw(18); letter-spacing: px2vw(6); text-shadow: 0 0 px2vw(8) rgba(0, 212, 255, 0.7); } diff --git a/src/view/masterStation/equipment/components/detail/components/trend/index.vue b/src/view/masterStation/equipment/components/detail/components/trend/index.vue index 0fb8fc0..842e716 100644 --- a/src/view/masterStation/equipment/components/detail/components/trend/index.vue +++ b/src/view/masterStation/equipment/components/detail/components/trend/index.vue @@ -18,8 +18,12 @@
线路列表 - 一键分闸 - 一键合闸 + 一键分闸 + 一键合闸
@@ -73,7 +77,7 @@
电气子节点: - 点击展开 + --
警情状态: @@ -101,10 +105,20 @@
- 合闸 - 分闸
@@ -584,7 +598,9 @@ --el-button-active-text-color: #d1fae5; --el-button-active-border-color: rgba(52, 211, 153, 0.95); --el-button-active-bg-color: rgba(16, 185, 129, 0.42); - box-shadow: inset 0 0 12px rgba(52, 211, 153, 0.12), 0 0 10px rgba(52, 211, 153, 0.12); + box-shadow: + inset 0 0 12px rgba(52, 211, 153, 0.12), + 0 0 10px rgba(52, 211, 153, 0.12); } :deep(.switch-action-button.el-button--danger.is-plain) { @@ -597,7 +613,9 @@ --el-button-active-text-color: #fee2e2; --el-button-active-border-color: rgba(248, 113, 113, 0.95); --el-button-active-bg-color: rgba(239, 68, 68, 0.42); - box-shadow: inset 0 0 12px rgba(248, 113, 113, 0.12), 0 0 10px rgba(248, 113, 113, 0.12); + box-shadow: + inset 0 0 12px rgba(248, 113, 113, 0.12), + 0 0 10px rgba(248, 113, 113, 0.12); } :deep(.switch-action-button.is-disabled), diff --git a/src/view/privateEquipment/equipment/components/detail/components/trend/index.vue b/src/view/privateEquipment/equipment/components/detail/components/trend/index.vue index 0fb8fc0..842e716 100644 --- a/src/view/privateEquipment/equipment/components/detail/components/trend/index.vue +++ b/src/view/privateEquipment/equipment/components/detail/components/trend/index.vue @@ -18,8 +18,12 @@
线路列表 - 一键分闸 - 一键合闸 + 一键分闸 + 一键合闸
@@ -73,7 +77,7 @@
电气子节点: - 点击展开 + --
警情状态: @@ -101,10 +105,20 @@
- 合闸 - 分闸
@@ -584,7 +598,9 @@ --el-button-active-text-color: #d1fae5; --el-button-active-border-color: rgba(52, 211, 153, 0.95); --el-button-active-bg-color: rgba(16, 185, 129, 0.42); - box-shadow: inset 0 0 12px rgba(52, 211, 153, 0.12), 0 0 10px rgba(52, 211, 153, 0.12); + box-shadow: + inset 0 0 12px rgba(52, 211, 153, 0.12), + 0 0 10px rgba(52, 211, 153, 0.12); } :deep(.switch-action-button.el-button--danger.is-plain) { @@ -597,7 +613,9 @@ --el-button-active-text-color: #fee2e2; --el-button-active-border-color: rgba(248, 113, 113, 0.95); --el-button-active-bg-color: rgba(239, 68, 68, 0.42); - box-shadow: inset 0 0 12px rgba(248, 113, 113, 0.12), 0 0 10px rgba(248, 113, 113, 0.12); + box-shadow: + inset 0 0 12px rgba(248, 113, 113, 0.12), + 0 0 10px rgba(248, 113, 113, 0.12); } :deep(.switch-action-button.is-disabled),