Преглед изворни кода

feat(地图统计): 添加地图切换功能并增强统计信息

添加地图类型切换功能,支持在"实施降酸措施"和"反酸一周期后"两种地图间切换
扩展统计信息,新增面积统计和百分比计算功能
重构数据加载和统计计算逻辑以适应不同地图类型
yes-yes-yes-k пре 1 дан
родитељ
комит
ba767e86b3
1 измењених фајлова са 146 додато и 11 уклоњено
  1. 146 11
      src/views/User/introduction/TotalIntroduction.vue

+ 146 - 11
src/views/User/introduction/TotalIntroduction.vue

@@ -18,7 +18,14 @@
      mildAcidCount: 0,
      mildAcidCount: 0,
      normalCount: 0,
      normalCount: 0,
      maxPH: 0,
      maxPH: 0,
-     minPH: 0
+     minPH: 0,
+     strongAcidArea: 0,
+     mildAcidArea: 0,
+     normalArea: 0,
+     totalArea: 0,
+     strongAcidPercent: 0,
+     mildAcidPercent: 0,
+     normalPercent: 0
    })
    })
 
 
   //  
   //  
@@ -39,10 +46,21 @@
       workspace:'acidmap',
       workspace:'acidmap',
       layerGroup:'leshujukanbanmap',
       layerGroup:'leshujukanbanmap',
       dataLayer:'le_soil_data',
       dataLayer:'le_soil_data',
-      wmsUrl:'/geoserver/acidmap/wms'
+      wmsUrl:'/geoserver/acidmap/wms',
+      phField: 'ph_mean'
+    },
+    reboundGeoserver:{
+      url:'/geoserver',
+      workspace:'acidmap',
+      layerGroup:'le_reflux_map',
+      dataLayer:'le_data_reflux_result',
+      wmsUrl:'/geoserver/acidmap/wms',
+      phField: 'ph_value'
     }
     }
    }
    }
 
 
