<template>
  <div>
    <div class="contro-header" >
      <div class="wrap1" 		@click="prevYear">
        <img src="@/assets/image/lj@2x.png" alt="">
      </div>
      <div class="wrap2" @click="prev">
        <img src="@/assets/image/adfcc.png" alt="">
      </div>
      <div class="wrap3">
        {{ state.selectMonth }}
      </div>
      <div class="wrap4" @click="next">
        <img src="@/assets/image/adfcc.png" alt="">
      </div>
      <div class="wrap5" 				@click="nextYear"	>
        <img src="@/assets/image/lj@2x.png" alt="">
      </div>
    </div>
    <div v-if="state.changeTxt == 'date'">
      <div class="calendar-pro__body">
        <table
          width="100%"
          cellspacing="0"
          class="fullscreen-table"
          v-if="props.fullscreen"
        >
          <thead>
          <tr>
            <th v-for="(weekDay, i) in state.weekTitle" :key="i">
              <span>周{{ weekDay }}</span>
            </th>
          </tr>
          </thead>
          <tbody>
          <!-- 工作日0 休息日1  是否是 -->
          <tr v-for="(item, index) in state.currentList" :key="index">
            <td
              v-for="(m, mIndex) in item"
              :key="mIndex"
              :class="m.isHoliday && props.isWeek ? 'showWeek' : ''"
              @click="getItem(m)"
            >
              <div class="td-con">
                <div
                  :class="[
											'day',
											m.isHoliday && props.isWeek ? 'colorff' : '',
											m.isOtherMonthDay ? 'colord9' : '',
											m.isSelect || m.isToday ? 'bgSelect' : '',
										]"
                >
                  {{ m.day }}
                </div>
                <div class="isDay" v-if="m.isToday">今天</div>
                <span class="festival" v-if="!m.isToday">{{
                    m.lunarFestival || m.festival
                  }}</span>

                <!-- 中间数据 -->
                <slot name="center-data" :index="m.timeIndex" :dateTime="m.dateTime"></slot>
                <div
                  :class="
											m.isHoliday && props.isWeek
												? 'lunar colorff'
												: m.isOtherMonthDay
												? 'lunar colord9'
												: 'lunar '
										"
                >
										<span v-if="m.lunar == '初一'"
                    >{{ m.lunarMonth }}{{ m.lunar }}</span
                    >
                  <span v-else>{{ m.lunar }}</span>
                </div>
              </div>
            </td>
          </tr>
          </tbody>
        </table>
        <table class="card-table" v-else>
          <thead>
          <tr>
            <th v-for="(weekDay, i) in state.weekTitle" :key="i">
              <span>周{{ weekDay }}</span>
            </th>
          </tr>
          </thead>
          <tbody>
          <!-- 工作日0 休息日1  是否是 -->
          <tr v-for="(item, index) in state.currentList" :key="index">
            <td
              v-for="(m, mIndex) in item"
              :key="mIndex"
              :class="m.isHoliday && props.isWeek ? 'showWeek' : ''"
              @click="getItem(m)"
            >
              <div class="day-item">
                <div
                  :class="['day',state.selectDateList.includes(m.dateTime)? 'select':'',state.chooseDateList.includes(m.dateTime)?'defualChoose':'']"
                  v-if="!m.isOtherMonthDay"
                  @click="selectDate(m.dateTime)"
                >
                  {{ m.day }}
                </div>
                <div v-else></div>
              </div>
            </td>
          </tr>
          </tbody>
        </table>
      </div>

      <slot name="footer-date"></slot>
    </div>

    <div v-if="state.changeTxt == 'month'">
      <slot name="month"></slot>
    </div>
  </div>
</template>

<script setup>
import {
  CaretLeftOutlined,
  CaretRightOutlined,
  CheckCircleOutlined,
  LeftOutlined,
  RightOutlined
} from "@ant-design/icons-vue";
import calendarJs from "../../../utils/calendar";
import { debounce } from "lodash-es";
import { message } from "ant-design-vue";
import {
  ref,
  reactive,
  toRefs,
  onMounted,
  defineEmits,
  defineProps,
  watch,
  onBeforeMount,
  defineExpose,
  getCurrentInstance
} from "vue";

