Skip to content

前言

企业版可视化业务组件模块, 框架基于 vue-echarts、echarts 封装,提供一系列图表组件,如:柱状图、折线图、饼图、雷达图、散点图、地图、雷达图、关系图等。

药品销售-全国医院销售数据-全局分析-销售趋势图为例:

配置&数据:
  • 后端 config 接口提供全局分析配置

  • 顶部搜索栏传递参数 queryData(数据搜索条件)

组件模块包含:
hooks依赖:

config

config接口的地址为:/external/medical/databases/${数据库alias}/chart/global/config,用于请求全局分析的配置数据,返回的格式如下:

Details
json

{

    "data": [

        {

            "id": 58,

            "category": "销售趋势",

            "hover": "",

            "dimensions": [

                {

                    "id": "year",

                    "name": "年度趋势",

                    "hover": "",

                    "checked": 1,

                    "route": "/external/medical/databases/d6a78428b3/chart/global/result/year",

                    "draw": {

                        "sort": {

                            "default": 1,

                            "options": [

                                {

                                    "name": "年份升序",

                                    "value": 1

                                },

                            ]

                        },

                        "limit": null,

                        "filters": [],

                        "group": null,

                        "series": null,

                        "quota": null,

                        "cluster": null

                    },

                    "icon": "icon-nianduqushi"

                },

                
            ]

        },


    ]

}

其中 dimensions全局分析 单个图形配置数据:

json

 {

    "id": "图表ID",

    "name": "图表名称",

    "hover": "",

    "checked": "默认是否显示", 

    "route": "请求图表数据接口地址",

    "draw": { // 图表的搜索栏配置项 

        "sort": "",

        "limit": null,

        "filters": [],

        "group": null,

        "series": null,

        "quota": null,

        "cluster": null

    },

    "icon": "icon-nianduqushi"

 }

queryData

queryData: 为企业版顶部搜索栏选中参数条件

Details
json

{

  "query": "",

  "p": [


  ],

  "per_page": 15,

  "page": 1,

  "searches": [

    {

      "module_id": -245030,

      "precise": 0,

      "value": [

        "化学药"

      ],

      "_label": {

        "title": "药品类型",

        "data": "化学药"

      },

      "type": 1,

      "subset_checked": true,

      "arr_val": [


      ]

    },

    {

      "module_id": -245040,

      "precise": 0,

      "value": [

        "2020",

        "2019",

        "2018"

      ],

      "_label": {

        "title": "年份",

        "data": "2020、2019、2018"

      },

      "type": 1,

      "subset_checked": true,

      "arr_val": [


      ]

    },

    {

      "module_id": -245060280,

      "precise": 0,

      "value": "乙类",

      "_label": {

        "title": "OTC分类",

        "data": "乙类"

      },

      "type": 1,

      "subset_checked": true,

      "arr_val": [


      ]

    }

  ]

}

WholeParseItem

WholeParseItem 为单个图表业务模块,每个数据库-全局分析-图表不同、逻辑不同,所以wholeParseItem不同;

需针对每个数据库全局分析自定义开发

  1. 药品销售-全国医院销售数据-销售趋势图.WholeParseItem JS 数据处理逻辑如下
js

const chartData = shallowRef({});

const reqCallBack = ({ sourceData }) => {

    // 接受后端返回的 图表数据,调用makeBarLineData方法处理数据,返回BarLine 需要的格式

    chartData.value =  makeBarLineData(cloneDeep(sourceData))

};

const props = defineProps({

    dimension: { type: Object, require: true }, // 当前图表维度信息 即config.dimensions

    queryData: { type: Object }, //为企业版顶部搜索栏选中参数条件

});


// 图表请求数据hooks, 请求url为 props.dimension.route, 参数为 props.queryData和props.dimension.draw,详情可查看 useChartRequest介绍

const { chartState, _copy_dimension, changeFilterActiveDraw, createOrdinaryParam } = useChartRequest({

    props: props,

    isOrdinary: true,

    reqCallBack,

});

// chart搜索条件改变

const bindFilterChange = event => {

    changeFilterActiveDraw(event.filter);

};


const chartItemRef = shallowRef();

// 图表工具函数、详情可查看 useChartTools介绍

const { removeImg, saveImg, exportDimsExcel, goChartDetail } = useChartTools(chartItemRef, props.dimension.name);


// 导出 excel

const onExport = () =>

    exportDimsExcel(_copy_dimension.value.alias, createOrdinaryParam(), _copy_dimension.value.scope);


const bindClose = () => {removeImg();};


const chartImgRef = shallowRef();

const activeTool = ref('bar');

const onSaveImg = () => {saveImg(_copy_dimension.value.name, options);

};

const route = useRoute();

const bindGoDetail = () => {goChartDetail();};


const chartTools = computed(() => {

    const tools = (chartState.sourceData.option?.types ?? []).slice();

    tools.push('dataView');

    return tools;

});

