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" />

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/926607.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis中的分布式锁(步步为营)

分布式锁 概述 分布式锁指的是&#xff0c;所有服务中的所有线程都去获取同一把锁&#xff0c;但只有一个线程可以成功的获得锁&#xff0c;其他没有获得锁的线程必须全部等待&#xff0c;直到持有锁的线程释放锁。 分布式锁是可以跨越多个实例&#xff0c;多个进程的锁 分布…

mmsegmentation自己的数据集

我最大的问题就是没安装官方给定的mask转换格式来转换 这种带白色的不行哦&#xff01; 黑色的可以&#xff0c;其实mask*50就可以看清楚标记的轮廓之类的。 数据集格式转换按照A,B,C代码直接转换&#xff1a;https://github.com/TommyZihao/Label2Everything/tree/main/lab…

yolov8的深度学习环境安装(cuda12.4、ubuntu22.04)

目录 一、先安装基础环境包 1.首先给Ubuntu安装Chrome浏览器&#xff08;搜索引擎换成百度即可&#xff09; 2、ubuntu 22.04中文输入法安装 3、安装 terminator 4、安装WPS for Linux 5、安装其它之前需要先安装anaconda 6、安装配置anaconda 7、安装完成anaconda后创建…

洛谷 B3626 跳跃机器人 C语言 记忆化搜索

题目&#xff1a; https://www.luogu.com.cn/problem/B3626 题目描述 地上有一排格子&#xff0c;共 n 个位置。机器猫站在第一个格子上&#xff0c;需要取第 n 个格子里的东西。 机器猫当然不愿意自己跑过去&#xff0c;所以机器猫从口袋里掏出了一个机器人&#xff01;这…

小型文件系统如何选择?FatFs和LittleFs优缺点比较

1 概述 文件系统在嵌入式系统中的作用不可或缺&#xff0c;它提供了对非易失性存储设备&#xff08;如闪存、SD卡等&#xff09;上的数据进行有效组织和管理的能力。通过文件系统&#xff0c;嵌入式系统可以像在传统计算机上一样创建、读取、写入和删除文件&#xff0c;实现了…

【JAVA] 杂谈: java中的拷贝(克隆方法)

这篇文章我们来介绍什么是拷贝&#xff0c;并且实现浅拷贝到深拷贝。 目录 一、浅拷贝 1.1 clone 方法 1.2 实现浅拷贝&#xff1a; 1.2.1 重写 clone方法 1.2.2 实现接口 Cloneable 1.2.3 调用克隆方法 1.2.4 原理图&#xff1a;​ 1.3 浅拷贝的不足 1.3.1 增加引用…

JS听到了双生花的回响

日期对象 学会了日期对象可以让网页显示日期 是用来表示时间的对象&#xff0c;可以得到当前系统的时间 实例化 new关键字&#xff0c;就是实例化的代表 就比如说&#xff0c;你没有对象&#xff0c;但是你是程序员&#xff0c;这个时候你可以先定义一个类&#xff08;你的…

BUUCTF—Reverse—Java逆向解密(10)

程序员小张不小心弄丢了加密文件用的秘钥&#xff0c;已知还好小张曾经编写了一个秘钥验证算法&#xff0c;聪明的你能帮小张找到秘钥吗&#xff1f; 注意&#xff1a;得到的 flag 请包上 flag{} 提交 需要用专门的Java反编译软件:jd-gui 下载文件&#xff0c;发现是个class文…

mac上的建议xftp 工具

mac上的建议xftp 工具 最近使用mac比较频繁了&#xff0c;但是第一次重度使用mac里面有很多的工具都是新的&#xff0c;有的window版本的工具无法使用。 xftp 的平替 Cyberduck 从它的官网上下载是免费的&#xff0c;但是如果使用 Apple store 要花费198呢。这不就剩下一大笔…

【文献阅读】自动化构音障碍严重程度分类:声学特征与深度学习技术的研究

自动化构音障碍严重程度分类:声学特征与深度学习技术的研究 文章目录 自动化构音障碍严重程度分类:声学特征与深度学习技术的研究思维导图摘要I. 引言A. 动机与相关工作II. 数据库III. 实验设计A. 分析 MFCC 和 CQCCB. 分析语言障碍特定特征C. 分析 i-向量IV. 特征设计V. 分类…

