Parcourir la source

优化DashboardView中的图表渲染逻辑,添加旧图表销毁和新画布重置功能,确保数据完整性验证,增强错误处理,提升用户体验。

wuyi il y a 2 mois
Parent
commit
3dd136c056
1 fichiers modifiés avec 128 ajouts et 61 suppressions
  1. 128 61
      src/views/DashboardView.vue

+ 128 - 61
src/views/DashboardView.vue

@@ -199,8 +199,26 @@ const loadIncomeStats = async () => {
       }
     }
 
+    // 获取数据前先销毁旧图表
+    if (chartInstance.value) {
+      try {
+        chartInstance.value.destroy()
+        chartInstance.value = null
+      } catch (e) {
+        console.warn('销毁旧图表实例失败:', e)
+      }
+    }
+
     const data = await getIncomeStatistics(startDate, endDate, userId)
-    incomeStats.value = data
+    
+    // 确保数据结构完整
+    incomeStats.value = {
+      dates: data?.dates || [],
+      total: data?.total || [],
+      totalTip: data?.totalTip || [],
+      totalCommission: data?.totalCommission || [],
+      agents: data?.agents || []
+    }
 
     // 渲染图表
     renderChart()
@@ -211,88 +229,137 @@ const loadIncomeStats = async () => {
   }
 }
 
+// 重置画布
+const resetCanvas = () => {
+  const chartContainer = document.querySelector('.chart-wrapper')
+  if (!chartContainer) return null
+
+  // 移除旧画布
+  const oldCanvas = document.getElementById('incomeChart')
+  if (oldCanvas) {
+    oldCanvas.remove()
+  }
+
+  // 创建新画布
+  const newCanvas = document.createElement('canvas')
+  newCanvas.id = 'incomeChart'
+  newCanvas.height = 300
+  chartContainer.appendChild(newCanvas)
+
+  return newCanvas
+}
+
 // 渲染图表
 const renderChart = () => {
-  if (!incomeStats.value) return
-
-  const chartElement = document.getElementById('incomeChart')
-  if (!chartElement) return
+  if (!incomeStats.value) {
+    console.warn('没有收入统计数据,跳过图表渲染')
+    return
+  }
 
-  // 如果已有图表实例,先销毁
-  if (chartInstance.value) {
-    chartInstance.value.destroy()
-    chartInstance.value = null
+  // 重置画布
+  const canvas = resetCanvas()
+  if (!canvas) {
+    console.error('无法创建图表画布')
+    return
   }
 
-  const ctx = chartElement.getContext('2d')
+  // 获取上下文
+  const ctx = canvas.getContext('2d')
+  if (!ctx) {
+    console.error('无法获取图表上下文')
+    return
+  }
 
   // 准备数据并验证
   const labels = incomeStats.value.dates || []
-  const data = incomeStats.value.total || []
-  const tipData = incomeStats.value.totalTip || []
-  const commissionData = incomeStats.value.totalCommission || []
-
+  
   // 验证数据完整性
-  if (!labels.length || !data.length) {
-    console.warn('图表数据不完整,跳过渲染')
+  if (!labels.length) {
+    console.warn('图表日期数据不完整,跳过渲染')
     return
   }
 
-  const datasets = [
-    {
+  // 准备数据集
+  const datasets = []
+  
+  // 添加总收入数据集
+  const totalData = incomeStats.value.total || []
+  if (totalData.length > 0) {
+    datasets.push({
       label: '总收入',
-      data: data,
+      data: [...totalData],
       borderColor: '#2563eb',
       backgroundColor: 'rgba(37, 99, 235, 0.1)',
       fill: true,
       tension: 0.4
-    },
-    {
-      label: '打赏收入',
-      data: tipData,
-      borderColor: '#10b981',
-      backgroundColor: 'rgba(16, 185, 129, 0.1)',
-      fill: true,
-      tension: 0.4
-    },
-    {
-      label: '返佣收入',
-      data: commissionData,
-      borderColor: '#f59e0b',
-      backgroundColor: 'rgba(245, 158, 11, 0.1)',
-      fill: true,
-      tension: 0.4
-    }
-  ]
+    })
+  }
 
-  // 创建图表
-  try {
-    chartInstance.value = new Chart(ctx, {
-      type: 'line',
-      data: { labels, datasets },
-      options: {
-        responsive: true,
-        maintainAspectRatio: false,
-        plugins: {
-          legend: {
-            position: 'top'
-          },
-          tooltip: {
-            mode: 'index',
-            intersect: false
-          }
+  // 添加打赏收入数据集
+  const tipData = incomeStats.value.totalTip || []
+  datasets.push({
+    label: '打赏收入',
+    data: [...tipData],
+    borderColor: '#10b981',
+    backgroundColor: 'rgba(16, 185, 129, 0.1)',
+    fill: true,
+    tension: 0.4
+  })
+
+  // 添加返佣收入数据集
+  const commissionData = incomeStats.value.totalCommission || []
+  datasets.push({
+    label: '返佣收入',
+    data: [...commissionData],
+    borderColor: '#f59e0b',
+    backgroundColor: 'rgba(245, 158, 11, 0.1)',
+    fill: true,
+    tension: 0.4
+  })
+
+  // 如果没有有效数据集,跳过渲染
+  if (datasets.length === 0) {
+    console.warn('没有有效的数据集,跳过图表渲染')
+    return
+  }
+
+  // 使用requestAnimationFrame确保DOM已更新
+  requestAnimationFrame(() => {
+    try {
+      // 创建图表配置
+      const config = {
+        type: 'line',
+        data: {
+          labels: [...labels],
+          datasets: datasets
         },
-        scales: {
-          y: {
-            beginAtZero: true
+        options: {
+          responsive: true,
+          maintainAspectRatio: false,
+          plugins: {
+            legend: {
+              position: 'top'
+            },
+            tooltip: {
+              mode: 'index',
+              intersect: false
+            }
+          },
+          scales: {
+            y: {
+              beginAtZero: true
+            }
           }
         }
       }
-    })
-  } catch (error) {
-    console.error('图表渲染失败:', error)
-    chartInstance.value = null
-  }
+
+      // 创建图表实例
+      chartInstance.value = new Chart(ctx, config)
+    } catch (error) {
+      console.error('图表渲染失败:', error)
+      chartInstance.value = null
+    }
+  })
 }
 
 // 监听团队选择变化