在JS部分的主要工作是通过configdimensions配置和queryData条件,使用useChartRequest请求单个图表数据,并处理各个图表辅助控件之间的数据交互逻辑。

  1. 药品销售-全国医院销售数据-销售趋势图.WholeParseItem HTML 组件结构如下
html

   <div class="chart-item-box p-box" ref="chartItemRef">

    <div class="top">

      <!-- 标题 -->

      <div class="title hover-title" >

        <chart-title :copyDimension="_copy_dimension":queryData="props.queryData"/>

      </div>

      <!-- 操作栏   -->

      <ChartButtonGroup >

        <ChartButton type="detail" title="点击跳转详情页" @click="bindGoDetail"></ChartButton>

        <ChartButton type="export" title="导出" color="#3787FD"></ChartButton>

        <ChartButton type="down" @click="onSaveImg"></ChartButton>

        <ChartButton type="close" @click="bindClose"></ChartButton>

      </ChartButtonGroup>

    </div>

    <div class="chart-content">

      <!-- 排序规则  -->

      <div class="filter-chart">

        <div class="filter-content" >

          <filter-group-row v-model="_copy_dimension.draw" @filter-change="bindFilterChange"></filter-group-row>

          <ChartToolBox :toolTypes="chartTools" v-model="activeTool" />

        </div>


        <!-- 图表 -->

        <div class="box-table-chart">

          <chart-empty-loading :is-empty="chartState.isEmpty" :loading="chartState.loading">

            <BarLineItem ref="chartImgRef" :chart-data="chartData"/>

          </chart-empty-loading>


          <Transition :duration="550">

            <div class="data-table" v-show="activeTool === 'dataView'">

              <BarLineTable

                :data="chartData"

                :x-name="chartState?.sourceData?.option?.xAxis"

              ></BarLineTable>

            </div>

          </Transition>

        </div>

      </div>

    </div>

 </div>

上述HTML由图表辅助控件中的chartTitleChartButtonGroupfilter-group-rowchart-empty-loading组件,

以及自定义组件BarLineItem; 和BarLineTable组件的结合构成。

如果实际开发中现有的组件不能满足需求,也可以使用自定义的DIV替换ChartTitle,实现自定义标题。

BarLineItem

BarLineItem 单个ECharts图表的自定义渲染模块,根据业务要求自定义ECharts图表的样式。

由于每个数据库的图表存在细微的差异,因此BarLineItem需要针对每个数据库进行自定义开发。

  1. BarLineItem HTML 组件结构如下
    html
    
        <ChartBox ref="chartBoxRef">
    
          <template #tooltip="{ data }">
    
            <Tooltip :data="tooltipList?.length ? tooltipList : data"></Tooltip>
    
          </template>
    
          <template #chart>
    
            <BarLine ref="barLineRef" :option="option" :dataZoomOpen="true"></BarLine>
    
          </template>
    
          <template #legend="{ legends, legendSelect }">
    
            <Legend :legendList="legends" @legendTap="legendSelect"></Legend>
    
          </template>
    
        </ChartBox>

BarLineItem的包括TooltipBarLineLegend三个部分。如果需要,也可以根据业务需求自定义替换tooltiplegend组件。如果当前图表不需要展示legend组件,也可以将其删除。

chartBox主要用于为tooltiplegend提供数据,如果tooltiplegend都不需要,那么chartBox也应被删除。

  1. BarLineItem JS 数据处理逻辑如下
js

const props = defineProps({

    chartData: Object,

    dimId: String,

});

const barLineRef = shallowRef();

const chartBoxRef = shallowRef();


const option = shallowRef({

    // 自定义 echarts.options 配置,会覆盖 定义的基础options配置

});


const tooltipList = shallowRef([]);


function drawChart(sourceData) {

    const { seriesData, xData } = makeBarLineData(sourceData);

    tooltipList.value = [];

    // 渲染图表

    barLineRef.value?.drawData(xData, seriesData);

    nextTick(() => {

        // 异步触发, 用户获取tooltip/legend数据

        chartBoxRef.value?.drawData();

    });

}


// 监听 wholeParseItem 传递的chartData数据

watch(

    [() => props.chartData?.seriesData, () => chart.value?.chart],

    () => {

        const sourceData = toRaw(props.chartData);

        if (chart.value?.chart && !$isEmpty(sourceData)) {

            drawChart(sourceData);

        }

    },

    { immediate: true, flush: 'post' },

);

监听来自WholeParseItemchartData 数据,通过makeBarLineData()将其处理为统一格式数据,最终调用BarLine.drawData()方法渲染ECharts图表。

option配置注意事项
  1. options 中 xAxis 必须为对象; yAxis、dataZoom、visualMap 为数组对象;

  2. options.yAxis.type='y\_${seriesType}', 例如:BarLine.option= [{type: 'y_line'}, {type: 'y_bar'}]

  3. 其它参考echarts.option 官方文档

More

以上为一个完整的 企业版-全局分析-图表开发流程。 WholeParseItem 负责图表的交互逻辑和数据获取。

BarLineItem 负责图表自定义渲染逻辑。