数据可视化中图表的低无一体

介绍

数据可视化提供了自定义图表模板的功能,以满足现有图表模板无法满足业务需求的情况。

如何使用

  1. 点击数据可视化页面头部的“图表模板”
    image.png
  2. 点击创建按钮后弹出图表模板表单,填写后提交保存
    image.png
  3. 找到刚刚创建的图表模板,点击操作栏中的“低无一体”按钮
    image.png
  4. 点击弹窗底部的“生成sdk”按钮
    image.png
  5. 上一步操作完成后会重新刷新页面,再次找到该条数据,点击“低无一体”按钮,再次进来可以看到“下载模板工程”的按钮已经可以点击了,点击该按钮就可以下载到该自定义图表模板的示例代码包文件kunlun-chart-sdk.zip
    image.png
  6. 解压kunlun-chart-sdk.zip后我们可以看到工程结构,在根目录下执行npm i安装依赖
    image.png
  7. 可以看到packages/kunlun-plugin/src/chart/CUSTOM_BAR.vue是我们自定义的图表vue组件,可以修改里面的自定义展示和逻辑处理
  8. 完成自定义代码后去根目录运行npm run build打包代码,打包后可以在packages/kunlun-plugin/dist下看到打包后的js和css文件(如模板中无css则不会生成css文件,无需理会)
    image.png
  9. 回到自定义图表模板的管理页面,找到对应的数据行,再次点击“低无一体”按钮,在弹窗内上传上一步生成的kunlun-plugin.umd.jskunlun-plugin.css文件,上传完成后点击弹窗底部的“确定”按钮保存
    image.png
  10. 进入图表的编辑页面,在图表分类选择处,可以看到柱状图的分类下有我们新增的“自定义柱状图”的子类,点击切换
    image.png
  11. 切换后可以看到图表已经从开始柱状图变成了我们在前面自定义的蓝色边框样式,内部是hello chart文字的图表。
    image.png

示例自定义图表组件

本例子以echarts的图表库实现柱状图,框架自带的是以G2的库实现的柱状图
demo-echarts-bar.vue

<template>
  <div class="data-designer-chart-instance demo-echarts-bar" ref="designerChartViewRef">
    <div class="data-designer-chart-container" ref="designerChartViewInnerRef"></div>
  </div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref, watch } from 'vue';
import DataSet from '@antv/data-set';

import * as echarts from 'echarts/core';
import { ECharts, EChartsCoreOption } from 'echarts/core';
import { GridComponent } from 'echarts/components';
import { BarChart, BarSeriesOption } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import { deepClone } from '@kunlun/dependencies';
import {
  filterDimensionScaleColumns,
  isSameObj,
  ChartTypeEnum,
  IChartData,
  IChartDataResult,
  chartViewMixin,
  isNeedRerenderChart,
  isShowChatView,
  watchEchartsSize,
  ChartRenderEngine
} from '@kunlun/data-designer-core';

echarts.use([GridComponent, BarChart, CanvasRenderer]);

export default defineComponent({
  props: {
    ...chartViewMixin.props
  },
  data() {
    return {
      engine: ChartRenderEngine.ECHARTS,
      chartType: [ChartTypeEnum.MAP_CHINA]
    };
  },
  mixins: [chartViewMixin],
  setup(props, { emit }) {
    const chart = ref<ECharts>();
    const designerChartViewRef = ref<HTMLElement>(null as any);
    const designerChartViewInnerRef = ref<HTMLElement>(null as any);
    onMounted(() => {
      initChart();
    });
    let option = {} as EChartsCoreOption;

    function initChart() {
      chart.value = echarts.init(designerChartViewInnerRef.value);
      option = {
        yAxis: {
          type: 'value'
        }
      };
    }

    let oldChartData = {} as IChartData;
    watch(
      () => props.chartData,
      (newVal) => {
        if (!newVal || !chart.value) {
          return;
        }
        if (!isNeedRerenderChart(newVal, oldChartData)) {
          oldChartData = deepClone(newVal);
          return;
        }
        render(chart.value!, newVal, props.chartDataResult);
        oldChartData = deepClone(newVal);
      },
      {
        immediate: true,
        deep: true
      }
    );
    let oldChartDataResult = {} as IChartDataResult;

    function watchDataList(chartData: IChartData, chartDataResult: IChartDataResult) {
      oldChartDataResult = deepClone(props.chartDataResult);
      if (!chart.value) {
        initChart();
      }
      render(chart.value!, chartData, chartDataResult);
    }

    // 监听数据的变动自动重新渲染
    watch(
      () => props.chartDataResult.data,
      () => {
        if (isSameObj(oldChartDataResult, props.chartDataResult)) {
          return;
        }
        if (!designerChartViewRef.value) {
          onMounted(() => {
            watchDataList(props.chartData, props.chartDataResult);
          });
        } else {
          watchDataList(props.chartData, props.chartDataResult);
        }
      },
      { immediate: true, deep: true }
    );

    /**
     * 自定义渲染逻辑
     * @param chart echarts图表对象
     * @param chartData 图表模板的定义
     * @param chartDataResult chartDataResult.data存放的是后端返回的图表数据
     */
    function render(chart: ECharts, chartData: IChartData, chartDataResult: IChartDataResult) {
      if (!isShowChatView(chartData)) {
        return;
      }
      if (!isSameObj(chartData, chartDataResult.chartData)) {
        return;
      }

      const {
        scales = [],
        dimensions = [],
      } = filterDimensionScaleColumns(chartData);

      const dataList = !scales.length || !dimensions.length ? [] : ((chartDataResult.data! || []) as any[]);

      dataList.forEach((a) => {
        if (dimensions.length && !a.name) {
          a.name = a[dimensions[0].chartField.displayName];
        }
        if (scales.length && !a.value) {
          a.value = a[scales[0].chartField.displayName] || null;
        }
      });
      const dv = new DataSet.DataView().source(dataList);

      option.xAxis = {
        type: 'category',
        data: dv.rows?.map((a) => a?.name)
      };
      option.series = [
        {
          type: 'bar',
          data: dv.rows?.map((a) => a?.value)
        } as BarSeriesOption
      ];
      chart.setOption(option);
    }

    // 监听图表容器大小
    watchEchartsSize(props, chart!);

    return { designerChartViewRef, designerChartViewInnerRef, chart };
  }
});
</script>
注册该模板
import { ChartRenderEngine, ChartRenderType, registerChartComponent } from '@kunlun/data-designer-core';
import component from './demo-echarts-bar.vue';

