Vue2+Echarts封装组件:专注逻辑,图表生成自动化

通过Vue2封装了一个Echarts图表组件,不需要关注图表的生成和渲染了,只需要关注逻辑开发即可,包含了柱状图、折线图、饼图、柱状叠加图、柱状图折线图组合、柱状叠加图与柱状图的组合等,包含了图表下钻、右键跳转明细功能,无需关注Echarts的实现,提高开发效率

开发者能够将注意力集中在业务逻辑的开发上,而无需担心底层图表的创建和渲染过程。这样的表述既体现了组件的便捷性,也突出了它对提高开发效率的帮助。同时,对于那些寻找简化ECharts集成解决方案的开发者来说,这也是一个很好的案例。

组件使用
(1调用)<SzqCommonChart :chart-data="charDataArray" :height="aotuMainHeight.height" />

(2data)data() {
    return {
      aotuMainHeight: {
        height: ''
      },
      charDataArray: [],
    }
  },
(3接口回调后)
	// legend 处理:
               const all = ['示例1','实例2','示例3']
	// 下钻的数据
	const idData = [{ name: '', id: '',userId: ''}]
	// 横坐标的数据
            	const xData = ['X1','X2','X3']
	// 图表的数据
               const mbData = [1,2,3] // 柱状图
               const sjData = [4,5,6] // 柱状图
               const lvData = [7,8,9] // 折线图
	// 图表的颜色
	const color = ['#73deb4', '#f6e0b4', '#5b8ff9']
	// Y轴单位
                 const unit = ['个', '']
	// 参数传递 ,
	// 2:  2代表左侧Y轴两个柱状图  1代表右侧Y轴的折线图  'barAndLine', 图的类型(此处为柱状图和折线图的组合,其他的见 SzqCommonChart)
	// true 是否下钻  标志1表示不同页面的不同图表的区分  all 图表实例 color图表颜色 unitY轴单位 true是否显示单位	
               this.charDataArray.push([2, 1, 'barAndLine', true, '标志1', all, color, unit, true])
            // 参数2:下钻参数.
            this.charDataArray.push(idData)
            // 参数3:横坐标
            this.charDataArray.push(xData)
            // 参数4 数据信息
            this.charDataArray.push([mbData, sjData, lvData])
/**
 * 最大值最小值
 */
export function szqMaxAndMin(data) {
  // series 中 所有数据的最大值和最小值
  let isLing = false
  const arrLing = []
  data.forEach(it => {
    if (it.yAxisIndex === 1) {
      arrLing.push(...it.data)
    }
  })
  isLing = arrLing.every(number => Number(number) === 0)
  const mm = maxAndMin(data)
  // Min 左边数值轴, Min1 右侧百分比轴
  const Max = Math.ceil(mm[0].max)
  const Max1 = Math.ceil(mm[1].max)
  let Min = mm[0].min
  let Min1 = mm[1].min
  const rat1 = Min / Max
  const rat2 = Min1 / Max1
  rat1 > rat2 ? Min = rat2 * Max : Min1 = rat1 * Max1
  return { max: Max, min: Math.ceil(Min), max1: Max1, min1: Math.ceil(Min1), isLing }
}
function maxAndMin(allData) {
  const result = {}
  allData.forEach(item => {
    const yAxisIndex = item.yAxisIndex
    const values = item.data.map(value => value && parseInt(value))
    if (!result[yAxisIndex]) {
      result[yAxisIndex] = {
        max: Math.max(...values),
        min: Math.min(...values)
      }
    } else {
      result[yAxisIndex].max = Math.max(result[yAxisIndex].max, ...values)
      result[yAxisIndex].min = Math.min(result[yAxisIndex].min, ...values)
    }
  })
  return result
}

