react-日期选择器封装

news2025/2/28 15:57:04

文件

import { useMemo, useState, useEffect } from "react"
import dayjs, { Dayjs } from "dayjs"
import "dayjs/locale/zh-cn"
import "./App.css"
dayjs.locale("zh-cn")

function SimpleCalendar() {
  // 当前时间对象
  const [month, setMonth] = useState(dayjs())
  // 当前日期
  const [currentDate, setCurrentDate] = useState('')

  // 结束日期
  const [endDate, setEndDate] = useState<any>('')

  // 时间段
  const [perioDate, setPerioDate] = useState<String[]>()

  // 获取一个月得天数
  const getDaysOfMonth = (year: number, month: number) => {
    // 每个月得第一天
    let firstDayOfMonth = dayjs(`${year}-${month}-1`)
    // 每个月最后一天
    let lastDayOfMonth = dayjs(`${year}-${month + 1}-1`).subtract(1, "day")
    // 开始补全第一天前的日期
    while (firstDayOfMonth.day() !== 0) {
      firstDayOfMonth = firstDayOfMonth.subtract(1, "day")
    }

    // 开始补全最后一天后的日期
    while (lastDayOfMonth.day() !== 6) {
      lastDayOfMonth = lastDayOfMonth.add(1, "day")
    }

    const days = []
    let tempDate = firstDayOfMonth
    while (tempDate.isBefore(lastDayOfMonth) || tempDate.isSame(lastDayOfMonth)) {
      days.push(tempDate)
      tempDate = tempDate.add(1, "day")
    }

    return days
  }

  const days = useMemo(() => {
    return getDaysOfMonth(month.year(), month.month() + 1)
  }, [month])

  // 标题
  const weekTitles = useMemo(() => {
    return [...Array(7)].map((_, weekInx) => {
      return dayjs().day(weekInx)
    })
  }, [])

  // 月份修改
  const onMonthSwitch = (action: number) => {
    setMonth((month) => {
      return month.add(action, "month")
    })
  }

  // 判断选中是否为本月天数
  const selectDays = (monthDay: Dayjs) => {
    const dayTiem = monthDay.format('YYYY-MM-DD')
    // 获取当前月份的第一天
    const firstDay = month.startOf("month").format('YYYY-MM-DD')
    return dayTiem >= firstDay ? true : false
    // // 获取当前月份的总天数
    // const totalDays = firstDay.daysInMonth()

    // // 生成包含本月所有日期的数组
    // const allDaysArray = Array.from({ length: totalDays }, (_, index) =>
    //   firstDay.add(index, "day").format("YYYY-MM-DD")
    // )

    // 选中日期
    // const selectedDate = monthDay.format("YYYY-MM-DD")
    // return allDaysArray.includes(selectedDate)
  }
  // 设置开始结束日期
  const timePeriod = (day: Dayjs) => {
    const dayTime = day.format('YYYY-MM-DD')
    // 开始日期
    if (!currentDate) {
      setCurrentDate(day.format('YYYY-MM-DD'))
      console.log(dayTime)
      // 有开始日期没有结束日期
    } else if (currentDate && !endDate) {
      // 开始和结束同一天
      if (dayTime == currentDate) {
        setEndDate(dayTime)
      }
      // 结束日期比开始日期小的时候
      if (dayTime < currentDate) {
        setCurrentDate('')
        return
      }
      setEndDate(day.format('YYYY-MM-DD'))
      const daysDiff = day.diff(currentDate, 'day')
      // 中间日期添加样式
      const middleDates = []
      for (let i = 1; i < daysDiff; i++) {
        const middleDate = dayjs(currentDate).add(i, 'day')
        middleDates.push(middleDate.format('YYYY-MM-DD'))
      }
      middleDates.push(dayTime)

      setPerioDate(middleDates)
      // 开始和结束日期都有后清空
    } else if (currentDate && endDate) {
      setCurrentDate('')
      setEndDate('')
      setPerioDate([])
    }
  }

  return (
    <div className="App">
      <div className="calendar">
        <div className="calendar-month">
          <div className="calendar-month-switch" onClick={() => onMonthSwitch(-1)}>
            {"<"}
          </div>
          <div>{month.format("MMM YYYY")}</div>
          <div className="calendar-month-switch" onClick={() => onMonthSwitch(1)}>
            {">"}
          </div>
        </div>
        <div className="calendar-title">
          {weekTitles.map((title, index) => {
            return (
              <div key={index} className="calendar-week">
                {title.format("dd")}
              </div>
            )
          })}
        </div>
        <div className="calendar-content">
          {days.map((day: Dayjs, index) => {
            const dayTime = day.format('YYYY-MM-DD')

            const dynamicClassName = `calendar-day ${selectDays(day) ? 'thisMonth' : 'non'} ${dayTime == currentDate ? 'active' : ''} ${perioDate?.includes(dayTime) ? 'perioDate' : ''} `
            return (
              <div key={index} onClick={() => timePeriod(day)} className={dynamicClassName}>
                {day.format("DD")}
              </div>
            )
          })}
        </div>
      </div>
      <div>开始日期:{currentDate}</div>
      <div>结束日期:{endDate}</div>
    </div>
  )
}

