Browse Source

Merge branch 'ding'

# Conflicts:
#	components.d.ts
#	src/views/User/HmOutFlux/atmosDeposition/airInputFlux.vue
yangtaodemon 1 week ago
parent
commit
bba6906bb3

+ 4 - 0
components.d.ts

@@ -39,6 +39,10 @@ declare module 'vue' {
     ElMain: typeof import('element-plus/es')['ElMain']
     ElMain: typeof import('element-plus/es')['ElMain']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
+<<<<<<< HEAD
+=======
+    ElOption: typeof import('element-plus/es')['ElOption']
+>>>>>>> ding
     ElRadio: typeof import('element-plus/es')['ElRadio']
     ElRadio: typeof import('element-plus/es')['ElRadio']
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElRow: typeof import('element-plus/es')['ElRow']

BIN
public/大气通量.jpg


BIN
src/assets/bg/background.jpg


+ 20 - 1
src/components/layout/AppLayout.vue

@@ -110,6 +110,25 @@ const bgRouteMap: Record<string, string> = {
   //添加地表径流相关页面的背景图
   //添加地表径流相关页面的背景图
   "/samplingDesc4": "surface-runoff.jpg",
   "/samplingDesc4": "surface-runoff.jpg",
   "/surfaceRunoffInputFlux": "surface-runoff.jpg",
   "/surfaceRunoffInputFlux": "surface-runoff.jpg",
+  "/totalInputFlux": "background.jpg",
+  "/totalOutputFlux": "background.jpg",
+  "/netFlux": "background.jpg",
+  "/currentYearConcentration": "background.jpg",
+  "/TotalCadmiumPrediction": "background.jpg",
+  "/EffectiveCadmiumPrediction": "background.jpg",
+  "/CropCadmiumPrediction": "background.jpg",
+  "/cropRiskAssessment": "background.jpg",
+  "/farmlandQualityAssessment": "background.jpg",
+  "/Calculation": "background.jpg",
+  "/SoilAcidReductionIterativeEvolution": "background.jpg",
+  "/AcidNeutralizationModel": "background.jpg",
+  "/SoilAcidificationIterativeEvolution": "background.jpg",
+  "/TraditionalFarmingRisk": "background.jpg",
+  "/HeavyMetalCadmiumControl": "background.jpg",
+  "/SoilAcidificationControl": "background.jpg",
+  "/DetectionStatistics": "background.jpg",
+  "/FarmlandPollutionStatistics": "background.jpg",
+  "/PlantingRiskStatistics": "background.jpg",
 };
 };
 
 
 // 当前是否为特殊背景图页面
 // 当前是否为特殊背景图页面
