当前位置: 首页 > article >正文

vue2日历组件

【效果图】
在这里插入图片描述

<template>
  <div style="width: 100%">
    <!-- <div> -->
    <!-- <div>{{ startDate.getMonth() + 1 + '-' + startDate.getDate() }}</div>
    <div>{{ endDate.getMonth() + 1 + '-' + endDate.getDate() }}</div> -->
    <!-- <button @click="generateDates">生成日期</button> -->
    <div class="lableBoxClass flexBetween">
      <div class="lableClass">请假日期</div>
      <div>{{ selectedDatesStr }}</div>
    </div>
    <div class="calenderBoxClass">
      <!-- <div>选中的日期:{{ selectedDatesStr }}</div> -->
      <div class="date-scale">
        <span v-for="(day, index) in scaleDays" :key="index">{{ day }}</span>
      </div>
      <ul class="date-list">
        <li v-for="(date, index) in showDates" :key="index">
          <div @click="toggleDateSelection(date)" class="date-item" :class="{ grayColor: isDateDisabled(date), selected: isSelected(date) }">{{ date }}</div>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
import { Toast } from 'vant'
export default {
  name: 'CalendarVue',
  props: {
    startDate: {
      type: Date,
      default() {
        return new Date()
      }
    },
    endDate: {
      type: Date,
      default() {
        return new Date()
      }
    }
  },
  data() {
    return {
      // startDate: new Date('2024-12-19'),
      // endDate: new Date('2025-01-05'),
      showDates: [], // 用于存储页面显示的日期数组
      selectableDates: [], // 用于存储可选的日期数组
      scaleDays: ['一', '二', '三', '四', '五', '六', '日'], // 用于存储日期刻度的数组
      selectedDates: {}, // 用于存储选中的日期,键为日期,值为是否选中
      selectedDatesArr: [] // 用于存储选中的日期数组
    }
  },
  computed: {
    selectedDatesStr() {
      if (this.selectedDatesArr.length > 0) {
        return this.selectedDatesArr.join(',')
      }
      return '请点击需要请假的日期'
    }
  },
  created() {
    // 生成日期
    this.generateDates()
    this.getSelectableDates()
  },
  mounted() {},
  methods: {
    isDateDisabled(date) {
      return !this.selectableDates.includes(date)
    },
    generateDates() {
      if (!this.startDate || !this.endDate) {
        alert('请选择开始日期和结束日期')
        return
      }

      // 重置日期数组和刻度数组
      this.showDates = []
      const startDate = new Date(this.startDate)
      const endDate = new Date(this.endDate)
      console.log(90, this.formatDate(startDate), this.formatDate(endDate))

      // 找到第一个星期一
      let currentDate = new Date(startDate)
      while (currentDate.getDay() !== 1) {
        // getDay() 返回的是 0(星期日) 到 6(星期六)
        currentDate.setDate(currentDate.getDate() + 1)
      }
      // 重新设置currentDate为区间开始日期
      currentDate = new Date(startDate)
      this.showDates = [...this.getDatesFromThisMonday(this.startDate)]
      console.log(100, this.showDates)

      // 生成日期数组
      while (currentDate <= endDate) {
        this.showDates.push(this.formatDate(currentDate))
        currentDate.setDate(currentDate.getDate() + 1)
      }
      console.log(107, this.showDates)

      let nextSundayArr = this.getDatesFromEndDateToNextSunday(this.endDate)
      if (nextSundayArr.length > 0) {
        nextSundayArr.forEach(item => {
          this.showDates.push(item)
        })
      }
      console.log(115, this.showDates)
    },
    // formatDate(date)<-->将日期对象转换为 "月份.日期" 格式
    formatDate(date) {
      const month = date.getMonth() + 1 // 月份从0开始,所以需要+1
      const day = date.getDate()
      return `${month}.${day}`
    },
    getSelectableDates() {
      let startShowDate = new Date(this.startDate)
      let endShowDate = new Date(this.endDate)
      console.log(131, startShowDate, endShowDate)
      while (startShowDate < endShowDate) {
        let formattedDate = startShowDate.getMonth() + 1 + '.' + startShowDate.getDate()
        this.selectableDates.push(formattedDate) // 将格式化后的日期添加到数组中
        startShowDate.setDate(startShowDate.getDate() + 1) // 移动到下一天
      }
      console.log(138000, this.selectableDates)
      // return this.selectableDates
    },
    //getDatesFromThisMonday(startDate)<-->获取从当前周一到起始日期【startDate】的日期数组,并转换为 "月份.日期" 格式(与参数【showDates】(页面展示的日期)相关)
    getDatesFromThisMonday(startDate) {
      // 创建一个当前日期的副本,以避免修改原始日期对象
      let today = new Date(startDate.getTime())

      // 找到这周一的日期
      let thisMonday = new Date(today.getTime())
      thisMonday.setDate(today.getDate() - today.getDay() + (today.getDay() === 0 ? -6 : 1)) // 设置为周一

      // 生成从这周一到今天的日期数组,并转换为 "月份.日期" 格式
      let dates = []
      let current = new Date(thisMonday.getTime()) // 从这周一开始
      while (current < today) {
        // 包含今天
        // 转换日期格式为 "月份.日期"
        let formattedDate = current.getMonth() + 1 + '.' + current.getDate()
        dates.push(formattedDate) // 将格式化后的日期添加到数组中
        current.setDate(current.getDate() + 1) // 移动到下一天
      }
      // console.log(136, dates)
      return dates // 返回日期数组
    },
    //getDatesFromEndDateToNextSunday(endDate)<-->获取从结束日期【endDate】到下一个周日之间的所有日期数组,并转换为 "月份.日期" 格式(与参数【showDates】(页面展示的日期)相关)
    getDatesFromEndDateToNextSunday(endDate) {
      let current = new Date(endDate.getTime())
      // 如果endDate是周日,则将日期设置为下一天(周一)
      if (current.getDay() == 0) {
        return []
      }
      current.setDate(current.getDate() + 1)
      let dates = []
      // 循环直到当前日期是下一个周日
      while (current.getDay() !== 0) {
        // 格式化日期为 "月份.日期"
        let formattedDate = current.getMonth() + 1 + '.' + current.getDate()
        // 将格式化后的日期字符串添加到数组中
        dates.push(formattedDate)
        // 将日期加1天
        current.setDate(current.getDate() + 1)
      }
      // 如果endDate不是周日,我们才添加当前周日
      if (endDate.getDay() !== 0) {
        let formattedSunday = current.getMonth() + 1 + '.' + current.getDate()
        dates.push(formattedSunday)
      }
      console.log(165, dates)

      // 返回包含所有格式化日期的数组
      return dates
    },
    toggleDateSelection(date) {
      // 切换日期的选中状态
      if (this.isDateDisabled(date)) {
        Toast('不可选择范围外的日期')
        return
      }

      // 切换选中状态
      const isSelected = this.isSelected(date)
      this.$set(this.selectedDates, date, !isSelected)

      // 根据新的选中状态更新数组
      if (!isSelected) {
        // 如果之前未选中,现在选中了,则添加到数组中
        this.selectedDatesArr.push(date)
      } else {
        // 如果之前已选中,现在取消了,则从数组中移除
        const index = this.selectedDatesArr.indexOf(date)
        if (index !== -1) {
          this.selectedDatesArr.splice(index, 1)
        }
      }
    },
    isSelected(date) {
      // 检查日期是否被选中
      return this.selectedDates[date] === true
    }
  }
}
</script>
<style lang="scss" scoped>
.lableBoxClass {
  padding: 15px;
  font-size: 15px;
  display: flex;
  .lableClass {
    width: 100px;
    color: #1f2022;
    flex-shrink: 0;
    &::after {
      content: '*'; /* 使用Unicode字符表示红星 */
      color: red;
      margin-left: 5px;
    }
  }
}
.calenderBoxClass {
  // padding-left: 15px;
  // padding-right: 10px;
  // background-color: yellow;
}
</style>