export default SimpleCalendar

样式

.calendar {
  display: flex;
  flex-direction: column;
  width: 350px;
  height: 400px;
  font-size: 16px;
}

.calendar-month {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 350px;
  height: 44px;
  Margin-bottom: 16px
}

.calendar-month-switch {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  width: 44px;
  height: 44px;
  Background-color: white;
}
.calendar-month-switch:hover {
  background-color: #e6e6e6;
}

.calendar-title {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  padding-bottom: 8px;
}

.calendar-content {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
}

.calendar-week {
  display: flex;
  align-items: center;
  justify-content: center;
}

.calendar-day {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1;
  width: 50px;
  height: 36px;
  cursor: pointer;
}
.calendar-day:hover{
  background-color: #e6e6e6;
}

.non{
  cursor:not-allowed;
}

.active{
  background-color:#FFFF76;
}

.perioDate{
  background-color: #006EDC;
}

效果图

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数值计算方法】数值积分微分-python实现-p2

原文链接&#xff1a;https://www.cnblogs.com/aksoam/p/18279394 更多精彩&#xff0c;关注博客园主页&#xff0c;不断学习&#xff01;不断进步&#xff01; 我的主页 csdn很少看私信&#xff0c;有事请b站私信 博客园主页-发文字笔记-常用 有限元鹰的主页 内容&#xf…

基于ThinkPHP开发的校园跑腿社区小程序系统源码,包含前后端代码

基于ThinkPHP开发的校园跑腿社区小程序系统源码&#xff0c;包含前后端代码 最新独立版校园跑腿校园社区小程序系统源码 | 附教程 测试环境&#xff1a;NginxPHP7.2MySQL5.6 多校版本&#xff0c;多模块&#xff0c;适合跑腿&#xff0c;外卖&#xff0c;表白&#xff0c;二…

【Android】Kotlin 实现底部弹框日历组件

需求 如下图所示, 底部弹出日历组件 原生插件使用的有一个好处是可以根据你的系统语言切换插件内的语言, 刚好我们这个app面向的国外用户, 而产品对日历组件的日期显示有特别要求, 因此这无疑减少了我们切换语言的开发工作量 代码 1. custom_bottom_datepicker.xml <R…

Java小白入门到实战应用教程-权限修饰符

Java小白入门到实战应用教程-权限修饰符 前言 在前面的内容中我们其实已经接触到了权限修饰符&#xff1a;public 在java中权限修饰符除了public外&#xff0c;还有private、protected、默认权限。 权限修饰符可用来修饰类、成员变量、方法(函数)。 其中修饰类只能用publi…

springboot的表现层/控制层controller开发

第一步&#xff1a;新建文件和注入业务层对象 需要使用的注解&#xff1a; 第一个声明是restful风格开发 第二个是需要设置网页访问路径 RestController RequestMapping("/fuels")//http://localhost/fuels注入服务层对象&#xff1a; Autowiredprivate FuelServ…

晶振输出频率偏差过大的影响

晶体振荡器作为电子系统中的关键部件之一&#xff0c;其输出频率的准确性直接影响着整个系统的性能。无论是实时响应系统还是通信设备&#xff0c;都需要高度精确的频率源来维持其正常运作。本文将探讨晶振输出频率偏差过大会带来的影响&#xff0c;并简要介绍频率稳定性的概念…

【docker】下载docker 容器

1.下载地址&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/rhel/9/x86_64/stable/ 2.配置仓库拉取容器镜像 docker镜像 通过软件仓库下载但不安装 挂载并放入一个东西里面&#xff08;存放rpm软件包&#xff0c;并不是软件仓库&#xff09; 采集rpm数据的…

VSCode安装和配置

一、VScode下载和安装 下载 Visual Studio Code - Mac、Linux、Windows 下载完成之后傻瓜式安装即可 二、 左侧活动栏介绍 三、安装中文插件 先下载&#xff0c;在重启即可 四、配置C语言运行环境 1、Code Runner 记得勾选图中的两个选项 2、安装C/C插件 3、安装编译器MinGW…

