Browse Source

feat: 企业小程序数据统计页面迁移至 taro-react-echarts

- 安装 echarts 和 taro-react-echarts 依赖
- 创建 echarts.js 按需引入图表组件
- 将所有图表从 @d8d/mini-charts 迁移到 taro-react-echarts
- 新增渲染函数:柱状图、横向柱状图、饼图、环形图
- 提升图表交互性和视觉效果

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 3 weeks ago
parent
commit
9c95c66b32
4 changed files with 315 additions and 248 deletions
  1. 3 1
      mini/package.json
  2. 41 0
      mini/src/assets/js/echarts.js
  3. 230 247
      mini/src/pages/yongren/statistics/index.tsx
  4. 41 0
      pnpm-lock.yaml

+ 3 - 1
mini/package.json

@@ -80,12 +80,14 @@
     "@weapp-tailwindcss/merge": "^1.2.3",
     "abortcontroller-polyfill": "^1.7.8",
     "class-variance-authority": "^0.7.1",
-    "dayjs": "~1.11.13",
     "clsx": "^2.1.1",
+    "dayjs": "~1.11.13",
+    "echarts": "^6.0.0",
     "hono": "4.8.5",
     "react": "^18.0.0",
     "react-dom": "^18.0.0",
     "react-hook-form": "^7.62.0",
