<template>
  <div ref="difference_chart" class="echart_content"></div>
</template>
<script>
import _ from "lodash";
import * as echarts from "echarts";

export default {
  name: "differenceChart", //率差图组件
  data() {
    return {
      echart: null, //图标实例
      
    };
  },

  props: {
    datax: {
      type: Array,
      default: function () {
        return [] //[1, 2, 3, 4, 5, 6, 7];
      },
    }, //x轴数据
    datay: {
      type: Array,
      default: function () {
        return []//[50, 60, 70, 80, 70, 70, 100];
      },
    }, //y轴数据

    tooltipData:{
        type:Array,
        default:()=>[],
    },//悬浮弹窗的数据

    title: {
      type: String,
      default: "率差",
    }, //标题

    rate: {
      type: Number,
      default: 60,
    }, //中间的刻度线位置 默认60

    unit: {
      type: String,
      default: "",
    },
    type:{
      type:String,
      default: "0",//0显示差值  1 显示原值
    },

    isClick:{
      type:Boolean,
      default:true,
    },//是否可以点击

    color: {
      type: Array,
      default: function () {
        return ["#3BA272", "#EE6666"];
      },
    },
    gridLeft:{
      type:Number,
      default:40
    },
    gridRight:{
      type:Number,
      default:60
    },
    gridTop:{
      type:Number,
      default:20
    },
    fontSize:{//字体大小
      type:[Number,String],
      default:''
    },
    fontColor:{
      type:String,
      default:''
    },
    showDataZoom:{//是否显示滚动条
      type:Boolean,
      default:true
    }
  },
  watch: {
    datay: {
      handler: "LoadEchart",
      deep: true,
    }, //数值变化时重新加载图表
  },
  created() {
    window.addEventListener("resize", this.handleResize); //创建时增加监听窗口变化事件
  },
  beforeDestroy() {
    // 组件销毁移除监听 防止内存泄漏
    window.removeEventListener("resize", this.handleResize);
  },
  mounted() {
    this.LoadEchart(); //初始化图表
  },
  methods: {
    //加载echarts
    LoadEchart() 
    {
      if (this.echart) {
        this.echart.dispose(); // 销毁之前的实例
      }
      const unit=this.unit;//单位
      //devicePixelRatio: 2   2表示每个逻辑像素对应 2 个物理像素。这会进一步提高图表的清晰度，适用于更高分辨率的屏幕  解决高分辨率显示器文字模糊的问题
      this.echart = echarts.init(this.$refs.difference_chart, {
        devicePixelRatio: 2,
      }); //获取echarts容器  如果组件同一个页面多处使用 这里不能用id获取实例
      let container = this.echart.getDom(); // 获取容器DOM元素
      let containerHeight = container.offsetHeight;
      let containerWidth = container.offsetWidth;
      //计算每个x轴的宽度 
      let totalWidth = this.$refs.difference_chart.clientWidth;
      let singleSeriesWidth = Math.ceil( (totalWidth - 140) / this.datax.length);
      // console.log("打印容器宽度",totalWidth);
      // console.log("this.datax.length",this.datax.length);
      // console.log("打印单系列宽度",singleSeriesWidth);
      const rateValue = parseFloat(this.rate);
      // console.log("打印this.datay",this.datay);
      // console.log("打印this.datax",this.datax);
      // console.log("打印中间刻度线的值",this.rate);
      // 将字符串数组转为数字数组
      const numArr = this.datay.map(parseFloat);
      // 获取最大值和最小值
      const max = Math.max(...numArr);
      const min = Math.min(...numArr);
      // console.log("打印最大值和最小值",max,min);
      let maxValue=this.GetMaxMinValue(max,min,rateValue).maxValue;
      let minValue=this.GetMaxMinValue(max,min,rateValue).minValue;
      

      const barMinWidth = 30; // 最小柱子宽度 加上两边间距的宽度
      const dataZoomNum = Math.floor((totalWidth - 140) / (barMinWidth * 1));// 当前区域内可显示的柱子的数量
      const dataZoomEnd = Math.floor((100 / this.datax.length) * dataZoomNum); // 当前区域内可显示柱子的占比
      let dataZoom = {
          start: 0, //默认为0
          end: dataZoomEnd, //  默认为100（重点）
          type: 'slider',
          show: true,
          // borderColor: 'red', // 滑动条边框颜色
          borderColor: 'transparent',// 滑动条背景颜色
          borderCap: 'round',
          xAxisIndex: [0],
          height: 8, //组件高度
          left: 20, //左边的距离
          right: 20, //右边的距离
          bottom: 0, //右边的距离
          fillerColor: 'transparent',// 滑动条选中区域颜色
          zoomLock: true,//是否锁定选择区域（或叫做数据窗口）的大小。
          handleSize: '0',
          handleStyle: {
              color: '#b8b8b8',// 滑动条手柄颜色
              borderWidth: 2
          },
          backgroundColor: 'transparent', //两边未选中的滑动条区域的颜色
          showDataShadow: false, //是否显示数据阴影 默认auto
          showDetail: false, //即拖拽时候是否显示详细数值信息 默认true
          filterMode: 'filter'

      };//设置滚动条的样式
      
      //y轴数据需要进行处理 以添加自定义属性
      const processedData = this.datay.map((YValue, index) => {
        //调整中间x轴的刻度线  所有数据需要减去中间x轴的刻度线
        const numValue=parseFloat(parseFloat(YValue)-parseFloat(rateValue)).toFixed(2);
        // console.log("打印value",numValue,YValue,rateValue);
        return {
          value: numValue,
          label: {
            show: singleSeriesWidth > 22,
            position: numValue > 0 ? "top" : "bottom",
            formatter: (params) => {
              if(this.type=='1')
              {
                //显示差值
                return `${this.$global.getFormatNumber(parseFloat(params.value).toFixed(2)) +unit}`;
              }
              else
              {
                //显示原始值
                let value=(parseFloat(params.value) + parseFloat(rateValue)).toFixed(2);
                return `${this.$global.getFormatNumber(value).toString()+unit}`;
              }
            },
            color: this.fontColor || "#666",
            fontSize: this.fontSize?this.fontSize:14,
          },
          itemStyle: {
            color: numValue > 0 ? this.color[0] : this.color[1],
          },
        };
      });
      let option = {
        tooltip: {
          trigger: "item",
          triggerOn: "mousemove",
        
          renderModel:'html',//使用html渲染模式
          confine:true,//是否将 tooltip 框限制在图表的区域内。
          extraCssText: 'border-radius: 4px;padding:5px 0px 5px 5px;white-space:normal;word-warp:break-word;max-width: 400px;', // 设置最大宽度和高度
          borderColor: "#fff",
          formatter: (params) => {
            // console.log("打印params",params);
            let tooltip = `<div class='tooltip_content'>`;
            let title = params.name; //标题
            let type=this.type=='1'?'分差':this.title;
            let value=this.type=='1'?`${params.value}${unit}`:(parseFloat(params.value)+ rateValue).toFixed(2)+unit;
            tooltip += `<div class='tooltip_title'>${title}</div>`;
            if(this.tooltipData.length>0)
            {
              let list=this.tooltipData[params.dataIndex].list;
              for(let i=0;i<list.length;i++)
              {
                let item = list[i];
                tooltip += `<div class='tooltip_student'>${item.name}：${item.value}</div>`;
              }

            }
            else
            {
              tooltip += `<div class='tooltip_student'>${type}：${value}</div>`;
            }
            
            tooltip += `</div>`;
            return tooltip;
          },
        },
        grid: {
          left: this.gridLeft,
          right: this.gridRight,
          top: this.gridTop,
          bottom:0,
          containLabel: true, //用于控制网格区域是否包含坐标轴的标签  true 可以确保所有标签都能完整显示，不会被裁剪。
        },
        dataZoom: this.showDataZoom?(singleSeriesWidth < barMinWidth ? dataZoom : null):null,
        xAxis: [
          {
            type: "category",
            data: this.datax,
            axisPointer: {
              type: "shadow",
            },
            axisLabel: {
              interval: 0,
              margin: 20,
              rotate: singleSeriesWidth < 80 ? 45 : 0,
              fontSize: this.fontSize?this.fontSize:14,
              color: this.fontColor || "#666",
              fontWeight: 400,
              formatter:function(value) 
              { 
                  //一个文字的长度大概约16.6  按16算
                  const valueWidth = value.length * 14;
                  // console.log("文字宽度",valueWidth);
                  // console.log("单系列宽度",singleSeriesWidth);
                  if(valueWidth>singleSeriesWidth) {

                    if(valueWidth > singleSeriesWidth) {
                        if (singleSeriesWidth < 80) {
                            if(valueWidth > 80) {
                                // let maxLength = Math.floor(80 / 14) - 1;
                                return value.slice(0, 2) + '...' + value.slice(-3)
                            } else {
                                return value;
                            }
                        } else {
                            let maxLength = Math.floor(singleSeriesWidth / 14) - 1;
                            return value.slice(0, maxLength) + '...';
                        }
                    } else {
                        return value;
                    }
                      
                  } else {
                      return value;
                  }
              },
            },
          },
        ],
        yAxis: {
          type: "value",
          // minInterval: 1,
          axisLabel: {
            formatter:(value)=> {
              
              let totalValue=this.GetFormatNumber(parseFloat(value)+parseFloat(rateValue));
              // console.log("打印y轴的value",value);
              // console.log("打印y轴的value",totalValue);
              return  totalValue.toString()+ unit;
            },
            color: this.fontColor || "#666",
            // interval: 0,
            fontSize: this.fontSize?this.fontSize:14,
          },
          max:maxValue,
          min:minValue,
          splitLine: {
            show: true,
            lineStyle: {
              color: "#E4E7ED",
              type: "solid",
            },
          }, //横向刻度线样式设置
          axisLine: {
            show: false, //不显示y轴线
            lineStyle: {
              color: "#E4E7ED",
              width: 1,
            },
          }, //y轴样式设置
          splitArea: {
            show: true,
            areaStyle: {
              color: ["#fafafa", "#ffffff"], // 交替颜色
            },
          }, //网格线设置隔行背景色
        },
        series: [
          {
            type: "bar",

            emphasis: {
              focus: "series",
            },
            barMinHeight:1,//设置柱状图的最小高度
            barMaxWidth: 50, // this.showDataZoom?50:30 设置柱状图的最大宽度
            barMinWidth: this.showDataZoom?20:1, ////设置柱状图的最小宽度
            data: processedData,
          },
        ],
      };
      // option.xAxis[0].axisLabel = {
      //   color: function (value, index) {
      //     return index == 0 ? "#2E64FA" : "#333";
      //   },
      // };//设置第一列的颜色
      this.echart.setOption(option);
      // console.log("打印option",option);
      if(this.isClick)
      {

        const xAxisDataLength = this.datax.length;//柱子的数量
        // 获取grid区域偏移量
        const gridRect = this.echart.getModel().getComponent('grid').coordinateSystem.getRect();
        const singleLabelWidth = gridRect.width / xAxisDataLength;//单个x轴系列的宽度
        
        this.echart.on("click", (params) => {
          if (params.seriesType === "bar") {
            let option = this.echart.getOption();
            option.xAxis[0].axisLabel = {
              color: function (value, index) {
                return index == params.dataIndex ? "#2E64FA" : "#333";
              },
            };
            const schoolAnswerPaintingId = params.data.id;
            let pixelPosition= this.echart.convertToPixel({ xAxisIndex: 0 }, params.name);
            this.echart.setOption({
              graphic: {
                id: "highlight-box",
                type: "rect",
                shape: {
                  x: pixelPosition - singleLabelWidth/2, // 根据需要调整X坐标
                  y: gridRect.y,//
                  width: singleLabelWidth, // 根据需要调整宽度
                  height: gridRect.height // 
                },
                style: {
                  fill: params.color+'30', // 设置背景色
                },
              },
            });
            // let paintingId=params.data.id;
            // let paintingName=params.data.name;
            let index = params.dataIndex;
            let xName = params.name;
            this.$emit("HandleChartClick", index,xName);
          }
        });
        //初始默认设置第一个柱子的背景色

      
        if(this.datax.length>1)
        {
          
          
         
          let defaultPixelPosition= this.echart.convertToPixel({ xAxisIndex: 0 }, this.datax[0]);
          this.echart.setOption({
            graphic: {
              id: "highlight-box",
              type: "rect",
              shape: {
                x: defaultPixelPosition - singleLabelWidth/2, // 根据需要调整X坐标
                y: gridRect.y,//
                width: singleLabelWidth, // 根据需要调整宽度
                height: gridRect.height // 
              },
              style: {
                fill: "rgba(84,112,198,0.1)", // 设置背景色
              },
            },
          });
        }
      }
      
    },

    //获取数字 
    GetFormatNumber(value) {
      return this.$global.getFormatNumber(value);     
    },

    //获取距离中间轴的最大值和最小值
    GetMaxMinValue(max,min,rateValue) {
      // console.log("打印max",max);
      // console.log("打印min",min);
      // console.log("打印rateValue",rateValue);
      let maxValue, minValue;
      if(rateValue==0)
      {
        let differenceValue = Math.abs(max)>Math.abs(min)?Math.abs(max):Math.abs(min);

        const thresholdMap =[
          {
            maxThreshold:0.3,//最大阈值0-0.6
            bound:0.3,//边界值
          },
          {
            maxThreshold:0.6,//最大阈值0-0.6
            bound:0.6,//边界值
          },
          {
            maxThreshold:1,//最大阈值 0.6 - 1
            bound:1,//边界值
          },
          {
            maxThreshold:1.5,//最大阈值 0.6 - 1
            bound:1.5,//边界值
          },
          {
            maxThreshold:2,//最大阈值 
            bound:2,//边界值
          },
          {
            maxThreshold:4,//最大阈值
            bound:4,//边界值
          },
          {
            maxThreshold:6,//最大阈值
            bound:10,//边界值
          },

        ];//配置区间规则
        //查找匹配的边界值
        const matchedRule = thresholdMap.find(({ maxThreshold }) => differenceValue < maxThreshold);

        // 处理超过阈值的情况（≥5）
        const bound = matchedRule 
          ? matchedRule.bound 
          : this.GetCustomRoundUp(differenceValue);

        maxValue = bound;
        minValue = -bound;
        // console.log("打印differenceValue",differenceValue);
        // console.log("打印maxValue",maxValue);
        // console.log("打印minValue",minValue);
      }
      else
      {
        //非标准分 标准差的情况 中间刻度线不为0的情况
        let maxValues= max-rateValue;
        let minValues= min-rateValue;
        let differenceValue = Math.abs(maxValues)>Math.abs(minValues)?Math.abs(maxValues):Math.abs(minValues);
        differenceValue=this.GetCustomRoundUp(differenceValue);
        // console.log("打印maxValue",maxValues);
        // console.log("打印minValue",minValues);
        // console.log("打印differenceValue",differenceValue);
        maxValue = differenceValue;
        minValue = -differenceValue;
        // console.log("打印maxValue",maxValue);
        // console.log("打印minValue",minValue);
      }
      return {
        maxValue: maxValue,
        minValue: minValue
      }
    },

    //将一个数值按区间向上取整到最近的 10 的倍数，但有一个关键规则：如果是 X5.0（如 25.0、35.0），则要进位到下一个 10 的倍数（如 25 → 40，35 → 50）否则按常规方式向上取整到最近的 10 的倍数
    GetCustomRoundUp(number) 
    {
      // const base = Math.floor(number);        // 取整数部分
      // const decimal = number - base;          // 小数部分

      // // 如果是 X5.0，比如 25.0、35.0、75.0，则直接进两位（如 25 → 40）
      // if (base % 10 === 5 && decimal === 0) {
      //     return (Math.floor(base / 10) + 2) * 10;
      // }

      // // 如果是 X5.xx，比如 25.5、35.1、85.21，也要进两位（如 25.5 → 40）
      // if (base % 10 >= 5) {
      //     return (Math.floor(base / 10) + 2) * 10;
      // }

      // // 普通情况：常规向上取整
      // return Math.ceil(number / 10) * 10;

          // 向上取整到最近的 10 的倍数
      const nearest10 = Math.ceil(number / 10) * 10;
      // console.log(nearest10, "打印nearest10")
      // 找出比 nearest10 大的最小 3 的倍数（且为 10 的倍数）
      let result = nearest10;
      // while (result % 3 !== 0 || result % 10 !== 0) {
      //   result += 10; // 每次加 10，保持是 10 的倍数
      // }

      // console.log(result, "打印nresult")
      return result;
    },

    // 监听窗口大小变化，重新计算表格高度 使用节流防止频繁改变窗口大小导致计算量过大而页面卡顿
    handleResize: _.throttle(function () {
      this.$nextTick(() => {
        this.LoadEchart();
      });
    }, 500), // 节流 500 毫秒内最多执行一次
  },
};
</script>
<style lang="scss" scoped>

</style>