文件
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;
}
效果图