<style scoped>
.date-scale {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  flex: 0 0 calc(100% / 7 - 10px); /* 假设你想要每个日期项之间有10px的间隙 */
  margin: 5px; /* 这将创建10px的间隙(每个方向5px) */
  text-align: center;
  margin-bottom: 10px;
}
.date-scale span {
  display: inline-block;
  width: 30px; /* 根据需要调整刻度宽度 */
  text-align: center;
}

.date-scale {
  display: flex;
  justify-content: space-between;
}

.date-list {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
}

.date-list li {
  flex: 0 0 calc(100% / 7 - 10px); /* 假设你想要每个日期项之间有10px的间隙 */
  /*width: calc(100vw / 7- 10px); */
  text-align: center;
  font-style: 16px;
}
.date-item {
  /*margin: 5px;*/
  background-color: #e6eefc;
  width: calc(100vw / 7);
  margin-bottom: 8px;
  height: 30px;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
}
.date-list:nth-child(3) {
  border-radius: 10px;
}
.grayColor {
  color: gray;
  background-color: white;
}

.selected {
  background-color: rgb(19, 96, 231); /* 选中的日期背景色为蓝色 */
  color: white; /* 选中的日期字体颜色为白色 */
  border-radius: 5px;
}
</style>

调用组件

   <CalendarVue :startDate="startDate" :endDate="endDate" />

http://www.kler.cn/a/412408.html

相关文章:

  • 概率论中交并集的公式
  • 蓝网科技临床浏览系统存在SQL注入漏洞
  • 自由学习记录(25)
  • 【Android+多线程】异步 多线程 知识总结:基础概念 / 多种方式 / 实现方法 / 源码分析
  • 数据新时代:如何选择现代数据治理平台(上)
  • ubuntu24挂载硬盘记录
  • java技术层面用调用jar包的class文件的技术
  • 时间序列预测——周期性解藕框架(PDF)
  • uniapp 地图移入的快,高亮显示两个
  • 建造者模式Builder——优雅的使用姿势
  • 241123_基于MindSpore学习Bert
  • 设备网络状态巡检系统需求文档
  • 实时数据开发 | checkpoints监控和调优
  • 【DVWA】File Upload任意文件上传实战
  • 运维面试题.云计算面试题
  • Scala身份证上的秘密以及Map的遍历
  • arcgis for js FeatureLayer和GeoJSON一个矢量点同时渲染图形和文本
  • Android按键点击事件三种实现方法
  • 88页精品PPT | 某电信集团大数据平台建设方案技术交流
  • JAVA-IO
  • 【iOS】UICollectionView的学习
  • CTF之密码学(BF与Ook)
  • SpringBoot集成ESAPI
  • 深入理解 Spring Boot 的 WebApplicationType
  • 设计模式:11、迭代器模式(游标)
  • 修改IDEA配置导致Spring Boot项目读取application.properties中文乱码问题