export function autoBottom(h, isTitle) {
  let height = ''
  let left = []
  let right = []
  if (h <= 400) {
    isTitle ? height = '42.5%' : height = '40%'
  } else if (h <= 450) {
    isTitle ? height = '42.5%' : height = '40%'
  } else if (h <= 500) {
    isTitle ? height = '37.5%' : height = '35%'
  } else if (h <= 550) {
    isTitle ? height = '34.5%' : height = '32%'
  } else if (h <= 600) {
    isTitle ? height = '33.5%' : height = '31%'
  } else if (h <= 650) {
    isTitle ? height = '30.5%' : height = '28%'
    left = [0, 10, -10, -20]
    right = [0, -30, -10, 0]
  } else if (h <= 700) {
    isTitle ? height = '27.5%' : height = '25%'
    left = [0, 10, -5, -20]
    right = [0, -30, -5, 0]
  } else if (h <= 750) {
    isTitle ? height = '26.5%' : height = '24%'
  } else if (h <= 800) {
    isTitle ? height = '23.5%' : height = '21%'
  } else {
    isTitle ? height = '22.5%' : height = '20%'
  }
  return { height, left, right }
}
<template>
  <!-- 图表区域 -->
  <div>
    <div ref="myEchart" :style="{ height: height, width: width }" />
  </div>
</template>

<script>
import * as echarts from 'echarts'

