<template>
  <div class="echart-render chart-box">
    <h3 class="chart-title">{{ chartTitle }}</h3>
    <v-chart
      :options="chartOption"
      :init-options="initOptions"
      v-if="chartOption"
      autoresize
      ref="vueChart"
    ></v-chart>
    <p class="chart-none" v-else>暂无数据</p>
  </div>
</template>

<script>
import echarts from "echarts/lib/echarts";

export default {
  name: "echart-render",
  props: {
    chartType: {
      type: String,
      required: true,
      validator(value) {
        return (
          [
            "bar",
            "barReverse",
            "pie",
            "line",
            "darkLines",
            "barGroup",
            "lineGroup"
          ].indexOf(value) !== -1
        );
      }
    },
    rendererType: {
      type: String,
      default: "canvas",
      validator(val) {
        return ["canvas", "svg"].indexOf(val) !== -1;
      }
    },
    animationIsOpen: {
      type: Boolean,
      default: true
    },
    chartData: {
      type: [Object, Array],
      required: true
    },
    chartTitle: {
      type: String,
      default: ""
    },
    chartColor: {
      type: Array,
      default() {
        return [
          "#22C0FF",
          "#41CD7D",
          "#FF7786",
          "#4E7CFF",
          "#6d32f9",
          "#dd7755"
        ];
      }
    }
  },
  data() {
    return {
      chartOption: null,
      initOptions: { renderer: "canvas" }
    };
  },
  mounted() {
    if (this.rendererType) this.initOptions.renderer = this.rendererType;
    this.getOptions();
  },
  methods: {
    getOptions() {
      const name = this.chartType[0].toUpperCase() + this.chartType.slice(1);
      this.chartOption = this[`get${name}Option`](this.chartData);
    },
    getDataURL(options) {
      return this.$refs.vueChart && this.$refs.vueChart.getDataURL(options);
    },
    getLineOption(datas) {
      let labels = [],
        vals = [];
      datas.map(item => {
        labels.push(item.name);
        vals.push(item.value);
      });
      const linearColor = new echarts.graphic.LinearGradient(0, 1, 0, 0, [
        {
          offset: 1,
          color: "rgba(34,192,255,1)"
        },
        {
          offset: 0,
          color: "rgba(34,192,255,0)"
        }
      ]);

      return {
        animation: this.animationIsOpen,
        grid: {
          top: "10%",
          bottom: "12%",
          left: "5%",
          right: "5%"
        },
        tooltip: {
          show: true,
          formatter: function(params) {
            return params.value + "%";
          }
        },
        xAxis: {
          type: "category",
          data: labels,
          splitLine: {
            show: true,
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLine: {
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLabel: {
            color: "#7C86A3",
            fontSize: 12,
            fontWeight: "bold"
          },
          axisTick: {
            show: false
          }
        },
        yAxis: {
          type: "value",
          splitLine: {
            show: true,
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLine: {
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLabel: {
            fontSize: 12,
            color: "#7C86A3",
            formatter: function(value, index) {
              return value + "%";
            }
          },
          axisTick: {
            show: false
          }
        },
        series: [
          {
            name: "数量",
            type: "line",
            smooth: true,
            data: vals,
            itemStyle: {
              color: "rgba(34, 192, 255, 1)"
            },
            lineStyle: {
              color: "rgba(34, 192, 255, 1)"
            },
            areaStyle: {
              color: linearColor
            }
          }
        ]
      };
    },
    getDarkLinesOption(datas) {
      if (!datas.length) return;
      const labels = datas[0].data.map(item => item.name);
      const colors = [
        {
          color: "rgba(21, 91, 146,1)",
          lineColor: "rgba(21, 91, 146,0.6)",
          linearColor: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
            {
              offset: 1,
              color: "rgba(21, 91, 146,1)"
            },
            {
              offset: 0,
              color: "rgba(21, 91, 146,0.2)"
            }
          ]),
          z: 4
        },
        {
          color: "rgba(204, 70, 53,1)",
          lineColor: "rgba(204, 70, 53,0.6)",
          linearColor: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
            {
              offset: 1,
              color: "rgba(204, 70, 53,1)"
            },
            {
              offset: 0,
              color: "rgba(204, 70, 53,0)"
            }
          ]),
          z: 3
        }
      ];

      const series = datas.map(function(item, index) {
        const data = item.data.map(function(elem) {
          return elem.value;
        });
        const color = colors[index];
        return {
          name: item.name,
          type: "line",
          smooth: true,
          data: data,
          symbol: "circle",
          symbolSize: 6,
          z: color.z,
          itemStyle: {
            color: color.color
          },
          lineStyle: {
            color: color.lineColor
          },
          areaStyle: {
            color: color.linearColor
          }
        };
      });

      return {
        animation: this.animationIsOpen,
        grid: {
          top: "10%",
          bottom: "12%",
          left: "3.5%",
          right: "3%"
        },
        tooltip: {
          show: true,
          formatter: function(params) {
            return params.value + "%";
          }
        },
        legend: {
          data: datas.map(data => data.name),
          right: "3%",
          itemWidth: 14,
          textStyle: {
            color: "#9d9c9c",
            fontSize: 14
          }
        },
        xAxis: {
          type: "category",
          data: labels,
          splitLine: {
            show: true,
            lineStyle: {
              color: "#3d3f55"
            }
          },
          axisLine: {
            lineStyle: {
              color: "#3d3f55"
            }
          },
          axisLabel: {
            color: "#9d9c9c",
            fontSize: 12,
            fontWeight: "bold"
          },
          axisTick: {
            show: false
          }
        },
        yAxis: {
          type: "value",
          splitLine: {
            show: true,
            lineStyle: {
              color: "#3d3f55"
            }
          },
          axisLine: {
            lineStyle: {
              color: "#3d3f55"
            }
          },
          axisLabel: {
            fontSize: 12,
            color: "#9d9c9c",
            formatter: "{value}%"
          },
          axisTick: {
            show: false
          }
        },
        series: series
      };
    },
    getPieOption(datas) {
      if (!datas.chartLabels.length) return;
      const seriesData = datas.chartLabels.map(function(item, index) {
        return {
          name: item,
          value: datas.chartData[0][index]
        };
      });
      return {
        animation: this.animationIsOpen,
        grid: {
          top: "24%",
          bottom: "10%"
        },
        tooltip: {
          trigger: "item",
          formatter: "{a} <br/>{b} : {c} ({d}%)"
        },
        legend: {
          show: true,
          itemGap: 20,
          itemWidth: 20,
          textStyle: {
            fontSize: 16
          }
        },
        series: [
          {
            name: "数量",
            type: "pie",
            radius: "70%",
            data: seriesData,
            label: {
              show: false
            },
            itemStyle: {
              emphasis: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: "rgba(0, 0, 0, 0.5)"
              }
            }
          }
        ]
      };
    },
    getBarOption(datas) {
      if (!datas.names.length) return;
      return {
        animation: this.animationIsOpen,
        color: this.chartColor,
        grid: {
          top: "20%",
          bottom: "10%",
          left: "8%",
          right: "5%"
        },
        tooltip: {
          show: true
        },
        xAxis: {
          type: "category",
          data: datas.names,
          axisLine: {
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLabel: {
            color: "#7C86A3",
            fontSize: 12,
            fontWeight: "bold"
          },
          axisTick: {
            show: false
          }
        },
        yAxis: {
          type: "value",
          splitLine: {
            show: true,
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLine: {
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLabel: {
            color: "#7C86A3",
            fontSize: 12,
            fontWeight: "bold"
          },
          axisTick: {
            show: false
          }
        },
        series: [
          {
            name: this.chartTitle || "值",
            type: "bar",
            barMaxWidth: 24,
            data: datas.dataList,
            label: {
              show: true,
              position: "top",
              color: "#666"
            },
            itemStyle: {
              barBorderRadius: 4
            }
          }
        ]
      };
    },
    getBarReverseOption(datas) {
      if (!datas.names.length) return;
      return {
        animation: this.animationIsOpen,
        color: this.chartColor,
        grid: {
          top: "20%",
          bottom: "10%",
          left: "12%",
          right: "5%"
        },
        tooltip: {
          show: true
        },
        yAxis: {
          type: "category",
          data: datas.names,
          axisLine: {
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          splitLine: {
            show: true,
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLabel: {
            color: "#7C86A3",
            fontSize: 12,
            fontWeight: "bold"
          },
          axisTick: {
            show: false
          }
        },
        xAxis: {
          type: "value",
          splitLine: {
            show: false,
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLine: {
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLabel: {
            color: "#7C86A3",
            fontSize: 12,
            fontWeight: "bold"
          },
          axisTick: {
            show: false
          }
        },
        series: [
          {
            name: this.chartTitle || "值",
            type: "bar",
            barMaxWidth: 24,
            data: datas.dataList,
            label: {
              show: true,
              position: "right",
              color: "#666"
            },
            itemStyle: {
              barBorderRadius: 4
            }
          }
        ]
      };
    },
    getBarGroupOption(datas) {
      if (!datas.names.length) return;
      const xAxis = datas.dataList.map(function(item) {
        return item.name;
      });
      const series = datas.names.map(function(name, index) {
        const data = datas.dataList.map(function(item) {
          return item.data[index];
        });
        return {
          name: name,
          type: "bar",
          data: data,
          barMaxWidth: 12,
          itemStyle: {
            barBorderRadius: 2
          }
        };
      });

      const options = {
        animation: this.animationIsOpen,
        color: this.chartColor,
        grid: {
          top: "20%",
          bottom: "10%",
          left: "8%",
          right: "5%"
        },
        tooltip: {
          show: true,
          trigger: "axis",
          axisPointer: {
            type: "shadow"
          },
          formatter: function(params) {
            const label = params[0].axisValueLabel;
            let infos = params.map(function(item) {
              return item.seriesName + "：" + item.value.toFixed(2) + "%";
            });
            infos.unshift(label);
            return infos.join("<br/>");
          }
        },
        legend: {
          data: datas.names,
          right: 0,
          itemWidth: 14,
          textStyle: {
            fontSize: 16
          }
        },
        xAxis: {
          type: "category",
          data: xAxis,
          axisLabel: {
            color: "#7C86A3",
            fontSize: 12,
            fontWeight: "bold"
          },
          axisTick: {
            show: false
          }
        },
        yAxis: {
          type: "value",
          splitLine: {
            show: true,
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLine: {
            lineStyle: {
              color: "rgba(231,234,241,1)"
            }
          },
          axisLabel: {
            color: "#7C86A3",
            fontSize: 12,
            fontWeight: "bold",
            formatter: function(value, index) {
              return value + "%";
            }
          },
          axisTick: {
            show: false
          }
        },
        series: series
      };

      return options;
    },
    getLineGroupOption(datas) {
      if (!datas.length) return;
      const names = datas.map(function(item) {
        return item.name;
      });
      const xaxis = datas[0].dataList.map(function(item, index) {
        return index;
      });

      const series = datas.map(function(item) {
        return {
          name: item.name,
          type: "line",
          symbol: "circle",
          smooth: true,
          itemStyle: {
            emphasis: {
              color: "#333"
            }
          },
          data: item.dataList.map(function(num) {
            return num * num;
          })
        };
      });
      return {
        animation: this.animationIsOpen,
        grid: {
          top: "15%",
          bottom: "12%"
        },
        tooltip: {
          show: true,
          trigger: "axis",
          axisPointer: {
            type: "shadow"
          },
          formatter: function(params) {
            const label = params[0].axisValueLabel;
            let infos = params.map(function(item) {
              return item.seriesName + "：" + Math.sqrt(item.value);
            });
            infos.unshift(label);
            return infos.join("<br/>");
          }
        },
        legend: {
          data: names,
          right: 0,
          itemWidth: 14,
          textStyle: {
            fontSize: 16
          }
        },
        xAxis: {
          type: "category",
          data: xaxis,
          axisLabel: {
            show: false,
            fontSize: 14
          },
          axisTick: {
            show: false
          }
        },
        yAxis: {
          type: "value",
          interval: 1,
          splitLine: {
            show: false
          },
          axisLabel: {
            fontSize: 14,
            formatter: function(value) {
              const num = Math.sqrt(value);
              return num % 1 ? "" : parseInt(num);
            }
          },
          axisTick: {
            show: false
          }
        },
        dataZoom: [
          {
            type: "inside",
            start: 0,
            end: 30
          },
          {
            type: "slider",
            start: 0,
            end: 30
          }
        ],
        series: series
      };
    }
  }
};
</script>