+    "taro-react-echarts": "^1.2.2",
     "zod": "^4.0.14"
   },
   "devDependencies": {

+ 41 - 0
mini/src/assets/js/echarts.js

@@ -0,0 +1,41 @@
+// Echarts 核心库导出
+// 使用完整版 echarts 以支持所有图表类型
+import * as echarts from 'echarts/core'
+
+// 按需引入图表类型
+import {
+  BarChart,
+  LineChart,
+  PieChart
+} from 'echarts/charts'
+
+// 引入组件
+import {
+  TitleComponent,
+  LegendComponent,
+  TooltipComponent,
+  GridComponent
+} from 'echarts/components'
+
+// 标签自动布局、全局过渡动画等特性
+import { LabelLayout, UniversalTransition } from 'echarts/features'
+
+// 引入 Canvas 渲染器
+// Taro 环境必须使用 Canvas 渲染器
+import { CanvasRenderer } from 'echarts/renderers'
+
+// 注册必须的组件
+echarts.use([
+  TitleComponent,
+  LegendComponent,
+  TooltipComponent,
+  GridComponent,
+  BarChart,
+  LineChart,
+  PieChart,
+  LabelLayout,
+  UniversalTransition,
+  CanvasRenderer
+])
+
+export default echarts

+ 230 - 247
mini/src/pages/yongren/statistics/index.tsx

@@ -4,13 +4,14 @@ import Taro from '@tarojs/taro'
 import { useQuery, useQueryClient } from '@tanstack/react-query'
 import { YongrenTabBarLayout } from '@/components/YongrenTabBarLayout'
 import { Navbar } from '@d8d/mini-shared-ui-components/components/navbar'
-import { ColumnChart, BarChart, PieChart, RingChart } from '@d8d/mini-charts'
 import { enterpriseStatisticsClient } from '@/api/enterpriseStatisticsClient'
 import type {
   EmploymentCountResponse,
   AverageSalaryResponse,
   EmploymentRateResponse
 } from '@/types/statisticsTypes'
+import Echarts from 'taro-react-echarts'
+import echarts from '@/assets/js/echarts.js'
 
 /**
  * 类型守卫:检查响应是否为成功的数据响应
@@ -74,38 +75,9 @@ const mergeProvinceData = (stats: any[]) => {
 }
 
 /**
- * 数据转换工具:将API统计数据转换为柱状图格式
- * 优先使用中文名称的 province,如果是数字ID则从 key 提取
- * 修复:合并相同省份的数据,人数显示为整数
+ * Echarts 柱状图颜色配置
  */
-const convertToColumnData = (stats: any[]) => {
-  console.debug('[convertToColumnData] Input stats:', JSON.stringify(stats))
-
-  // 先合并相同省份的数据
-  const mergedStats = mergeProvinceData(stats)
-
-  const result = {
-    categories: mergedStats.map(item => item.province),
-    series: [{
-      name: '人数',
-      data: mergedStats.map(item => item.value)
-    }]
-  }
-  console.debug('[convertToColumnData] Merged stats:', JSON.stringify(mergedStats))
-  console.debug('[convertToColumnData] Output categories:', result.categories)
-  console.debug('[convertToColumnData] Output series:', result.series)
-  return result
-}
-
-/**
- * 数据转换工具:将API统计数据转换为饼图格式
- * 修复:人数显示为整数
- */
-const convertToPieData = (stats: any[]) =>
-  stats.map(item => ({
-    name: item.key,
-    data: Math.round(item.value || 0)
-  }))
+const BAR_COLORS = ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444', '#ec4899']
 
 export interface StatisticsProps {
   // 组件属性定义(目前为空)
@@ -279,6 +251,192 @@ const Statistics: React.FC<StatisticsProps> = () => {
     gcTime: 10 * 60 * 1000 // 缓存时间10分钟
   })
 
+  /**
+   * 渲染柱状图(垂直)
+   */
+  const renderBarChart = (stats: any[]) => {
+    const mergedStats = mergeProvinceData(stats)
+    return (
+      <Echarts
+        echarts={echarts}
+        option={{
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'shadow'
+            }
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            data: mergedStats.map(item => item.province),
+            axisLabel: {
+              interval: 0,
+              rotate: 30
+            }
+          },
+          yAxis: {
+            type: 'value',
+            minInterval: 1
+          },
+          series: [{
+            name: '人数',
+            type: 'bar',
+            data: mergedStats.map(item => item.value),
+            itemStyle: {
+              color: '#3b82f6'
+            },
+            label: {
+              show: true,
+              position: 'top',
+              formatter: '{c}'
+            }
+          }]
+        }}
+        style={{ height: '280px' }}
+      />
+    )
+  }
+
+  /**
+   * 渲染横向柱状图
+   */
+  const renderHorizontalBarChart = (stats: any[]) => {
+    const mergedStats = mergeProvinceData(stats)
+    return (
+      <Echarts
+        echarts={echarts}
+        option={{
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'shadow'
+            }
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'value',
+            minInterval: 1
+          },
+          yAxis: {
+            type: 'category',
+            data: mergedStats.map(item => item.province)
+          },
+          series: [{
+            name: '人数',
+            type: 'bar',
+            data: mergedStats.map(item => item.value),
+            itemStyle: {
+              color: (params: any) => BAR_COLORS[params.dataIndex % BAR_COLORS.length]
+            },
+            label: {
+              show: true,
+              position: 'right',
+              formatter: '{c}'
+            }
+          }]
+        }}
+        style={{ height: `${Math.max(280, mergedStats.length * 50)}px` }}
+      />
+    )
+  }
+
+  /**
+   * 渲染饼图
+   */
+  const renderPieChart = (stats: any[]) => {
+    return (
+      <Echarts
+        echarts={echarts}
+        option={{
+          tooltip: {
+            trigger: 'item',
+            formatter: '{b}: {c} ({d}%)'
+          },
+          legend: {
+            orient: 'vertical',
+            right: 10,
+            top: 'center'
+          },
+          series: [{
+            name: '人数',
+            type: 'pie',
+            radius: '60%',
+            center: ['35%', '50%'],
+            data: stats.map(item => ({
+              name: item.key,
+              value: Math.round(item.value || 0)
+            })),
+            emphasis: {
+              itemStyle: {
+                shadowBlur: 10,
+                shadowOffsetX: 0,
+                shadowColor: 'rgba(0, 0, 0, 0.5)'
+              }
+            },
+            label: {
+              formatter: '{b}: {c}'
+            }
+          }]
+        }}
+        style={{ height: '280px' }}
+      />
+    )
+  }
+
+  /**
+   * 渲染环形图
+   */
+  const renderDoughnutChart = (stats: any[]) => {
+    return (
+      <Echarts
+        echarts={echarts}
+        option={{
+          tooltip: {
+            trigger: 'item',
+            formatter: '{b}: {c} ({d}%)'
+          },
+          legend: {
+            orient: 'vertical',
+            right: 10,
+            top: 'center'
+          },
+          series: [{
+            name: '人数',
+            type: 'pie',
+            radius: ['40%', '70%'],
+            center: ['35%', '50%'],
+            data: stats.map(item => ({
+              name: item.key,
+              value: Math.round(item.value || 0)
+            })),
+            emphasis: {
+              itemStyle: {
+                shadowBlur: 10,
+                shadowOffsetX: 0,
+                shadowColor: 'rgba(0, 0, 0, 0.5)'
+              }
+            },
+            label: {
+              formatter: '{b}: {c}'
+            }
+          }]
+        }}
+        style={{ height: '280px' }}
+      />
+    )
+  }
+
   return (
     <YongrenTabBarLayout activeKey="statistics">
       <ScrollView
@@ -351,30 +509,11 @@ const Statistics: React.FC<StatisticsProps> = () => {
             <Text className="text-gray-500 text-center py-4">加载中...</Text>
           ) : (() => {
             const stats = getStats(disabilityData)
-            if (stats.length > 0) {
-              const chartData = convertToColumnData(stats)
-              return (
-                <View className="mt-3">
-                  <ColumnChart
-                    canvasId="disability-type-chart"
-                    width={650}
-                    height={320}
-                    categories={chartData.categories}
-                    series={chartData.series}
-                    config={{
-                      color: ['#3b82f6'],
-                      dataLabel: true,
-                      yAxis: {
-                        min: 0,
-                        format: (val: number) => Number.isInteger(val) ? val.toString() : '',
-                      },
-                    }}
-                  />
-                </View>
-              )
-            } else {
-              return <Text className="text-gray-500 text-center py-4 mt-3">暂无数据</Text>
-            }
+            return stats.length > 0 ? (
+              <View className="mt-3">{renderBarChart(stats)}</View>
+            ) : (
+              <Text className="text-gray-500 text-center py-4 mt-3">暂无数据</Text>
+            )
           })()}
         </View>
 
