vue3 momentjs自定义自然日、数据周、自然月 左右切换

发布时间:2024年01月19日
<template>
  <div class="custom-date">
    <div class="left">
      <el-icon
        v-if="currentIndex != 3"
        @click="preNum"
        ><ArrowLeft
      /></el-icon>
      <div v-if="currentIndex == 0">{{ currentDay }}</div>
      <div v-if="currentIndex == 1">{{ currentWeek }}</div>
      <div v-if="currentIndex == 2">{{ currentMonth }}</div>
      <el-date-picker
        v-if="currentIndex == 3"
        v-model="currentCustom"
        :teleported="false"
        @change="cusomChange"
        @calendar-change="calendarChange"
        type="daterange"
        :disabled-date="disabledDate"
        style="width: 225px; height: 30px"
        format="YYYY/MM/DD"
        value-format="YYYY-MM-DD"
        :clearable="false"
        range-separator="~"
        start-placeholder="开始日期"
        end-placeholder="结束日期" />
      <el-icon
        v-if="currentIndex != 3"
        @click="nextNum"
        ><ArrowRight
      /></el-icon>
    </div>
    <div class="right">
      <template
        v-for="(item, index) in dateArr"
        :key="index">
        <div
          @click="callbackDateType(index)"
          :class="['right-item', currentIndex == index ? 'active' : '']">
          {{ item }}
        </div>
      </template>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
import moment from 'moment';
moment.locale('zh-cn'); //dayjs 时间本地化
type Props = {
  delay?: number;
};

const props = withDefaults(defineProps<Props>(), {
  delay: 400
});
const emits = defineEmits(['changeCurrentTime']);
const currentIndex = ref<number>(0);
const logIndex = ref<number>(0); // 记录index
const dateArr = ref(['日', '周', '月', '自定义']);
const currentDay = ref('');
const currentDayNum = ref(1);
const currentWeek = ref('');
const currentWeekNum = ref(1);
const currentMonth = ref('');
const currentMonthNum = ref(1);
const currentCustom = ref();
const optionalRange = ref();
const timer = ref();

const clearAllNum = () => {
  currentDayNum.value = 1;
  currentWeekNum.value = 1;
  currentMonthNum.value = 1;
  currentCustom.value = getCurrentWeek('log');
};

// 点击日、周、月、自定义
const callbackDateType = (index) => {
  currentIndex.value = index;
  if (logIndex.value == currentIndex.value) return;
  clearAllNum(); // 清楚缓存时间
  if (currentIndex.value == 0) {
    getCurrentDay();
  } else if (currentIndex.value == 1) {
    getCurrentWeek();
  } else if (currentIndex.value == 2) {
    getCurrentMonth();
  } else if (currentIndex.value == 3) {
    if (timer.value) {
      clearTimeout(timer.value);
    }
    timer.value = setTimeout(() => {
      emits('changeCurrentTime', currentCustom.value[0], currentCustom.value[1], 'custom');
    }, props.delay);
  }
  logIndex.value = index;
};

/**
 * @funciton 获取日
 */
const getCurrentDay = () => {
  const arr = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
  let day = moment().subtract(currentDayNum.value, 'day').format('YYYY/MM/DD');
  let week = moment().subtract(currentDayNum.value, 'day').weekday() - 1;
  currentDay.value = arr[week == -1 ? 6 : week] + ' ' + day;
  if (timer.value) {
    clearTimeout(timer.value);
  }
  timer.value = setTimeout(() => {
    emits('changeCurrentTime', day, '', 'day');
  }, props.delay);
};
/**
 * @funciton 获取周
 */
const getCurrentWeek = (isReturn?) => {
  // 获取当前日期
  const currentDate = moment();
  // clone必须加否则会改变currentDate当前日期
  let currentWeekDay = currentDate.clone().weekday();
  // day指定周几   subtract指定本周、上周为2 下周-1
  let firstThursday = currentDate
    .clone()
    .day(5)
    .subtract(currentWeekDay > 4 ? currentWeekNum.value : currentWeekNum.value + 1, 'week')
    .format('YYYY/MM/DD');
  let lastThursday = currentDate
    .clone()
    .day(4)
    .subtract(currentWeekDay > 4 ? currentWeekNum.value - 1 : currentWeekNum.value, 'week')
    .format('YYYY/MM/DD');
  if (isReturn == 'log') {
    return [firstThursday, lastThursday];
  } else {
    currentWeek.value = firstThursday + '~' + lastThursday;
    if (timer.value) {
      clearTimeout(timer.value);
    }
    timer.value = setTimeout(() => {
      emits('changeCurrentTime', firstThursday, lastThursday, 'week');
    }, props.delay);
  }
};
/**
 * @funciton 获取月
 */
const getCurrentMonth = () => {
  // clone必须加否则会改变currentDate当前日期
  const day = moment().subtract(currentMonthNum.value, 'month').format('YYYY-MM');
  let monthfirst = moment(day).startOf('month').format('YYYY/MM/DD');
  let monthend = moment(day).endOf('month').format('YYYY/MM/DD');
  currentMonth.value = monthfirst + '~' + monthend;
  if (timer.value) {
    clearTimeout(timer.value);
  }
  timer.value = setTimeout(() => {
    emits('changeCurrentTime', monthfirst, monthend, 'month');
  }, props.delay);
};
/**
 * @funciton 获取自定义
 */
