echarts与dataV实现前端看板

前言

echarts与dataV作为看板开发模板,以本次项目为例,逐一实现项目中的难点问题

一、ui图

在这里插入图片描述

首先这是ui图,也就是本次项目要实现的目标

二、分析

ui图中有大致五个区域,其中四个区域为轮播,也就是月度计划中的进度条,日计划的表格,以及下方的柱状图和饼图左右轮播。

三、实现

1.dataV轮播

这算是本次项目中最简单的一环,作为优秀的可视化ul组件,dataV给我们创造了很多便利,代码如下:

const config = {
      header: [
        this.headStyle('物料编码'),
        this.headStyle('物料描述'),
        this.headStyle('派工数量'),
        this.headStyle('实际交付'),
        this.headStyle('计划达成率'),
      ],
      data,
      align: ['center', 'center', 'center', 'center', 'center'],
      rowNum: 5,
      headerBGC: '#223764',
      columnWidth: [80, 95, 80, 80, 90],
      hoverPause: false,
      oddRowBGC: '#203864',
      evenRowBGC: '#374D74',
      waitTime: second*1000,
    };

这是轮播图dataV中的配置代码,其中的data需要我们从后端取值,较为可取的方法便是将其便利,再进行配置,代码如下:

const data = [];
    const {dataSource, second} = this.props;
    dataSource.map((list) => {
        return data.push([
          `<span title="${list.materialCode}" style='font-size:12px;display: inline-block;width: auto;'>${list.materialCode}</span>`,
          `<span title="${list.materialName}" style='font-size:12px;display: inline-block;width: auto;'>${list.materialName}</span>`,
          `<span title="${list.dispatchQty}" style='font-size:12px;display: inline-block;width: auto;'>${list.dispatchQty}</span>`,
          `<span title="${list.actualDeliverQty}" style='font-size:12px;display: inline-block;width: auto;'>${list.actualDeliverQty}</span>`,
          `<span title="${list.planReachRate}%" style='font-size:12px;display: inline-block;width: auto;'>${list.planReachRate}%</span>`,
        ]);
    });

最终效果图:在这里插入图片描述

2. 柱状图轮播

这是项目中较难的一环,原因在于柱状图的左右轮播不能再像dataV那样取现成的组件,而是需要自己写一些代码逻辑,去实现轮播,起初也是有一定的难度,但在经过一番思索和请教高人后,也是找到了解决方法:

  • 首先我们需要用到父子组件,子组件需要接收来自父组件不同的数据,毕竟这是要与后端联调,所以刚开始就不能把数据写死,但若是测试数据则是行得通的。
  • 引用hzero-ui的走马灯,也就是轮播图插件Carousel,
    import { Carousel } from 'hzero-ui';
    
    用div将子组件包裹,然后在父组件接收后端的值将其传给子组件。

那么问题来了,如何进行轮播?
传统的轮播图是利用插件对图片轮播,但这次是数据,而且是格式尚不明确的数据,所以前端在刚开始开发的时候就要想到这一点,于是我将这次的轮播换了一个写法,先看一处代码:

const count = Math.floor(topList.length / 4);
    const attr = [];
    const leftAttr = [];
    for (let i = 0; i < count; i++) {
      attr.push(i);
    }
    const left = topList.length % 4;
    for (let i = left - 1; i >= 0; i--) {
      leftAttr.push(topList.length - 1 - i);
    }

这是很简单的几行代码,但它却是这次项目中的核心,简单点说,我们会将整个屏幕分成24份,每一个柱状图区域占去6份:在这里插入图片描述
这样一来,我们也就确定了一个页面一组数据有四个,那就简单了,上面的代码里面我们的操作便是取到后端的数据,将其数据长度除以4,然后得到商和余数,分别放进不同的数组之中,得到两种结果:

  • 余数为0,也就是数据长度为4的倍数,不考虑其他因素,利用map函数循环,取出e的下标,然后给子组件分别传递不同下标的数据,像这样:

    attr.map(e => {
                        return (
                          <div>
                            <Row>
                              <Col span={6}>
                                <ProcessNcChart data={topList[e]} />
                              </Col>
                              <Col span={6}>
                                <ProcessNcChart data={topList[e + 1]} />
                              </Col>
                              <Col span={6}>
                                <ProcessNcChart data={topList[e + 2]} />
                              </Col>
                              <Col span={6}>
                                <ProcessNcChart data={topList[e + 3]} />
                              </Col>
                            </Row>
                          </div>
                        );
                      })
    

    然后我们进入子组件中,就可以打印出此时获取到的不同数据,即可进行展示;这是第一种情况。

  • 余数不为0,这个时候我们就要考虑,将剩下的数据紧紧跟在上一组数据之后,代码如下:

    {left > 0 && (
                      <div>
                        <Row>
                          {leftAttr.map(e => {
                            return (
                              <Col span={6}>
                                <ProcessNcChart data={topList[e]} e={e} />
                              </Col>
                            );
                          })}
                        </Row>
                      </div>
                    )}
    

    left这个数组即是我们之前拿到的余数数组,将其map循环,然后利用e下标传递给子组件不同的数组。

