Explorar o código

修改通量Cd的数据展示

yes-yes-yes-k hai 2 días
pai
achega
6a378c907a
Modificáronse 1 ficheiros con 188 adicións e 134 borrados
  1. 188 134
      src/components/soilcdStatistics/fluxcdStatictics.vue

+ 188 - 134
src/components/soilcdStatistics/fluxcdStatictics.vue

@@ -8,45 +8,47 @@
         </div>
       </div>
     </div>
-    
-    <!-- 加载状态 & 错误提示 -->
-    <div v-if="isLoading" class="fixed inset-0 bg-white bg-opacity-80 flex items-center justify-center z-50">
-      <div class="text-center">
-        <div class="spinner mx-auto"></div>
-        <p class="mt-4 text-gray-700">数据加载中,请稍候...</p>
-        <p class="text-sm text-gray-500 mt-2">正在初始化图表容器</p>
-      </div>
-    </div>
+  
     <div v-if="error" class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-6">
       <p>数据加载失败: {{ error.message }}</p>
       <button class="mt-2 px-3 py-1 bg-red-500 text-white rounded" @click="initCharts">重试</button>
     </div>
     
     <!-- 1. 初始Cd 单独箱线图 -->
-    <section class="mb-6 chart-container" v-if="!isLoading && !error">
-      <h3 class="section-title text-base font-semibold">初始Cd(Initial_Cd)分布箱线图</h3>
-      <div ref="initialCdChart" style="width: 100%; height: 400px;"></div>
-      <div v-if="!chartInstanceInitial" class="bg-yellow-50 border border-yellow-200 p-4 rounded mt-4">
-        <p class="text-yellow-700">图表初始化中...</p>
-        <button class="mt-2 px-3 py-1 bg-yellow-500 text-white rounded" @click="initInitialCdChart">
-          重新尝试初始化
-        </button>
-      </div>
-    </section>
-    
-    <!-- 2. 其他指标 合并箱线图 -->
-    <section class="mb-6 chart-container" v-if="!isLoading && !error">
-      <div class="flex flex-wrap justify-between items-center mb-4">
-        <h3 class="section-title text-base font-semibold">其他通量Cd指标分布箱线图</h3>
-      </div>
-      <div ref="otherIndicatorsChart" style="width: 100%; height: 400px;"></div>
-      <div v-if="!chartInstanceOther" class="bg-yellow-50 border border-yellow-200 p-4 rounded mt-4">
-        <p class="text-yellow-700">图表初始化中...</p>
-        <button class="mt-2 px-3 py-1 bg-yellow-500 text-white rounded" @click="initOtherIndicatorsChart">
-          重新尝试初始化
-        </button>
-      </div>
-    </section>
+<section class="mb-6 chart-container">
+  <h3 class="section-title text-base font-semibold">初始Cd(Initial_Cd)分布箱线图</h3>
+  <div ref="initialCdChart" style="width: 100%; height: 400px;"></div>
+  <!-- 容器内的加载遮罩 -->
+  <div v-if="isLoading" class="absolute inset-0 bg-white bg-opacity-80 flex items-center justify-center">
+    <div class="spinner"></div>
+  </div>
+  <!-- 错误提示(保留重试按钮) -->
+  <div v-if="error && !chartInstanceInitial" class="bg-yellow-50 border border-yellow-200 p-4 rounded mt-4">
+    <p class="text-yellow-700">图表初始化失败: {{ error.message }}</p>
+    <button class="mt-2 px-3 py-1 bg-yellow-500 text-white rounded" @click="initInitialCdChart">
+      重新尝试初始化
+    </button>
+  </div>
+</section>
+
+<!-- 2. 其他指标 合并箱线图 -->
+<section class="mb-6 chart-container">
+  <div class="flex flex-wrap justify-between items-center mb-4">
+    <h3 class="section-title text-base font-semibold">其他通量Cd指标分布箱线图</h3>
+  </div>
+  <div ref="otherIndicatorsChart" style="width: 100%; height: 400px;"></div>
+  <!-- 容器内的加载遮罩 -->
+  <div v-if="isLoading" class="absolute inset-0 bg-white bg-opacity-80 flex items-center justify-center">
+    <div class="spinner"></div>
+  </div>
+  <!-- 错误提示(保留重试按钮) -->
+  <div v-if="error && !chartInstanceOther" class="bg-yellow-50 border border-yellow-200 p-4 rounded mt-4">
+    <p class="text-yellow-700">图表初始化失败: {{ error.message }}</p>
+    <button class="mt-2 px-3 py-1 bg-yellow-500 text-white rounded" @click="initOtherIndicatorsChart">
+      重新尝试初始化
+    </button>
+  </div>
+</section>
   </div>
 </template>
 
