Antd DatePicker之旬查询(本月上旬、本月中旬、本月下旬)

需求

实现旬查询,本月上旬为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;

效果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值