Просмотр исходного кода

✨ feat(docs): 新增 Taro 2D 环形图 class 组件使用示例文档

- 新增 `taro-2d环形图class使用示例.md` 文档,提供完整的 u-charts 环形图在 Taro 中的实现示例
- 包含完整的 React class 组件代码、样式配置及数据模拟逻辑

🐛 fix(charts): 修复饼图/环形图数据校验逻辑

- 在 `BaseChart.tsx` 中优化数据准备检查逻辑
- 【修复】对于饼图(pie)和环形图(ring)类型,现在仅检查 `series` 数组是否有数据,不再要求 `categories`
- 【修复】对于其他图表类型,仍保持同时检查 `categories` 和 `series` 的原有逻辑
- 在渲染条件判断(`isReady`)中应用相同的逻辑,确保组件正确渲染

🔧 chore(statistics): 清理统计页面图表配置并添加测试组件

- 在 `Statistics.tsx` 中移除多个 `PieChart` 组件上冗余的 `config` 属性(如 `fontSize`, `dataLabel`, `legend`)和 `tooltipFormatter` 函数
- 这些配置已在组件默认值或 `BaseChart` 中处理,移除以避免覆盖
- 在页面底部添加 `PieChartFCExample` 测试组件区块,用于功能验证
yourname 2 недель назад
Родитель
Сommit
36c6e5f0a9

+ 129 - 0
docs/小程序图表库示例/taro-2d环形图class使用示例.md

@@ -0,0 +1,129 @@
+```jsx
+//index.js
+import React, { Component } from 'react';
+import Taro from '@tarojs/taro';
+import { View, Canvas } from '@tarojs/components';
+import uCharts from '../../js_sdk/u-charts/u-charts.js';
+import './index.scss';
+var uChartsInstance = {};
+export default class Index extends Component { 
+  constructor(){
+    super(...arguments)    
+    this.state = {
+      cWidth: 750,
+      cHeight: 500,
+      pixelRatio: 1,
+    }
+  }
+
+  componentDidMount(){
+    const sysInfo = Taro.getSystemInfoSync();
+    const pixelRatio = sysInfo.pixelRatio;
+    //这里的第一个 750 对应 css .charts 的 width
+    const cWidth = 750 / 750 * sysInfo.windowWidth;
+    //这里的 500 对应 css .charts 的 height
+    const cHeight = 500 / 750 * sysInfo.windowWidth;
+    this.setState({cWidth, cHeight, pixelRatio},()=>this.getServerData());
+  }
+
+  getServerData = ()=>{
+    //模拟从服务器获取数据时的延时
+    setTimeout(() => {
+      //模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接
+      let res = {
+            series: [
+              {
+                data: [{"name":"一班","value":50},{"name":"二班","value":30},{"name":"三班","value":20},{"name":"四班","value":18},{"name":"五班","value":8}]
+              }
+            ]
+          };
+      this.drawCharts('hFZBqQqTarCLkxHkRhJqQzfdJRqCDybT', res);
+    }, 500);
+  }
+
+  drawCharts = (id, data)=>{
+    const { cWidth, cHeight, pixelRatio } = this.state;
+    const query = Taro.createSelectorQuery();
+    query.select('#' + id).fields({ node: true, size: true }).exec(res => {
+      if (res[0]) {
+        const canvas = res[0].node;
+        const ctx = canvas.getContext('2d');
+        canvas.width = res[0].width * pixelRatio;
+        canvas.height = res[0].height * pixelRatio;
+        uChartsInstance[id] = new uCharts({
+          type: "ring",
+          context: ctx,
+          width: cWidth * pixelRatio,
+          height: cHeight * pixelRatio,
+          series: data.series,
+          pixelRatio: pixelRatio,
+          animation: true,
+          rotate: false,
+          rotateLock: false,
+          background: "#FFFFFF",
+          color: ["#1890FF","#91CB74","#FAC858","#EE6666","#73C0DE","#3CA272","#FC8452","#9A60B4","#ea7ccc"],
+          padding: [5,5,5,5],
+          dataLabel: true,
+          enableScroll: false,
+          legend: {
+            show: true,
+            position: "right",
+            lineHeight: 25
+          },
+          title: {
+            name: "收益率",
+            fontSize: 15,
+            color: "#666666"
+          },
+          subtitle: {
+            name: "70%",
+            fontSize: 25,
+            color: "#7cb5ec"
+          },
+          extra: {
+            ring: {
+              ringWidth: 60,
+              activeOpacity: 0.5,
+              activeRadius: 10,
+              offsetAngle: 0,
+              labelWidth: 15,
+              border: false,
+              borderWidth: 3,
+              borderColor: "#FFFFFF"
+            }
+          }
+        });
+      }else{
+        console.error("[uCharts]: 未获取到 context");
+      }
+    });
+  }
+
+  tap = (e)=>{
+    uChartsInstance[e.target.id].touchLegend(e);
+    uChartsInstance[e.target.id].showToolTip(e);
+  }
+
+  render () {
+    const { cWidth, cHeight } = this.state;
+    const canvasProps = { style: { width: cWidth, height: cHeight } };
+    return (
+      <View>
+        <Canvas
+          {...canvasProps}
+          canvas-id="hFZBqQqTarCLkxHkRhJqQzfdJRqCDybT"
+          id="hFZBqQqTarCLkxHkRhJqQzfdJRqCDybT"
+          type="2d"
+          class="charts"
+          onTouchEnd={this.tap}/>
+      </View>
+    )
+  }
+}
+
+/*index.scss*/
+.charts{
+  width: 750rpx;
+  height: 500rpx;
+}
+```