@@ -384,32 +523,13 @@ const Statistics: React.FC<StatisticsProps> = () => {
           {isLoadingGender ? (
             <Text className="text-gray-500 text-center py-4">加载中...</Text>
           ) : (() => {
-              const genderStats = getStats(genderData)
-              return genderStats.length > 0 ? (
-                <View className="mt-3">
-                  <ColumnChart
-                    canvasId="gender-chart"
-                    width={650}
-                    height={320}
-                    categories={genderStats.map(s => s.key)}
-                    series={[{
-                      name: '人数',
-                      data: genderStats.map(s => s.value || 0)
-                    }]}
-                    config={{
-                      color: ['#3b82f6', '#ec4899'],
-                      dataLabel: true,
-                      yAxis: {
-                        min: 0,
-                        format: (val: number) => Number.isInteger(val) ? val.toString() : '',
-                      },
-                    }}
-                  />
-                </View>
-              ) : (
-                <Text className="text-gray-500 text-center py-4">暂无数据</Text>
-              )
-            })()}
+            const genderStats = getStats(genderData)
+            return genderStats.length > 0 ? (
+              <View className="mt-3">{renderBarChart(genderStats)}</View>
+            ) : (
+              <Text className="text-gray-500 text-center py-4">暂无数据</Text>
+            )
+          })()}
         </View>
 
         {/* 年龄分布 */}
@@ -418,36 +538,13 @@ const Statistics: React.FC<StatisticsProps> = () => {
           {isLoadingAge ? (
             <Text className="text-gray-500 text-center py-4">加载中...</Text>
           ) : (() => {
-              const ageStats = getStats(ageData)
-              return ageStats.length > 0 ? (
-                <View className="mt-3">
-                  <PieChart
-                    canvasId="age-chart"
-                    width={650}
-                    height={320}
-                    series={convertToPieData(ageStats)}
-                    config={{
-                      color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
-                      dataLabel: true,
-                      extra: {
-                        pie: {
-                          activeRadius: 15,
-                          labelWidth: 18,
-                          borderWidth: 2,
-                        }
-                      },
-                      legend: {
-                        show: true,
-                        position: "right",
-                        lineHeight: 22
-                      }
-                    }}
-                  />
-                </View>
-              ) : (
-                <Text className="text-gray-500 text-center py-4">暂无数据</Text>
-              )
-            })()}
+            const ageStats = getStats(ageData)
+            return ageStats.length > 0 ? (
+              <View className="mt-3">{renderPieChart(ageStats)}</View>
+            ) : (
+              <Text className="text-gray-500 text-center py-4">暂无数据</Text>
+            )
+          })()}
         </View>
 
         {/* 户籍省份分布 */}
