Procházet zdrojové kódy

Cesium文件修改

WQQ před 6 dny
rodič
revize
8a85095f62
1 změnil soubory, kde provedl 375 přidání a 307 odebrání
  1. 375 307
      src/components/CesiumMap.vue

+ 375 - 307
src/components/CesiumMap.vue

@@ -1,13 +1,10 @@
 <template>
-  <div id="cesiumContainer" class="cesium-ignore-autofit"
-    style="width: 100%; height: 100%; position: relative; z-index: 1; transform: none !important; zoom: 1 !important;">
-  </div>
-
+  <div id="cesiumContainer" class="cesium-ignore-autofit" style="width: 100%; height: 100%; position: relative; z-index: 1; transform: none !important; zoom: 1 !important;"></div>
+  
   <!-- POI详情弹窗 -->
   <div v-if="showPopup" class="poi-popup" :style="popupStyle">
     <div class="popup-header">
-      <span class="popup-title">{{ poiData.name }} <a href="#" class="popup-detail"
-          @click.prevent="goToTwinStation">详情</a></span>
+      <span class="popup-title">{{ poiData.name }} <a href="#" class="popup-detail" @click.prevent="goToTwinStation">详情</a></span>
       <button class="popup-close" @click="closePopup">×</button>
     </div>
     <div class="popup-content">
@@ -26,335 +23,404 @@
   </div>
 </template>
 
-<script>
+<script setup>
+import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
 import * as Cesium from 'cesium'
 import 'cesium/Build/CesiumUnminified/Widgets/widgets.css'
+import { useRouter } from 'vue-router'
 