这就是两种不同的情况,代码写到这里基本已经完成,但还要注意一点,也是我写完代码现场业务人员测出来的问题,就是传递的下标问题,举个例子,业务那边要的是每一次轮播之后刷新四个柱状图数据,但是我之前的代码是只会刷新一个数据,具体是这样:

第一个页面之中,四组数据的下标是0,1,2,3,然后到轮播完成后的第二个页面中下标便会成为:1,2,3,4;问题原因便在于传递时代码逻辑错误:在这里插入图片描述
所以只需要改变e为4*e即可在这里插入图片描述
成品:
在这里插入图片描述
轮播的话大家自己脑补就可以了哈~这里没有截动态图片,
最后给上子组件的整体柱状图代码

import React, { PureComponent } from 'react';
import { isEmpty } from 'lodash';
import Chart from '@/utils/chart';

import styles from './index.less';

export default class InspectorInspectionCharts extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      mount: '',
    };
  }

  render() {
    const {
      data = [],
    } = this.props;
    const list = [];
    const map = [];
    let valuename;// top产线
    let valuenames;// 直通率产线
    if (data.chartsValueList.length !== 0) {
      valuename = data.chartsValueList[0].prodLineName;
    };
    if (data.proLineName) {
      valuenames = data.proLineName;// 直通率与top产线优先展示
      this.setState({
        mount: valuenames,
      });
    };

    if (data.chartValueList) {
      data.chartValueList.map((e) => {
        return list.push([e.productionGroupCode]);
      });
    }
    if (data.chartValueList) {
      data.chartValueList.map((e) => {
        return map.push(((e.throughRate) * 100).toFixed(0));
      });
    }
    if (!data.proLineName) {
      this.setState({
        mount: valuename,
      });
    }
    const option = {
      // 设置柱状图位置,x:与左侧边界距离;y:与上侧边界距离;width:柱状图宽度;height:柱状图高度
      grid: {
        top: '20%',
        left: '15%',
        bottom: '25%',
        right: '5%',
      },
      // 图表标题设置,其内容以及位置
      title: {
        text: this.state.mount,
        textStyle: {
          color: '#00ffff',
          fontSize: 12,
        },
        left: 'center',
      },
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          lineStyle: {
            color: {
              type: 'shadow',
              x: 0,
              y: 0,
              x2: 0,
              y2: 1,
              colorStops: [
                {
                  offset: 0,
                  color: 'rgba(0, 255, 233,0)',
                },
                {
                  offset: 0.5,
                  color: 'rgba(255, 255, 255,1)',
                },
                {
                  offset: 1,
                  color: 'rgba(0, 255, 233,0)',
                },
              ],
              global: false,
            },
          },
          type: 'shadow',
        },
      },
      // X轴
      xAxis: [
        {
          gridIndex: 0, // 定义index
          type: 'category',
          data: list,
          axisLabel: {
            rotate: 40,
            show: true,
            textStyle: {
              color: '#2B92FD',
              fontSize: 10,
            },
            formatter(value) {
              if (value && value.length > 5) {
                return `${value.slice(0, 5)}...`;
              } else {
                return value;
              }
            },
          },
          splitLine: {
            show: false,
          },
          nameRotate: 30,
          axisLine: {
            lineStyle: {
              color: '#2B92FD',
            },
          },
        },
      ],
      yAxis: [ // y轴
        {
          gridIndex: 0,
          axisLabel: {
            textStyle: {
              fontFamily: 'PingFang-SC-Medium',
              color: 'rgba(240, 235, 235, 0.5)',
              fontSize: 10,
            },
            show: true,
            interval: 'auto',
            formatter: '{value} %',
          },
          splitLine: {
            show: false,
          },
          axisLine: {
            lineStyle: {
              color: '#2B92FD',
            },
          },
        }, // 定义y轴index
      ],
      series: [
        {
          type: 'bar',
          xAxisIndex: 0, // 使用x轴的index-0,y轴的index-0
          yAxisIndex: 0,
          show: false, // 是否进行展示
          data: map,
          barMaxWidth: 40,
          barMinWidth: 10,
          itemStyle: {
            normal: {
              color: '#2B92FD',
              label: {
                show: true,
                formatter: `{c}%`,
                position: 'top',
                textStyle: {
                  color: '#2B92FD',
                  fontSize: 10,
                },
              },
            },
          },
        },

      ],

    };
    return (
      <div style={{ height: '3.2rem' }}>
        {isEmpty(list) ? (
          <div>
            <div className={styles.directRate} style={{ marginBottom: '1rem' }}>{this.state.mount}</div>
            <div className={styles.directRate}>暂无数据</div>
          </div>
        ) : (
          <Chart
            option={option}
          />
        )}
      </div>
    );
  }
}

之后的代码里面包括饼图的左右轮播,进度条的上下轮播,也都是和柱状图一个道理哈!

最后给上ui图和成品图的对比:

ui在这里插入图片描述
成品在这里插入图片描述
  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值