<!--
 * @Author: zhangtq 2452618307@qq.com
 * @Date: 2024-11-15 14:26:52
 * @LastEditors: zhangtq 2452618307@qq.com
 * @LastEditTime: 2024-11-19 09:32:39
 * @FilePath: src/views/screen/components/dataManagement/EquipInfo.vue
 * @Description: 这是默认设置,可以在设置》工具》File Description中进行配置
 -->
<template>
  <div :class="className" :style="{height: height, width: width, backgroundColor: 'transparent'}"></div>
</template>

<script>
import * as echarts from 'echarts'
import 'echarts-gl' // Import echarts-gl for 3D charts
require('echarts/theme/macarons') // echarts theme

export default {
  name: 'EquipInfo',
  props: {
    data: {
      type: Array,
      default: () => []
    },
    className: {
      type: String,
      default: 'chart'
    },
    width: {
      type: String,
      default: '100%'
    },
    height: {
      type: String,
      default: '100%'
    }
  },
  data() {
    return {
      chart: null
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart()
    })
  },
  watch: {
    data: {
      handler: function() {
        this.initChart()
      },
      deep: true
    }
  },
  beforeDestroy() {
    if (this.chart) {
      this.chart.dispose()
      this.chart = null
    }
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$el, 'macarons')
      this.chart.setOption(this.getPie3D(this.$props.data, 0))
    },
    getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h, i) {
      let midRatio = (startRatio + endRatio) / 2
      let startRadian = startRatio * Math.PI * 2
      let endRadian = endRatio * Math.PI * 2
      let midRadian = midRatio * Math.PI * 2

      if (startRatio === 0 && endRatio === 1) {
        isSelected = false
      }

      k = typeof k !== 'undefined' ? k : 1 / 3
      let offsetX = isSelected ? Math.cos(midRadian) * -0.1 : 0
      let offsetY = isSelected ? Math.sin(midRadian) * -0.1 : 0
      let offsetZ = i == 1 ? -2.11 : 0
      let hoverRate = isHovered ? 1.05 : 1.6

      return {
        u: {
          min: -Math.PI,
          max: Math.PI * 3,
          step: Math.PI / 32
        },
        v: {
          min: 0,
          max: Math.PI * 2,
          step: Math.PI / 32
        },
        x: function(u, v) {
          if (u < startRadian) {
            return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          if (u > endRadian) {
            return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate
        },
        y: function(u, v) {
          if (u < startRadian) {
            return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          if (u > endRadian) {
            return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate
        },
        z: function(u, v) {
          if (u < -Math.PI * 0.5) {
            return offsetZ + Math.sin(u)
          }
          if (u > Math.PI * 2.5) {
            return offsetZ + Math.sin(u)
          }
          return offsetZ + (Math.sin(v) > 0 ? 0.2 * h : -1)
        }
      }
    },
    getPie3D(pieData, internalDiameterRatio) {
      let series = []
      let sumValue = 0
      let startValue = 0
      let endValue = 0
      let legendData = []
      let k = typeof internalDiameterRatio !== 'undefined' ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio) : 1 / 3
      sumValue += pieData.reduce((prev, cur) => {
        return prev + Number(cur.value)
      }, 0)

      for (let i = 0; i < pieData.length; i++) {
        let seriesItem = {
          name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
          type: 'surface',
          parametric: true,
          wireframe: {
            show: false
          },
          pieData: pieData[i],
          pieStatus: {
            selected: false,
            hovered: false,
            k: k
          },
          label: {
            show: true,
            color: '#fff',
            position: 'outside',
            formatter: function(params) {
              let value = pieData[params.seriesIndex].value
              let percentage = ((value / sumValue) * 100).toFixed(2)
              return `${params.seriesName}: ${value} (${percentage}%)`
            },
          }
        }
        if (typeof pieData[i].itemStyle != 'undefined') {
          let itemStyle = {}
          typeof pieData[i].itemStyle.color != 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : null
          typeof pieData[i].itemStyle.opacity != 'undefined' ? (itemStyle.opacity = pieData[i].itemStyle.opacity) : null
          seriesItem.itemStyle = itemStyle
        }
        series.push(seriesItem)
      }

      for (let i = 0; i < series.length; i++) {
        endValue = startValue + series[i].pieData.value
        series[i].pieData.startRatio = startValue / sumValue
        series[i].pieData.endRatio = endValue / sumValue
        series[i].parametricEquation = this.getParametricEquation(
          series[i].pieData.startRatio,
          series[i].pieData.endRatio,
          true,
          false,
          k,
          i === 0 ? 10 : 10,
          i
        )
        startValue = endValue
        legendData.push(series[i].name)
      }

      let option = {
        legend: {
          show: false,
          right: "2%",
          itemGap: 30,
          itemHeight: 14,
          itemWidth: 24,
          top:'12%',
          textStyle: {
            color: "#fff",
            fontSize: 12,
            rich: {
              name: {
                width: 100,
                fontSize: 18,
                color: "#B0D8DF",
                fontFamily: "Source Han Sans CN",
              },
              value: {
                width: 30,
                fontSize: 18,
                padding: [0, 5, 0, 5],
                color: "#fff",
                fontFamily: "Source Han Sans CN",
              },
              A: {
                fontSize: 20,
                color: "#B0D8DF",
                fontFamily: "Source Han Sans CN",
              },
              rate: {
                width: 40,
                fontSize: 18,
                padding: [0, 5, 0, 5],
                color: "#B0D8DF",
                fontFamily: "Source Han Sans CN",
              },
              B: {
                fontSize: 18,
                color: "#B0D8DF",
                fontFamily: "Source Han Sans CN",
              },
            },
          },
          formatter: function (name) {
            let target;
            for (let i = 0; i < pieData.length; i++) {
              if (pieData[i].name === name) {
                target = pieData[i].value;
              }
            }
            let arr = [
              "{name|" + name + "：}",
              "{value|" + target + "}",
              "{rate|" + ((target / sumValue) * 100).toFixed(2) + "}{B|%}",
            ];
            return arr.join("  ");
          },
          data: legendData,
          // textStyle: {
          //   color: '#fff' // Set legend font color to white
          // }
        },
        tooltip: {
          show: true,
          formatter: function(params) {
            let name = params.seriesName
            let value = pieData[params.seriesIndex].value
            let percentage = ((value / sumValue) * 100).toFixed(2)
            return `${name}: ${value} (${percentage}%)`
          }
        },
        xAxis3D: {
          min: -1,
          max: 1
        },
        yAxis3D: {
          min: -1,
          max: 1
        },
        zAxis3D: {
          min: -1,
          max: 1
        },
        label: {
          show: true
        },
        grid3D: {
          show: false,
          boxHeight: 20,
          left: '-20%',
          top: '-10%',
          viewControl: {
            alpha: 45,
            beta: 70,
            rotateSensitivity: 1,
            zoomSensitivity: 0,
            panSensitivity: 0,
            autoRotate: false,
            distance: 400
          }
        },
        series: series
      }
      return option
    }
  }
}
</script>

<style scoped>
.chart {
  width: 100%;
  height: 100%;
}
</style>