export default {
  name: 'BasicChart',
  props: {
    options: {
      type: Object,
      default: () => {}
    },
    height: { type: String, default: '100%' },
    width: { type: String, default: '100%' }
  },
  data() {
    return {
      myEchart: null,
      eChart: null,
      showPopover: false,
      popData: [],
      aotuPHeight: {
        left: '',
        top: ''
      },
      popName: '',
      topS: 0,
      popup: '',
      state: {
        sType: '',
        x: '',
        xl: '',
        value: '',
        id: '',
        userId: ''
      }
    }
  },
  watch: {
    options: {
      handler(next) {
        this.$nextTick(() => {
          // 如果只改变了颜色或者坐标轴等信息,不刷新图表
          this.eChart ? this.eChart.setOption(next, true) : ''
        })
      },
      deep: true,
      immediate: false
    }
  },
  mounted() {
    // 初始化图表数据
    this.initEChart()
    window.addEventListener('resize', this.resizeChart)
    document.addEventListener('click', this.handleScreenClick)
    document.addEventListener('mousemove', this.handleMouseMove)
    window.addEventListener('scroll', this.handleScroll, true)
  },
  beforeDestroy() {
    this.eChart ? this.eChart.clear() : ''
    window.removeEventListener('resize', this.resizeChart)
  },
  methods: {
    handleScroll(event) {
      this.topS = event.srcElement.scrollTop
    },
    handleMouseMove(event) {
      if (this.showPopover) {
        this.aotuPHeight.left = (event.clientX + 20) + 'px'
        this.aotuPHeight.top = (this.topS + (event.clientY - 60)) + 'px'
      }
    },
    initEChart() {
      // 图表初始化
      this.$nextTick(() => {
        this.eChart = echarts.init(this.$refs.myEchart)
        this.eChart.setOption(this.options, false)
        this.eChart.on('legendselectchanged', (params) => {})
        // 鼠标移入后自定义的数据显示弹窗
        this.eChart.on('mouseover', (params) => {})
        // 鼠标移除处理
        this.eChart.on('mouseout', (params) => {})
        // 单机事件,针对于没有下钻有明细的
        this.eChart.on('click', (params) => {
          if (this.options.onlyClickBUYAOLE) {
            // 不需要传递参数的例子
            if (this.options.sType === '标志1') {
              this.$bus.emit('ld-mx-no-params', 'MX')
            } else if (this.options.sType === '标志2') {
              //  需要传递参数的例子获取点击的图表数据
              const name = params.name
              this.$bus.emit('ld-mx-bing', name, 'MX')
            }
          }
        })
        // 右键事件
        this.eChart.on('contextmenu', (params) => {
          if (this.options.xzFlag) {
            // 决定处理那个图表
            this.state.sType = this.options.sType
            // 点击的横坐标
            this.state.x = params.name
            // 点击的系列
            this.state.xl = params.seriesName
            // 点击的值
            this.state.value = params.value
            // 在 横坐标放了隐藏数据,记录了一些数据
            if (this.options && this.options.xAxis.length === 2) {
              const id = this.options.xAxis[1].data.filter(item => item.name === params.name)
              id.length > 0 ? this.state.id = id[0].id : this.state.id = []
              id.length > 0 ? id[0].userId ? this.state.userId = id[0].userId : this.state.userId = '' : this.state.userId = ''
            }
            if (this.popup && this.popup.innerHTML !== '') {
              this.popup.innerHTML = ''
            }
            console.log('111111111111111111111', this.options, params, this.state)
            // 根据每个图表的sType判断不同的模块及模块对应的图表
            // 显示右键菜单
            this.showContextMenu(params.dataIndex, this.state, '')
          }
          // 右键明细的案例
          if (this.options.onlyClick) {
            if (this.popup && this.popup.innerHTML !== '') {
              this.popup.innerHTML = ''
            }
            let hehe = ''
            console.log('333333333333333', params)
            if (this.options.sType === '标志1') {
              this.state.value = params.data.unit
              hehe = 'HEHE'
            } else if (this.options.sType === '标志2') {
              this.state.value = params.name
              hehe = 'HEHE'
            }
            this.showContextMenu(params.dataIndex, this.state, hehe)
          }
        })
      })
    },
    // 显示右键菜单
    showContextMenu(dataIndex, state, type) {
      this.popup = document.createElement('div')
      this.popup.style.position = 'absolute'
      this.popup.id = 'ID' + dataIndex
      this.popup.className = 'custom-context-menu'
      this.popup.style.left = event.pageX + 'px'
      this.popup.style.top = event.pageY + 'px'
      this.popup.style.zIndex = 100
      if ((state.userId && state.userId !== '' && state.userId !== undefined) || type === 'HEHE') {
        this.popup.innerHTML = `<div style="width: 120px; height: 40px;background-color: rgba(0, 0, 0, .4);border-radius: 5px; text-align: center; color: #ffffff; font-size: 15px;cursor:pointer">
        <div id="myButton2" style="height: 40px; text-align: center; line-height: 40px;">明细</div>
        </div>`
        document.body.appendChild(this.popup)
        document.getElementById('myButton2').addEventListener('click', () => {
          this.clickMx()
        })
      } else {
        this.popup.innerHTML = `<div style="width: 120px; height: 80px;background-color: rgba(0, 0, 0, .4);border-radius: 5px; text-align: center; color: #ffffff; font-size: 15px;cursor:pointer">
        <div id="myButton1" style="height: 40px; text-align: center; line-height: 40px; border-bottom: 1px solid #d7d7d7">下钻</div>
        <div id="myButton2" style="height: 40px; text-align: center; line-height: 40px;">明细</div>
        </div>`
        document.body.appendChild(this.popup)
        document.getElementById('myButton1').addEventListener('click', () => {
          this.clickXz()
        })
        document.getElementById('myButton2').addEventListener('click', () => {
          this.clickMx()
        })
      }
    },
    // 处理下钻
    clickXz() {
      if (this.state.sType === '标志1') {
        this.$bus.emit('customer-coverage', this.state, 'XZ')
      }
    },
    // 明细处理
    clickMx() {
      if (this.state.sType === '标志1') {
        this.$bus.emit('customer-coverage', this.state, 'MX')
      } 
    },
    handleScreenClick() {
      if (this.popup && this.popup.innerHTML !== '') {
        this.popup.innerHTML = ''
      }
    },
    resizeChart() {
      this.eChart && this.eChart.resize()
    }
  }
}
</script>

<style scoped lang="scss">
.popoverClass {
  background-color: rgba(0,0,0,0.5);
  border: 1px solid rgba(0,0,0,0.4);
  z-index: 10;
  position: absolute;
  color:white;
  border-radius: 5px;
}
</style>

<template>
  <BasicChart id="echart" :height="height" :width="width" :options="option" />
</template>

