Selaa lähdekoodia

refactor(地图交互): 优化地图数据获取和点击交互处理

- 更新数据层配置为 le_data_block_map 和 le_data_reflux_result
- 重构数据获取逻辑,增加错误处理和 JSON 解析验证
- 将地图点击交互改为使用 WMS GetFeatureInfo 查询地块属性
- 移除调试用的 console.log 并添加注释说明
- 调整样式和统计信息显示
yes-yes-yes-k 10 tuntia sitten
vanhempi
commit
736e917bd9
1 muutettua tiedostoa jossa 129 lisäystä ja 57 poistoa
  1. 129 57
      src/views/User/introduction/TotalIntroduction.vue

+ 129 - 57
src/views/User/introduction/TotalIntroduction.vue

@@ -40,12 +40,12 @@
    const CONFIG = {
     center:[25.202903, 113.25383],
     zoom:11,
-    getPoint:'/api/vector/export/all?table_name=le_soil_data&format=geojson',
+    getPoint:'/api/vector/export/all?table_name=le_data_block_map&format=geojson',
     geoserver:{
       url:'/geoserver',
       workspace:'acidmap',
       layerGroup:'leshujukanbanmap',
-      dataLayer:'le_soil_data',
+      dataLayer:'le_data_block_map',
       wmsUrl:'/geoserver/acidmap/wms',
       phField: 'ph_mean'
     },
@@ -55,9 +55,10 @@
       layerGroup:'le_reflux_map',
       dataLayer:'le_data_reflux_result',
       wmsUrl:'/geoserver/acidmap/wms',
-      phField: 'ph_value'
+      phField: 'le_data__4'
     }
    }
+   // 图层配置已验证:正常地图使用 le_data_block_map,反酸地图使用 le_data_reflux_result
 
    const currentMapType = ref('normal')
 
@@ -132,8 +133,8 @@ function getPHComment(avgPH) {
       attribution: '© GeoServer - Acidmap'
     }).addTo(map)
     
-    console.log(`地图已切换到:${mapType === 'rebound' ? '反酸一周期后' : '实施降酸措施'}`)
-    console.log('新图层:', `${config.workspace}:${config.layerGroup}`)
+    // console.log(`地图已切换到:${mapType === 'rebound' ? '反酸一周期后' : '实施降酸措施'}`)
+    // console.log('新图层:', `${config.workspace}:${config.layerGroup}`)
     
     // 重新加载对应地图的数据和统计
     await loadMapData()
