Browse Source

Merge branch 'lili' of qw/12 into master

Ding 2 months ago
parent
commit
5258e9def3

+ 11 - 1
package-lock.json

@@ -29,6 +29,7 @@
         "leaflet": "^1.9.4",
         "leaflet-compass": "^1.5.6",
         "leaflet.chinatmsproviders": "^3.0.6",
+        "leaflet.markercluster": "^1.5.3",
         "lodash.kebabcase": "^4.1.1",
         "pinia": "^2.3.0",
         "proj4": "^2.19.10",
@@ -8643,7 +8644,7 @@
     },
     "node_modules/leaflet": {
       "version": "1.9.4",
-      "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
+      "resolved": "https://registry.npmmirror.com/leaflet/-/leaflet-1.9.4.tgz",
       "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
       "license": "BSD-2-Clause"
     },
@@ -8662,6 +8663,15 @@
       "integrity": "sha512-B4UPSn2MT//RkFoyrVjwqQyfKuf4tSmMjJDKQ6nqwCCGgirYKRWHafSH9JmA88WoG5pkuMXBcKQhY32FobxU/g==",
       "license": "MIT"
     },
+    "node_modules/leaflet.markercluster": {
+      "version": "1.5.3",
+      "resolved": "https://registry.npmmirror.com/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz",
+      "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==",
+      "license": "MIT",
+      "peerDependencies": {
+        "leaflet": "^1.3.1"
+      }
+    },
     "node_modules/levn": {
       "version": "0.4.1",
       "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz",

+ 1 - 0
package.json

@@ -33,6 +33,7 @@
     "leaflet": "^1.9.4",
     "leaflet-compass": "^1.5.6",
     "leaflet.chinatmsproviders": "^3.0.6",
+    "leaflet.markercluster": "^1.5.3",
     "lodash.kebabcase": "^4.1.1",
     "pinia": "^2.3.0",
     "proj4": "^2.19.10",

+ 1 - 1
src/views/User/HmOutFlux/irrigationWater/irriWaterSampleData.vue

@@ -3,7 +3,7 @@
     <!-- 页眉设计 -->
     <div class="section-header">
         <div class="section-icon">📊</div>
-        <h1 class="page-title">灌溉水采样点分析系统</h1>
+        <h1 class="page-title">灌溉水采样点分析</h1>
     </div>
 
     <!-- 主内容区 -->

+ 473 - 225
src/views/User/cadmiumPrediction/CropCadmiumPrediction.vue

@@ -47,7 +47,7 @@
     <div class="content-area">
       <!-- 地图区域 - 单独一行 -->
       <div class="map-section">
-        <h3>作物态Cd预测地图</h3>
+        <h3>水稻Cd预测地图</h3>
         <div v-if="loadingMap" class="loading-container">
           <el-icon class="loading-icon"><Loading /></el-icon>
           <span>地图加载中...</span>
@@ -62,12 +62,35 @@
           <el-icon class="loading-icon"><Loading /></el-icon>
           <span>乡镇地图加载中...</span>
         </div>
-        <!-- ECharts地图容器 -->
+        <div class="township-map-wrapper">
+          <!-- Leaflet地图容器 -->
+        <div class="town-map-title">水稻Cd含量预测镇域统计分布图</div>
         <div 
           v-show="!loadingTownshipMap" 
           ref="townshipMapRef" 
           class="township-map-container"
         ></div>
+        </div>
+        
+        <!-- 颜色图例 -->
+        <div class="legend">
+          <div class="legend-item">
+            <div class="color-box" style="background-color: #00FF00;"></div>
+            <span>安全区间 (0.0-0.2 mg/kg)</span>
+          </div>
+          <div class="legend-item">
+            <div class="color-box" style="background-color: #FFFF00;"></div>
+            <span>预警区间 (0.2-0.3 mg/kg)</span>
+          </div>
+          <div class="legend-item">
+            <div class="color-box" style="background-color: #FF0000;"></div>
+            <span>超标区间 (≥0.3 mg/kg)</span>
+          </div>
+          <div class="legend-item">
+            <div class="color-box" style="background-color: #CCCCCC;"></div>
+            <span>无数据</span>
+          </div>
+        </div>
         <div v-if="!loadingTownshipMap && !townshipMapInstance" class="no-data">
           <el-icon><Location /></el-icon>
           <p>暂无乡镇边界数据</p>
@@ -76,7 +99,7 @@
 
        <!-- 统计图表区域 -->
       <div class="stats-area">
-        <h3>作物态Cd预测统计信息</h3>
+        <h3>水稻Cd预测统计信息</h3>
         <div class="model-info">
           <el-tag type="info">{{ modelInfo.modelType || 'Cd预测模型' }}</el-tag>
           <span class="update-time">
@@ -133,7 +156,7 @@
 
      <!-- 直方图区域 - 单独一行 -->
       <div class="histogram-section">
-        <h3>作物态Cd预测直方图</h3>
+        <h3>水稻Cd预测直方图</h3>
         <div v-if="loadingHistogram" class="loading-container">
           <el-icon class="loading-icon"><Loading /></el-icon>
           <span>直方图加载中...</span>
@@ -149,20 +172,30 @@
 
 <script>
 import * as XLSX from 'xlsx';
-import * as echarts from 'echarts';
 import { saveAs } from 'file-saver';
 import { api8000 } from '@/utils/request';
 import { 
-   Location,Loading, Upload, Picture, Histogram, Download, Document, Box, DataAnalysis
+   Location, Loading, Upload, Picture, Histogram, Download, Document, Box, DataAnalysis
 } from '@element-plus/icons-vue';
+// 引入Leaflet相关资源
+import L from 'leaflet';
+import 'leaflet/dist/leaflet.css';
+import 'leaflet.markercluster/dist/MarkerCluster.css';
+import 'leaflet.markercluster/dist/MarkerCluster.Default.css';
+import 'leaflet.markercluster';
 
 export default {
   name: 'CropCadmiumPrediction',
   components: { 
+    Location,
     Loading, Upload, Picture, Histogram, Download, Document, Box, DataAnalysis
   },
   data() {
     return {
+      mapContainerStyle: {
+      width: '100%',
+      height: '800px'
+    },
       isCalculating: false,
       isCalculatingFromDB: false,
       loadingMap: false,
@@ -183,16 +216,16 @@ export default {
       mapBlob: null,
       histogramBlob: null,
       selectedFile: null,
-      // 新增:乡镇地图相关数据
+      // 乡镇地图相关数据
       loadingTownshipMap: false, // 乡镇地图加载状态
-      townshipMapInstance: null, // ECharts实例
-      townshipGeoJson: null,     // 本地边界数据(TopoJSON/GeoJSON)
+      townshipMapInstance: null, // Leaflet实例
+      townshipGeoJson: null,     // 本地边界数据(GeoJSON)
       townshipData: [],          // 接口获取的乡镇Cd数据
       countyName: '乐昌市', // 默认县市名称
-      townshipMapRef :null,
       currentTooltipTown: '', // 当前悬浮的乡镇
       currentTooltipData: null, // 当前乡镇的详情数据
       isTooltipLoading: false, // tooltip 是否在加载中
+      dataMap:{},
     };
   },
 
@@ -200,25 +233,41 @@ export default {
     // 组件挂载时获取最新数据
     this.fetchLatestResults();
     this.fetchStatistics();
-    this.initTownshipMap();
+
+    // 使用更智能的初始化时机
+    this.$nextTick(() => {
+      // 等待下一个动画帧,确保DOM完全渲染
+      requestAnimationFrame(() => {
+        setTimeout(() => {
+          this.initTownshipMap();
+        }, 300);
+      });
+    });
     
     // 添加窗口调整事件监听
     window.addEventListener('resize', this.handleResize);
   },
 
   beforeDestroy() {
-    if (this.mapImageUrl) URL.revokeObjectURL(this.mapImageUrl);
-    if (this.histogramImageUrl) URL.revokeObjectURL(this.histogramImageUrl);
-    // 新增:销毁ECharts实例,避免内存泄漏
+    // 清理ResizeObserver
+  if (this.resizeObserver) {
+    this.resizeObserver.disconnect();
+  }
+    // 组件销毁前移除事件监听,避免内存泄漏
+    window.removeEventListener('resize', this.handleResize);
     if (this.townshipMapInstance) {
-      this.townshipMapInstance.dispose();
+      this.townshipMapInstance.remove();
       this.townshipMapInstance = null;
     }
-    
-    // 移除窗口调整事件监听
-    window.removeEventListener('resize', this.handleResize);
   },
+
+
   methods: {
+    handleResize() {
+      if (this.townshipMapInstance) {
+        this.townshipMapInstance.invalidateSize();
+      }
+    },
     // 触发文件选择
     triggerFileUpload() {
       this.$refs.fileInput.click();
@@ -381,14 +430,36 @@ export default {
       }
     },
 
-    // 新增方法:根据乡镇名请求接口
+    // 根据Cd含量获取对应的颜色
+    getColorByCdValue(cdValue) {
+      if (cdValue === null || cdValue === undefined) {
+        return '#CCCCCC'; // 无数据时显示灰色
+      }
+      const numValue = Number(cdValue);
+      if (isNaN(numValue)) {
+        return '#CCCCCC';
+      }
+      if (numValue >= 0.0 && numValue < 0.2) {
+        return '#00FF00'; // 安全区间 - 绿色
+      } else if (numValue >= 0.2 && numValue < 0.3) {
+        return '#FFFF00'; // 预警区间 - 黄色
+      } else if (numValue >= 0.3) {
+        return '#FF0000'; // 超标区间 - 红色
+      }
+      return '#CCCCCC'; // 默认灰色
+    },
+
+    // 根据乡镇名请求接口
     async fetchTownshipDetailByName(townName) {
+      if (this.dataMap[townName]) {
+         return this.dataMap[townName];
+       }
+
       try {
-        // 调用对应乡镇的接口,假设接口地址为 /api/township-details/{townName}
         const encodedTownName = encodeURIComponent(townName);
         const response = await api8000.get(`/api/cd-prediction/crop-cd/statistics/town/${encodedTownName}`);
         if (response.data && response.data.success) {
-          return response.data.data;
+          return response.data;
         }
        return null;
       } catch (error) {
@@ -397,176 +468,331 @@ export default {
       }
     },
 
-    // 新增1:初始化乡镇边界地图(核心逻辑,仅加载边界)
-    async initTownshipMap() {
-      try {
-        this.loadingTownshipMap = true;
-        // 步骤1:加载本地 GeoJSON 边界文件
-        await this.loadLocalGeoJson();
-        // 步骤2:等待DOM更新完成
-        await this.$nextTick();
-        // 步骤3:渲染边界地图(不关联接口数据)
-        this.renderTownshipMap();
-      } catch (error) {
-        console.error('乡镇边界加载失败:', error);
-        this.townshipMapInstance = null; // 标记加载失败
-      } finally {
-        this.loadingTownshipMap = false;
+    // 初始化乡镇边界地图
+async initTownshipMap() {
+    try {
+      this.loadingTownshipMap = true;
+      
+      // 先强制设置容器尺寸
+      this.forceMapContainerSize();
+      
+      await this.loadLocalGeoJson(); 
+
+      const mapContainer = this.$refs.townshipMapRef;
+      if (!mapContainer) {
+        throw new Error('地图容器不存在');
       }
-    },
 
-    // 新增2:加载本地 GeoJSON 文件(关键:路径必须正确)
+      // 使用增强的尺寸等待方法
+      await this.waitForContainerSizeWithFallback(mapContainer);
+
+      const townNames = this.townshipGeoJson.features.map(feature => feature.properties.name);
+
+      const dataPromises = townNames.map(async (townName) => {
+        try {
+          const response = await this.fetchTownshipDetailByName(townName);
+          return { townName, response, success: true };
+        } catch (error) {
+          console.warn(`获取${townName}数据失败:`, error);
+          return { townName, response: null, success: false };
+        }
+      });
+
+      const allResults = await Promise.all(dataPromises);
+
+      this.dataMap = {};
+      allResults.forEach(result => {
+        this.dataMap[result.townName] = result.success ? result.response : null;
+      });
+
+      // 确保DOM更新后渲染地图
+      await this.$nextTick();
+      this.renderTownshipMap(); 
+
+    } catch (error) {
+      console.error('乡镇地图加载失败:', error);
+      this.townshipMapInstance = null;
+      // 重试机制
+      setTimeout(() => {
+        this.initTownshipMap();
+      }, 500);
+    } finally {
+      this.loadingTownshipMap = false;
+    }
+  },
+
+  // 强制设置地图容器尺寸
+  forceMapContainerSize() {
+    this.mapContainerStyle = {
+      width: '100%',
+      height: '800px',
+      minHeight: '600px',
+      display: 'block',
+      visibility: 'visible'
+    };
+  },
+
+  // 增强的尺寸等待方法
+  waitForContainerSizeWithFallback(container) {
+    return new Promise((resolve, reject) => {
+      let retries = 0;
+      const maxRetries = 30; // 减少重试次数,更快失败
+      
+      const checkSize = () => {
+        // 添加更严格的尺寸检查
+        const width = container.offsetWidth || container.clientWidth;
+        const height = container.offsetHeight || container.clientHeight;
+        
+        console.log(`容器尺寸检查: ${width}x${height}, 重试: ${retries}`);
+        
+        if (width > 100 && height > 100) { // 降低尺寸阈值
+          console.log('容器尺寸有效,继续初始化');
+          resolve();
+          return;
+        }
+        
+        if (retries >= maxRetries) {
+          console.warn('容器尺寸等待超时,尝试强制初始化');
+          // 即使尺寸不理想也继续,Leaflet可以处理
+          this.applyEmergencySize(container);
+          resolve();
+          return;
+        }
+        
+        retries++;
+        setTimeout(checkSize, 100); // 增加检查间隔
+      };
+      
+      // 立即检查一次
+      setTimeout(checkSize, 0);
+    });
+  },
+
+  // 紧急情况下的尺寸处理
+  applyEmergencySize(container) {
+    console.warn('应用紧急尺寸设置');
+    const parent = container.parentElement;
+    if (parent) {
+      const parentWidth = parent.offsetWidth;
+      if (parentWidth > 0) {
+        container.style.width = parentWidth + 'px';
+        container.style.height = '600px'; // 设置一个合理的最小高度
+      }
+    }
+  },
+
+    // 加载本地 GeoJSON 文件
     async loadLocalGeoJson() {
       try {
-        // 1. 确认文件路径:public/data/韶关市乡镇划分图5.geojson
         const geoJsonPath = '/data/韶关市乡镇划分图5.geojson';
-        
-        // 2. 发送请求加载 GeoJSON
         const response = await fetch(geoJsonPath);
-        // 3. 检查请求是否成功(状态码 200-299 为成功)
+        
         if (!response.ok) {
           throw new Error(`文件加载失败:状态码 ${response.status}(路径:${geoJsonPath})`);
         }
         
-        // 4. 解析 GeoJSON 数据
         let originalGeoJson = await response.json();
 
-        // 关键修改:过滤只保留 FXZQMC 为"乐昌市"的特征数据
+        // 过滤只保留 FXZQMC 为"乐昌市"的特征数据
         this.townshipGeoJson = {
-          ...originalGeoJson,  // 保留原有属性(如 type、crs 等)
-          features: originalGeoJson.features// 过滤出乐昌市的乡镇
-        .filter(feature => feature.properties?.FXZQMC === '乐昌市')
-        // 为每个乡镇添加name字段,值为TXZQMC(ECharts默认读取name字段)
-        .map(feature => ({
-          ...feature,
-          properties: {
-            ...feature.properties,
-            name: feature.properties?.TXZQMC || '未知乡镇' // 核心:映射TXZQMC到name
-          }
-        }))
+          ...originalGeoJson,
+          features: originalGeoJson.features
+            .filter(feature => feature.properties?.FXZQMC === '乐昌市')
+            .map(feature => ({
+              ...feature,
+              properties: {
+                ...feature.properties,
+                name: feature.properties?.TXZQMC || '未知乡镇'
+              }
+            }))
         };
         
-        // 5. 验证 GeoJSON 格式(必须包含 features 数组,否则是无效格式)
         if (!this.townshipGeoJson.features || !Array.isArray(this.townshipGeoJson.features)) {
           throw new Error('GeoJSON 格式错误:缺少 features 数组');
         }
 
-        console.log('GeoJSON 加载成功,包含乡镇数量:', this.townshipGeoJson.features.length);
       } catch (error) {
         console.error('GeoJSON 加载异常:', error);
-        throw error; // 抛出错误,让 initTownshipMap 捕获
+        throw error;
       }
     },
 
-    // 新增3:渲染乡镇边界(仅显示边界和乡镇名,不关联数据)
-    renderTownshipMap() {
-      // 1. 获取地图容器 DOM(必须存在)
-      const mapContainer = this.$refs.townshipMapRef;
-      if (!mapContainer) {
-        throw new Error('ECharts 容器不存在:请检查 ref="townshipMapRef" 是否正确');
-      }
+    // 使用Leaflet渲染乡镇地图并填充颜色
+    // 修改渲染地图方法,增加错误处理
+// 使用Leaflet渲染乡镇地图并填充颜色
+renderTownshipMap() {
+  try {
+    const mapContainer = this.$refs.townshipMapRef;
+    if (!mapContainer || !this.townshipGeoJson) {
+      console.error('渲染条件不满足');
+      return;
+    }
+
+    // 最终尺寸检查
+    const width = mapContainer.offsetWidth;
+    const height = mapContainer.offsetHeight;
+    
+    if (width === 0 || height === 0) {
+      console.error('最终检查: 地图容器尺寸为0,无法渲染');
+      mapContainer.style.width = '100%';
+      mapContainer.style.height = '600px';
+      setTimeout(() => {
+        this.renderTownshipMap();
+      }, 100);
+      return;
+    }
 
-      // 2. 初始化 ECharts 实例
-      this.townshipMapInstance = echarts.init(mapContainer);
+    console.log(`开始渲染地图,容器尺寸: ${width}x${height}`);
 
-      // 3. 注册地图:将 GeoJSON 数据注册到 ECharts(名称用 countyName:乐昌市)
-      echarts.registerMap(this.countyName, this.townshipGeoJson);
+    // 销毁旧地图实例
+    if (this.townshipMapInstance) {
+      this.townshipMapInstance.remove();
+    }
 
-      // 4. ECharts 配置项(仅显示边界和乡镇名,无数据关联)
-      const option = {
-        // 标题(可选,显示在地图上方)
-        title: {
-          text: '乐昌市乡镇边界',
-          left: 'center',
-          textStyle: { fontSize: 16, fontWeight: 'bold' }
-        },
-        // 提示框(鼠标悬浮时显示乡镇名)
-        tooltip: {
-          trigger: 'item', // 按乡镇区域触发
-          formatter: () => {
-    if (this.isTooltipLoading) {
-      return '<div style="padding: 5px;">加载中...</div>';
-    } else if (this.currentTooltipData) {
-      const detail = this.currentTooltipData;
-      let content = `
-        <div class="town-tooltip">
-          <h3 style="margin: 0 0 5px; color: #0066CC; text-align : center;">${this.currentTooltipTown}</h3>
-          <div style="height: 1px; background-color: #0066CC; margin-bottom: 8px;"></div>
-          <p>采样点数量: ${detail.基础统计.采样点数量}</p>
-          <p>平均值: ${detail.基础统计.平均值.toFixed(4)} mg/kg</p>
-          <p>最小值: ${detail.基础统计.最小值.toFixed(4)} mg/kg</p>
-          <p>最大值: ${detail.基础统计.最大值.toFixed(4)} mg/kg</p>
-          <p>数据更新时间: ${new Date(detail.数据更新时间).toLocaleString()}</p>
-          <div style="height: 1px; background-color: #0066CC; margin-bottom: 8px;"></div>
-          <p style="color:black; font-size:16px;">分布统计:</p>
-          <p>安全区间占比: ${detail.分布统计表格.汇总.安全区间占比}</p>
-          <p>预警区间占比: ${detail.分布统计表格.汇总.预警区间占比}</p>
-          <p>超标区间占比: ${detail.分布统计表格.汇总.超标区间占比}</p>
-        </div>
-      `;
-      return content;
-    } 
-  },
+    // 创建地图实例
+    this.townshipMapInstance = L.map(mapContainer, {
+      zoomControl: false,
+      attributionControl: false
+    });
 
-        },
-        // 地图系列(核心:渲染边界)
-        series: [
-          {
-            type: 'map',
-            map: this.countyName, // 对应注册的地图名称(乐昌市)
-            roam: true, // 允许鼠标缩放、平移地图(方便查看)
-            label: {
-              show: true, // 显示乡镇名称标签
-              fontSize: 10, // 标签字体大小(避免重叠)
-              color: '#333' // 标签颜色
-            },
-            itemStyle: {
-              color: 'transparent', // 乡镇区域填充色(透明,仅显示边界)
-              borderColor: '#000000', // 边界颜色(青色,醒目)
-              borderWidth: 1.5 // 边界宽度
-            },
-            emphasis: {
-              // 鼠标悬浮时的样式(高亮边界和标签)
-              label: { color: '#fff', fontSize: 11 },
-              itemStyle: { color: 'rgba(71, 195, 185, 0.3)' } // 悬浮区域填充色
-            }
+    // 添加缩放控件
+    L.control.zoom({
+      position: 'bottomright'
+    }).addTo(this.townshipMapInstance);
+
+    // 添加空白底图
+    L.tileLayer('').addTo(this.townshipMapInstance);
+
+    // 处理GeoJSON数据
+    const geoJsonLayer = L.geoJSON(this.townshipGeoJson, {
+      style: (feature) => {
+        const townName = feature.properties.name;
+        const townData = this.dataMap[townName];
+        let avgValue = null;
+        
+        if (townData?.data?.基础统计) {
+          avgValue = Number(townData.data.基础统计.平均值);
+        }
+        
+        return {
+          fillColor: this.getColorByCdValue(avgValue),
+          weight: 2,
+          opacity: 1,
+          color: '#000',
+          dashArray: '',
+          fillOpacity: 0.7
+        };
+      },
+      onEachFeature: (feature, layer) => {
+        const townName = feature.properties.name;
+        
+        // 保存原始样式,用于恢复
+        const originalStyle = {
+          weight: 2,
+          color: '#000',
+          dashArray: '',
+          fillOpacity: 0.7,
+          fillColor: this.getColorByCdValue(this.dataMap[townName]?.data?.基础统计?.平均值)
+        };
+        
+        // 鼠标悬停事件 - 修复版本
+        layer.on('mouseover', (e) => {
+          // 高亮当前区域
+          layer.setStyle({
+            weight: 6,
+            color: '#0066CC',
+            dashArray: '',
+            fillOpacity: 0.95
+          });
+          
+          // 显示tooltip
+          this.showTooltip(layer, townName, e.latlng);
+        });
+        
+        // 鼠标离开事件 - 修复版本
+        layer.on('mouseout', (e) => {
+          // 恢复原始样式 - 使用保存的样式而不是resetStyle
+          layer.setStyle(originalStyle);
+          
+          // 正确关闭tooltip
+          if (layer._tooltip) {
+            layer.closeTooltip();
           }
-        ]
-      };
+        });
+        
+        // 点击事件
+        layer.on('click', () => {
+          this.$message.info(`${townName} 的Cd含量数据已显示`);
+        });
+      }
+    }).addTo(this.townshipMapInstance);
 
-      this.townshipMapInstance.setOption(option);
-  // 监听鼠标悬浮事件
-  this.townshipMapInstance.on('mouseover', async (params) => {
-    if (params.componentType === 'series' && params.seriesType === 'map') {
-      const townName = params.name;
-      this.currentTooltipTown = townName;
-      this.isTooltipLoading = true;
-      this.currentTooltipData = null;
-      // 手动触发 tooltip 更新
-      this.townshipMapInstance.setOption({ tooltip: {} });
-      const detail = await this.fetchTownshipDetailByName(townName);
-      this.isTooltipLoading = false;
-      this.currentTooltipData = detail;
-      // 再次手动触发 tooltip 更新,显示获取到的数据
-      this.townshipMapInstance.setOption({ tooltip: {} });
+    // 调整地图视野
+    if (geoJsonLayer.getBounds().isValid()) {
+      // 方式1:完全禁用 fitBounds,直接设置中心和zoom
+      const bounds = geoJsonLayer.getBounds();
+      const center = bounds.getCenter();
+      
+      // 直接设置视图,不使用 fitBounds
+      this.townshipMapInstance.setView(center, 10.5); // 直接设置zoom级别为11
+      
+      console.log(`直接设置地图中心: ${center.lat}, ${center.lng}, zoom: 11`);
+      
+    } else {
+      // 设置默认视图
+      this.townshipMapInstance.setView([25.0, 113.0], 10);
     }
-  });
-  // 监听鼠标移出事件,重置状态
-  this.townshipMapInstance.on('mouseout', () => {
-    this.currentTooltipTown = '';
-    this.currentTooltipData = null;
-    this.isTooltipLoading = false;
-  });
-      // 5. 渲染地图
-      this.townshipMapInstance.setOption(option);
+    
+    console.log('地图渲染完成');
 
-      // 6. 关键修复:添加延迟resize确保地图正确渲染
-      setTimeout(() => {
-        if (this.townshipMapInstance) {
-          this.townshipMapInstance.resize();
-        }
-      }, 100);
-    },
+  } catch (error) {
+    console.error('渲染地图时发生错误:', error);
+    this.$message.error('地图渲染失败: ' + error.message);
+  }
+},
+
+  // 新增:显示tooltip的方法
+// 修复显示tooltip的方法
+showTooltip(layer, townName, latlng) {
+  const townData = this.dataMap[townName];
+  let tooltipContent = `<div class="town-tooltip"><h3>${townName}</h3>`;
+  
+  if (!townData?.data?.基础统计) {
+    tooltipContent += '<p>数据加载中...</p></div>';
+  } else {
+    const stats = townData.data.基础统计;
+    const dist = townData.data.分布统计表格;
+    tooltipContent += `
+      <div style="height:1px;background:#0066CC;margin:5px 0;"></div>
+      <p><strong>样本数量:</strong> ${stats.采样点数量 ?? '无数据'}</p>
+      <p><strong>平均值:</strong> ${stats.平均值?.toFixed(4) ?? '无数据'} mg/kg</p>
+      <p><strong>最小值:</strong> ${stats.最小值?.toFixed(4) ?? '无数据'} mg/kg</p>
+      <p><strong>最大值:</strong> ${stats.最大值?.toFixed(4) ?? '无数据'} mg/kg</p>
+      <div style="height:1px;background:#0066CC;margin:5px 0;"></div>
+      <p><strong>安全区间占比:</strong> ${dist?.汇总?.安全区间占比 ?? '无'}%</p>
+      <p><strong>预警区间占比:</strong> ${dist?.汇总?.预警区间占比 ?? '无'}%</p>
+      <p><strong>超标区间占比:</strong> ${dist?.汇总?.超标区间占比 ?? '无'}%</p>
+    </div>`;
+  }
+  
+  // 先解除之前的tooltip绑定
+  if (layer._tooltip) {
+    layer.unbindTooltip();
+  }
+  
+  // 使用Leaflet的tooltip
+  layer.bindTooltip(tooltipContent, {
+    className: 'custom-town-tooltip',
+    direction: 'top',
+    permanent: false,
+    sticky: true,
+    offset: [0, -10],
+    interactive: false // 确保tooltip不会拦截鼠标事件
+  });
+  
+  // 打开tooltip
+  layer.openTooltip(latlng);
+},
     
     // 上传并计算
     async calculate() {
@@ -584,7 +810,7 @@ export default {
         const formData = new FormData();
         formData.append('area', this.countyName);
         formData.append('data_file', this.selectedFile);
-        formData.append('use_database', 'false'); // 使用上传的文件
+        formData.append('use_database', 'false');
         
         // 调用作物Cd地图接口
         const mapResponse = await api8000.post(
@@ -607,7 +833,7 @@ export default {
         await this.fetchStatistics();
         
         this.$message.success('计算完成!');
-         await this.initTownshipMap();
+        await this.initTownshipMap();
         
       } catch (error) {
         console.error('计算失败:', error);
@@ -641,7 +867,7 @@ export default {
         // 创建FormData
         const formData = new FormData();
         formData.append('area', this.countyName);
-        formData.append('use_database', 'true'); // 使用数据库数据
+        formData.append('use_database', 'true');
         
         // 调用作物Cd地图接口
         const mapResponse = await api8000.post(
@@ -739,13 +965,6 @@ export default {
         this.$message.error('导出数据失败: ' + (error.response?.data?.detail || '请稍后重试'));
       }
     },
-    
-    // 处理窗口大小变化
-    handleResize() {
-      if (this.townshipMapInstance) {
-        this.townshipMapInstance.resize();
-      }
-    },
   }
 };
 </script>
@@ -762,17 +981,91 @@ export default {
   box-sizing: border-box;
 }
 
+.township-map-wrapper {
+  position: relative;
+  width: 100%;
+  max-width: 1000px;
+  margin: 15px auto;
+  border: 1px solid #e0e0e0;
+  border-radius: 8px;
+  background: white;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+  overflow: hidden;
+}
+
+.town-map-title {
+  text-align: center;
+  font-size: 18px;
+  font-weight: bold;
+  background: linear-gradient(135deg, #47C3B9, #36a897);
+  color: white;
+  margin: 0;
+  padding: 12px 0;
+  border-bottom: 1px solid #e0e0e0;
+}
+
+/* 图例样式 */
+.legend {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 15px;
+  margin: 15px 0;
+  padding: 10px;
+  background-color: rgba(255, 255, 255, 0.8);
+  border-radius: 4px;
+}
+
+.legend-item {
+  display: flex;
+  align-items: center;
+  gap: 5px;
+}
+
+.color-box {
+  width: 20px;
+  height: 20px;
+  border: 1px solid #999;
+}
+
+.town-tooltip {
+  min-width: 200px;
+  max-width: 300px;
+}
+
+.town-tooltip h3 {
+  margin: 0 0 5px;
+  color: #0066CC;
+  text-align: center;
+  font-size: 16px;
+}
 
+.town-tooltip p {
+  margin: 2px 0;
+  font-size: 12px;
+  line-height: 1.4;
+}
+
+/* Leaflet地图容器样式 */
 .township-map-container {
-  width: 90%; /* 使用百分比宽度 */
-  max-width: 1000px; /* 最大宽度限制 */
-  height: 500px;
+  width: 100% !important;
+  max-width: 1000px;
+  height: 800px !important;
   border-radius: 4px;
-  background-color: #fff;
-  margin: 15px auto; /* 上下15px,水平自动居中 */
+  background-color: #f5f5f5;
   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  z-index: 10;
+  position: relative;
+  margin: 0 auto;
 }
 
+/* Leaflet自定义tooltip样式 */
+::v-deep .custom-tooltip {
+  background-color: rgba(255, 255, 255, 0.95) !important;
+  border: 1px solid #ccc !important;
+  border-radius: 4px !important;
+  padding: 5px !important;
+  box-shadow: 0 1px 5px rgba(0,0,0,0.2) !important;
+}
 
 .toolbar {
   display: flex;
@@ -838,8 +1131,8 @@ export default {
   padding: 15px;
   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
   position: relative;
-  min-height: 500px;
   backdrop-filter: blur(5px);
+  overflow: visible !important;
 }
 
 .map-image {
@@ -933,55 +1226,6 @@ export default {
   animation: rotate 2s linear infinite;
 }
 
-/* 新增样式 */
-.summary-info {
-  margin-top: 20px;
-}
-
-.card-header {
-  font-weight: bold;
-  color: #409EFF;
-}
-
-.summary-items {
-  display: flex;
-  flex-direction: column;
-  gap: 10px;
-}
-
-.summary-item {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  padding: 8px 0;
-  border-bottom: 1px solid #ebeef5;
-}
-
-.summary-item:last-child {
-  border-bottom: none;
-}
-
-.summary-item .label {
-  font-weight: bold;
-  color: #606266;
-}
-
-.summary-item .value {
-  font-weight: bold;
-}
-
-.summary-item .value.safe {
-  color: #67C23A;
-}
-
-.summary-item .value.warning {
-  color: #E6A23C;
-}
-
-.summary-item .value.danger {
-  color: #F56C6C;
-}
-
 @keyframes rotate {
   from {
     transform: rotate(0deg);
@@ -1014,5 +1258,9 @@ export default {
   .file-name {
     text-align: center;
   }
+  
+  .township-map-container {
+    height: 500px !important;
+  }
 }
-</style>
+</style>