@@ -120,7 +139,7 @@ function getBgImageUrl(): string {
   console.log("根据路径查找背景文件名:", bgFile);
   console.log("根据路径查找背景文件名:", bgFile);
   if (bgFile) {
   if (bgFile) {
     try {
     try {
-      const url = `url(${new URL(`../../assets/bg/${bgFile}`, import.meta.url).href})`;
+      const url = `url(${new URL(`../../assets/bg/background.jpg`, import.meta.url).href})`;
       return url;
       return url;
     } catch (error) {
     } catch (error) {
       console.error("加载背景图失败:", error);
       console.error("加载背景图失败:", error);

+ 92 - 11
src/views/User/HmOutFlux/atmosDeposition/airInputFlux.vue

@@ -1,23 +1,104 @@
 <template>
 <template>
-  <div class="">
-    
+  <div class="atmosphere-flux-container">
+    <div class="map-title">大气通量分布图</div>
+    <div class="map-image-container">
+      <img 
+        src="/大气通量.jpg" 
+        alt="大气通量分布图" 
+        class="map-image"
+      >
+    </div>
   </div>
   </div>
 </template>
 </template>
 
 
 <script>
 <script>
 export default {
 export default {
-  name: '',
-  data() {
-    return {
-      
-    };
-  },
-  methods: {
-    
-  }
+  name: 'AtmosphereFluxMap',
 };
 };
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
+<<<<<<< HEAD
+
+=======
+.atmosphere-flux-container {
+  width: 100%;
+  max-width: 900px;
+  margin: 0 auto;
+  background: white;
+  border-radius: 12px;
+  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
+  overflow: hidden;
+  font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
+}
+
+.map-title {
+  background: linear-gradient(to right, #1a5fad, #2c8fd1);
+  color: white;
+  text-align: center;
+  padding: 18px 0;
+  font-size: 1.8rem;
+  font-weight: 600;
+  letter-spacing: 1px;
+  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
+}
+
+.map-image-container {
+  padding: 25px;
+  background: #f8fafc;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  min-height: 500px;
+}
+
+.map-image {
+  max-width: 100%;
+  max-height: 100%;
+  object-fit: contain;
+  border: 1px solid #e0e7ff;
+  border-radius: 8px;
+  box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
+  transition: transform 0.3s ease;
+}
+
+.map-image:hover {
+  transform: scale(1.02);
+}
+
+.map-footer {
+  background: #f1f5f9;
+  padding: 15px 0;
+  text-align: center;
+  font-size: 0.95rem;
+  color: #4b5563;
+  border-top: 1px solid #e5e7eb;
+}
 
 
+@media (max-width: 768px) {
+  .map-title {
+    font-size: 1.5rem;
+    padding: 15px 0;
+  }
+  
+  .map-image-container {
+    padding: 15px;
+    min-height: 350px;
+  }
+  
+  .map-footer {
+    font-size: 0.85rem;
+  }
+}
+
+@media (max-width: 480px) {
+  .map-title {
+    font-size: 1.3rem;
+  }
+  
+  .map-image-container {
+    min-height: 280px;
+  }
+}
+>>>>>>> ding
 </style>
 </style>

+ 26 - 9
src/views/User/HmOutFlux/irrigationWater/irriWaterInputFlux.vue

@@ -1,7 +1,7 @@
 <template>
 <template>
-  <div class="irrigation-management">
+   <div class="irrigation-management" style="display: flex; justify-content: center;">
     <!-- 计算页面 -->
     <!-- 计算页面 -->
-    <div v-if="showCalculation">
+    <div v-if="showCalculation" class="page-container">
       <el-card shadow="always" class="gradient-card">
       <el-card shadow="always" class="gradient-card">
         <el-radio-group v-model="selectedLandType" style="width: 100%;">
         <el-radio-group v-model="selectedLandType" style="width: 100%;">
           <!-- 水地 -->
           <!-- 水地 -->
@@ -99,7 +99,7 @@
     </div>
     </div>
 
 
     <!-- 结果页面 -->
     <!-- 结果页面 -->
-    <div v-if="showResults">
+    <div v-if="showResults" class="page-container">
       <el-card shadow="always" class="results-card">
       <el-card shadow="always" class="results-card">
         <div class="results-header">
         <div class="results-header">
           <el-button 
           <el-button 
@@ -113,16 +113,11 @@
         
         
         <div class="results-container">
         <div class="results-container">
           <el-row :gutter="20" style="margin-top: 30px;">
           <el-row :gutter="20" style="margin-top: 30px;">
-            <el-col :span="12">
+            <el-col :span="24">
               <div class="result-subtitle">Cd含量地图</div>
               <div class="result-subtitle">Cd含量地图</div>
               <img v-if="mapImageUrl" :src="mapImageUrl" alt="Cd含量地图" class="result-image">
               <img v-if="mapImageUrl" :src="mapImageUrl" alt="Cd含量地图" class="result-image">
               <div v-else class="image-placeholder">地图加载中...</div>
               <div v-else class="image-placeholder">地图加载中...</div>
             </el-col>
             </el-col>
-            <el-col :span="12">
-              <div class="result-subtitle">Cd含量直方图</div>
-              <img v-if="histogramImageUrl" :src="histogramImageUrl" alt="Cd含量直方图" class="result-image">
-              <div v-else class="image-placeholder">直方图加载中...</div>
-            </el-col>
           </el-row>
           </el-row>
           
           
           <el-row style="margin-top: 30px;">
           <el-row style="margin-top: 30px;">
@@ -736,4 +731,26 @@ export default {
 .back-button:hover {
 .back-button:hover {
   background: linear-gradient(to right, #7de8df, #20a03d);
   background: linear-gradient(to right, #7de8df, #20a03d);
 }
 }
+.irrigation-management {
+  width: 100%;
+}
+
+.page-container {
+  width: 100%;
+  display: flex;
+  justify-content: center;
+  max-width: 1200px;
+}
+
+/* 调整卡片宽度 */
+.gradient-card {
+  width: 90% !important;
+  max-width: 800px;
+}
+
+.results-card {
+  width: 95% !important;
+  max-width: 1200px;
+}
+
 </style>
 </style>

+ 461 - 125
src/views/User/farmlandQualityAssessment/farmlandQualityAssessment.vue

@@ -1,187 +1,523 @@
 <template>
 <template>
   <div>
   <div>
-    <!-- 三个按钮 -->
-    <div class="button-container">
-      <!-- 优先保护类按钮 -->
-      <el-button class="custom-button priority" @click="handleClick('优先保护类', '#4E94F4')">优先保护类</el-button>
-      <!-- 安全利用类按钮 -->
-      <el-button class="custom-button safe" @click="handleClick('安全利用类', '#26BB91')">安全利用类</el-button>
-      <!-- 严格管控类按钮 -->
-      <el-button class="custom-button strict" @click="handleClick('严格管控类', '#77B369')">严格管控类</el-button>
-    </div>
-
-    <!-- 文字和图表区域,只有选中按钮后才显示 -->
-    <div v-show="selectedText" class="info-section">
-      <!-- 显示选中的类别文字 -->
-      <div class="selected-text" :style="{ color: selectedColor }">{{ selectedText }}</div>
-
-      <!-- 图表区域 -->
-      <div class="charts">
-        <!-- 柱状图容器 -->
-        <div ref="barChart" class="chart"></div>
-        <!-- 饼图容器 -->
-        <div ref="pieChart" class="chart"></div>
+    <!-- 顶部信息卡片区域 -->
+    <div class="dashboard">
+      <!-- 合并的统计与分布卡片 -->
+      <div class="dashboard-card combined-card">
+        <div class="card-title">统计与分布</div>
+        <div class="combined-content">
+          <!-- 左侧:单元统计 -->
+          <div class="statistics-section">
+            <h3>单元统计</h3>
+            <div class="statistics">
+              <div class="stat-item">
+                <div class="stat-value">{{ statistics.total_units }}</div>
+                <div class="stat-label">总单元数</div>
+              </div>
+              <div class="stat-item">
+                <div class="stat-value">{{ statistics.units_with_data }}</div>
+                <div class="stat-label">有数据单元</div>
+              </div>
+              <!-- 仅当无数据单元数不为0时显示 -->
+              <div class="stat-item" v-if="statistics.units_without_data !== 0">
+                <div class="stat-value">{{ statistics.units_without_data }}</div>
+                <div class="stat-label">无数据单元</div>
+              </div>
+            </div>
+          </div>
+          
+          <!-- 右侧:分类分布 -->
+          <div class="distribution-section">
+            <h3>分类分布</h3>
+            <div class="distribution">
+              <div v-for="(count, category) in statistics.category_distribution" :key="category" 
+                  class="category-dist" :style="{ backgroundColor: categoryColors[category] }">
+                <div class="dist-category">{{ category }}</div>
+                <div class="dist-count">{{ count }}</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      
+      <!-- 饼图卡片 -->
+      <div class="dashboard-card chart-card">
+        <div class="card-title">点位分类分布</div>
+        <div ref="pointPieChart" class="chart"></div>
       </div>
       </div>
     </div>
     </div>
+    
+    <!-- 地图区域 -->
+    <div class="map-area">
+      <div class="map-title">土壤分类分布地图</div>
+      <div ref="mapContainer" class="map-container"></div>
+    </div>
   </div>
   </div>
 </template>
 </template>
 
 
 <script>
 <script>
-import * as echarts from 'echarts'; // 引入echarts库
+import * as echarts from 'echarts';
+
+// 分类颜色配置
+const categoryColors = {
+  '优先保护类': 'rgba(255, 214, 0, 0.7)', // #FFD600 转换为RGBA
+  '安全利用类': 'rgba(0, 200, 83, 0.7)', // #00C853 转换为RGBA
+  '严格管控类': 'rgba(213, 0, 0, 0.7)'   // #D50000 转换为RGBA
+};
 
 
 export default {
 export default {
-  name: 'CategoryButtons',
+  name: 'CategoryMap',
   data() {
   data() {
     return {
     return {
-      selectedText: '',        // 当前选中的类别文字
-      selectedColor: '',       // 当前选中的类别颜色
-      barChartInstance: null,  // 柱状图实例
-      pieChartInstance: null   // 饼图实例
+      map: null,
+      geoJSONLayer: null,
+      multiPolygon: null, 
+      categoryColors,
+      statistics: {
+        total_units: 0,
+        units_with_data: 0,
+        units_without_data: 0,
+        category_distribution: {
+          '优先保护类': 0,
+          '安全利用类': 0,
+          '严格管控类': 0
+        },
+        point_distribution: {
+          '优先保护类': 0,
+          '安全利用类': 0,
+          '严格管控类': 0
+        }
+      },
+      groupingData: [] // 存储接口数据
     };
     };
   },
   },
-  mounted() {
-  // 默认选中“优先保护类”
-  this.handleClick('优先保护类', '#4E94F4');
-},
+  async mounted() {
+    // 获取分类数据
+    await this.fetchGroupingData();
+    
+    // 初始化地图
+    await this.initMap();
+    
+    // 初始化点位分布饼图
+    this.initPointPieChart();
+  },
   methods: {
   methods: {
-    // 按钮点击事件,设置类别和颜色,并生成随机数据
-    handleClick(category, color) {
-      this.selectedText = category;
-      this.selectedColor = color;
-
-      // 模拟柱状图数据
-      const barData = [
-        { name: 'A', value: Math.floor(Math.random() * 100) },
-        { name: 'B', value: Math.floor(Math.random() * 100) },
-        { name: 'C', value: Math.floor(Math.random() * 100) }
-      ];
-
-      // 模拟饼图数据
-      const pieData = [
-        { name: 'X', value: Math.floor(Math.random() * 100) },
-        { name: 'Y', value: Math.floor(Math.random() * 100) },
-        { name: 'Z', value: Math.floor(Math.random() * 100) }
-      ];
-
-      // 等DOM更新后初始化图表
-      this.$nextTick(() => {
-        this.initBarChart(barData);
-        this.initPieChart(pieData);
+    // 获取分类数据
+    async fetchGroupingData() {
+      try {
+        const response = await fetch(`http://localhost:8000/api/unit-grouping/h_xtfx`);
+        const result = await response.json();
+        
+        if (result.success) {
+          this.groupingData = result.data;
+          this.statistics = result.statistics;
+        }
+      } catch (error) {
+        console.error('获取分类数据失败:', error);
+      }
+    },
+    
+    // 初始化地图
+    async initMap() {
+      // 加载TMap SDK
+      const TMap = await this.loadSDK();
+      
+      // 创建地图实例
+      this.map = new TMap.Map(this.$refs.mapContainer, {
+        center: new TMap.LatLng(24.81088, 113.59762),
+        zoom: 12,
+        mapStyleId: 'style1'
       });
       });
+      
+      // 加载GeoJSON数据
+      const geojsonData = await this.loadGeoJSON('https://soilgd.com/data/单元格.geojson');
+      
+      // 初始化GeoJSON图层 - 传递TMap对象
+      this.initMapWithGeoJSON(geojsonData, TMap);
     },
     },
-
-    // 初始化柱状图
-    initBarChart(data) {
-      // 如果实例不存在则初始化
-      if (!this.barChartInstance) {
-        this.barChartInstance = echarts.init(this.$refs.barChart);
-      }
-      // 柱状图配置项
-      const option = {
-        title: { text: '柱状图', left: 'center' },
-        xAxis: { type: 'category', data: data.map(d => d.name) },
-        yAxis: { type: 'value' },
-        series: [
-          {
-            data: data.map(d => d.value),
-            type: 'bar',
-            itemStyle: {
-              color: this.selectedColor // 使用选中的颜色
-            }
+    
+    // 加载SDK
+    loadSDK() {
+      return new Promise((resolve, reject) => {
+        if (window.TMap) return resolve(window.TMap);
+        
+        const script = document.createElement('script');
+        script.src = `https://map.qq.com/api/gljs?v=2.exp&libraries=basic,service,vector&key=${import.meta.env.VITE_TMAP_KEY}&callback=initTMap`;
+        
+        window.initTMap = () => {
+          if (!window.TMap) {
+            reject(new Error('TMap SDK 加载失败'));
+            return;
           }
           }
-        ]
-      };
-      // 设置配置项
-      this.barChartInstance.setOption(option);
+          resolve(window.TMap);
+        };
+        
+        script.onerror = (err) => {
+          reject(new Error('加载地图SDK失败'));
+          document.head.removeChild(script);
+        };
+        
+        document.head.appendChild(script);
+      });
+    },
+    
+    // 加载GeoJSON数据
+    async loadGeoJSON(url) {
+      try {
+        const response = await fetch(url);
+        if (!response.ok) {
+          throw new Error(`加载GeoJSON失败: ${response.statusText}`);
+        }
+        return await response.json();
+      } catch (error) {
+        console.error('加载GeoJSON数据失败:', error);
+        return { type: 'FeatureCollection', features: [] };
+      }
     },
     },
+    
+    // 初始化GeoJSON图层 - 使用MultiPolygon的setStyles方法
+    initMapWithGeoJSON(geojsonData, TMap) {
+      try {
+        // 创建分类映射表
+        const categoryMap = {};
+        this.groupingData.forEach(item => {
+          categoryMap[item.OBJECTID] = item.h_xtfx;
+        });
+        
+        // 处理GeoJSON特征
+        geojsonData.features.forEach(feature => {
+          const objectId = feature.properties.OBJECTID;
+          const category = categoryMap[objectId];
+          
+          // 添加分类属性
+          feature.properties.category = category;
+        });
+        
+        // 检查TMap对象是否有效
+        if (!TMap || !TMap.PolygonStyle) {
+          throw new Error('TMap对象无效,缺少PolygonStyle');
+        }
+        
+        // 创建GeoJSON图层
+        this.geoJSONLayer = new TMap.vector.GeoJSONLayer({
+          map: this.map,
+          data: geojsonData,
+          polygonStyle: new TMap.PolygonStyle({
+            color: 'rgba(0,0,0,0)',
+            showBorder: false
+          })
+        });
 
 
-    // 初始化饼图
-    initPieChart(data) {
-      // 如果实例不存在则初始化
-      if (!this.pieChartInstance) {
-        this.pieChartInstance = echarts.init(this.$refs.pieChart);
+        
+        // 获取多边形覆盖层
+        this.multiPolygon = this.geoJSONLayer.getGeometryOverlay('polygon');
+        this.multiPolygon.setMap(this.map);
+        const polygons = this.multiPolygon.getGeometries();
+        
+        // 创建样式映射
+        const styles = {};
+        
+        // 遍历所有多边形,为每个多边形设置样式和唯一ID
+        // 遍历所有多边形,为每个多边形设置样式
+        polygons.forEach((polygon) => {
+          // 直接访问properties属性
+          const properties = polygon.properties;
+          const category = properties.category;
+          
+          // 使用多边形的id作为样式ID的键
+          const styleId = `style_${polygon.id}`;
+          
+          // 根据分类设置颜色
+          const color = category ? this.categoryColors[category] : '#CCCCCC';
+          
+          // 添加样式到映射表
+          styles[styleId] = new TMap.PolygonStyle({
+            color: color,
+            showBorder: true,
+            borderColor: '#000000',
+            borderWidth: 2
+          });
+          
+          // 关键修复:为每个多边形设置样式ID(正确方式)
+          polygon.styleId = styleId; // 直接设置属性
+        });
+        // 使用setStyles方法一次性设置所有样式
+        this.multiPolygon.setStyles(styles);
+        
+        // 更新几何体以应用新样式
+        this.multiPolygon.updateGeometries(polygons);
+        
+      
+      } catch (error) {
+        console.error('初始化GeoJSON图层失败:', error);
       }
       }
-      // 饼图配置项
+    },
+    
+    // 初始化点位分布饼图
+    initPointPieChart() {
+      const chartDom = this.$refs.pointPieChart;
+      if (!chartDom) return;
+      
+      const chart = echarts.init(chartDom);
+      
+      // 准备饼图数据
+      const pieData = Object.entries(this.statistics.category_distribution).map(([name, value]) => ({
+        name,
+        value,
+        itemStyle: { color: this.categoryColors[name] || '#CCCCCC' }
+      }));
+      
       const option = {
       const option = {
-        title: { text: '饼图', left: 'center' },
-        tooltip: { trigger: 'item' },
+        title: {
+          text: '点位分类分布',
+          left: 'center',
+          textStyle: {
+            fontSize: 18,
+            fontWeight: 'bold'
+          }
+        },
+        tooltip: {
+          trigger: 'item',
+          formatter: '{b}: {c} ({d}%)'
+        },
+        legend: {
+          orient: 'horizontal',
+          bottom: 10,
+          data: Object.keys(this.statistics.point_distribution)
+        },
         series: [
         series: [
           {
           {
+            name: '点位分布',
             type: 'pie',
             type: 'pie',
-            radius: '60%',
-            data,
+            radius: ['40%', '70%'],
+            center: ['50%', '45%'],
+            avoidLabelOverlap: true,
+            itemStyle: {
+              borderRadius: 10,
+              borderColor: '#fff',
+              borderWidth: 2
+            },
+            label: {
+              show: true,
+              formatter: '{b}: {c}\n({d}%)',
+              fontSize: 14
+            },
             emphasis: {
             emphasis: {
+              label: {
+                show: true,
+                fontSize: 16,
+                fontWeight: 'bold'
+              },
               itemStyle: {
               itemStyle: {
                 shadowBlur: 10,
                 shadowBlur: 10,
                 shadowOffsetX: 0,
                 shadowOffsetX: 0,
                 shadowColor: 'rgba(0, 0, 0, 0.5)'
                 shadowColor: 'rgba(0, 0, 0, 0.5)'
               }
               }
-            }
+            },
+            data: pieData
           }
           }
         ]
         ]
       };
       };
-      // 设置配置项
-      this.pieChartInstance.setOption(option);
+      
+      chart.setOption(option);
+      
+      // 响应式调整
+      window.addEventListener('resize', () => {
+        chart.resize();
+      });
     }
     }
-  },
-  
+  }
 };
 };
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
-.button-container {
+/* 顶部信息卡片区域 */
+.dashboard {
   display: flex;
   display: flex;
-  justify-content: space-between;
-  padding: 56px 350px 0 350px;
+  flex-wrap: wrap;
+  gap: 20px;
+  margin-bottom: 20px;
 }
 }
 
 
-.custom-button {
-  width: 320px;
-  height: 120px;
-  font-size: 36px;
-  font-weight: bold;
-  color: #fff;
-  border: none;
-  border-radius: 8px;
+.dashboard-card {
+  flex: 1;
+  min-width: 280px;
+  background: white;
+  border-radius: 12px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+  padding: 20px;
+  transition: transform 0.3s ease;
 }
 }
 
 
-.priority {
-  background-color: #4E94F4; /* 优先保护类按钮颜色 */
+.dashboard-card:hover {
+  transform: translateY(-3px);
 }
 }
 
 
-.safe {
-  background-color: #26BB91; /* 安全利用类按钮颜色 */
+.chart-card {
+  min-width: 350px;
+  display: flex;
+  flex-direction: column;
 }
 }
 
 
-.strict {
-  background-color: #77B369; /* 严格管控类按钮颜色 */
+.combined-card {
+  min-width: 500px;
 }
 }
 
 
-.info-section {
-  margin-top: 30px;
-  margin-left: 50px;
+.card-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #1a1a1a;
+  padding-bottom: 12px;
+  margin-bottom: 15px;
+  border-bottom: 1px solid #eee;
 }
 }
 
 
-.selected-text {
-  font-size: 36px;
-  font-weight: bold;
-  margin-bottom: 20px;
+/* 合并内容样式 */
+.combined-content {
+  display: flex;
+  gap: 20px;
+}
+
+.statistics-section, .distribution-section {
+  flex: 1;
+}
+
+.statistics-section h3, .distribution-section h3 {
+  font-size: 16px;
+  font-weight: 600;
+  margin-bottom: 15px;
+  color: #409EFF;
+  text-align: center;
 }
 }
 
 
-.charts {
+/* 统计信息样式 */
+.statistics {
   display: flex;
   display: flex;
-  justify-content: center;
-  gap: 100px; /* 图表之间的间距 */
-  flex-wrap: wrap; /* 可选:小屏幕时换行显示 */
-  margin-top: 20px;
+  flex-direction: column;
+  gap: 15px;
+}
+
+.stat-item {
+  text-align: center;
+  padding: 15px;
+  background: #f8fafc;
+  border-radius: 8px;
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
+  transition: all 0.3s ease;
+}
+
+.stat-item:hover {
+  transform: translateY(-3px);
+  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
+}
+
+.stat-value {
+  font-size: 26px;
+  font-weight: 700;
+  color: #409EFF;
+  margin-bottom: 5px;
+}
+
+.stat-label {
+  font-size: 14px;
+  color: #666;
+}
+
+/* 分类分布样式 */
+.distribution {
+  display: flex;
+  flex-direction: column;
+  gap: 12px;
+}
+
+.category-dist {
+  padding: 15px;
+  border-radius: 8px;
+  color: white;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
+  transition: transform 0.2s ease;
+}
+
+.category-dist:hover {
+  transform: scale(1.02);
 }
 }
 
 
+.dist-category {
+  font-size: 16px;
+  font-weight: 600;
+}
+
+.dist-count {
+  font-size: 24px;
+  font-weight: bold;
+}
+
+/* 饼图样式 */
 .chart {
 .chart {
-  width: 600px;
-  height: 450px;
-  background-color: #fff;
+  height: 300px;
+  width: 100%;
+  margin-top: 10px;
+}
+
+/* 地图区域样式 */
+.map-area {
+  margin-top: 20px;
+  background: white;
   border-radius: 12px;
   border-radius: 12px;
-  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+  overflow: hidden;
+}
+
+.map-title {
+  font-size: 18px;
+  font-weight: 600;
+  padding: 15px 25px;
+  background-color: #f8fafc;
+  border-bottom: 1px solid #eee;
 }
 }
 
 
+.map-container {
+  width: 100%;
+  height: 60vh; /* 调整为60vh,更紧凑 */
+  min-height: 400px; /* 降低最小高度 */
+  max-height: 700px; /* 添加最大高度限制 */
+}
+
+/* 响应式调整 */
+@media (max-width: 992px) {
+  .dashboard {
+    flex-direction: column;
+  }
+  
+  .dashboard-card {
+    width: 100%;
+  }
+  
+  .combined-content {
+    flex-direction: column;
+  }
+  
+  .combined-card, .chart-card {
+    min-width: 100%;
+  }
+  
+  /* 移动设备上地图高度调整 */
+  .map-container {
+    height: 55vh;
+    min-height: 350px;
+    max-height: 600px;
+  }
+}
+
+/* 小屏幕设备进一步调整 */
+@media (max-width: 768px) {
+  .map-container {
+    height: 50vh;
+    min-height: 300px;
+    max-height: 500px;
+  }
+}
 </style>
 </style>