首页 > 其他分享 >calendar

calendar

时间:2022-12-18 00:56:22浏览次数:27  
标签:const color value month year date calendar

export const weekMapZh = ['日', ' 一', '二', '三', '四', '五', '六'];
const calendarGrid = 42; // 7 * 6宫格;
export interface CalendarItem {
  year: number;
  month: number;
  day: number;
  isCurrentMonth: boolean;
}
// 是否为闰年
const isLeap = (year: number) => {
  return (year % 4 === 0 && year % 100 !== 0) || year % 100 === 0;
};

// 获取[month]月有几天
const getDays = (year: number, month: number): number => {
  const feb = isLeap(year) ? 29 : 28;
  const daysPerMonth = [31, feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  return daysPerMonth[month];
};

// 获取下个月/上个月有多少天
const getNextOrLastMonthDays = (date: Date, type: 'next' | 'last') => {
  const month = date.getMonth();
  const year = date.getFullYear();
  if (type === 'last') {
    const lastMonth = month === 0 ? 11 : month - 1;
    const lastYear = lastMonth === 11 ? year - 1 : year;
    return {
      year: lastYear,
      month: lastMonth,
      days: getDays(lastYear, lastMonth),
    };
  }
  const nextMonth = month === 11 ? 0 : month + 1;
  const nextYear = nextMonth === 0 ? year + 1 : year;
  return {
    year: nextYear,
    month: nextMonth,
    days: getDays(nextYear, nextMonth),
  };
};

export const generateCalendar = (date: Date) => {
  const currentYear = date.getFullYear();
  const currentMonth = date.getMonth();
  // 当月天数
  const days = getDays(currentYear, currentMonth);
  // 获取上月末尾天数和下月开头的天数,用于填补当月日历空白
  const { days: lastMonthDays, year: lastMonthYear, month: lastMonth } = getNextOrLastMonthDays(date, 'last');
  const { year: nextMonthYear, month: nextMonth } = getNextOrLastMonthDays(date, 'next');
  // 1号是星期几
  const weekIndex = new Date(`${currentYear}/${currentMonth + 1}/1`).getDay();
  // 显示在当月末尾的下月天数
  const trailDays = calendarGrid - weekIndex - days;
  let trailVal = 0;
  const calendarTable: CalendarItem[] = [];
  for (let i = 0; i < calendarGrid; i++) {
    // 补充上月天数
    if (i < weekIndex) {
      calendarTable[i] = {
        year: lastMonthYear,
        month: lastMonth,
        day: lastMonthDays - weekIndex + i + 1,
        isCurrentMonth: false,
      };
      // 补充下月天数
    } else if (i >= days + weekIndex) {
      if (trailVal < trailDays) {
        trailVal += 1;
      }
      calendarTable[i] = {
        year: nextMonthYear,
        month: nextMonth,
        day: trailVal,
        isCurrentMonth: false,
      };
    }
  }
  // 填充当月日期
  for (let d = 1; d <= days; d++) {
    calendarTable[weekIndex + d - 1] = {
      year: currentYear,
      month: currentMonth,
      day: d,
      isCurrentMonth: true,
    };
  }

  return calendarTable;
};

<template>
  <div class="calendar">
    <div class="calendar-operate">
      <div class="button-group">
        <button class="button" @click="changeMonth('prev')">
          <i class="icon ri-arrow-left-s-line"></i>
        </button>
        <button class="button" @click="changeMonth('next')">
          <i class="icon ri-arrow-right-s-line"></i>
        </button>
      </div>
      <div class="calendar-operate__title">{{ dateText }}</div>
      <button class="button" :disabled="isToday" @click="currentDate">今天</button>
    </div>
    <div class="calendar-header">
      <span
        v-for="(item, index) in weekMapZh"
        :key="index"
        class="calendar-header__item"
        :class="{ gray: index === 0 || index === 6 }"
        >{{ item }}</span
      >
    </div>
    <div class="calendar-content" :data-month="date.getMonth() + 1">
      <div
        v-for="(item, index) in calendarTable"
        :key="index"
        class="calendar-content__item"
        :class="[{ light: !item.isCurrentMonth }, { active: isActive(item) }]"
      >
        {{ item.day }}
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { weekMapZh, generateCalendar } from './calendar';
import { isAllTrue } from '@/utils/common';
import { CalendarItem } from './calendar';

const date = ref<Date>(new Date());
const calendarTable = computed(() => generateCalendar(date.value));
const dateText = computed(() => {
  return `${date.value.getFullYear()}/${date.value.getMonth() + 1}`;
});

const isToday = computed(() => {
  const current = new Date();
  const validArr = [
    date.value.getFullYear() === current.getFullYear(),
    date.value.getMonth() === current.getMonth(),
    date.value.getDay() === current.getDay(),
  ];
  return isAllTrue(validArr);
});
/**
 * 当天日期高亮显示, 兼容切换日期:
 * 年月日都要对上才能高亮
 * ps: 日历可能会显示下月/上月的同样日期, 仅当月日期高亮
 */
const isActive = (item: CalendarItem) => {
  return isAllTrue([
    item.day === date.value.getDate(),
    item.isCurrentMonth,
    item.month === new Date().getMonth(),
    item.year === new Date().getFullYear(),
  ]);
};
// 切换到今天
const currentDate = () => {
  date.value = new Date();
};
// 切换月份, 上个月 or 下个月
const changeMonth = (type: 'prev' | 'next'): void => {
  let month = 0;
  let year = 1970;
  if (type === 'prev') {
    month = date.value.getMonth() === 0 ? 11 : date.value.getMonth() - 1;
    year = month === 11 ? date.value.getFullYear() - 1 : date.value.getFullYear();
  } else {
    month = date.value.getMonth() === 11 ? 0 : date.value.getMonth() + 1;
    year = month === 0 ? date.value.getFullYear() + 1 : date.value.getFullYear();
  }

  if (month === new Date().getMonth()) {
    currentDate();
    return;
  }

  date.value.setDate(1);
  date.value.setMonth(month);
  date.value.setFullYear(year);

  date.value = new Date(date.value);
};
</script>
<style lang="scss" scoped>
$gap: 8px;
$sub-active-color: #dbf0ff;
$active-color: #0065ff;
$gray: #979797;

.button {
  height: 28px;
  font-size: 12px;
  background: #fff;
  margin: 0;
  padding: 0 16px;
  border: 1px solid rgba($gray, 0.4);
  border-radius: 14px;
  cursor: pointer;
  &:hover {
    color: $active-color;
  }
  &:active {
    background-color: rgba(0, 0, 0, 6%);
  }
  &:disabled {
    color: $gray;
    background-color: rgba(0, 0, 0, 6.5%);
    cursor: not-allowed;
  }
}

.button-group {
  .button:first-child {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
  }
  .button:last-child {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    border-left: 0;
  }
  .button:not(:first-child):not(:last-child) {
    border-radius: 0;
    border-left: 0;
  }
}

.icon {
  height: 100%;
  font-size: 24px;
  display: inline-flex;
  align-items: center;
}

.calendar-operate {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid rgba($gray, 0.15);
  font-size: 18px;
  position: relative;
  &__title {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    margin: 0 8px;
  }
}

.calendar-header {
  margin-top: 6px;
  padding: 8px 0;
  font-size: 14px;
  font-weight: bold;
  display: flex;
  &__item {
    flex: 1;
    text-align: right;
    border-radius: 1px;
    &.gray {
      color: $gray;
      font-weight: normal;
    }
  }
}

.calendar-content {
  display: flex;
  flex-wrap: wrap;
  margin: 20px 0;
  position: relative;
  color: #333;
  &::after {
    content: attr(data-month);
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 10em;
    font-weight: bold;
    color: rgba($gray, 0.1);
  }
  &__item {
    height: 6em;
    flex: calc(14.2% - $gap);
    font-size: 14px;
    box-sizing: border-box;
    transition: all 0.2s ease;
    text-align: right;
    padding: 10px 0;
    margin-right: $gap;
    &:nth-child(7n),
    &:nth-child(7n-6) {
      color: $gray;
    }
    &:nth-child(7n) {
      margin-right: 0;
    }
    &.active {
      color: $active-color;
      font-weight: bold;
      border-bottom: 2px solid $active-color;
    }
    &:hover {
      background-color: rgba($sub-active-color, 0.4);
      cursor: pointer;
    }
    &.light {
      color: rgba($gray, 0.4);
      cursor: not-allowed;
    }
  }
}
</style>

标签:const,color,value,month,year,date,calendar
From: https://www.cnblogs.com/chyshy/p/16989890.html

相关文章

  • Calendar类解析
    ......
  • vue fullcalendar日历拖拽插入整理
    <!--交易时间管理--><template><divclass="container"><Row><Colspan="6"><divclass="module-title">假期列表</div><divclass="......
  • js插件fullcalendar配置项及样例
     部分配置项<linkhref="./plugins/fullcalendar-5.11.2/lib/main.css"rel="stylesheet"/><scripttype="text/javascript"language="javascript"src="./plugins/......
  • 使用fullcalendar构建简单会议室预约页面
    <linkhref="./plugins/fullcalendar-5.11.2/fullcalendar-scheduler/main.min.css"rel="stylesheet"/><scripttype="text/javascript"language="javascript"src=".......
  • jQuery插件FullCalendar日程表实现可扩展Google日历功能
    这个介绍jQuery日历FullCalendar插件是一个非常不错的日历工具,可用于制作日程表或计划安排等,可扩展Google日历功能,制作个性化的日程表,同时可绑定点击事件或拖动事件,使用非常......
  • java常用类中Calendar【日历】
    Calendar类Calendar:它为特定瞬间与一组诸如YEAR、MONTH、DAY_OF_MONTH、HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方......
  • 博弈论练习4 Calendar Game(SG函数)
    题目链接在这里:D-CalendarGame_牛客竞赛博弈专题班组合游戏基本概念、对抗搜索、Bash游戏、Nim游戏习题(nowcoder.com)这题网上有关于奇偶性来找规律的做法,有点人类智慧......
  • java日历类Calendar的基本使用方法
    packageA_ShangGuiGu.DateTimeTest;importorg.junit.Test;importjava.util.Calendar;importjava.util.Date;publicclassCalendarTest01{@Testpublicvoidc......
  • el-calendar 自定义我的日程
    效果图1. el-calendar官方文档内容太少,具体需要css样式,可以根据ui设置自行修改,一下的代码只展示JS的逻辑.2. 遍历日期,确定显示内容<el-calendarv-model="value"><te......
  • vue fullcalendar月周日历
    参考https://fullcalendar.io/demoshttps://www.cnblogs.com/czk1634798848/p/13386178.htmlhttps://blog.csdn.net/qq_39863107/article/details/105387879引入了Day.......