react 项目,基于 Ant-Design 的 DatePicker 组件的二次封装,实现以下功能:
昨天,今天,上周,本周,上月,本月
时间范围快捷选择选择某天数范围之内的日期
,默认无限制某天以后的时间不能选择
,默认今天/**
* 日期选择组件
* - 设置只能选择limitDay天数范围之内的日期
* - 设置endOfDay以后的时间不能选择
*/
import React, { useState } from 'react'
import { DatePicker } from 'antd'
import 'moment/locale/zh-cn'
import locale from 'antd/lib/date-picker/locale/zh_CN'
import moment from 'moment'
import { cloneDeep } from 'lodash'
const RangeDatePicker = ({
value, // 日期
onChange, // 时间发生变化的回调,发生在用户选择时间时
showTime = false, // 是否增加时间选择功能(时分秒)
limitDay = 0, // 只能选择limitDay天数范围之内的日期,默认无限制
endOfDay = moment().endOf('day'), // endOfDay以后的时间不能选择,默认今天
...rest // 其他参数
}) => {
const { RangePicker } = DatePicker
const startOfDay = moment()
.subtract(limitDay, 'days')
.endOf('day') // 今天之前limitDay天
const [selectDate, setSelectDate] = useState([startOfDay, endOfDay])
const [selectvalue, setSelectValue] = useState([startOfDay, endOfDay])
// 不可选择的日期
const disabledTaskDate = current => {
let date = cloneDeep(selectDate)
if (selectDate && selectDate?.length > 0 && limitDay > 0) {
// 控制只能选择limitDay天数范围之内的日期
let startOfStage = date?.[1]?.subtract(limitDay, 'days').endOf('day')
let endOfStage = date?.[0]?.add(limitDay, 'days').endOf('day')
if (endOfStage > endOfDay) {
endOfStage = endOfDay
}
return current < startOfStage || current > endOfStage
} else {
// endOfDay以后的时间不能选择
return current > endOfDay
}
}
// 待选日期发生变化的回调
const onDateChange = dates => {
if (!dates || !dates?.length) return
setSelectDate([cloneDeep(dates?.[0]), cloneDeep(dates?.[1])])
}
// 弹出日历和关闭日历的回调
const onDateOpenChange = open => {
if (open) {
if (selectvalue && selectvalue?.length) return
setSelectDate([])
}
}
// 时间发生变化的回调
const onPickerChange = value => {
setSelectValue(value)
onChange(value)
}
// 获取预设时间范围快捷选择
const getRanges = () => {
// 今天
const toDayRange =
moment().startOf('day') <= endOfDay
? { 今天: [moment().startOf('day'), moment().endOf('day')] }
: {}
// 本周
const thisWeekRange =
moment().startOf('week') <= endOfDay ? { 本周: [moment().startOf('week'), endOfDay] } : {}
// 本月
const thisMonthRange =
moment().startOf('month') <= endOfDay ? { 本月: [moment().startOf('month'), endOfDay] } : {}
return {
// 昨天
昨天: [
moment()
.subtract(1, 'days')
.startOf('day'),
moment()
.subtract(1, 'days')
.endOf('day'),
],
// 今天
...toDayRange,
// 上周
上周: [
moment(new Date())
.subtract(1, 'week')
.startOf('week'),
moment(new Date())
.subtract(1, 'week')
.endOf('week'),
],
// 本周
...thisWeekRange,
// 上月
上月: [
moment(new Date())
.subtract(1, 'month')
.startOf('month'),
moment(new Date())
.subtract(1, 'month')
.endOf('month'),
],
// 本月
...thisMonthRange,
}
}
return (
<RangePicker
locale={locale} // 国际化配置(汉化)
getPopupContainer={triggerNode => triggerNode.parentNode} // 定义浮层的容器(解决选项框随页面滚动分离问题)
showTime={
showTime
? {
hideDisabledOptions: true, // 隐藏禁止选择的选项
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')], // 默认时间
}
: null
}
format={showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD'} // 日期格式
ranges={{
// 昨天: [
// moment()
// .subtract(1, 'days')
// .startOf('day'),
// moment()
// .subtract(1, 'days')
// .endOf('day'),
// ],
// 今天: [moment().startOf('day'), moment().endOf('day')],
// 上周: [
// moment(new Date())
// .subtract(1, 'week')
// .startOf('week'),
// moment(new Date())
// .subtract(1, 'week')
// .endOf('week'),
// ],
// 本周: [moment().startOf('week'), moment().endOf('week')],
// 上月: [
// moment(new Date())
// .subtract(1, 'month')
// .startOf('month'),
// moment(new Date())
// .subtract(1, 'month')
// .endOf('month'),
// ],
// 本月: [moment().startOf('month'), moment().endOf('month')],
...getRanges(),
}}
value={value} // 日期
onChange={onPickerChange} // 时间发生变化的回调
disabledDate={disabledTaskDate} // 不可选择的日期
onCalendarChange={onDateChange} // 待选日期发生变化的回调
onOpenChange={onDateOpenChange} // 弹出日历和关闭日历的回调
{...rest}
/>
)
}
export default RangeDatePicker
import RangeDatePicker from '@/components/RangeDatePicker'
......
<RangeDatePicker onChange={() => {}} />
import RangeDatePicker from '@/components/RangeDatePicker'
......
<RangeDatePicker showTime={true} onChange={() => {}} />
import RangeDatePicker from '@/components/RangeDatePicker'
......
// 只能选择7天数范围之内的日期
<RangeDatePicker limitDay={7} onChange={() => {}} />
import RangeDatePicker from '@/components/RangeDatePicker'
......
// 昨天以后的时间不能选择
<RangeDatePicker endOfDay={moment().subtract(1, 'days').endOf('day')} onChange={() => {}} />