const cusomChange = (e) => {
  optionalRange.value = '';
  emits('changeCurrentTime', e[0], e[1], 'custom');
};

const calendarChange = (e) => {
  optionalRange.value = e[0];
};

/**
 * @function 禁止时间
 */
const disabledDate = (time: Date) => {
  const startDay = new Date(moment(optionalRange.value).subtract(90, 'days').format('YYYY-MM-DD')).getTime();
  const endDay = new Date(moment(optionalRange.value).subtract(-90, 'days').format('YYYY-MM-DD')).getTime();
  const yesterday = moment().subtract(1, 'days').format('YYYY-MM-DD');
  if (!optionalRange.value) {
    return time.getTime() > new Date(yesterday).getTime();
  } else {
    const day = Math.abs(moment(yesterday).diff(moment(optionalRange.value).format('YYYY-MM-DD'), 'days'));
    if (day < 90) {
      return time.getTime() > new Date(yesterday).getTime() || time.getTime() < startDay;
    } else {
      return time.getTime() < startDay || time.getTime() > endDay;
    }
  }
};

/**
 * @function 点击<
 * currentIndex.value == 0 日 1 周 2月
 */
const preNum = () => {
  if (currentIndex.value == 0) {
    currentDayNum.value += 1;
    getCurrentDay();
  } else if (currentIndex.value == 1) {
    currentWeekNum.value += 1;
    getCurrentWeek();
  } else if (currentIndex.value == 2) {
    currentMonthNum.value += 1;
    getCurrentMonth();
  }
};

/**
 * @function 点击>
 * currentIndex.value == 0 日 1 周 2月
 */
const nextNum = () => {
  if (currentIndex.value == 0) {
    if (
      new Date(currentDay.value.slice(3, currentDay.value.length)).getTime() >=
      new Date(moment().subtract(1, 'day').format('YYYY/MM/DD')).getTime()
    )
      return;
    currentDayNum.value -= 1;
    getCurrentDay();
  } else if (currentIndex.value == 1) {
    const currentWeekDay = moment().clone().weekday();
    const lastweek = new Date(
      moment()
        .clone()
        .day(4)
        .subtract(currentWeekDay > 0 && currentWeekDay < 5 ? 1 : 0, 'week')
        .format('YYYY/MM/DD')
    ).getTime();
    // 如果可选择数据周周四 大于本周四则直接返回
    if (new Date(currentWeek.value.slice(11, currentWeek.value.length)).getTime() >= lastweek) return;
    currentWeekNum.value -= 1;
    getCurrentWeek();
  } else if (currentIndex.value == 2) {
    const lastmonth = new Date(
      moment(moment().subtract(1, 'month').format('YYYY-MM')).endOf('month').format('YYYY/MM/DD')
    ).getTime();
    if (new Date(currentMonth.value.slice(11, currentMonth.value.length)).getTime() >= new Date(lastmonth).getTime())
      return;
    currentMonthNum.value -= 1;
    getCurrentMonth();
  }
};

const init = () => {
  clearAllNum();
  getCurrentDay();
};
init();
</script>
<style lang="less" scoped>
.custom-date {
  display: flex;
  align-items: center;

  ::v-deep(.today .el-date-table-cell__text) {
    font-weight: normal;
    color: var(--el-text-color-placeholder);
  }
  .left {
    display: flex;
    width: 225px;
    height: 32px;
    align-items: center;
    border-radius: 3px;
    border: 1px solid #dcdcdc;
    justify-content: space-around;
    color: rgba(0, 0, 0, 0.9);
    font-family: 'PingFang SC';
    font-size: 14px;
    font-style: normal;
    font-weight: 400;
    margin-right: 8px;

    ::v-deep(.el-range-input),
    ::v-deep(.el-range-input)::placeholder {
      height: 32px;
      color: rgba(0, 0, 0, 0.9) !important;
      font-size: 14px !important;
    }

    ::v-deep(.el-select),
    ::v-deep(.el-cascader),
    ::v-deep(.el-input),
    ::v-deep(.el-date-editor),
    ::v-deep(.el-range-editor) {
      box-shadow: none !important;
      border: none !important;
      .el-input__wrapper {
        box-shadow: none !important;
        border: none !important;
      }
    }
    ::v-deep(.el-date-editor .el-range-separator) {
      color: rgba(0, 0, 0, 0.9) !important;
    }
    .el-icon {
      cursor: pointer;
    }
  }
  .right {
    display: flex;
    align-items: center;
    .right-item {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 74px;
      height: 32px;
      color: #00000099;
      text-align: center;
      font-family: 'PingFang SC';
      font-size: 14px;
      font-style: normal;
      font-weight: 400;
      border-bottom: 1px solid #dcdcdc;
      border-top: 1px solid #dcdcdc;
      border-left: 1px solid #dcdcdc;
      box-sizing: border-box;
      cursor: pointer;
    }
    .right-item:nth-of-type(1) {
      border-top-left-radius: 3px;
      border-bottom-left-radius: 3px;
    }
    .right-item:last-child {
      border-right: 1px solid #dcdcdc;
      border-top-right-radius: 3px;
      border-bottom-right-radius: 3px;
    }
    .active {
      border: 1px solid #4679fa !important;
      color: #0052d9;
      box-sizing: border-box;
    }
  }
}
</style>

文章来源:https://blog.csdn.net/m0_71349739/article/details/135690749
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。