需求
实现旬查询,本月上旬为1-10号,本月中旬11-20号,本月下旬21-月底
由于Antd 3.x 的RangePicker没有上月、下月、上年、下年的点击回调,我不能判断当前是哪年哪月,时间范围快捷选择不能动态改变,所以我用监听DOM节点实现
代码
.main-container {
:global {
/* 禁用日历日期的点击 */
.ant-calendar-tbody {
pointer-events: none;
}
// 月选择器可以选下月,禁用
.ant-calendar-month-panel-current-cell + .ant-calendar-month-panel-cell {
pointer-events: none;
.ant-calendar-month-panel-month {
color: rgba(0, 0, 0, 0.25);
background: #f5f5f5;
}
}
/* 隐藏右边日历 上月、下月、上年、下年按钮, 禁用 年选择器、月选择器 的点击 */
.ant-calendar-range-right {
.ant-calendar-next-month-btn {
display: none;
//pointer-events: none;
}
.ant-calendar-next-year-btn {
display: none;
//pointer-events: none;
}
.ant-calendar-prev-year-btn {
display: none;
//pointer-events: none;
}
.ant-calendar-prev-month-btn {
display: none;
//pointer-events: none;
}
.ant-calendar-year-select, .ant-calendar-month-select {
pointer-events: none;
color: rgba(0, 0, 0, 0.25);
}
}
}
}
import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { DatePicker } from 'antd';
import styles from './index.less'
/**
* Created by yjl on 2021-08-19
* 旬选择器(本月上旬、本月中旬、本月下旬)
* */
const XunPicker = (props) => {
const { colName, form } = props;
const [currentTime, setCurrentTime] = useState();
const [pickerValue, setPickerValue] = useState();
const ObserverRef = useRef(null);
useEffect(() => {
// 监听dom节点改变,下月、下年按钮要在上月、上年按钮点击后才显示
ObserverRef.current = new MutationObserver(() => {
observerDomChange();
});
return () => ObserverRef.current.disconnect();
}, []);
const addListener = (status) => {
if (status) {
// 日期归位,当前月和下月,因为左边面板日期不能大于右边面板日期
if (pickerValue) {
setPickerValue([moment(), moment().add(1, 'month')]);
setTimeout(() => {
setPickerValue([undefined, undefined])
setCurrentTime(undefined);
})
}
// 日历面板打开时,节点尚未渲染完毕,所以要延时
setTimeout(() => {
const leftCalendar = document.querySelector(`.ant-calendar-range-part.ant-calendar-range-left`);
ObserverRef.current.observe(leftCalendar, {
childList: true,
subtree: true
});
observerDomChange();
});
}
};
const observerDomChange = () => {
const prevMonth = document.querySelector('.ant-calendar-range-left .ant-calendar-prev-month-btn') || {};
const nextMonth = document.querySelector('.ant-calendar-range-left .ant-calendar-next-month-btn') || {};
const prevYear = document.querySelector('.ant-calendar-range-left .ant-calendar-prev-year-btn') || {};
const nextYear = document.querySelector('.ant-calendar-range-left .ant-calendar-next-year-btn') || {};
prevMonth.onclick = () => handleDateChange('prevMonth');
nextMonth.onclick = () => handleDateChange('nextMonth');
prevYear.onclick = () => handleDateChange('prevYear');
nextYear.onclick = () => handleDateChange('nextYear');
};
const handleDateChange = (type) => {
if (type === 'prevMonth') {
setCurrentTime((prevValue) => moment(prevValue).subtract(1, 'month'));
}
else if (type === 'nextMonth') {
setCurrentTime((prevValue) => moment(prevValue).add(1, 'month'));
}
else if (type === 'prevYear') {
setCurrentTime((prevValue) => moment(prevValue).subtract(1, 'years'));
}
else if (type === 'nextYear') {
setCurrentTime((prevValue) => moment(prevValue).add(1, 'years'));
}
};
return (
<DatePicker.RangePicker
disabledDate={(current) => current > moment().endOf('month')}
dropdownClassName={styles['main-container']}
value={pickerValue}
onOk={(dates) => {
setPickerValue(dates);
form.setFieldsValue({
[colName]: dates
})
}}
onPanelChange={(dates) => {
setCurrentTime(dates[0] > moment().endOf('month') ? moment() : dates[0])
}}
onOpenChange={(status) => addListener(status)}
ranges={{
'本月上旬': [moment(currentTime).startOf('month'), moment(currentTime).startOf('month').add(9, 'day')],
'本月中旬': [moment(currentTime).startOf('month').add(10, 'day'), moment(currentTime).startOf('month').add(19, 'day')],
'本月下旬': [moment(currentTime).startOf('month').add(20, 'day'), moment(currentTime).endOf('month')]
}}
/>
)
}
XunPicker.propTypes = {
form: PropTypes.object.isRequired, // 表单form对象
colName: PropTypes.string.isRequired // 表单字段名
}
export default XunPicker;
效果
