<template>
  <div class="yearPicker" :ref="yearPicker">
    <div class="_inner" :style="{ width: props.labelWidth + 'px' }">
      <el-icon><Calendar color="#c0c4cc" /></el-icon>
    </div>

    <input
      class="_inner"
      :ref="inputLeft"
      v-model="data.startShowYear"
      @focus="onFocus"
      @click="clickInput"
      type="text"
      name="yearInput"
      @input="checkStartInput()"
      :placeholder="props.startYear1"
    />&ensp;&ensp;&ensp; <span>{{ props.sp }}</span>
    &ensp;&ensp;&ensp;
    <input
      class="_inner"
      :ref="inputRight"
      v-model="data.endShowYear"
      @focus="onFocus"
      @click="clickInput"
      type="text"
      name="yearInput"
      @input="checkEndInput()"
      :placeholder="props.endYear2"
    />
    <div class="_inner floatPanel" v-if="data.showPanel">
      <div class="_inner leftPanel">
        <div class="_inner panelHead">
          <el-icon @click="onClickLeft"><DArrowLeft color="#303133" /></el-icon>
          {{ leftYearList[0] + "-" + leftYearList[9] }}
        </div>
        <div class="_inner panelContent">
          <div
            :class="{
              disabled: checkValidYear(item),
              oneSelected: item === data.startYear && oneSelected,
              startSelected: item === data.startYear,
              endSelected: item === data.endYear,
              _inner: true,
              betweenSelected: item > data.startYear && item < data.endYear
            }"
            v-for="item in leftYearList"
            :key="item"
          >
            <a
              :class="{
                cell: true,
                _inner: true,
                selected: item === data.startYear || item === data.endYear
              }"
              @click="onClickItem(item)"
              @mouseover="onHoverItem(item)"
            >
              {{ item }}
            </a>
          </div>
        </div>
      </div>
      <div class="_inner rightPanel">
        <div class="_inner panelHead">
          <!-- <i class="_inner">&gt;&gt;</i> -->
          <el-icon @click="onClickRight"><DArrowRight color="#303133" /></el-icon>
          {{ rightYearList[0] + "-" + rightYearList[9] }}
        </div>
        <div class="_inner panelContent">
          <div
            :class="{
              disabled: checkValidYear(item),
              startSelected: item === data.startYear,
              endSelected: item === data.endYear,
              betweenSelected: item > data.startYear && item < data.endYear
            }"
            v-for="item in rightYearList"
            :key="item"
          >
            <a
              :class="{
                cell: true,
                _inner: true,
                selected: item === data.endYear || item === data.startYear
              }"
              @click="onClickItem(item)"
              @mouseover="onHoverItem(item)"
            >
              {{ item }}
            </a>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { VNodeRef, computed, nextTick, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref } from "vue";

interface Emits {
  (e: "updateTimeRange", startYear: string, endYear: string): void;
}
interface Props {
  labelWidth: number;
  sp?: string;
  initYear?: { startYear: number; endYear: number };
  startYear1?: string;
  endYear2?: string;
}
const SELECT_STATE = {
  unselect: 0,
  selecting: 1,
  selected: 2
};

const data = reactive<any>({
  itemBg: {},
  startShowYear: null,
  endShowYear: null,
  yearList: [],
  showPanel: false,
  startYear: null,
  endYear: null,
  curYear: 0,
  curSelectedYear: 0,
  curState: SELECT_STATE.unselect
});

const yearPicker = ref<VNodeRef>();
const inputLeft = ref<VNodeRef>();
const inputRight = ref<VNodeRef>();

const oneSelected = computed(() => {
  return data.curState === SELECT_STATE.selecting && (data.startYear === data.endYear || data.endYear == null);
});

const leftYearList = computed(() => {
  return data.yearList.slice(0, 10);
});
const rightYearList = computed(() => {
  return data.yearList.slice(10, 20);
});

const emits = defineEmits<Emits>();

const props = withDefaults(defineProps<Props>(), {
  labelWidth: 80,
  sp: "-",
  startYear1: "",
  endYear2: ""
});

const clickInput = (e: any) => {
  e.stopPropagation();
  return false;
};

const checkValidYear = (iYear: number) => {
  if (props.initYear) {
    if (iYear > props.initYear.endYear) {
      return 1;
    } else if (iYear < props.initYear.startYear) {
      return -1;
    }
  }
  return 0;
};
const checkStartInput = () => {
  if (isNaN(data.startShowYear)) {
    data.startShowYear = data.startYear;
  } else {
    data.startYear = data.startShowYear * 1;
  }
};

const checkEndInput = () => {
  if (isNaN(data.endShowYear)) {
    data.endShowYear = data.endYear;
  } else {
    data.endYear = data.endShowYear * 1;
  }
};
// const changeYear = () => {
//   if (data.startYear > data.endYear) {
//     let tmp = data.endYear;
//     data.endYear = data.startYear;
//     data.startYear = tmp;
//   }
//   if (props.initYear) {
//     data.startYear = Math.max(data.startYear, props.initYear.startYear);
//     data.endYear = Math.min(data.endYear, props.initYear.endYear);
//   }
//   data.startShowYear = data.startYear;
//   data.endShowYear = data.endYear;