registerChartComponent({
  engine: ChartRenderEngine.ECHARTS,
  render: ChartRenderType.CANVAS,
  chartTemplateCode: 'test002'
},
  {
    component
  } as any
);
效果展示

数据可视化中图表的低无一体

Oinone社区 作者:nation原创文章,如若转载,请注明出处:https://doc.oinone.top/designer/70.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
nation's avatarnation数式员工
Previous 2023年6月20日 pm4:07
Next 2023年11月2日 pm1:58

相关推荐

  • 如何把平台功能菜单加到项目中?

    概述 在使用Oinone低代码平台进行项目开发的过程中,会存在把平台默认提供的菜单加到自己的项目中。这篇文章介绍实现方式,以角色管理为例。 1. 低代码情况 即项目是通过后端代码初始化菜单的方式。 通常在 XXXMenu.java类通过@UxMenu注解的方式,代码片段如下: 此种情况与添加项目本地的菜单无区别,具体代码: @UxMenu(value = "账号管理", icon = "icon-yonghuguanli") class AccountManage { @UxMenu("用户管理") @UxRoute(value = CustomerCompanyUserProxy.MODEL_MODEL, title = "用户管理") class CompanyUserManage { } @UxMenu("角色管理") @UxRoute(value = AuthRole.MODEL_MODEL, module = AdminModule.MODULE_MODULE, title = "角色管理") class RoleManage { } @UxMenu("操作日志") @UxRoute(value = OperationLog.MODEL_MODEL, module = AdminModule.MODULE_MODULE/***菜单所挂载的模块**/) class OperateLog { } } 2. 无代码情况 在界面设计器中,新建菜单–>选择绑定已有页面,进行发布即可。

    2024年4月19日
    1.9K00
  • 接口日志内容记录频率限制功能说明

    为有效避免接口调用日志记录占用过多存储空间,从而减少对数据库资源的消耗,自5.2.0之后的版本,对于成功请求的集成接口与开放接口,其日志将不再进行完整记录。请求及响应参数将依据默认的千分之一概率进行选择性完整记录。 修改日志完整记录频率 日志完整记录频率默认0.01,即千分之一。 取值范围0~1,0为完全不记录,1为100%记录。 pamirs: eip: log: frequency: 0.01 临时开启某接口日志完整记录 在“集成接口”应用中,可临时针对某一接口开启完整日志记录功能,此功能适用于集成接口与开放接口。 在“集成设计器”中也支持此功能。 注意事项 请求失败的接口不会受到配置的影响,日志内容将被完整记录。

    2024年10月8日
    1.1K00
  • 流程设计流程结束通知SPI接口

    1.实现SPI接口 import pro.shushi.pamirs.meta.common.spi.SPI; import pro.shushi.pamirs.meta.common.spi.factory.SpringServiceLoaderFactory; import pro.shushi.pamirs.workflow.app.api.entity.WorkflowContext; import pro.shushi.pamirs.workflow.app.api.model.WorkflowInstance; @SPI(factory = SpringServiceLoaderFactory.class) public interface WorkflowEndNoticeApi { void execute(WorkflowContext context, WorkflowInstance instance); } 自定义通知逻辑 /** * 自定义扩展流程结束时扩展点 */ @Order(999) @Component @SPI.Service public class MyWorkflowEndNoticeApi implements WorkflowEndNoticeApi { @Override public void execute(WorkflowContext context, WorkflowInstance instance) { Long dataBizId = instance.getDataBizId(); //todo自定义逻辑 } }

    2023年12月26日
    1.7K00
  • 弹窗或抽屉表单视图rootRecord获取不到对应的数据

    在平台默认的实现中,rootRecord 代表的是根视图的数据。比如,在表格页面点击按钮打开了弹窗,弹窗里面包含一个表单视图,但是该视图获取 rootRecord 却是最外层的视图数据。 如果期望 rootRecord 数据是弹窗的视图数据,需要手动修改表单的 rootRecord。下面的代码演示了如何重写 rootData 以确保其数据是弹窗的数据: @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Form, widget: 'MyCustomFormWidgetFormWidget' }) ) export class MyCustomFormWidgetFormWidget extends FormWidget { @Widget.Reactive() @Widget.Provide() public get rootData(): any[] | undefined { return this.activeRecords; } } 上述代码重写了 rootData,这样就可以确保 rootData 的数据是弹窗的数据。 接下来就是注册: registerLayout( ` <view type="FORM"> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <element widget="MyCustomFormWidgetFormWidget" slot="form"> <xslot name="fields" slotSupport="pack,field" /> </element> </view> `, { viewType: ViewType.Form, model: '弹窗模型', viewName: '弹窗视图名称' } )

    2023年11月13日
    2.2K00
  • 集成接口测试功能

    API、 WebService、数据库的测试功能

    2025年8月26日
    99300

Leave a Reply

Please Login to Comment