const currentInstance = getCurrentInstance();
const { $request } = currentInstance.appContext.config.globalProperties;
const emits = defineEmits([
  "year-change",
  "monthChange",
  "getDate",
  "getNowMonth",
  "clickDateData",
  "clickDateArr"
]);

const props = defineProps({
  defaultDate: {
    // 默认日期
    type: [Date, String],
    default() {
      return new Date();
    }
  },
  highlighterDate: {
    type: Array,
    default: () => []
  },
  //  高亮周末
  isWeek: {
    type: Boolean,
    default: true
  },
  weekTitleAlign: {
    type: String,
    default: "right"
  },
  fullscreen: {
    // 是否是日历 ， false == 简易卡片
    type: Boolean,
    default: true
  },
  headerRender: {
    // 头部左边显示
    type: Boolean,
    default: true
  },
  chooseDateList: {
    type: Array,
    default: () => []
  }
});

watch(() => props.chooseDateList, (val) => {
  if (val) {
    state.chooseDateList = val.length > 0 ? val : [];
  }
});
const defaultDate = ref(props.defaultDate);
const highlighterDate = ref(props.highlighterDate);
let date = new Date(defaultDate.value);
const state = reactive({
  renderYear: date.getFullYear(),
  renderMonth: date.getMonth() + 1,
  currentMonthDays: [],
  weekTitle: [],
  weekCount: 6,
  currentList: [],
  selectDate: "",
  changeTxt: "date",
  selectMonth:
    date.getFullYear() +
    "年" +
    (date.getMonth() + 1 < 10
      ? "0" + (date.getMonth() + 1)
      : date.getMonth() + 1) +
    "月",
  selectDateList: [],
  chooseDateList: [],
  checked: false
});
onBeforeMount(() => {
  render(state.renderYear, state.renderMonth);
});
// 处理选择的数据
const selectDate = (date) => {
  state.selectDateList.indexOf(date) > -1
    ? state.selectDateList.splice(state.selectDateList.indexOf(date), 1)
    : state.selectDateList.push(date);
  emits("clickDateArr", state.selectDateList);
};
const allChoose = () => {
  state.checked = !state.checked;
  // 月份全选 / 取消
  if (state.checked) {
    console.log(state.renderMonth);
    state.currentList.forEach((i) => {
      console.log(i);
      i.forEach((m) => {
        if (m.month == state.renderMonth && !state.selectDateList.includes(m.dateTime)) {
          state.selectDateList.push(m.dateTime);
        }
      });
    });
  } else {
    state.currentList.forEach((i) => {
      i.forEach((m) => {
        if (m.month == state.renderMonth && state.selectDateList.includes(m.dateTime)) {
          state.selectDateList.splice(
            state.selectDateList.indexOf(m.dateTime),
            1
          );
        }
      });
    });
  }
  emits("clickDateArr", state.selectDateList);
};
// 切换选择日、月考勤统计
const change = (txt) => {
  state.changeTxt = txt;
  if (state.changeTxt == "month") {
    let time = state.selectMonth.split("年")[0] + "-" + state.selectMonth.split("年")[1].split("月")[0];
    emits("monthChange", time);
  }
};
// 上一月
const prev = debounce(() => {
  let year = state.renderYear;
  let month = state.renderMonth;

  if (month == 1) {
    year = year - 1;
    month = 12;
  } else {
    month = month - 1;
  }
  render(year, month);
  state.selectMonth = year + "年" + (month < 10 ? "0" + month : month) + "月";
  console.log(year, month);
}, 500);// 上一月
const prevYear = debounce(() => {
  let year = state.renderYear;
  let month = state.renderMonth;
  year = Number(year) - 1;
  render(year, month);
  state.selectMonth = year + "年" + (month < 10 ? "0" + month : month) + "月";
}, 500);
// 下一月
const next = debounce(() => {
  let year = state.renderYear
  let month = state.renderMonth
  if (month == 12) {
    year = Number(year) + 1
    month = 1;
  } else {
    month = Number(month) + 1;
  }
  render(year, month);
  state.selectMonth = year + "年" + (month < 10 ? "0" + month : month) + "月";
}, 500);
const nextYear = debounce(() => {
  let year = state.renderYear;
  let month = state.renderMonth;
  year = Number(year) + 1
  render(year, month);
  state.selectMonth = year + "年" + (month < 10 ? "0" + month : month) + "月";
}, 500);