-export default {
-  name: 'CesiumMap',
-  props: {
-    simulationTime: {
-      type: Number,
-      default: 0
-    },
-    simulationData: {
-      type: Object,
-      default: () => ({})
-    }
-  },
-  data() {
-    return {
-      viewer: null,
-      showPopup: false,
-      popupPosition: { x: 0, y: 0 },
-      poiData: {
-        name: '黑林水文站',
-        waterLevel: '3.25',
-        flow: '12.5',
-        rainfall: '0.5',
-        historyWaterLevel: '3.10',
-        historyFlow: '11.8',
-        device: 'HL-Sensor-001'
-      },
-      blinkInterval: null,
-      heilinEntity: null,
-      reservoirEntity: null
-    }
-  },
-  computed: {
-    popupStyle() {
-      return {
-        left: this.popupPosition.x + 'px',
-        top: this.popupPosition.y + 'px'
-      }
-    }
-  },
-  watch: {
-    simulationData: {
-      handler(newData) {
-        this.$nextTick(() => {
-          this.updateMapMarkers(newData)
-        })
-      },
-      deep: true,
-      immediate: true
-    }
+const emit = defineEmits(['toggleMap'])
+
+const viewer = ref(null)
+const showPopup = ref(false)
+const popupPosition = ref({ x: 0, y: 0 })
+
+const props = defineProps({
+  simulationTime: {
+    type: Number,
+    default: 0
   },
-  methods: {
-    addPoiMarker() {
-      const heilinPosition = Cesium.Cartesian3.fromDegrees(118.8770798, 35.0320627)
-
-      const clickEntity = this.viewer.entities.add({
-        id: 'heilin-station-click',
-        position: heilinPosition,
-        point: {
-          pixelSize: 30,
-          color: Cesium.Color.TRANSPARENT,
-          outlineColor: Cesium.Color.TRANSPARENT,
-          outlineWidth: 0
-        }
-      })
+  simulationData: {
+    type: Object,
+    default: () => ({})
+  }
+})
 
-      this.heilinEntity = this.viewer.entities.add({
-        id: 'heilin-station',
-        position: heilinPosition,
-        billboard: {
-          image: '/src/assets/images/水文站.png',
-          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
-          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
-          pixelOffset: new Cesium.Cartesian2(0, -15),
-          scale: 0.8,
-          width: 30,
-          height: 37.5,
-          disableDepthTestDistance: Number.POSITIVE_INFINITY
-        },
-        label: {
-          text: `水位 ${this.simulationData.heilinStation?.waterLevel || '3.25'}m\n流量 ${this.simulationData.heilinStation?.flow || '12.5'}m³/s\n降雨量 ${this.simulationData.heilinStation?.rainfall || '0.5'}mm/h`,
-          font: 'bold 14px 黑体',
-          fillColor: Cesium.Color.WHITE,
-          outlineColor: Cesium.Color.fromCssColorString('#003860'),
-          outlineWidth: 2,
-          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
-          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
-          horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
-          pixelOffset: new Cesium.Cartesian2(0, -30),
-          showBackground: true,
-          backgroundColor: new Cesium.Color(0, 0.3, 0.5, 0.7),
-          backgroundPadding: new Cesium.Cartesian2(8, 4),
-          disableDepthTestDistance: Number.POSITIVE_INFINITY
-        }
-      })
+const router = useRouter()
 
-      this.viewer.entities.add({
-        id: 'heilin-station-title',
-        position: heilinPosition,
-        label: {
-          text: '黑林水文站',
-          font: 'bold 14px sans-serif',
-          fillColor: Cesium.Color.WHITE,
-          outlineColor: Cesium.Color.fromCssColorString('#003860'),
-          outlineWidth: 2,
-          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
-          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
-          horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
-          pixelOffset: new Cesium.Cartesian2(0, -85),
-          showBackground: true,
-          backgroundColor: new Cesium.Color(0, 0.2, 0.4, 0.9),
-          backgroundPadding: new Cesium.Cartesian2(22, 4),
-          disableDepthTestDistance: Number.POSITIVE_INFINITY
-        }
-      })
+const DESIGN_WIDTH = 1920
+const DESIGN_HEIGHT = 1080
 
-      const reservoirPosition = Cesium.Cartesian3.fromDegrees(118.9540555, 34.9355329)
-
-      this.reservoirEntity = this.viewer.entities.add({
-        id: 'tashan-reservoir',
-        position: reservoirPosition,
-        billboard: {
-          image: '/src/assets/images/水库蓝.png',
-          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
-          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
-          pixelOffset: new Cesium.Cartesian2(0, -15),
-          scale: 0.8,
-          width: 30,
-          height: 30,
-          disableDepthTestDistance: Number.POSITIVE_INFINITY
-        },
-        label: {
-          text: `库水位 ${this.simulationData.reservoir?.waterLevel || '18.5'}m\n库容 ${this.simulationData.reservoir?.storage || '2350.8'}万m³\n汛限 20.0m`,
-          font: 'bold 14px 黑体',
-          fillColor: Cesium.Color.WHITE,
-          outlineColor: Cesium.Color.fromCssColorString('#003860'),
-          outlineWidth: 2,
-          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
-          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
-          horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
-          pixelOffset: new Cesium.Cartesian2(0, -30),
-          showBackground: true,
-          backgroundColor: new Cesium.Color(0, 0.3, 0.5, 0.7),
-          backgroundPadding: new Cesium.Cartesian2(8, 4),
-          disableDepthTestDistance: Number.POSITIVE_INFINITY
-        }
-      })
+const getScaleRatio = () => {
+  return Math.min(window.innerWidth / DESIGN_WIDTH, window.innerHeight / DESIGN_HEIGHT)
+}
 
-      this.viewer.entities.add({
-        id: 'tashan-reservoir-title',
-        position: reservoirPosition,
-        label: {
-          text: '小塔山水库',
-          font: 'bold 14px sans-serif',
-          fillColor: Cesium.Color.WHITE,
-          outlineColor: Cesium.Color.fromCssColorString('#003860'),
-          outlineWidth: 2,
-          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
-          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
-          horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
-          pixelOffset: new Cesium.Cartesian2(0, -85),
-          showBackground: true,
-          backgroundColor: new Cesium.Color(0, 0.2, 0.4, 0.9),
-          backgroundPadding: new Cesium.Cartesian2(22, 4),
-          disableDepthTestDistance: Number.POSITIVE_INFINITY
-        }
-      })
+const poiData = ref({
+  name: '黑林水文站',
+  waterLevel: '3.25',
+  flow: '12.5',
+  rainfall: '0.5',
+  historyWaterLevel: '3.10',
+  historyFlow: '11.8',
+  device: 'HL-Sensor-001'
+})
 
-      const handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
+const popupStyle = computed(() => {
+  return {
+    left: popupPosition.value.x + 'px',
+    top: popupPosition.value.y + 'px'
+  }
+})
 
-      handler.setInputAction((movement) => {
-        const pickedObjects = this.viewer.scene.drillPick(movement.position)
-        for (let i = 0; i < pickedObjects.length; i++) {
-          const pickedObj = pickedObjects[i]
-          if (Cesium.defined(pickedObj) && pickedObj.id) {
-            if (pickedObj.id.id === 'heilin-station' || pickedObj.id.id === 'heilin-station-click') {
-              this.showPopup = true
-              this.popupPosition = { x: movement.position.x - 120, y: movement.position.y - 150 }
+let blinkInterval = null
+
+const addPoiMarker = () => {
+    // 添加黑林水文站POI
+    const heilinPosition = Cesium.Cartesian3.fromDegrees(118.8770798, 35.0320627)
+    
+    // 创建一个不可见的点实体,用于扩大点击区域
+    const clickEntity = viewer.value.entities.add({
+      id: 'heilin-station-click',
+      position: heilinPosition,
+      point: {
+        pixelSize: 30,
+        color: Cesium.Color.TRANSPARENT,
+        outlineColor: Cesium.Color.TRANSPARENT,
+        outlineWidth: 0
+      }
+    })
+    
+    const entity = viewer.value.entities.add({
+      id: 'heilin-station',
+      position: heilinPosition,
+      billboard: {
+        image: '/src/assets/images/水文站.png',
+        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+        pixelOffset: new Cesium.Cartesian2(0, -15),
+        scale: 0.8,
+        width: 30,
+        height: 37.5,
+        disableDepthTestDistance: Number.POSITIVE_INFINITY
+      },
+      label: {
+        text: '水位 3.25m\n流量 12.5m³/s\n降雨量 0.5mm/h',
+        font: 'bold 14px 黑体',
+        fillColor: Cesium.Color.WHITE,
+        outlineColor: Cesium.Color.fromCssColorString('#003860'),
+        outlineWidth: 2,
+        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+        horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
+        pixelOffset: new Cesium.Cartesian2(0, -30),
+        showBackground: true,
+        backgroundColor: new Cesium.Color(0, 0.3, 0.5, 0.7),
+        backgroundPadding: new Cesium.Cartesian2(8, 4),
+        disableDepthTestDistance: Number.POSITIVE_INFINITY
+      }
+    })
+    
+    // 添加标题标签
+    viewer.value.entities.add({
+      id: 'heilin-station-title',
+      position: heilinPosition,
+      label: {
+        text: '黑林水文站',
+        font: 'bold 14px sans-serif',
+        fillColor: Cesium.Color.WHITE,
+        outlineColor: Cesium.Color.fromCssColorString('#003860'),
+        outlineWidth: 2,
+        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+        horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
+        pixelOffset: new Cesium.Cartesian2(0, -85),
+        showBackground: true,
+        backgroundColor: new Cesium.Color(0, 0.2, 0.4, 0.9),
+        backgroundPadding: new Cesium.Cartesian2(22, 4),
+        disableDepthTestDistance: Number.POSITIVE_INFINITY
+      }
+    })
 
-              break
+    // 添加塔山小水库POI
+    const reservoirPosition = Cesium.Cartesian3.fromDegrees(118.9540555, 34.9355329)
+    
+    const reservoirEntity = viewer.value.entities.add({
+      id: 'tashan-reservoir',
+      position: reservoirPosition,
+      billboard: {
+        image: '/src/assets/images/水库蓝.png',
+        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+        pixelOffset: new Cesium.Cartesian2(0, -15),
+        scale: 0.8,
+        width: 30,
+        height: 30,
+        disableDepthTestDistance: Number.POSITIVE_INFINITY
+      },
+      label: {
+        text: '库水位 18.5m\n库容 2350.8万m³\n汛限 20.0m',
+        font: 'bold 14px 黑体',
+        fillColor: Cesium.Color.WHITE,
+        outlineColor: Cesium.Color.fromCssColorString('#003860'),
+        outlineWidth: 2,
+        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+        horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
+        pixelOffset: new Cesium.Cartesian2(0, -30),
+        showBackground: true,
+        backgroundColor: new Cesium.Color(0, 0.3, 0.5, 0.7),
+        backgroundPadding: new Cesium.Cartesian2(8, 4),
+        disableDepthTestDistance: Number.POSITIVE_INFINITY
+      }
+    })
+    
+    // 添加标题标签
+    viewer.value.entities.add({
+      id: 'tashan-reservoir-title',
+      position: reservoirPosition,
+      label: {
+        text: '小塔山水库',
+        font: 'bold 14px sans-serif',
+        fillColor: Cesium.Color.WHITE,
+        outlineColor: Cesium.Color.fromCssColorString('#003860'),
+        outlineWidth: 2,
+        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+        horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
+        pixelOffset: new Cesium.Cartesian2(0, -85),
+        showBackground: true,
+        backgroundColor: new Cesium.Color(0, 0.2, 0.4, 0.9),
+        backgroundPadding: new Cesium.Cartesian2(22, 4),
+        disableDepthTestDistance: Number.POSITIVE_INFINITY
+      }
+    })
+
+    const handler = new Cesium.ScreenSpaceEventHandler(viewer.value.scene.canvas)
+    
+    handler.setInputAction((movement) => {
+      const scaleRatio = getScaleRatio()
+      const correctedX = movement.position.x / scaleRatio
+      const correctedY = movement.position.y / scaleRatio
+      
+      const pickedObjects = viewer.value.scene.drillPick(new Cesium.Cartesian2(correctedX, correctedY))
+      for (let i = 0; i < pickedObjects.length; i++) {
+        const pickedObj = pickedObjects[i]
+        if (Cesium.defined(pickedObj) && pickedObj.id) {
+          if (pickedObj.id.id === 'heilin-station' || pickedObj.id.id === 'heilin-station-click') {
+            showPopup.value = true
+            popupPosition.value = { 
+              x: movement.position.x - 120, 
+              y: movement.position.y - 150 
             }
+            break
           }
         }
-      }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
-    },
-    updateMapMarkers(data) {
-      if (!data) return
-
-      if (this.heilinEntity && data.heilinStation) {
-        const waterLevel = data.heilinStation.waterLevel || '3.25'
-        const flow = data.heilinStation.flow || '12.5'
-        const rainfall = data.heilinStation.rainfall || '0.5'
-
-        this.heilinEntity.label.text = `水位 ${waterLevel}m\n流量 ${flow}m³/s\n降雨量 ${rainfall}mm/h`
-        this.poiData.waterLevel = waterLevel
-        this.poiData.flow = flow
-        this.poiData.rainfall = rainfall
       }
+    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
+
+    // 移除闪烁效果
+    entity.billboard.scale = 0.8
+    reservoirEntity.billboard.scale = 0.8
+    
+    // 立即更新一次标记数据
+    updateMapMarkers()
+  }
 
-      if (this.reservoirEntity && data.reservoir) {
-        const waterLevel = data.reservoir.waterLevel || '18.5'
-        const storage = data.reservoir.storage || '2350.8'
-
-        this.reservoirEntity.label.text = `库水位 ${waterLevel}m\n库容 ${storage}万m³\n汛限 20.0m`
-      }
-    },
-    closePopup() {
-      this.showPopup = false
-    },
-    goToTwinStation() {
-      const heilinPosition = Cesium.Cartesian3.fromDegrees(118.8770798, 35.0320627, 10000)
-      this.viewer.camera.flyTo({
-        destination: heilinPosition,
-        duration: 2.0,
-        easingFunction: Cesium.EasingFunction.SINE_IN_OUT
-      })
-      this.closePopup()
-    }
-  },
-  async mounted() {
-    this.viewer = new Cesium.Viewer('cesiumContainer', {
-      terrainProvider: await Cesium.createWorldTerrainAsync(),
-      animation: false,
-      baseLayerPicker: false,
-      fullscreenButton: false,
-      geocoder: false,
-      homeButton: false,
-      infoBox: false,
-      sceneModePicker: false,
-      selectionIndicator: false,
-      timeline: false,
-      navigationHelpButton: false,
-      navigationInstructionsInitiallyVisible: false,
-      shouldAnimate: false,
-      showRenderLoopErrors: false
-    })
+const updateMapMarkers = () => {
+  if (!viewer.value) return
+  
+  const heilinData = props.simulationData?.heilinStation || {
+    waterLevel: '3.25',
+    flow: '12.5',
+    rainfall: '0.5'
+  }
+  
+  const reservoirData = props.simulationData?.reservoir || {
+    waterLevel: '18.5',
+    storage: '2350.8'
+  }
+  
+  // 更新黑林水文站标签
+  const heilinEntity = viewer.value.entities.getById('heilin-station')
+  if (heilinEntity && heilinEntity.label) {
+    heilinEntity.label.text = `水位 ${heilinData.waterLevel}m\n流量 ${heilinData.flow}m³/s\n降雨量 ${heilinData.rainfall}mm/h`
+  }
+  
+  // 更新小塔山水库标签
+  const reservoirEntity = viewer.value.entities.getById('tashan-reservoir')
+  if (reservoirEntity && reservoirEntity.label) {
+    reservoirEntity.label.text = `库水位 ${reservoirData.waterLevel}m\n库容 ${reservoirData.storage}万m³\n汛限 20.0m`
+  }
+  
+  // 更新弹窗数据
+  if (poiData.value.name === '黑林水文站') {
+    poiData.value.waterLevel = heilinData.waterLevel
+    poiData.value.flow = heilinData.flow
+    poiData.value.rainfall = heilinData.rainfall
+  }
+}
 
-    if (this.viewer.cesiumWidget.creditContainer) {
-      this.viewer.cesiumWidget.creditContainer.style.display = 'none'
-    }
+watch(() => props.simulationData, () => {
+  updateMapMarkers()
+}, { deep: true, immediate: true })
 
-    const toolbar = this.viewer._element.querySelector('.cesium-viewer-toolbar')
-    if (toolbar) toolbar.style.display = 'none'
+const createPoiImage = () => {
+  const canvas = document.createElement('canvas')
+  canvas.width = 40
+  canvas.height = 50
+  const ctx = canvas.getContext('2d')
+  
+  ctx.beginPath()
+  ctx.moveTo(20, 0)
+  ctx.lineTo(40, 30)
+  ctx.lineTo(20, 50)
+  ctx.lineTo(0, 30)
+  ctx.closePath()
+  
+  const gradient = ctx.createRadialGradient(20, 25, 5, 20, 25, 25)
+  gradient.addColorStop(0, '#00ffff')
+  gradient.addColorStop(1, '#0066ff')
+  ctx.fillStyle = gradient
+  ctx.fill()
+  
+  ctx.strokeStyle = '#ffffff'
+  ctx.lineWidth = 2
+  ctx.stroke()
+  
+  return canvas
+}
 
-    const animationContainer = this.viewer._element.querySelector('.cesium-viewer-animationContainer')
-    if (animationContainer) animationContainer.style.display = 'none'
+const closePopup = () => {
+  showPopup.value = false
+}
 
-    const timelineContainer = this.viewer._element.querySelector('.cesium-viewer-timelineContainer')
-    if (timelineContainer) timelineContainer.style.display = 'none'
+const goToTwinStation = () => {
+  // 执行平滑flyto动画到黑林水文站位置
+  const heilinPosition = Cesium.Cartesian3.fromDegrees(118.8770798, 35.0320627, 10000)
+  viewer.value.camera.flyTo({
+    destination: heilinPosition,
+    duration: 2.0,
+    easingFunction: Cesium.EasingFunction.SINE_IN_OUT
+  })
+  
+  // 延迟跳转到水文站详情页面
+  setTimeout(() => {
+    router.push('/heilin-station')
+  }, 2000)
+  
+  closePopup()
+}
 
+onMounted(async () => {
+  viewer.value = new Cesium.Viewer('cesiumContainer', {
+    terrainProvider: await Cesium.createWorldTerrainAsync(),
+    animation: false,
+    baseLayerPicker: false,
+    fullscreenButton: false,
+    geocoder: false,
+    homeButton: false,
+    infoBox: false,
+    sceneModePicker: false,
+    selectionIndicator: false,
+    timeline: false,
+    navigationHelpButton: false,
+    navigationInstructionsInitiallyVisible: false,
+    shouldAnimate: false,
+    showRenderLoopErrors: false
+  })
+  
+  if (viewer.value.cesiumWidget.creditContainer) {
+    viewer.value.cesiumWidget.creditContainer.style.display = 'none'
+  }
+  
+  const toolbar = viewer.value._element.querySelector('.cesium-viewer-toolbar')
+  if (toolbar) toolbar.style.display = 'none'
+  
+  const animationContainer = viewer.value._element.querySelector('.cesium-viewer-animationContainer')
+  if (animationContainer) animationContainer.style.display = 'none'
+  
+  const timelineContainer = viewer.value._element.querySelector('.cesium-viewer-timelineContainer')
+  if (timelineContainer) timelineContainer.style.display = 'none'
+
+  try {
+    // 加载流域边界GeoJSON
+    const response = await fetch('/Heilin.geojson')
+    const geojson = await response.json()
+    
+    const dataSource = await Cesium.GeoJsonDataSource.load(geojson, {
+      stroke: Cesium.Color.fromCssColorString('#00d5ff'),
+      strokeWidth: 3,
+      fill: Cesium.Color.fromCssColorString('#00d5ff').withAlpha(0.1)
+    })
+    
+    viewer.value.dataSources.add(dataSource)
+    
+    // 加载水系GeoJSON
     try {
-      const response = await fetch('/Heilin.geojson')
-      const geojson = await response.json()
-
-      const dataSource = await Cesium.GeoJsonDataSource.load(geojson, {
-        stroke: Cesium.Color.fromCssColorString('#00d5ff'),
-        strokeWidth: 3,
-        fill: Cesium.Color.fromCssColorString('#00d5ff').withAlpha(0.1)
+      const waterResponse = await fetch('/黑林水系.geojson')
+      const waterGeojson = await waterResponse.json()
+      
+      const waterDataSource = await Cesium.GeoJsonDataSource.load(waterGeojson, {
+        stroke: Cesium.Color.fromCssColorString('#62f6fb'),
+        strokeWidth: 2,
+        fill: Cesium.Color.fromCssColorString('#62f6fb').withAlpha(0.2)
       })
-
-      this.viewer.dataSources.add(dataSource)
-
-      try {
-        const waterResponse = await fetch('/黑林水系.geojson')
-        const waterGeojson = await waterResponse.json()
-
-        const waterDataSource = await Cesium.GeoJsonDataSource.load(waterGeojson, {
-          stroke: Cesium.Color.fromCssColorString('#62f6fb'),
-          strokeWidth: 2,
-          fill: Cesium.Color.fromCssColorString('#62f6fb').withAlpha(0.2)
-        })
-
-        this.viewer.dataSources.add(waterDataSource)
-      } catch (waterError) {
-        console.error('加载水系GeoJSON失败:', waterError)
-      }
-
-      try {
-        const reservoirResponse = await fetch('/小塔山水库.geojson')
-        const reservoirGeojson = await reservoirResponse.json()
-
-        const reservoirDataSource = await Cesium.GeoJsonDataSource.load(reservoirGeojson, {
-          stroke: Cesium.Color.fromCssColorString('#00d4ff'),
-          strokeWidth: 2,
-          fill: Cesium.Color.fromCssColorString('#00d4ff').withAlpha(0.3)
-        })
-
-        this.viewer.dataSources.add(reservoirDataSource)
-      } catch (reservoirError) {
-        console.error('加载小塔山水库GeoJSON失败:', reservoirError)
-      }
-
-      const entities = dataSource.entities.values
-      if (entities.length > 0) {
-        let minLat = 90, maxLat = -90, minLon = 180, maxLon = -180
-
-        for (const entity of entities) {
-          if (entity.polygon && entity.polygon.hierarchy) {
-            const hierarchy = entity.polygon.hierarchy.getValue()
-            const positions = hierarchy.positions
-
-            for (const pos of positions) {
-              const cartographic = Cesium.Cartographic.fromCartesian(pos)
-              const lat = Cesium.Math.toDegrees(cartographic.latitude)
-              const lon = Cesium.Math.toDegrees(cartographic.longitude)
-
-              minLat = Math.min(minLat, lat)
-              maxLat = Math.max(maxLat, lat)
-              minLon = Math.min(minLon, lon)
-              maxLon = Math.max(maxLon, lon)
-            }
+      
+      viewer.value.dataSources.add(waterDataSource)
+    } catch (waterError) {
+      console.error('加载水系GeoJSON失败:', waterError)
+    }
+    
+    // 加载小塔山水库GeoJSON
+    try {
+      const reservoirResponse = await fetch('/小塔山水库.geojson')
+      const reservoirGeojson = await reservoirResponse.json()
+      
+      const reservoirDataSource = await Cesium.GeoJsonDataSource.load(reservoirGeojson, {
+        stroke: Cesium.Color.fromCssColorString('#00d4ff'),
+        strokeWidth: 2,
+        fill: Cesium.Color.fromCssColorString('#00d4ff').withAlpha(0.3)
+      })
+      
+      viewer.value.dataSources.add(reservoirDataSource)
+    } catch (reservoirError) {
+      console.error('加载小塔山水库GeoJSON失败:', reservoirError)
+    }
+    
+    const entities = dataSource.entities.values
+    if (entities.length > 0) {
+      let minLat = 90, maxLat = -90, minLon = 180, maxLon = -180
+      
+      for (const entity of entities) {
+        if (entity.polygon && entity.polygon.hierarchy) {
+          const hierarchy = entity.polygon.hierarchy.getValue()
+          const positions = hierarchy.positions
+          
+          for (const pos of positions) {
+            const cartographic = Cesium.Cartographic.fromCartesian(pos)
+            const lat = Cesium.Math.toDegrees(cartographic.latitude)
+            const lon = Cesium.Math.toDegrees(cartographic.longitude)
+            
+            minLat = Math.min(minLat, lat)
+            maxLat = Math.max(maxLat, lat)
+            minLon = Math.min(minLon, lon)
+            maxLon = Math.max(maxLon, lon)
           }
         }
-
-        this.viewer.camera.flyTo({
-          destination: Cesium.Cartesian3.fromDegrees(118.9019, 34.985, 33000),
-          duration: 0
-        })
       }
-    } catch (error) {
-      console.error('加载GeoJSON失败:', error)
-      this.viewer.camera.flyTo({
+      
+      viewer.value.camera.flyTo({
         destination: Cesium.Cartesian3.fromDegrees(118.9019, 34.985, 33000),
         duration: 0
       })
     }
+  } catch (error) {
+    console.error('加载GeoJSON失败:', error)
+    viewer.value.camera.flyTo({
+        destination: Cesium.Cartesian3.fromDegrees(118.9019, 34.985, 33000),
+        duration: 0
+      })
+  }
 
   addPoiMarker()
   
@@ -372,7 +438,10 @@ onUnmounted(() => {
   if (blinkInterval) {
     clearInterval(blinkInterval)
   }
-}
+  if (viewer.value) {
+    viewer.value.destroy()
+  }
+})
 </script>
 
 <style scoped>
@@ -459,5 +528,4 @@ onUnmounted(() => {
   margin-bottom: 5px;
   line-height: 1.5;
 }
-</script>
 </style>