@@ -456,52 +553,13 @@ const Statistics: React.FC<StatisticsProps> = () => {
           {isLoadingHousehold ? (
             <Text className="text-gray-500 text-center py-4">加载中...</Text>
           ) : (() => {
-              const stats = getStats(householdData)
-              // 详细调试信息
-              console.log('📊 [户籍省份分布] 原始 API 数据:', JSON.stringify(householdData, null, 2))
-              console.log('📊 [户籍省份分布] stats 数组:', JSON.stringify(stats, null, 2))
-              if (stats.length > 0) {
-                const chartData = convertToColumnData(stats)
-                console.log('📊 [户籍省份分布] 转换后的 categories:', chartData.categories)
-                console.log('📊 [户籍省份分布] 转换后的 series:', JSON.stringify(chartData.series, null, 2))
-                // 检查每个 stat 项的 province 值
-                stats.forEach((item, index) => {
-                  console.log(`📊 [户籍省份分布] stat[${index}]:`, {
-                    key: item.key,
-                    province: item.province,
-                    isNumericProvince: item.province ? /^\d+$/.test(item.province) : 'N/A'
-                  })
-                })
-                return (
-                  <View className="mt-3">
-                    <BarChart
-                      canvasId="household-chart"
-                      width={650}
-                      height={320}
-                      categories={chartData.categories}
-                      series={chartData.series}
-                      config={{
-                        color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444', '#ec4899'],
-                        dataLabel: true,
-                        xAxis: {
-                          disableGrid: true,
-                          tofix: 0,  // X 轴显示整数(人数)
-                          splitNumber: 1,  // 只生成 2 个刻度(min 和 max)
-                          min: 0,  // 确保 X 轴从 0 开始,让柱状图正常显示
-                        },
-                        extra: {
-                          bar: {
-                            width: 45,
-                          }
-                        }
-                      }}
-                    />
-                  </View>
-                )
-              } else {
-                return <Text className="text-gray-500 text-center py-4 mt-3">暂无数据</Text>
-              }
-            })()}
+            const stats = getStats(householdData)
+            return stats.length > 0 ? (
+              <View className="mt-3">{renderHorizontalBarChart(stats)}</View>
+            ) : (
+              <Text className="text-gray-500 text-center py-4 mt-3">暂无数据</Text>
+            )
+          })()}
         </View>
 
         {/* 在职状态统计 */}
@@ -510,38 +568,13 @@ const Statistics: React.FC<StatisticsProps> = () => {
           {isLoadingJobStatus ? (
             <Text className="text-gray-500 text-center py-4">加载中...</Text>
           ) : (() => {
-              const stats = getStats(jobStatusData)
-              if (stats.length > 0) {
-                return (
-                  <View className="mt-3">
-                    <RingChart
-                      canvasId="job-status-chart"
-                      width={650}
-                      height={320}
-                      ringWidth={0.75}
-                      series={convertToPieData(stats)}
-                      config={{
-                        color: ['#3b82f6', '#f59e0b', '#ef4444', '#10b981'],
-                        dataLabel: true,
-                        legend: {
-                          show: true,
-                          position: "right",
-                          lineHeight: 25
-                        },
-                        extra: {
-                          ring: {
-                            activeRadius: 15,
-                            labelWidth: 18,
-                          }
-                        }
-                      }}
-                    />
-                  </View>
-                )
-              } else {
-                return <Text className="text-gray-500 text-center py-4">暂无数据</Text>
-              }
-            })()}
+            const stats = getStats(jobStatusData)
+            return stats.length > 0 ? (
+              <View className="mt-3">{renderDoughnutChart(stats)}</View>
+            ) : (
+              <Text className="text-gray-500 text-center py-4">暂无数据</Text>
+            )
+          })()}
         </View>
 
         {/* 薪资分布 */}
@@ -550,65 +583,15 @@ const Statistics: React.FC<StatisticsProps> = () => {
           {isLoadingSalary ? (
             <Text className="text-gray-500 text-center py-4">加载中...</Text>
           ) : (() => {
-              const stats = getStats(salaryData)
-              if (stats.length > 0) {
-                const chartData = convertToColumnData(stats)
-                return (
-                  <View className="mt-3">
-                    <BarChart
-                      canvasId="salary-chart"
-                      width={650}
-                      height={320}
-                      categories={chartData.categories}
-                      series={chartData.series}
-                      config={{
-                        color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
-                        dataLabel: true,
-                        xAxis: {
-                          disableGrid: true,
-                          tofix: 0,  // X 轴显示整数(人数)
-                          splitNumber: 1,  // 只生成 2 个刻度(min 和 max)
-                          min: 0,  // 确保 X 轴从 0 开始,让柱状图正常显示
-                        },
-                        extra: {
-                          bar: {
-                            width: 50,
-                          }
-                        }
-                      }}
-                    />
-                  </View>
-                )
-              } else {
-                return <Text className="text-gray-500 text-center py-4">暂无数据</Text>
-              }
-            })()}
+            const stats = getStats(salaryData)
+            return stats.length > 0 ? (
+              <View className="mt-3">{renderHorizontalBarChart(stats)}</View>
+            ) : (
+              <Text className="text-gray-500 text-center py-4">暂无数据</Text>
+            )
+          })()}
         </View>
 