@@ -144,15 +145,31 @@ function getPHComment(avgPH) {
     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`
-      );
+      const url = `${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}`);
+      // console.log('🔍 请求 WFS 数据:', url);
       
-      const geoJsonData = await response.json();
+      const response = await fetch(url);
       
-      console.log('✅ 获取到数据:', geoJsonData.features.length, '条记录');
+      if (!response.ok) {
+        const errorText = await response.text();
+        console.error('❌ WFS 响应错误:', errorText);
+        throw new Error(`HTTP error! status: ${response.status}`);
+      }
+      
+      const text = await response.text();
+      // console.log('📦 原始响应:', text.substring(0, 200));
+      
+      // 尝试解析 JSON
+      let geoJsonData;
+      try {
+        geoJsonData = JSON.parse(text);
+      } catch (parseError) {
+        console.error('❌ JSON 解析失败,响应内容:', text);
+        throw new Error('GeoServer 返回的数据格式不正确,不是有效的 JSON');
+      }
+      
+      // console.log('✅ 获取到地图数据:', geoJsonData.features?.length || 0, '条记录');
 
       // 保存数据用于统计和交互
       allFeatures = geoJsonData.features;
@@ -269,7 +286,7 @@ function getPHComment(avgPH) {
       normalPercent
     };
 
-    console.log('✅ 统计数据加载完成:', statistics.value);
+    // console.log('✅ 统计数据加载完成:', statistics.value);
   } catch (err) {
     console.error('加载统计数据失败:', err);
   }
@@ -278,15 +295,40 @@ function getPHComment(avgPH) {
 // 修改为只获取数据用于统计,不渲染到地图
   async function fetchDataForStatistics() {
     try {
-      const response = await fetch(
-        `${CONFIG.geoserver.url}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${CONFIG.geoserver.workspace}:${CONFIG.geoserver.dataLayer}&outputFormat=application/json`
-      );
+      const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
+      
+      const url = `${config.url}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${config.workspace}:${config.dataLayer}&outputFormat=application/json`
+      
+      // console.log('🔍 请求 WFS 数据:', url);
       
-      if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
+      const response = await fetch(url);
+      
+      if (!response.ok) {
+        const errorText = await response.text();
+        console.error('❌ WFS 响应错误:', errorText);
+        throw new Error(`HTTP error! status: ${response.status}`);
+      }
       
-      const geoJsonData = await response.json();
+      const text = await response.text();
+      // console.log('📦 原始响应:', text.substring(0, 200));
       
-      console.log('✅ 获取到数据:', geoJsonData.features.length, '条记录');
+      // 尝试解析 JSON
+      let geoJsonData;
+      try {
+        geoJsonData = JSON.parse(text);
+      } catch (parseError) {
+        console.error('❌ JSON 解析失败,响应内容:', text);
+        throw new Error('GeoServer 返回的数据格式不正确,不是有效的 JSON');
+      }
+      
+      // console.log('✅ 获取到数据:', geoJsonData.features?.length || 0, '条记录');
+      
+      // 调试:打印第一个要素的 properties
+      // if (geoJsonData.features && geoJsonData.features.length > 0) {
+      //   console.log('📋 第一个要素的 properties:', geoJsonData.features[0].properties);
+      //   console.log('📋 pH 字段值 (ph_mean):', geoJsonData.features[0].properties.ph_mean);
+      //   console.log('📋 pH 字段值 (le_data__4):', geoJsonData.features[0].properties.le_data__4);
+      // }
 
       // 保存数据用于统计和交互
       allFeatures = geoJsonData.features;
@@ -296,12 +338,8 @@ function getPHComment(avgPH) {
       calculatePHDistribution(allFeatures);
       loadStatistics();
       
-      // 添加点击事件监听(不显示标记点)
-      map.on('click', function(e) {
-        const latlng = e.latlng;
-        // 查找最近的采样点
-        findNearestPoint(latlng);
-      });
+      // 添加点击事件监听
+      map.on('click', handleMapClick);
       
     } catch (err) {
       console.error('❌ 加载统计数据失败:', err);
@@ -330,47 +368,81 @@ function getPHComment(avgPH) {
     phDistribution.value = distribution
   }
 
-  // 查找最近的采样点
-  function findNearestPoint(latlng) {
-    let nearestPoint = null;
-    let minDistance = Infinity;
+  // 处理地图点击,查询地块属性
+  async function handleMapClick(e) {
+    const latlng = e.latlng;
+    // console.log('🔍 地图点击:', latlng);
     
-    // 根据当前地图类型选择 pH 字段
-    const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
-    
-    allFeatures.forEach(feature => {
-      const coords = feature.geometry.coordinates;
-      if (coords && coords.length >= 2) {
-        const pointLat = coords[1];
-        const pointLng = coords[0];
-        const distance = Math.sqrt(
-          Math.pow(pointLat - latlng.lat, 2) + 
-          Math.pow(pointLng - latlng.lng, 2)
-        );
-        
-        if (distance < minDistance && distance < 0.01) { // 10 米范围内
-          minDistance = distance;
-          nearestPoint = feature;
-        }
+    try {
+      // 根据当前地图类型选择配置
+      const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
+      
+      // console.log('📋 当前地图类型:', currentMapType.value);
+      // console.log('📋 查询的数据层:', config.dataLayer);
+      
+      // 构建 WMS GetFeatureInfo 请求
+      const size = map.getSize();
+      const point = map.latLngToContainerPoint(latlng);
+      
+      const params = new URLSearchParams({
+        SERVICE: 'WMS',
+        VERSION: '1.1.1',
+        REQUEST: 'GetFeatureInfo',
+        LAYERS: `${config.workspace}:${config.dataLayer}`,
+        QUERY_LAYERS: `${config.workspace}:${config.dataLayer}`,
+        STYLES: '',
+        SRS: 'EPSG:4326',
+        BBOX: map.getBounds().toBBoxString(),
+        WIDTH: size.x,
+        HEIGHT: size.y,
+        X: Math.round(point.x),
+        Y: Math.round(point.y),
+        INFO_FORMAT: 'application/json',
+        FEATURE_COUNT: 1
+      });
+      
+      const url = `${config.wmsUrl}?${params.toString()}`;
+      // console.log('🔍 查询 URL:', url);
+      
+      const response = await fetch(url);
+      
+      if (!response.ok) {
+        throw new Error(`HTTP error! status: ${response.status}`);
       }
-    });
-    
-    if (nearestPoint) {
-      const ph = parsePHValue(nearestPoint.properties[config.phField]);
       
-      selectedPoint.value = {
-        ph: ph,
-        properties: nearestPoint.properties
-      };
+      const data = await response.json();
+      
+      // console.log('� 查询结果:', data);
       
-      console.log('✅ 选中地块:', nearestPoint.properties);
-      console.log('pH 字段:', config.phField, '= ', nearestPoint.properties[config.phField]);
+      if (data.features && data.features.length > 0) {
+        const feature = data.features[0];
+        const ph = parsePHValue(feature.properties[config.phField]);
+        
+        // console.log('📋 pH 字段:', config.phField);
+        // console.log('📋 pH 值:', ph);
+        // console.log('📋 完整属性:', feature.properties);
+        
+        selectedPoint.value = {
+          ph: ph,
+          properties: feature.properties
+        };
+        
+        // console.log('✅ 选中地块:', selectedPoint.value);
+      } else {
+        // console.log('⚠️ 该位置没有地块数据');
+        selectedPoint.value = null;
+      }
+      
+    } catch (err) {
+      console.error('❌ 查询地块信息失败:', err);
+      alert('查询地块信息失败,请重试');
     }
   }
 
 
 onUnmounted(()=>{
     if(map) {
+      map.off('click', handleMapClick) // 移除点击事件监听
       map.remove()
       map = null
     }
@@ -413,7 +485,7 @@ onUnmounted(()=>{
       <h4>📊 乐昌县土壤 pH 统计</h4>
       
       <div class="stat-row">
-        <span class="stat-label">采样点总数:</span>
+        <span class="stat-label">地块总数:</span>
         <span class="stat-value">{{ statistics.totalBlocks }} 个</span>
       </div>
       
@@ -725,7 +797,7 @@ onUnmounted(()=>{
 
 .distribution-chart {
   position: absolute;
-  top:600px;
+  top:700px;
   right: 10px;
   background: rgba(255, 255, 255, 0.95);
   padding: 15px;