+ 12 - 11
mini-ui-packages/mini-charts/src/components/BaseChart.tsx

@@ -78,12 +78,17 @@ const BaseChartInner: React.FC<BaseChartProps> = (props) => {
     setCWidth(cw);
     setCWidth(cw);
     setCHeight(ch);
     setCHeight(ch);
 
 
-    // 确保数据已准备好:categories 和 series 都有数据
-    const isDataReady = categories.length > 0 && series.length > 0;
+    // 确保数据已准备好
+    // 对于饼图(pie/ring),只需要 series 有数据
+    // 对于其他图表,需要 categories 和 series 都有数据
+    const isPieChart = type === 'pie' || type === 'ring';
+    const isDataReady = isPieChart ? series.length > 0 : categories.length > 0 && series.length > 0;
 
 
     if (!isDataReady) {
     if (!isDataReady) {
       console.log('[BaseChart] 数据未准备好,等待数据...', {
       console.log('[BaseChart] 数据未准备好,等待数据...', {
         canvasId,
         canvasId,
+        type,
+        isPieChart,
         categoriesLength: categories.length,
         categoriesLength: categories.length,
         seriesLength: series.length
         seriesLength: series.length
       });
       });
@@ -106,6 +111,7 @@ const BaseChartInner: React.FC<BaseChartProps> = (props) => {
           const extendedCtx = ctx as ExtendedCanvasContext;
           const extendedCtx = ctx as ExtendedCanvasContext;
 
 
           // Canvas 2D: 使用 canvas 的实际 width/height
           // Canvas 2D: 使用 canvas 的实际 width/height
+          // 基础配置
           const chartConfig: ChartsConfig = {
           const chartConfig: ChartsConfig = {
             type,
             type,
             context: extendedCtx,
             context: extendedCtx,
@@ -125,14 +131,6 @@ const BaseChartInner: React.FC<BaseChartProps> = (props) => {
             yAxis: {
             yAxis: {
               data: [{ min: 0 }]
               data: [{ min: 0 }]
             },
             },
-            extra: {
-              column: {
-                type: 'group',
-                width: 30,
-                activeBgColor: '#000000',
-                activeBgOpacity: 0.08
-              }
-            },
             ...config,
             ...config,
           };
           };
 
 
@@ -223,7 +221,10 @@ export const BaseChart: React.FC<BaseChartProps> = (props) => {
   const stableConfig = useMemo(() => config, [JSON.stringify(config)]);
   const stableConfig = useMemo(() => config, [JSON.stringify(config)]);
 
 
   // 只有数据准备好才渲染 Inner 组件
   // 只有数据准备好才渲染 Inner 组件
-  const isReady = categories.length > 0 && series.length > 0;
+  // 对于饼图(pie/ring),只需要 series 有数据
+  // 对于其他图表,需要 categories 和 series 都有数据
+  const isPieChart = type === 'pie' || type === 'ring';
+  const isReady = isPieChart ? series.length > 0 : categories.length > 0 && series.length > 0;
 
 
   if (!isReady) {
   if (!isReady) {
     return null;
     return null;

+ 13 - 23
mini-ui-packages/yongren-statistics-ui/src/pages/Statistics/Statistics.tsx

@@ -6,6 +6,7 @@ import { Navbar } from '@d8d/mini-shared-ui-components/components/navbar'
 import { ColumnChart } from '@d8d/mini-charts/components/ColumnChart'
 import { ColumnChart } from '@d8d/mini-charts/components/ColumnChart'
 import { BarChart } from '@d8d/mini-charts/components/BarChart'
 import { BarChart } from '@d8d/mini-charts/components/BarChart'
 import { PieChart } from '@d8d/mini-charts/components/PieChart'
 import { PieChart } from '@d8d/mini-charts/components/PieChart'
+import { PieChartFCExample } from '@d8d/mini-charts/components/PieChartFCExample'
 import { enterpriseStatisticsClient } from '../../api/enterpriseStatisticsClient'
 import { enterpriseStatisticsClient } from '../../api/enterpriseStatisticsClient'
 import type {
 import type {
   DisabilityTypeDistributionResponse,
   DisabilityTypeDistributionResponse,
@@ -323,13 +324,6 @@ const Statistics: React.FC<StatisticsProps> = () => {
                     series={convertToPieData(ageStats)}
                     series={convertToPieData(ageStats)}
                     config={{
                     config={{
                       color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
                       color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
-                      fontSize: 10,
-                      dataLabel: true,
-                      legend: { show: true }
-                    }}
-                    tooltipFormatter={(item: any) => {
-                      const statItem = ageStats.find(s => s.key === item.name)
-                      return `${item.name} ${item.data}人 (${statItem?.percentage || 0}%)`
                     }}
                     }}
                   />
                   />
                 </View>
                 </View>
@@ -358,14 +352,6 @@ const Statistics: React.FC<StatisticsProps> = () => {
                       series={chartData.series}
                       series={chartData.series}
                       config={{
                       config={{
                         color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444', '#ec4899'],
                         color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444', '#ec4899'],
-                        fontSize: 10,
-                        dataLabel: true,
-                        xAxis: { disableGrid: true },
-                        yAxis: {}
-                      }}
-                      tooltipFormatter={(item: any, category: string) => {
-                        const statItem = stats.find(s => s.key === category)
-                        return `${category} ${item.data}人 (${statItem?.percentage || 0}%)`
                       }}
                       }}
                     />
                     />
                   </View>
                   </View>
@@ -423,14 +409,6 @@ const Statistics: React.FC<StatisticsProps> = () => {
                       series={chartData.series}
                       series={chartData.series}
                       config={{
                       config={{
                         color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
                         color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
-                        fontSize: 10,
-                        dataLabel: true,
-                        xAxis: { disableGrid: true },
-                        yAxis: {}
-                      }}
-                      tooltipFormatter={(item: any, category: string) => {
-                        const statItem = stats.find(s => s.key === category)
-                        return `${category} ${item.data}人 (${statItem?.percentage || 0}%)`
                       }}
                       }}
                     />
                     />
                   </View>
                   </View>
@@ -441,6 +419,18 @@ const Statistics: React.FC<StatisticsProps> = () => {
             })()}
             })()}
         </View>
         </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>
+
       </ScrollView>
       </ScrollView>
     </YongrenTabBarLayout>
     </YongrenTabBarLayout>
   )
   )