-        {/* PieChartFCExample 测试组件 */}
-        {/* <View className="card bg-white p-4 mb-4 rounded-lg shadow-sm flex flex-col">
-          <Text className="font-semibold text-gray-700">饼图示例测试 (PieChartFCExample)</Text>
-          <View className="mt-3">
-            <PieChartFCExample
-              canvasId="pie-chart-fc-example-test"
-              width={650}
-              height={400}
-            />
-          </View>
-        </View> */}
-
-        {/* RingChartFCExample 测试组件 */}
-        {/* <View className="card bg-white p-4 mb-4 rounded-lg shadow-sm flex flex-col">
-          <Text className="font-semibold text-gray-700">环形图示例测试 (RingChartFCExample)</Text>
-          <View className="mt-3">
-            <RingChartFCExample
-              canvasId="ring-chart-fc-example-test"
-              width={650}
-              height={400}
-            />
-          </View>
-        </View> */}
-
       </ScrollView>
     </YongrenTabBarLayout>
   )

+ 41 - 0
pnpm-lock.yaml

@@ -1216,6 +1216,9 @@ importers:
       dayjs:
         specifier: ~1.11.13
         version: 1.11.18
+      echarts:
+        specifier: ^6.0.0
+        version: 6.0.0
       hono:
         specifier: 4.8.5
         version: 4.8.5
@@ -1228,6 +1231,9 @@ importers:
       react-hook-form:
         specifier: ^7.62.0
         version: 7.65.0(react@18.3.1)
+      taro-react-echarts:
+        specifier: ^1.2.2
+        version: 1.2.2(@tarojs/components@4.1.4(@tarojs/helper@4.1.4)(@types/react@18.3.26)(html-webpack-plugin@5.6.4(webpack@5.91.0(@swc/core@1.3.96)))(postcss@8.5.6)(rollup@3.29.5)(vue@3.5.22(typescript@5.8.3))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.91.0(@swc/core@1.3.96)))(webpack@5.91.0(@swc/core@1.3.96)))(@tarojs/taro@4.1.4(@tarojs/components@4.1.4(@tarojs/helper@4.1.4)(@types/react@18.3.26)(html-webpack-plugin@5.6.4(webpack@5.91.0(@swc/core@1.3.96)))(postcss@8.5.6)(rollup@3.29.5)(vue@3.5.22(typescript@5.8.3))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.91.0(@swc/core@1.3.96)))(webpack@5.91.0(@swc/core@1.3.96)))(@tarojs/helper@4.1.4)(@tarojs/shared@4.1.4)(@types/react@18.3.26)(html-webpack-plugin@5.6.4(webpack@5.91.0(@swc/core@1.3.96)))(postcss@8.5.6)(rollup@3.29.5)(vue@3.5.22(typescript@5.8.3))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.91.0(@swc/core@1.3.96)))(webpack@5.91.0(@swc/core@1.3.96)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       zod:
         specifier: ^4.0.14
         version: 4.1.12
@@ -13330,6 +13336,9 @@ packages:
   ecdsa-sig-formatter@1.0.11:
     resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
 
+  echarts@6.0.0:
+    resolution: {integrity: sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==}
+
   ee-first@1.1.1:
     resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
 
@@ -17793,6 +17802,14 @@ packages:
     resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
     engines: {node: '>=10'}
 
+  taro-react-echarts@1.2.2:
+    resolution: {integrity: sha512-NHzngwaA8/EPHirJPiUU2xxs1YggEVD8JYD6lauZjGLI0bd7OiaIDb35VPuYADwZSmkQg5zYj7DEBcbNRMFmUg==}
+    peerDependencies:
+      '@tarojs/components': '>=3'
+      '@tarojs/taro': '>=3'
+      react: '>=16.9'
+      react-dom: '>=16.9'
+
   terser-webpack-plugin@5.3.14:
     resolution: {integrity: sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==}
     engines: {node: '>= 10.13.0'}
@@ -18026,6 +18043,9 @@ packages:
   tslib@1.14.1:
     resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
 
+  tslib@2.3.0:
+    resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
+
   tslib@2.8.1:
     resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
 
@@ -18790,6 +18810,9 @@ packages:
   zod@4.1.12:
     resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==}
 