//   if (data.startYear && data.endYear) {
//     emits("updateTimeRange", data.startYear, data.endYear);
//   } else {
//     console.warn("WARN:年份不合法", data.startYear, data.endYear);
//   }
// };
const onHoverItem = (iYear: number) => {
  if (checkValidYear(iYear) != 0) {
    return;
  }
  if (data.curState === SELECT_STATE.selecting) {
    let tmpStart = data.curSelectedYear;
    data.endYear = Math.max(tmpStart, iYear);
    data.startYear = Math.min(tmpStart, iYear);
  }
};
const onClickItem = (iYear: number) => {
  if (checkValidYear(iYear) != 0) {
    return;
  }
  if (data.curState === SELECT_STATE.unselect || data.curState === SELECT_STATE.selected) {
    data.startYear = iYear;
    data.curSelectedYear = iYear;
    data.endYear = null;
    data.curState = SELECT_STATE.selecting;
  } else if (data.curState === SELECT_STATE.selecting) {
    data.endShowYear = data.endYear;
    data.startShowYear = data.startYear;
    data.curState = SELECT_STATE.selected;
    emits("updateTimeRange", data.startYear, data.endYear);

    setTimeout(() => {
      //为动画留的时间，可优化
      data.showPanel = false;
    }, 300);
  }
};
const onFocus = () => {
  nextTick(() => {
    data.showPanel = true;
  });
};

const updateYearList = () => {
  let iStart = Math.floor(data.curYear / 10) * 10 - 10;
  iStart = iStart < 0 ? 0 : iStart;
  data.yearList = [];
  for (let index = 0; index < 20; index++) {
    data.yearList.push(iStart + index);
  }
};
const closePanel = (e: any) => {
  if (!data.showPanel) {
    return;
  }
  if (typeof e.target.className !== "string" || e.target.className === "") {
    nextTick(() => {
      // changeYear();
      data.showPanel = false;
    });
    return;
  }

  if (
    e.target.className.indexOf("_inner") === -1 ||
    (e.target.name === "yearInput" && e.target !== inputLeft.value && e.target !== inputRight.value)
  ) {
    nextTick(() => {
      // changeYear();
      data.showPanel = false;
    });
  }

  e.stopPropagation();
  return false;
};
const onClickLeft = () => {
  data.curYear = data.curYear * 1 - 10;
  updateYearList();
};
const onClickRight = () => {
  data.curYear = data.curYear * 1 + 10;
  updateYearList();
};

onBeforeMount(() => {
  data.curYear = new Date().getFullYear();
  updateYearList();
});
onBeforeUnmount(() => {
  document.removeEventListener("click", closePanel.bind(data));
});

onMounted(() => {
  document.addEventListener("click", closePanel.bind(data));
});
</script>
<style lang="scss" scoped>
.yearPicker {
  position: relative;
  box-sizing: border-box;
  display: flex;
  height: 40px;
  padding: 0 8px;
  font-size: 14px;
  line-height: 40px;
  background-color: #ffffff;
  border: 1.5px solid #dcdfe6;
  border-radius: 4px;
  transition: all 0.3s;
  input:first-child {
    text-align: right;
  }
  span {
    height: 40px;
    padding: 0 8px;
    line-height: 40px;
  }
  .floatPanel {
    > div {
      width: 50%;
    }

    position: absolute;
    top: 50px;
    left: -50px;
    z-index: 2000;
    display: flex;
    width: 650px;
    height: 250px;
    padding: 0 16px;
    background-color: #ffffff;
    border-radius: 4px;
    box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
    .panelContent {
      display: flex;
      flex-wrap: wrap;
      width: 100%;
      height: calc(100% - 70px);
      .disabled {
        color: #cccccc;
      }
      .oneSelected {
        border-top-right-radius: 24px;
        border-bottom-right-radius: 24px;
      }
      .startSelected {
        background-color: #f6f6f7;
        border-top-left-radius: 24px;
        border-bottom-left-radius: 24px;
      }
      .endSelected {
        background-color: #f6f6f7;
        border-top-right-radius: 24px;
        border-bottom-right-radius: 24px;
      }
      .betweenSelected {
        background-color: #f6f6f7;
      }
      > div {
        width: 75px;
        height: 48px;
        margin: 3px 0;
        line-height: 48px;

        // border-radius: 24px;
        text-align: center;
        a {
          display: inline-block;
          width: 60px;
          height: 40px;
          line-height: 40px;
          cursor: pointer;
          border-radius: 18px;
        }
        .selected {
          color: #ffffff;
          background-color: #3e77fc;
        }
      }
    }
    .panelHead {
      position: relative;
      height: 46px;
      line-height: 46px;
      text-align: center;
      .el-icon {
        margin-top: 16px;
      }
      i {
        position: absolute;
        cursor: pointer;
        &:hover {
          color: #3e77fc;
        }
      }
    }
    .rightPanel {
      padding-left: 8px;
    }
    .leftPanel .panelHead i {
      left: 20px;
    }
    .rightPanel .panelHead i {
      right: 20px;
    }
  }
  .floatPanel::before {
    position: absolute;
    left: 50%;
    width: 1px;
    height: 100%;
    content: "";
    border-left: 1px solid #e4e4e4;
  }
}
input {
  box-sizing: border-box;
  width: 60px;
  height: 40px;
  font-size: 14px;
  line-height: 40px;
  color: #606266;
  text-align: center;
  background-color: transparent;
  border: none;
}
input:focus {
  background-color: transparent;
  outline: none;
}
.yearPicker:hover {
  border-color: #3e77fc;
}
.dateIcon {
  position: absolute;
  top: 9px;
  right: 16px;
  color: #adb2bc;
}
</style>

​