<script>
import BasicChart from './BasicChart/index'
import { szqMaxAndMin, autoBottom } from './cockpit.js'
export default {
  name: 'SzqCommonChart',
  components: {
    BasicChart
  },
  props: {
    // 图表数据
    chartData: {
      type: Array,
      default: () => null
    },
    // 图表高度
    height: { type: String, default: '400px' },
    // 图标宽度
    width: { type: String, default: '100%' },
    // 是否显示弹窗
    showTooltoip: { type: Boolean, default: true },
    // 是否有标题
    isTitle: { type: Boolean, default: false },
    // 设置图表边距
    setGrid: {
      type: Object,
      default() {
        return { left: '1.5%', right: '1%', top: '12%', bottom: '19%' }
      }
    },
    // 是否显示示例1
    showLegend: { type: Boolean, default: true },
    // 示例排布,纵向 vertical 横向 horizontal
    orientLengent: { type: String, default: 'horizontal' },
    // 示例位置,以right为准,设置auto则居中
    rightLengent: { type: String, default: '10' },
    leftLengent: { type: String, default: 'auto' },
    topLengent: { type: String, default: 'auto' },
    funcType: { type: String, default: '' }
  },
  data() {
    return {
      windowHeight: window.innerHeight,
      isRate: true,
      option: {
        // 提示框1
        tooltip: {
          show: this.showTooltoip,
          trigger: 'axis',
          axisPointer: {
            type: 'shadow',
            animation: false,
            snap: true, // 让 axisPointer 自动对齐到最近的数据点
            crossStyle: {
              color: '#999'
            }
          },
          borderColor: 'rgba(0,0,0,0.4)',
          showContent: true, // 是否显示悬浮提示框
          alwaysShowContent: false, // 是否一直显示悬浮窗
          backgroundColor: 'rgba(0,0,0,0.5)',
          formatter: (params) => {
            if (this.funcType === 'KHSL') {
              return ''
            }
            // 自定义弹窗显示样式1
            // 获取xAxis data中的数据
            let dataStr = `<div><p style="font-weight:bold;margin:0 8px 15px;color:white">${params[0].name}</p></div>`
            params.forEach((item) => {
              let data = ''
              let name = ''
              if (this.funcType === 'PASS') {
                data = Number(item.data)
                const ind = item.componentIndex
                if (ind <= 3) {
                  name = item.seriesName + '(同期)'
                } else {
                  name = item.seriesName + '(当期)'
                }
              } else {
                name = item.seriesName
                // 如果返回的是整数,不保留小数
                if (item.seriesType === 'line') {
                  if (this.isRate) {
                    data = Number.isInteger(Number(item.data)) ? Number(item.data) + '%' : Number(item.data).toFixed(2) + '%'
                  } else {
                    data = Number.isInteger(Number(item.data)) ? Number(item.data) : Number(item.data).toFixed(2)
                  }
                } else {
                  data = Number.isInteger(Number(item.data)) ? Number(item.data) : Number(item.data).toFixed(2)
                }
              }
              dataStr += `<div>
                              <div style="margin: 0 8px;">
                                  <span style="display:inline-block;margin-right:5px;width:10px;height:10px;background-color:${item.color};"></span>
                                  <span style="color:#FFFFFF">${name}:</span>
                                  <span style="float:right;color:#FFFFFF;margin-left:20px;">${data}</span>

                                  </div>
                      </div>`
            })
            return dataStr
          }
        },
        // 图表边距
        grid: {
          left: this.setGrid.left,
          right: this.setGrid.right,
          top: this.setGrid.top,
          bottom: this.setGrid.bottom,
          containLabel: true
        },
        // 系列
        legend: {
          show: this.showLegend,
          orient: this.orientLengent, // 示例排布,横纵向
          right: this.rightLengent, // 不设置则居中显示
          left: this.leftLengent, // 不设置则居中显示
          top: this.topLengent,
          itemGap: 25, // type: 'scroll', height: '300', !!饼图示例出界可以用
          animation: false,
          data: [],
          textStyle: {
            fontSize: 12,
            color: '#303313'
          }
        },
        xAxis: [
          {
            show: false,
            type: 'category', // 类目轴,适用于离散的类目数据
            inverse: false,
            name: '',
            data: [],
            nameLocation: 'end', // 坐标轴名称显示的位置
            nameTextStyle: {
              // 名称的样式
              fontStyle: 'normal',
              fontWeight: 'bold', // 粗体
              fontSize: 14,
              align: 'left',
              padding: [30, 0, 0, 0],
              color: '#303313' // X轴 文本字体的颜色
            },
            axisLine: {
              lineStyle: {
                width: 1, // 线的宽度
                color: '#7d7d7d' // X轴的颜色
              }
            }, // 轴线相关配置
            axisLabel: {
              // 坐标轴刻度标签相关配置
              show: true,
              color: '#858689',
              padding: [5, 0, 0, 5],
              interval: '0', // 自动计算间隔
              formatter: (value) => {
                return value && value.split('(').length > 0 ? value.split('(')[0] : value
              },
              // rotate: 12,
              // fontSize: 11,
              rich: {
                year: {},
                month: {
                  padding: [0, 0, 3, 0],
                  fontWeight: 'bold'
                }
              }
            },
            axisTick: {
              alignWithLabel: true // 刻度线与标签对齐
            }
          },
          {
            show: false,
            data: []
          }
        ],
        yAxis: [
          {
            show: false,
            type: 'value',
            name: '', // 单位
            position: 'left', // Y 轴的位置
            inverse: false,
            nameTextStyle: {
              fontStyle: 'normal',
              fontSize: 13,
              align: 'left',
              padding: [0, 0, 0, -20]
            },
            nameGap: 18,
            axisLabel: {
              color: '#858689',
              interval: 'auto',
              // Y轴内容文字颜色
              formatter: (value) => {
                return Number.isInteger(Number(value)) ? Number(value) : Number(value).toFixed(2)
              }
            },
            axisLine: {
              // y轴线的配置
              show: false, // 是否展示
              lineStyle: {
                color: '#7d7d7d', // y轴线的颜色(若只设置了y轴线的颜色,未设置y轴文字的颜色,则y轴文字会默认跟设置的y轴线颜色一致)
                width: 1, // y轴线的宽度
                type: 'solid' // y轴线为实线
              }
            },
            splitLine: {
              lineStyle: {
                type: 'dashed',
                color: '#e5e6eb', // 虚线颜色
                width: 1
              }
            },
            axisTick: {
              lineStyle: {
                color: '#7d7d7d' // 轴小横线的颜色
              }
            }
          },
          {
            show: false,
            type: 'value',
            name: '',
            position: 'right', // Y 轴的位置
            inverse: false,
            axisLabel: {
              color: '#858689',
              // Y轴内容文字颜色
              formatter: (value) => {
                if (this.isRate) {
                  return Number.isInteger(Number(value)) ? Number(value) + '%' : Number(value).toFixed(2) + '%'
                } else {
                  return Number.isInteger(Number(value)) ? Number(value) : Number(value).toFixed(2)
                }
              }
            },
            axisLine: {
              // y轴线的配置
              show: false, // 是否展示
              lineStyle: {
                color: '#7d7d7d', // y轴线的颜色(若只设置了y轴线的颜色,未设置y轴文字的颜色,则y轴文字会默认跟设置的y轴线颜色一致)
                width: 1, // y轴线的宽度
                type: 'solid' // y轴线为实线
              }
            },
            splitLine: {
              show: false,
              lineStyle: {
                type: 'dashed',
                color: '#e5e6eb', // 虚线颜色
                width: 1
              }
            }
          }
        ],
        color: [],
        series: [],
        onlyClick: false, // 是否点击下钻
        xzFlag: false, // 是否右键下钻
        sType: '' // 功能类型
      },
      serviceType: {
        'bar': {
          name: '', // 合同额目标
          type: 'bar',
          stack: '', // 叠加使用
          itemStyle: {
            color: ''
          },
          data: [],
          // emphasis: {
          //   focus: 'series'
          // },
          label: {
            show: false,
            position: 'top',
            formatter: (params) => {
              if (parseFloat(params.value) === 0) {
                return ''
              }
              return params.value === null ? '' : parseFloat(params.value).toFixed(2)
            }
          },
          markLine: {
            symbol: 'none', // 折线为点
            symbolSize: 2, // 点大小
            precision: 1,
            lineStyle: {
              color: '#73deb4',
              width: 0
            },
            data: [
              {
                name: '',
                yAxis: 5,
                label: {
                  show: true, // 是否显示标签
                  formatter: '{b}', // :{c}
                  fontSize: 11,
                  color: '#303313',
                  padding: [0, 0, 20, 0],
                  position: 'end' // 标签位置
                }
              }
            ]
          },
          yAxisIndex: 0
        },
        'line': {
          name: '',
          type: 'line',
          itemStyle: {
            color: ''
          },
          yAxisIndex: 0,
          data: [],
          label: {
            show: true,
            position: 'top',
            formatter: '{c}' + '%'
          }
        },
        'pie': {
          name: '',
          type: 'pie',
          radius: '0%',
          left: -100,
          top: -50,
          label: {
            show: true,
            formatter: ''
          },
          data: []
        }
      },
      service: []
    }
  },
  watch: {
    chartData: {
      handler(next) {
        if (next && next.length > 0) {
          this.chartHandler(next)
        } else {
          this.option.sType = ''
          this.option.legend.data = []
          this.option.yAxis[0].name = ''
          this.option.series = []
          this.service = []
          this.option.xAxis[0].show = false
          this.option.xAxis[0].data = []
          this.option.xAxis[1].data = []
        }
      },
      deep: true,
      immediate: true
    }
  },
  mounted() {
    this.handleResize()
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResize)
  },
  methods: {
    // 渲染图表
    chartHandler(next) {
      // 创建一个service, 保存图表个数
      this.service = []
      // 1: 参数说明
      // num1 左侧Y轴显示图表个数  num2 右侧个数,一般图表都是左右分布的,左侧柱状图,右侧折线图
      const num1 = next[0].length > 0 ? next[0][0] : 0
      const num2 = next[0].length > 0 ? next[0][1] : 0
      // 图表的类型 目前6种 bar line barAndLine addBar addBarAndLine,doubleAddBar
      // 只有柱状图、只有折线图、柱状图加折线图、柱状叠加图、柱状叠加图加折线图、双排柱状叠加图
      const type = next[0].length > 0 ? next[0][2] : ''
      // 基础数据赋值
      this.commonMes(next)
      // 不同类型不同处理
      if (type === 'bar' || type === 'line') {
        this.option.yAxis[0].show = true
        this.option.yAxis[1].show = false
        const chartType = type
        // 只有柱状图或者折线图(单个图标)
        this.barHandler(type, num1, next, chartType)
      } else if (type === 'addBar') {
        this.option.yAxis[0].show = true
        this.option.yAxis[1].show = false
        // 柱状叠加图
        this.barHandler('bar', num1, next, 'addBar')
      } else if (type === 'pie') {
        this.option.yAxis[0].show = false
        this.option.yAxis[1].show = false
        this.option.xAxis[0].show = false
        // 饼图
        this.preHandler(next, type)
      } else if (type === 'barAndLine') {
        this.option.yAxis[0].show = true
        this.option.yAxis[1].show = true
        // 柱状图和折线图混合
        this.barAndLineHandler('bar', 'line', num1, num2, next, 'bar', 'line')
      } else if (type === 'addBarAndLine') {
        this.option.yAxis[0].show = true
        this.option.yAxis[1].show = true
        // 叠加柱状图和折线图混合
        this.barAndLineHandler('bar', 'line', num1, num2, next, 'addBar', 'line')
      } else if (type === 'doubleAddBar') {
        this.option.yAxis[0].show = true
        this.option.yAxis[1].show = false
        // 双叠加柱状图
        this.barAndLineHandler('bar', 'bar', num1, num2, next, 'tqAddBar', 'dqAddBar')
      }
      this.option.series = this.service
      // 处理Y轴0刻度保持水平,防止某个Y轴出现负值,造成  X为0时,两个Y轴的0刻度不在一个水平
      if (this.option.yAxis[0].show && this.option.yAxis[1].show) {
        // 最大值和最小值
        const minMax = szqMaxAndMin(this.option.series)
        // 某个Y轴有负数的时候处理
        if (Number(minMax.min) < 0 || Number(minMax.min1) < 0) {
          minMax.min ? this.option.yAxis[0].min = Number(minMax.min) : this.option.yAxis[0].min = 0
          minMax.min1 ? this.option.yAxis[1].min = Number(minMax.min1) : this.option.yAxis[1].min = 0
        } else {
          this.option.yAxis[0].min = 0
          this.option.yAxis[1].min = 0
        }
      }
    },
    commonMes(next) {
      // 是否下钻,xzFlag:即下钻又明细 onlyClick:仅明细
      if (next[0].length > 0) {
        if (next[0][3]) {
          this.option.xzFlag = true
          this.option.onlyClick = false
        } else {
          this.option.xzFlag = false
          this.option.onlyClick = true
        }
      }
      // 功能类型,一般使用中文标注,用于区分下钻和明细
      this.option.sType = next[0].length > 0 ? next[0][4] : ''
      // 示例
      this.option.legend.data = next[0].length > 0 ? next[0][5] : ''
      // 单位,两个Y轴的
      this.option.yAxis[0].name = next[0].length > 0 ? next[0][7][0] : ''
      this.option.yAxis[1].name = next[0].length > 0 ? next[0][7][1] : ''
      // 显示赋值横坐标
      this.option.xAxis[0].show = true
      this.option.xAxis[0].data = next[2]
      // 下钻参数,保存到第二个横坐标
      this.option.xAxis[1].data = next[1]
      // 是否加%
      this.isRate = next[0].length > 0 ? next[0][8] : true
    },
    // 处理柱状图或者折线图
    barHandler(type, num, next, chartTyep) {
      for (let i = 0; i < num; i++) {
        const newData = JSON.parse(JSON.stringify(this.serviceType[type]))
        this.setData(newData, 0, next, 0, i, chartTyep)
        this.service.push(newData)
      }
    },
    // 处理柱状图和折线图的混合(混合图表)
    barAndLineHandler(type1, type2, num1, num2, next, chartType1, chartType2) {
      // 先柱后折
      for (let i = 0; i < num1; i++) {
        const newData = JSON.parse(JSON.stringify(this.serviceType[type1]))
        this.setData(newData, 0, next, 0, i, chartType1)
        this.service.push(newData)
      }
      // 只有双叠加柱状图才会是0
      let leftOrRight = 1
      chartType1 === 'tqAddBar' ? leftOrRight = 0 : leftOrRight = 1
      for (let i = 0; i < num2; i++) {
        const newData = JSON.parse(JSON.stringify(this.serviceType[type2]))
        this.setData(newData, leftOrRight, next, num1, i, chartType2)
        this.service.push(newData)
      }
    },
    // 饼图处理
    preHandler(next, type) {
      const newData = JSON.parse(JSON.stringify(this.serviceType[type]))
      newData.radius = '50%'
      newData.color = next[0].length > 0 ? next[0][6] : []
      newData.data = next[3][0]
      newData.label.formatter = (value) => {
        return value.name + '' + value.data.num
      }
      this.service.push(newData)
    },
    // 设置数据
    setData(newData, yAxisIndex, next, num1, i, type) {
      // 设置Y轴为左右
      newData.yAxisIndex = yAxisIndex
      // 设置示例颜色
      newData.itemStyle.color = next[0].length > 0 ? next[0][6][num1 + i] : ''
      // 放置数据
      newData.data = next[3].length > 0 ? next[3][num1 + i] : []
      // 名称
      newData.name = next[0].length > 0 ? next[0][5][num1 + i] : ''
      // 单个叠加柱状图的处理DQ当期 TQ同期
      if (type === 'addBar') {
        newData.stack = 'DQ'
      } else if (type === 'tqAddBar') {
        newData.stack = 'TQ'
      } else if (type === 'dqAddBar') {
        newData.stack = 'DQ'
      }
      // 折线图一般是率,需要加百分号
      if (this.isRate && type === 'line') {
        newData.label.formatter = '{c}' + '%'
      } else {
        newData.label.formatter = '{c}'
      }
    },
    handleResize() {
      // 更新windowWidth的值,更好看一点
      this.$nextTick(() => {
        this.windowHeight = window.innerHeight
        const ob = autoBottom(window.innerHeight, this.isTitle)
        this.option.grid.bottom = ob.height
        if (ob.left.length > 0) {
          this.option.yAxis[0].nameTextStyle.padding = ob.left
        }
        if (ob.right.length > 0) {
          this.option.yAxis[1].nameTextStyle.padding = ob.right
        }
      })
    }
  }
}
</script>

<style scoped lang="scss">
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力奋斗小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值