/**
 * 获取当前渲染的月份
 * @returns {{year: number | *, month: methods.renderMonth, days: methods.renderMonth}}
 */
const getRenderedMonth = () => {
  return {
    year: state.renderYear,
    month: state.renderMonth,
    days: state.currentMonthDays
  };
};
/**
 * 强制渲染某个月份
 * @param year
 * @param month
 */
const renderThisMonth = (year, month) => {
  render(year, month);
};
/**
 * 渲染
 * @param year
 * @param month
 * @param weekCount
 */
const render = async (year, month) => {
  let result = monthDetail(year, month);
  state.currentMonthDays = result;
  state.currentList = await resultList(result);
  state.renderYear = year;
  state.renderMonth = month;
  if (state.changeTxt == "month") {
    let time = year + "-" + (month < 10 ? "0" + month : month);
    emits("monthChange", time);
  }
  let startDate = result[0].year + "-" + addZero(result[0].month) + "-" + addZero(result[0].day);
  let endDate = result[41].year + "-" + addZero(result[41].month) + "-" + addZero(result[41].day);
  // 当前日历的时间范围
  emits("getDate", { startDate: startDate, endDate: endDate });
  emits("getNowMonth", result);
  let pramas = {
    beginDate: result[0].year + "-" + addZero(result[0].month) + "-" + addZero(result[0].day),
    endDate: result[41].year + "-" + addZero(result[41].month) + "-" + addZero(result[41].day)
  };
  if (props.fullscreen) {
    await getMulti(pramas, result);
  }
};

const getMulti = async (data, list) => {
  await $request.HTTP.workAttendance
    .multiList(data)
    .then(async (res) => {
      if (res.status == 0 && res.data) {
        list.forEach((i, index) => {

          res.data.forEach((j, jIndex) => {
            if (i.year == j.year && i.month == j.month && i.day == j.day) {
              i.dayType = j.type; // 0 工作日 1 休息日
              i.dayDes = j.typeDes;
            }
          });
        });
        state.currentMonthDays = list;
        state.currentList = await resultList(list);
      }
    })
    .catch((e) => {
      // message.error(e.response.data.msg || "操作失败，请稍后再试");
    });
};
const addZero = (num) => {
  if (num < 10) {
    num = `0${num}`;
  }
  return num;
};
// 点击选择某一天
const getItem = (event) => {
  state.selectDate = event.year + "-" + addZero(event.month) + "-" + addZero(event.day);
  resultList(state.currentMonthDays);
  emits("clickDateData", state.selectDate, event);
};

// 处理工作日 休息日的样式问题
const resultList = async (data) => {
  let chunk = 7;
  let list = [];
  for (var i = 0, j = data.length; i < j; i += chunk) {
    list.push(data.slice(i, i + chunk));
  }
  await list.forEach((item, index) => {
    item.forEach((m, mIndex) => {
      m.isHoliday = false;
      m.isSelect = false;
      m.dateTime = m.year + "-" + addZero(m.month) + "-" + addZero(m.day);
      if (m.dayType == 0) {
        m.isHoliday = false;
      } else if (m.dayType == 1) {
        m.isHoliday = true;
      } else {
        m.isHoliday = m.isWeekend;
      }
      let date = m.year + "-" + addZero(m.month) + "-" + addZero(m.day);
      if (state.selectDate == date) {
        m.isSelect = true;
      }
    });
  });
  return list;
};

const selectCancel = () => {
  state.selectDateList = [];
  emits("clickDateArr", state.selectDateList);
};

// 暴露方法,父组件调用
defineExpose({ render, selectCancel });
// 日期格式化yyyy-mm-dd
const formatDate = (date) => {
  let year = date.getFullYear();
  let month = date.getMonth() + 1;
  let day = date.getDate();

  if (month < 10) {
    month = "0" + month;
  }
  if (day < 10) {
    day = "0" + day;
  }
  return year + "-" + month + "-" + day;
};
//  日期转时间戳
const dateToTime = (date) => {
  let timestamp = new Date(date).getTime();
  return timestamp;
};
/**
 * 计算该月需要渲染的日期信息
 * @param year
 * @param month
 * @param weekCount
 * @returns {Array}
 */