+  zrender@6.0.0:
+    resolution: {integrity: sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==}
+
 snapshots:
 
   '@adobe/css-tools@4.3.3': {}
@@ -26347,6 +26370,11 @@ snapshots:
     dependencies:
       safe-buffer: 5.2.1
 
+  echarts@6.0.0:
+    dependencies:
+      tslib: 2.3.0
+      zrender: 6.0.0
+
   ee-first@1.1.1: {}
 
   electron-to-chromium@1.5.262: {}
@@ -31969,6 +31997,13 @@ snapshots:
       mkdirp: 1.0.4
       yallist: 4.0.0
 
+  taro-react-echarts@1.2.2(@tarojs/components@4.1.4(@tarojs/helper@4.1.4)(@types/react@18.3.26)(html-webpack-plugin@5.6.4(webpack@5.91.0(@swc/core@1.3.96)))(postcss@8.5.6)(rollup@3.29.5)(vue@3.5.22(typescript@5.8.3))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.91.0(@swc/core@1.3.96)))(webpack@5.91.0(@swc/core@1.3.96)))(@tarojs/taro@4.1.4(@tarojs/components@4.1.4(@tarojs/helper@4.1.4)(@types/react@18.3.26)(html-webpack-plugin@5.6.4(webpack@5.91.0(@swc/core@1.3.96)))(postcss@8.5.6)(rollup@3.29.5)(vue@3.5.22(typescript@5.8.3))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.91.0(@swc/core@1.3.96)))(webpack@5.91.0(@swc/core@1.3.96)))(@tarojs/helper@4.1.4)(@tarojs/shared@4.1.4)(@types/react@18.3.26)(html-webpack-plugin@5.6.4(webpack@5.91.0(@swc/core@1.3.96)))(postcss@8.5.6)(rollup@3.29.5)(vue@3.5.22(typescript@5.8.3))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.91.0(@swc/core@1.3.96)))(webpack@5.91.0(@swc/core@1.3.96)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+    dependencies:
+      '@tarojs/components': 4.1.4(@tarojs/helper@4.1.4)(@types/react@18.3.26)(html-webpack-plugin@5.6.4(webpack@5.91.0(@swc/core@1.3.96)))(postcss@8.5.6)(rollup@3.29.5)(vue@3.5.22(typescript@5.8.3))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.91.0(@swc/core@1.3.96)))(webpack@5.91.0(@swc/core@1.3.96))
+      '@tarojs/taro': 4.1.4(@tarojs/components@4.1.4(@tarojs/helper@4.1.4)(@types/react@18.3.26)(html-webpack-plugin@5.6.4(webpack@5.91.0(@swc/core@1.3.96)))(postcss@8.5.6)(rollup@3.29.5)(vue@3.5.22(typescript@5.8.3))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.91.0(@swc/core@1.3.96)))(webpack@5.91.0(@swc/core@1.3.96)))(@tarojs/helper@4.1.4)(@tarojs/shared@4.1.4)(@types/react@18.3.26)(html-webpack-plugin@5.6.4(webpack@5.91.0(@swc/core@1.3.96)))(postcss@8.5.6)(rollup@3.29.5)(vue@3.5.22(typescript@5.8.3))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.91.0(@swc/core@1.3.96)))(webpack@5.91.0(@swc/core@1.3.96))
+      react: 18.3.1
+      react-dom: 18.3.1(react@18.3.1)
+
   terser-webpack-plugin@5.3.14(@swc/core@1.13.5)(esbuild@0.21.5)(webpack@5.91.0(@swc/core@1.13.5)):
     dependencies:
       '@jridgewell/trace-mapping': 0.3.31
@@ -32332,6 +32367,8 @@ snapshots:
 
   tslib@1.14.1: {}
 
+  tslib@2.3.0: {}
+
   tslib@2.8.1: {}
 
   tsx@4.20.6:
@@ -33541,3 +33578,7 @@ snapshots:
   zod@3.25.76: {}
 
   zod@4.1.12: {}
+
+  zrender@6.0.0:
+    dependencies:
+      tslib: 2.3.0