@@ -129,18 +131,28 @@ const calculateFieldStats = (data, fieldKey, fieldName) => {
   const rawValues = data.map(item => item[fieldKey]);
   const values = rawValues
     .map((val, idx) => {
+      // 更严格的数值校验
+      if (val === null || val === undefined || val === '' || isNaN(Number(val))) {
+        log(`无效数据: ${fieldName} 第${idx+1}条 → ${val}`, fieldName);
+        return null;
+      }
       const num = Number(val);
-      if (isNaN(num)) log(`无效数据: ${fieldName} 第${idx+1}条 →`, val);
-      return isNaN(num) ? null : num;
+      // 过滤极端值(根据业务需求调整阈值)
+      if (num < -1000000 || num > 1000000) {
+        log(`极端值过滤: ${fieldName} 第${idx+1}条 → ${num}`, fieldName);
+        return null;
+      }
+      return num;
     })
     .filter(v => v !== null);
-  //console.log(`${fieldName}有效数据量:`,values.length);
   
+  // 处理无有效数据的情况
   if (values.length === 0) {
-    log(`无有效数据: ${fieldName}`);
+    log(`无有效数据: ${fieldName}`, fieldName);
     return { key: fieldKey, name: fieldName, min: null, q1: null, median: null, q3: null, max: null };
   }
   
+  // 排序并计算分位数(保持原逻辑)
   const sorted = [...values].sort((a, b) => a - b);
   const min = sorted[0];
   const max = sorted[sorted.length - 1];
@@ -186,119 +198,131 @@ const buildBoxplotData = (statsArray) => {
 };
 
 // 初始化【初始Cd】图表(独立箱线图)
-const initInitialCdChart = (retryCount = 0) => {
-  // 容器检查与重试机制
+const initInitialCdChart = () => {
+  // 容器存在性检查
   if (!initialCdChart.value) {
-    if (retryCount < 10) {
-      console.warn(`initialCdChart容器未找到,第${retryCount+1}次重试...`);
-      setTimeout(() => initInitialCdChart(retryCount + 1), 100);
-      return;
-    } else {
-      console.error('initialCdChart容器未找到,重试超时');
-      return;
-    }
+    console.error('initialCdChart容器未找到');
+    error.value = new Error('初始Cd图表容器未找到,请刷新页面重试');
+    return;
   }
   
   // 容器尺寸检查
-  if (initialCdChart.value.offsetWidth === 0 || initialCdChart.value.offsetHeight === 0) {
-    if (retryCount < 5) {
-      setTimeout(() => initInitialCdChart(retryCount + 1), 200);
-      return;
-    }
+  const { offsetWidth, offsetHeight } = initialCdChart.value;
+  if (offsetWidth === 0 || offsetHeight === 0) {
+    console.error('initialCdChart容器尺寸异常', { offsetWidth, offsetHeight });
+    error.value = new Error('初始Cd图表容器尺寸异常,请检查页面样式');
+    return;
   }
 
-  if (chartInstanceInitial.value) chartInstanceInitial.value.dispose();
-  chartInstanceInitial.value = echarts.init(initialCdChart.value);
-  const xAxisData = fieldConfig.initialCd.map(ind => ind.name);
-  const boxData = buildBoxplotData(initialCdStats.value);
+  // 销毁旧实例
+  if (chartInstanceInitial.value) {
+    chartInstanceInitial.value.dispose();
+  }
   
-  chartInstanceInitial.value.setOption({
-    title: { text: '初始Cd分布箱线图', left: 'center', textStyle: { fontSize: 14 } },
-    tooltip: {
-      trigger: "item",
-      formatter: (params) => formatTooltip(initialCdStats.value[params.dataIndex])
-    },
-    grid: { top: 60, right: 30, bottom: 25, left: 60 },
-    xAxis: { 
-      type: "category", 
-      data: xAxisData,
-      axisLabel: { fontSize: 12 }
-    },
-    yAxis: { 
-      type: "value", 
-      name: 'g/ha', 
-      nameTextStyle: { fontSize: 12 }, 
-      axisLabel: { fontSize: 11 },
-      scale: true
-    },
-    series: [{
-      name: '初始Cd', 
-      type: "boxplot",
-      itemStyle: { 
-        color: (p) => fieldConfig.initialCd[p.dataIndex].color,
-        borderWidth: 2 
+  // 初始化图表
+  try {
+    chartInstanceInitial.value = echarts.init(initialCdChart.value);
+    const xAxisData = fieldConfig.initialCd.map(ind => ind.name);
+    const boxData = buildBoxplotData(initialCdStats.value);
+    
+    chartInstanceInitial.value.setOption({
+      // 保持原配置不变...
+      title: { text: '初始Cd分布箱线图', left: 'center', textStyle: { fontSize: 14 } },
+      tooltip: {
+        trigger: "item",
+        formatter: (params) => formatTooltip(initialCdStats.value[params.dataIndex])
       },
-      data: boxData
-    }]
-  });
+      grid: { top: 60, right: 30, bottom: 25, left: 60 },
+      xAxis: { 
+        type: "category", 
+        data: xAxisData,
+        axisLabel: { fontSize: 12 }
+      },
+      yAxis: { 
+        type: "value", 
+        name: 'g/ha', 
+        nameTextStyle: { fontSize: 12 }, 
+        axisLabel: { fontSize: 11 },
+        scale: true
+      },
+      series: [{
+        name: '初始Cd', 
+        type: "boxplot",
+        itemStyle: { 
+          color: (p) => fieldConfig.initialCd[p.dataIndex].color,
+          borderWidth: 2 
+        },
+        data: boxData
+      }]
+    });
+  } catch (err) {
+    console.error('初始Cd图表初始化失败', err);
+    error.value = new Error(`初始Cd图表初始化失败: ${err.message}`);
+  }
 };
 
+
 // 初始化【其他指标】合并图表
-const initOtherIndicatorsChart = (retryCount = 0) => {
+const initOtherIndicatorsChart = () => {
+  // 容器存在性检查
   if (!otherIndicatorsChart.value) {
-    if (retryCount < 10) {
-      console.warn(`otherIndicatorsChart容器未找到,第${retryCount+1}次重试...`);
-      setTimeout(() => initOtherIndicatorsChart(retryCount + 1), 100);
-      return;
-    } else {
-      console.error('otherIndicatorsChart容器未找到,重试超时');
-      return;
-    }
+    console.error('otherIndicatorsChart容器未找到');
+    error.value = new Error('其他指标图表容器未找到,请刷新页面重试');
+    return;
   }
   
   // 容器尺寸检查
-  if (otherIndicatorsChart.value.offsetWidth === 0 || otherIndicatorsChart.value.offsetHeight === 0) {
-    if (retryCount < 5) {
-      setTimeout(() => initOtherIndicatorsChart(retryCount + 1), 200);
-      return;
-    }
+  const { offsetWidth, offsetHeight } = otherIndicatorsChart.value;
+  if (offsetWidth === 0 || offsetHeight === 0) {
+    console.error('otherIndicatorsChart容器尺寸异常', { offsetWidth, offsetHeight });
+    error.value = new Error('其他指标图表容器尺寸异常,请检查页面样式');
+    return;
   }
 
-  if (chartInstanceOther.value) chartInstanceOther.value.dispose();
-  chartInstanceOther.value = echarts.init(otherIndicatorsChart.value);
-  const xAxisData = fieldConfig.otherIndicators.map(ind => ind.name);
-  const boxData = buildBoxplotData(otherIndicatorsStats.value);
+  // 销毁旧实例
+  if (chartInstanceOther.value) {
+    chartInstanceOther.value.dispose();
+  }
   
-  chartInstanceOther.value.setOption({
-    title: { text: '其他通量Cd指标分布对比', left: 'center', textStyle: { fontSize: 14 } },
-    tooltip: {
-      trigger: "item",
-      formatter: (params) => formatTooltip(otherIndicatorsStats.value[params.dataIndex])
-    },
-    grid: { top: 60, right: 30, bottom: 70, left: 60 },
-    xAxis: { 
-      type: "category", 
-      data: xAxisData,
-      axisLabel: { fontSize: 11, rotate: 45 }
-    },
-    yAxis: { 
-      type: "value", 
-      name: 'g/ha/a', 
-      nameTextStyle: { fontSize: 12 }, 
-      axisLabel: { fontSize: 11 }
-    },
-    series: [{
-      name: '其他指标', 
-      type: "boxplot",
-      itemStyle: { 
-        color: (p) => fieldConfig.otherIndicators[p.dataIndex].color,
-        borderWidth: 2 
+  // 初始化图表
+  try {
+    chartInstanceOther.value = echarts.init(otherIndicatorsChart.value);
+    const xAxisData = fieldConfig.otherIndicators.map(ind => ind.name);
+    const boxData = buildBoxplotData(otherIndicatorsStats.value);
+    
+    chartInstanceOther.value.setOption({
+      // 保持原配置不变...
+      title: { text: '其他通量Cd指标分布对比', left: 'center', textStyle: { fontSize: 14 } },
+      tooltip: {
+        trigger: "item",
+        formatter: (params) => formatTooltip(otherIndicatorsStats.value[params.dataIndex])
       },
-      data: boxData
-    }]
-  });
-  
-
+      grid: { top: 60, right: 30, bottom: 70, left: 60 },
+      xAxis: { 
+        type: "category", 
+        data: xAxisData,
+        axisLabel: { fontSize: 11, rotate: 45 }
+      },
+      yAxis: { 
+        type: "value", 
+        name: 'g/ha/a', 
+        nameTextStyle: { fontSize: 12 }, 
+        axisLabel: { fontSize: 11 }
+      },
+      series: [{
+        name: '其他指标', 
+        type: "boxplot",
+        itemStyle: { 
+          color: (p) => fieldConfig.otherIndicators[p.dataIndex].color,
+          borderWidth: 2 
+        },
+        data: boxData
+      }]
+    });
+  } catch (err) {
+    console.error('其他指标图表初始化失败', err);
+    error.value = new Error(`其他指标图表初始化失败: ${err.message}`);
+  }
 };
 
 
@@ -323,15 +347,45 @@ const initCharts = async () => {
   try {
     isLoading.value = true;
     error.value = null;
+    chartInstanceInitial.value = null;
+    chartInstanceOther.value = null;
     
+    // 1. 获取数据
     const data = await fetchData();
+    if (!data || data.length === 0) {
+      throw new Error('未获取到有效数据');
+    }
+    
+    // 2. 计算统计数据
     calculateAllStats(data);
     
-    await nextTick(); // 等待DOM渲染完成
+    // 3. 等待DOM更新
+    await nextTick(); 
+    
+    // 4. 轮询检查容器尺寸(最多等待3秒)
+    const checkContainers = () => {
+      return new Promise((resolve, reject) => {
+        let checkCount = 0;
+        const interval = setInterval(() => {
+          // 检查两个容器的宽度是否有效
+          const initialWidth = initialCdChart.value?.offsetWidth || 0;
+          const otherWidth = otherIndicatorsChart.value?.offsetWidth || 0;
+          
+          if (initialWidth > 0 && otherWidth > 0) {
+            clearInterval(interval);
+            resolve();
+          } else if (checkCount >= 30) { // 30 * 100ms = 3秒
+            clearInterval(interval);
+            reject(new Error('图表容器尺寸异常,准备超时,请检查样式'));
+          }
+          checkCount++;
+        }, 100);
+      });
+    };
     
-    // 添加额外延迟确保容器渲染
-    await new Promise(resolve => setTimeout(resolve, 300));
+    await checkContainers(); 
     
+    // 5. 初始化图表
     initInitialCdChart();
     initOtherIndicatorsChart();