const monthDetail = (year, month) => {
  // console.log(year, month);
  // 计算用的month为传入month - 1
  var monthToUse = month - 1;
  // console.log('monthToUse', monthToUse);
  // 构建该月第一天date对象
  var firstDate = new Date(year, monthToUse);
  // console.log('firstDate',firstDate);
  // 获取周几信息,0表示周日
  var weekDay = firstDate.getDay();
  // console.log("weekDay", weekDay);
  // firstDayOfWeek设置每周起始日，默认周日
  state.weekTitle = ["日", "一", "二", "三", "四", "五", "六"];
  firstDate.setDate(1 - weekDay);
  // 该月要显示的所有日期对象数组,包括前后月补完
  var monthDays = [];
  var todayDate = new Date();
  for (let i = 0, cursor = firstDate; i < state.weekCount * 7; i++) {
    // console.log("cursor",cursor)
    let day = cursor.getDate();

    let thisDate = new Date(cursor);
    let isToday =
      todayDate.getFullYear() == thisDate.getFullYear() &&
      todayDate.getMonth() == thisDate.getMonth() &&
      todayDate.getDate() == thisDate.getDate();

    let tempDate = formatDate(thisDate);
    let isHighlighter = highlighterDate.value.indexOf(tempDate) >= 0 || false;
    var defaultDate = date;
    let isDefaultDate =
      defaultDate.getFullYear() == defaultDate.getFullYear() &&
      defaultDate.getMonth() == defaultDate.getMonth() &&
      defaultDate.getDate() == defaultDate.getDate();
    let dateObj = calendarJs.solar2lunar(
      thisDate.getFullYear(),
      thisDate.getMonth() + 1,
      thisDate.getDate()
    );
    monthDays.push({
      // 当前日期信息
      date: thisDate,
      year: thisDate.getFullYear(),
      month: thisDate.getMonth() + 1,
      day: thisDate.getDate(),
      weekDay: thisDate.getDay(),
      astro: dateObj.astro, //星座
      animal: dateObj.Animal, // 属相
      gzDay: dateObj.gzDay, //天干地支
      gzMonth: dateObj.gzMonth, //天干地支
      gzYear: dateObj.gzYear, //天干地支
      lunar: dateObj.IDayCn, // 农历日
      lunarMonth: dateObj.IMonthCn, // 农历月
      lunarFestival: dateObj.lunarFestival, // 节日
      festival: dateObj.festival, // 节日
      term: dateObj.Term, // 节气
      isToday,
      // 是否是默认的那天
      isDefaultDate,
      // 是否是周末
      isWeekend: thisDate.getDay() == 0 || thisDate.getDay() == 6,
      isHighlighter,
      // 是否是当前渲染月份中的日子
      isOtherMonthDay: thisDate.getMonth() + 1 != month,
      // 当前面板渲染的年、月
      renderYear: year,
      renderMonth: month,
      timeIndex: i
    });
    cursor.setDate(day + 1);
  }
  return monthDays;
};
/**
 * 从当前渲染的月份中根据第几周，第几天获取日期数据
 * @param week
 * @param day
 * @returns {*}
 */
const currentDate = (week, day, pramas) => {
  var index = (week - 1) * 7 + day - 1;
  return state.currentMonthDays[index][pramas];
};
/**
 * 向后跳转几月，负数则是向前
 * @param step
 */
const turn = (step) => {
  var year = state.renderYear,
    month = state.renderMonth - 1;
  var date = new Date(year, month);
  date.setMonth(date.getMonth() + step);

  // 获取要渲染的年份、月份
  var toRenderYear = date.getFullYear();
  var toRenderMonth = date.getMonth() + 1;
  // 渲染
  render(toRenderYear, toRenderMonth);
};
/**
 * 跳转到当前月
 */
const turnNow = () => {
  var date = new Date();
  // 获取要渲染的年份、月份
  var toRenderYear = date.getFullYear();
  var toRenderMonth = date.getMonth() + 1;
  // 渲染
  render(toRenderYear, toRenderMonth);
};