cpp学习记录05:类和对象02

继承 面向对象的语法思想都差不多继承的好处就是方便 语法&#xff1a; class 子类 : 继承方式 父类 继承方式 公共继承&#xff1a;继承的内容权限不变 保护继承&#xff1a;继承的内容权限变为protected 私有继承&#xff1a;继承的内容权限变为private 这三类继承都不…

1000W长连接,如何建立和维护?千万用户IM 架构设计

1000W长连接&#xff0c;如何建立和维护&#xff1f;千万用户IM 架构设计 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的架构类/设计类…

哈夫曼树及哈夫曼编码

目录 一. 前言 二. 哈夫曼树的构造 三. 哈夫曼编码 一. 前言 在学习哈夫曼树之前&#xff0c;我们先了解几个基本概念。 1.路径&#xff1a;从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径。 2.结点的路径长度&#xff1a;两结点间路径上的分支数。 3.树的…

Visual Studio 2022 安装步骤

一、官方下载 下载地址&#xff1a;https://visualstudio.microsoft.com/zh-hans/vs/ 下载完成&#xff0c;得到VisualStudioSetup.exe文件 二、安装 Visual Studio 2022 由于我有 Professional 版本的密钥&#xff0c;因此安装Professional 版本。 Visual Studio 2022 Profes…

libtorch学习历程(一):libtorch2.4.0+opencv4.10+Qt6安装

开发环境 Win11RTX4060CUDA12.1libtorch 2.4.0 ,CUDA12.1,release版VS2022opencv4.10版本Qt 6.6.3 软件下载 libtorch下载 直接去pytorch官网下载即可&#xff0c;根据需要下载realease与debug版。 而CUDA的版本则查看CUDA版本教程&#xff0c;来选择合适的。 debug版与r…

大数据核心概念与技术架构简介

大数据基本概念 大数据是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。 大数据特征&#xff1a; 数据量大&#xff1a;一般以P&#xff08;1000个TB&a…

详解DDR3原理以及使用Xilinx MIG IP核(app 接口)实现DDR3读写测试

系列文章目录 &#xff08;1&#xff09;详解SDRAM基本原理以及FPGA实现读写控制 文章目录 系列文章目录一、DDR简介1.1 什么是 SDRAM、DDR、DDR2、DDR31.2 SDRAM、DDR、DDR2、DDR3核心频率、工作频率以及等效频率的计算1.3 DDR3带宽以及容量的计算 二、MIG IP核的介绍三、MIG…

Datawhale AI夏令营第三期 AI+物质科学学习记录 Task2 RNN建模SMILES进行反应产率预测

引导 如何将化学知识转化为计算机可识别的形式 提到化学应该会想到元素周期表&#xff0c;分子式&#xff0c;化学反应方程等等&#xff0c;化学这门学科的知识和内容都有专有符号记录的&#xff0c;但计算机不能理解&#xff0c;所以需要将这些符号让计算机能理解 Ai4Chemi…

python orm框架有哪些

ORM概念 ORM&#xff08;Object Ralational Mapping&#xff0c;对象关系映射&#xff09;用来把对象模型表示的对象映射到基于SQL的关系模型数据库结构中去。这样&#xff0c;我们在具体的操作实体对象的时候&#xff0c;就不需要再去和复杂的SQL语句打交道&#xff0c;只需简…

5 postgresql 并行查询

并行扫描会占用更多的cpu/IO内存资源&#xff0c;开启的时候要小心配置。 大部分场景都能提高查询效率 之前有过一个生产案例&#xff0c;开启并行之后性能反而没有普通的好&#xff0c;原因就是占有了太多资源&#xff0c;查询慢了&#xff0c;增加表锁概率&#xff0c;产生…

ISO 14001:引领企业绿色革命的环境管理体系

ISO 14001 以其预防为主、系统化管理的特点&#xff0c;在众多管理体系中脱颖而出。该标准强调通过识别和控制环境因素&#xff0c;提前预防潜在环境问题&#xff0c;从根本上减少企业对环境的负面影响。这种预防性管理模式&#xff0c;不仅能够有效保护环境&#xff0c;还能降…

.[datastore@cyberfear.com].mkp勒索病毒数据怎么处理|数据解密恢复

引言 近年来&#xff0c;网络安全威胁日益严峻&#xff0c;其中勒索病毒成为了一种极具破坏性的恶意软件。特别是[conkichinmodlconkichinmodl.com].mkp 、[datastorecyberfear.com].mkp勒索病毒&#xff0c;其通过加密用户文件并索取赎金的方式&#xff0c;给受害者带来了巨大…