+   const currentMapType = ref('normal')
+
 
 
    // 获取 pH 等级对应的 CSS 类
    // 获取 pH 等级对应的 CSS 类
 function getPHLevelClass(ph) {
 function getPHLevelClass(ph) {
@@ -94,6 +112,61 @@ function getPHComment(avgPH) {
 
 
   }
   }
 
 
+  async function switchMap(mapType) {
+    if (!map || !wmsLayer) return
+    
+    currentMapType.value = mapType
+    
+    const config = mapType === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
+    
+    // 移除旧的 WMS 图层
+    map.removeLayer(wmsLayer)
+    
+    // 创建新的 WMS 图层
+    wmsLayer = L.tileLayer.wms(config.wmsUrl, {
+      layers: `${config.workspace}:${config.layerGroup}`,
+      format: 'image/png',
+      transparent: true,
+      version: '1.1.0',
+      srs:'EPSG:4326',
+      attribution: '© GeoServer - Acidmap'
+    }).addTo(map)
+    
+    console.log(`地图已切换到:${mapType === 'rebound' ? '反酸一周期后' : '实施降酸措施'}`)
+    console.log('新图层:', `${config.workspace}:${config.layerGroup}`)
+    
+    // 重新加载对应地图的数据和统计
+    await loadMapData()
+  }
+  
+  // 加载当前地图类型的数据
+  async function loadMapData() {
+    try {
+      const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
+      
+      const response = await fetch(
+        `${config.url}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${config.workspace}:${config.dataLayer}&outputFormat=application/json`
+      );
+      
+      if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
+      
+      const geoJsonData = await response.json();
+      
+      console.log('✅ 获取到数据:', geoJsonData.features.length, '条记录');
+
+      // 保存数据用于统计和交互
+      allFeatures = geoJsonData.features;
+      samplePointsData.value = geoJsonData.features;
+      
+      // 计算统计信息
+      calculatePHDistribution(allFeatures);
+      loadStatistics();
+      
+    } catch (err) {
+      console.error('❌ 加载数据失败:', err);
+    }
+  }
+
   function createPointIcon(feature) {
   function createPointIcon(feature) {
     const ph = feature.properties.ph || feature.properties.value
     const ph = feature.properties.ph || feature.properties.value
     let color = '#22c55e'
     let color = '#22c55e'
@@ -126,6 +199,9 @@ function getPHComment(avgPH) {
   try {
   try {
     // 等待数据加载完成
     // 等待数据加载完成
     if (samplePointsData.value.length === 0) return;
     if (samplePointsData.value.length === 0) return;
+    
+    // 根据当前地图类型选择 pH 字段
+    const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
 
 
     let phCount = 0
     let phCount = 0
     let avgPH = 0
     let avgPH = 0
@@ -134,10 +210,21 @@ function getPHComment(avgPH) {
     let normalCount = 0
     let normalCount = 0
     let maxPH = -Infinity
     let maxPH = -Infinity
     let minPH = Infinity
     let minPH = Infinity
+    let strongAcidArea = 0
+    let mildAcidArea = 0
+    let normalArea = 0
+    let totalArea = 0
 
 
     samplePointsData.value.forEach(feature => {
     samplePointsData.value.forEach(feature => {
-      const numericPh = parsePHValue(feature.properties.ph || feature.properties.value)
+      const numericPh = parsePHValue(feature.properties[config.phField])
+      const area = parseFloat(feature.properties.area) || 0
+      
+      // 累加总面积
+      if (area > 0) {
+        totalArea += area
+      }
       
       
+      // 过滤无效 pH 值
       if (numericPh && numericPh > 0 && !isNaN(numericPh)) {
       if (numericPh && numericPh > 0 && !isNaN(numericPh)) {
         phCount++
         phCount++
         const delta = numericPh - avgPH;
         const delta = numericPh - avgPH;
@@ -145,12 +232,26 @@ function getPHComment(avgPH) {
         maxPH = Math.max(maxPH, numericPh)
         maxPH = Math.max(maxPH, numericPh)
         minPH = Math.min(minPH, numericPh)
         minPH = Math.min(minPH, numericPh)
         
         
-        if (numericPh <= 5.2) strongAcidCount++
-        else if (numericPh < 6.0) mildAcidCount++
-        else normalCount++
+        if (numericPh <= 5.2) {
+          strongAcidCount++
+          strongAcidArea += area
+        }
+        else if (numericPh < 6.0) {
+          mildAcidCount++
+          mildAcidArea += area
+        }
+        else {
+          normalCount++
+          normalArea += area
+        }
       }
       }
     });
     });
 
 
+    // 计算面积占比
+    const strongAcidPercent = totalArea > 0 ? parseFloat(((strongAcidArea / totalArea) * 100).toFixed(2)) : 0
+    const mildAcidPercent = totalArea > 0 ? parseFloat(((mildAcidArea / totalArea) * 100).toFixed(2)) : 0
+    const normalPercent = totalArea > 0 ? parseFloat(((normalArea / totalArea) * 100).toFixed(2)) : 0
+
     statistics.value = {
     statistics.value = {
       totalBlocks: samplePointsData.value.length,
       totalBlocks: samplePointsData.value.length,
       avgPH:  phCount > 0 ? parseFloat(avgPH.toFixed(2)) : 0,  // ✅ 确保是数字
       avgPH:  phCount > 0 ? parseFloat(avgPH.toFixed(2)) : 0,  // ✅ 确保是数字
@@ -158,7 +259,14 @@ function getPHComment(avgPH) {
       mildAcidCount,
       mildAcidCount,
       normalCount,
       normalCount,
       maxPH: maxPH === -Infinity ? 0 : parseFloat(maxPH.toFixed(2)),
       maxPH: maxPH === -Infinity ? 0 : parseFloat(maxPH.toFixed(2)),
-      minPH: minPH === Infinity ? 0 : parseFloat(minPH.toFixed(2))
+      minPH: minPH === Infinity ? 0 : parseFloat(minPH.toFixed(2)),
+      strongAcidArea: parseFloat(strongAcidArea.toFixed(2)),
+      mildAcidArea: parseFloat(mildAcidArea.toFixed(2)),
+      normalArea: parseFloat(normalArea.toFixed(2)),
+      totalArea: parseFloat(totalArea.toFixed(2)),
+      strongAcidPercent,
+      mildAcidPercent,
+      normalPercent
     };
     };
 
 
     console.log('✅ 统计数据加载完成:', statistics.value);
     console.log('✅ 统计数据加载完成:', statistics.value);
@@ -202,6 +310,7 @@ function getPHComment(avgPH) {
 
 
   // 计算 pH 分布
   // 计算 pH 分布
   function calculatePHDistribution(features) {
   function calculatePHDistribution(features) {
+    const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
     const distribution = {
     const distribution = {
       range1: 0,
       range1: 0,
       range2: 0,
       range2: 0,
@@ -209,7 +318,7 @@ function getPHComment(avgPH) {
     }
     }
 
 
     features.forEach(feature => {
     features.forEach(feature => {
-      const phValue = feature.properties.ph || feature.properties.value
+      const phValue = feature.properties[config.phField]
       const numericPh = typeof phValue === 'string' ? parseFloat(phValue) : phValue
       const numericPh = typeof phValue === 'string' ? parseFloat(phValue) : phValue
       if (numericPh && numericPh > 0) {
       if (numericPh && numericPh > 0) {
         if (numericPh <= 5.2) distribution.range1++
         if (numericPh <= 5.2) distribution.range1++
@@ -226,6 +335,9 @@ function getPHComment(avgPH) {
     let nearestPoint = null;
     let nearestPoint = null;
     let minDistance = Infinity;
     let minDistance = Infinity;
     
     
+    // 根据当前地图类型选择 pH 字段
+    const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
+    
     allFeatures.forEach(feature => {
     allFeatures.forEach(feature => {
       const coords = feature.geometry.coordinates;
       const coords = feature.geometry.coordinates;
       if (coords && coords.length >= 2) {
       if (coords && coords.length >= 2) {
@@ -244,12 +356,15 @@ function getPHComment(avgPH) {
     });
     });
     
     
     if (nearestPoint) {
     if (nearestPoint) {
-      const ph = parsePHValue(nearestPoint.properties.ph || nearestPoint.properties.value);
+      const ph = parsePHValue(nearestPoint.properties[config.phField]);
       
       
       selectedPoint.value = {
       selectedPoint.value = {
         ph: ph,
         ph: ph,
         properties: nearestPoint.properties
         properties: nearestPoint.properties
       };
       };
+      
+      console.log('✅ 选中地块:', nearestPoint.properties);
+      console.log('pH 字段:', config.phField, '= ', nearestPoint.properties[config.phField]);
     }
     }
   }
   }
 
 
@@ -290,8 +405,8 @@ onUnmounted(()=>{
 
 
     <!-- 计算刷新按钮 -->
     <!-- 计算刷新按钮 -->
      <div class="compute">
      <div class="compute">
-      <button class="combtn">实施降酸措施一周期后</button>
-      <button class="combtn">反酸一周期后</button>
+      <button class="combtn" @click="switchMap('normal')">实施降酸措施一周期后</button>
+      <button class="combtn" @click="switchMap('rebound')">反酸一周期后</button>
      </div>
      </div>
     <!-- pH 统计 -->
     <!-- pH 统计 -->
     <div class="statistics-panel">
     <div class="statistics-panel">
@@ -314,18 +429,38 @@ onUnmounted(()=>{
         <span class="stat-value danger">{{ statistics.strongAcidCount }} 个</span>
         <span class="stat-value danger">{{ statistics.strongAcidCount }} 个</span>
       </div>
       </div>
       
       
+      <div class="stat-row">
+        <span class="stat-label">强酸性面积占比:</span>
+        <span class="stat-value danger">{{ statistics.strongAcidPercent }}%</span>
+      </div>
+      
       <div class="stat-row">
       <div class="stat-row">
         <span class="stat-label">弱酸性 (pH 5.2~6.0):  </span>
         <span class="stat-label">弱酸性 (pH 5.2~6.0):  </span>
         <span class="stat-value warning">{{ statistics.mildAcidCount }} 个</span>
         <span class="stat-value warning">{{ statistics.mildAcidCount }} 个</span>
       </div>
       </div>
       
       
+      <div class="stat-row">
+        <span class="stat-label">弱酸性面积占比:</span>
+        <span class="stat-value warning">{{ statistics.mildAcidPercent }}%</span>
+      </div>
+      
       <div class="stat-row">
       <div class="stat-row">
         <span class="stat-label">正常 (pH≥6.0):</span>
         <span class="stat-label">正常 (pH≥6.0):</span>
         <span class="stat-value success">{{ statistics.normalCount }} 个</span>
         <span class="stat-value success">{{ statistics.normalCount }} 个</span>
       </div>
       </div>
       
       
+      <div class="stat-row">
+        <span class="stat-label">正常面积占比:</span>
+        <span class="stat-value success">{{ statistics.normalPercent }}%</span>
+      </div>
+      
       <div class="stat-divider"></div>
       <div class="stat-divider"></div>
       
       
+      <div class="stat-row small">
+        <span class="stat-label">总面积:</span>
+        <span class="stat-value">{{ statistics.totalArea }} 亩</span>
+      </div>
+      
       <div class="stat-row small">
       <div class="stat-row small">
         <span class="stat-label">最高 pH:</span>
         <span class="stat-label">最高 pH:</span>
         <span class="stat-value success">{{ statistics.maxPH || '-' }}</span>
         <span class="stat-value success">{{ statistics.maxPH || '-' }}</span>