watch(
  () => state.defaultDate,
  (date) => {
    var day = new Date(date);
    var year = day.getFullYear();
    var month = day.getMonth() + 1;
    render(year, month);
  }
)
</script>

<style lang="scss" scoped>
.contro-header {
  padding-bottom: 15px;
  border-bottom: 1px solid #E8E8E8;
  cursor: pointer;
  justify-content: center;
  display: flex;

  .wrap4 {
    margin-right: 31px;
    img {
      width: 7.68px;
      height: 13.83px;
    }
    transform: rotate(180deg);
  }

  .wrap5 {
    img {
      width: 16.9px;
      height: 15.36px;
    }

    transform: rotate(180deg);
  }

  .wrap3 {
    margin-left: 88px;
    margin-right: 88px;
    font-size: 16px;
    color: #000;
  }

  .wrap2 {
    margin-left: 31px;
    img {
      width: 7.68px;
      height: 13.83px;
    }
  }

  .wrap1 {

    img {
      width: 16.9px;
      height: 15.36px;
    }
  }
}

.fullscreen-table {
  border-collapse: collapse;

  thead {
    font-size: 16px;
    color: #000;
    font-weight: 500;
  }

  th {
    padding: 18px 30px;
    font-weight: normal;
  }

  td {
    position: relative;
    border: 2px solid #E8E8E8;
    width: 300px;
    height: 90px;
  }
}

.card-table {
  border-collapse: collapse;

  thead {
    font-size: 14px;
    color: $theme-primary;
  }

  th {
    padding: 10px 10px;
    font-weight: normal;
  }

  td {
    position: relative;
    width: 100px;
    height: 50px;
  }
}

.color80 {
  color: #808080 !important;
}

.colorff {
  color: #fff !important;
}

.colord9 {
  color: #d9d9d9 !important;
}

.bgSelect {
  background: #f0ecf8 !important;
}

.td-con {
  .day {
    font-size: 12px;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 30px;
    padding-left: 12px;
    line-height: 30px;
    color: #000000;
    font-weight: bold;
  }

  .isDay {
    position: absolute;
    top: 5px;
    right: 5px;
    color: #fff;
    background: $theme-primary;
    padding: 1px 8px;
    border-radius: 30px;
    font-size: 10px;
  }

  .festival {
    position: absolute;
    top: 5px;
    right: 5px;
    color: $theme-primary;
    font-size: 10px;
  }

  .lunar {
    position: absolute;
    bottom: 5px;
    right: 9px;
    font-size: 14px;
    color: #8B8B8B;
  }
}

.day-item {
  display: flex;
  justify-content: center;

  .day {
    width: 30px;
    height: 30px;
    line-height: 30px;
    border-radius: 50%;
    text-align: center;
    cursor: pointer;
  }

  .select {
    background: #E8E8E8;
    color: $theme-primary;
  }

  .defualChoose {
    background: #E8E8E8;
  }
}

.row {
  display: flex;
  justify-content: space-between;

  .left-select {
    padding: 10px;
    background: #E8E8E8;
    color: #000000;
    font-size: 14px;
    display: flex;
    justify-content: space-around;
    align-items: center;

    .active {
      color: #fff;
      background: $theme-primary;
      border-radius: 4px;
    }

    span {
      padding: 6px 14px;
      cursor: pointer;
    }
  }

  .right-select-date {
    display: flex;
    justify-content: space-around;
    align-items: center;
    /* 火狐 */
    -moz-user-select: none;
    /* Safari 和 欧朋 */
    -webkit-user-select: none;
    /* IE10+ and Edge */
    -ms-user-select: none;
    /* Standard syntax 标准语法(谷歌) */
    user-select: none;
  }

  .allSelect {
    margin: 15px 0 10px 20px;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    cursor: pointer;

    .noCheck {
      width: 12px;
      height: 12px;
      border: 1px solid $theme-primary;
      border-radius: 50%;
      margin-right: 5px;
    }

    .check {
      width: 12px;
      height: 12px;
      border: 1px solid $theme-primary;
      background: #6d5c9c;
      border-radius: 50%;
      margin-right: 5px;
    }
  }
}
</style>