基于HTML和CSS的校园网页设计与实现

摘要 随着计算机、互联网与通信技术的进步&#xff0c;Internet在人们的学习、工作和生活中的地位也变得越来越高&#xff0c;校园网站已经成为学校与学生&#xff0c;学生与学生之间交流沟通的重要平台&#xff0c;对同学了解学校内发生的各种事情起到了重要的作用。学校网站…

操作系统 | 学习笔记 | 王道 | 2.2处理机调度

2.2 处理机调度 文章目录 2.2 处理机调度2.2.1 调度的概念2.2.2 调度的目标2.2.3 调度的实现2.2.4 典型的调度算法错题总结&#xff1a; 2.2.1 调度的概念 调度的基本概念 处理机调度是对处理机进行分配&#xff0c;即从就绪队列中按照一定的算法&#xff08;公平、高效的原则&…

论文概览 |《Urban Analytics and City Science》2023.05 Vol.50 Issue.4

本次给大家整理的是《Environment and Planning B: Urban Analytics and City Science》杂志2023年5月第50卷第4期的论文的题目和摘要&#xff0c;一共包括19篇SCI论文&#xff01; 论文1 Data analytics and sustainable urban development in global cities 全球城市的数据…

【C++】优先队列(Priority Queue)全知道

亲爱的读者朋友们&#x1f603;&#xff0c;此文开启知识盛宴与思想碰撞&#x1f389;。 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 目录 一、前言 二、优先队列&#xff08;Priority Queue&#xff09…

服务熔断-熔断器设计

文章目录 服务为什么需要熔断熔断器设计思想熔断器代码实现 服务为什么需要熔断 对于服务端采用的保护机制为服务限流。 对于服务调用端是否存在保护机制&#xff1f; 假如要发布一个服务 B&#xff0c;而服务 B 又依赖服务 C&#xff0c;当一个服务 A 来调用服务 B 时&#x…

新能源汽车智慧充电桩管理方案:应用选型与充电协议应该怎么做?

新能源智慧充电桩平台采用虚拟化技术&#xff0c;使多种应用共享服务器、存储等硬件资源&#xff0c;可以帮助用户提供IT基础设施资源的利用效率&#xff0c;提升基础设施的应用和管理水平&#xff0c;实现计算资源的动态优化&#xff0c;使平台应用易维护、易扩充。 1、行业背…

SickOs: 1.1靶场学习小记

学习环境 kali攻击机&#xff1a;Get Kali | Kali Linux vulnhub靶场&#xff1a;https://download.vulnhub.com/sickos/sick0s1.1.7z 靶场描述&#xff1a; 这次夺旗赛清晰地模拟了在安全环境下如何对网络实施黑客策略从而入侵网络的过程。这个虚拟机与我在进攻性安全认证专…

[极客大挑战 2019]PHP--详细解析

信息搜集 想查看页面源代码&#xff0c;但是右键没有这个选项。 我们可以ctrlu或者在url前面加view-source:查看&#xff1a; 没什么有用信息。根据页面的hint&#xff0c;我们考虑扫一下目录看看能不能扫出一些文件. 扫到了备份文件www.zip&#xff0c;解压一下查看网站源代码…

python学习笔记 - python安装与环境变量配置

目录 前言1. 版本选择1.1 什么版本合适&#xff1f;1.2 版本越新越好吗&#xff1f;1.3 维护中的大版本里&#xff0c;选择最早的好吗&#xff1f;1.4 我的选择1.5 Python 发布周期1.6 Python维护中的版本及截止时间 2. 安装包下载2.1 官网地址2.2 下载安装包3. 环境安装3.1 新…

[Linux] 进程间通信——匿名管道命名管道

标题&#xff1a;[Linux] 进程间通信——匿名管道&&命名管道 水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 一、进程间通信 二、进程间通信的方案——匿名管道 &#xff08;1&#xff09;匿名管道的原理 &#xff08;2&#xff09;使用匿名管道 三、进…