From ce2a2e1029dd8f8ebca92d360a15a37d0ebbdbda Mon Sep 17 00:00:00 2001 From: Tinsson <695724046@qq.com> Date: Fri, 11 Oct 2024 17:40:44 +0800 Subject: [PATCH] fix(date-range-quick-picker): support the time disabled of props (min, max) (#2070) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 修复DateRangeQuickPicker的min和max对时间不生效问题 Co-authored-by: daitingyuan --- .../date-range-quick-picker.spec.jsx | 21 ++++- .../components/RangePickerBase.tsx | 9 ++- .../hooks/useNormalizeDisabledTime.ts | 16 ++++ .../utils/unifiedDisabledTimeFromProps.ts | 77 +++++++++++++++++++ 4 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 packages/zent/src/date-picker/hooks/useNormalizeDisabledTime.ts create mode 100644 packages/zent/src/date-picker/utils/unifiedDisabledTimeFromProps.ts diff --git a/packages/zent/__tests__/date-range-quick-picker.spec.jsx b/packages/zent/__tests__/date-range-quick-picker.spec.jsx index 30d9efb7f2..1294030b4a 100644 --- a/packages/zent/__tests__/date-range-quick-picker.spec.jsx +++ b/packages/zent/__tests__/date-range-quick-picker.spec.jsx @@ -36,30 +36,47 @@ describe('DateRangeQuickPicker', () => { value={[1524106071377, 1524107071377]} onChange={onChange} valueType="number" + format="YYYY-MM-DD HH:mm:ss" + min="2020-04-19 10:05:12" + max="2025-01-01 12:05:12" /> ); wrapper.instance().handleChosenDays(1); expect(onChange.mock.calls.length).toBe(1); + wrapper.find('.zent-datepicker-trigger').at(1).simulate('click'); }); it('suppports default preset', () => { const onChange = jest.fn(); - mount( + const wrapper = mount( ); expect(onChange.mock.calls.length).toBe(0); + wrapper.find('.zent-datepicker-trigger').at(0).simulate('click'); - mount( + const wrapper2 = mount( { + return { + disabledHours: () => [], + disabledMinutes: () => [], + disabledSeconds: () => [], + }; + }} /> ); expect(onChange.mock.calls.length).toBe(1); + wrapper2.find('.zent-datepicker-trigger').at(1).simulate('click'); }); }); diff --git a/packages/zent/src/date-picker/components/RangePickerBase.tsx b/packages/zent/src/date-picker/components/RangePickerBase.tsx index 2126cd9712..61f4a4d7a2 100644 --- a/packages/zent/src/date-picker/components/RangePickerBase.tsx +++ b/packages/zent/src/date-picker/components/RangePickerBase.tsx @@ -6,6 +6,7 @@ import useRangeMergedProps from '../hooks/useRangeMergedProps'; import useRangeDisabledDate from '../hooks/useRangeDisabledDate'; import { useShowTimeRangeOption } from '../hooks/useShowTimeOption'; import useNormalizeDisabledDate from '../hooks/useNormalizeDisabledDate'; +import useNormalizeDisabledTime from '../hooks/useNormalizeDisabledTime'; import { useEventCallbackRef } from '../../utils/hooks/useEventCallbackRef'; import { @@ -46,7 +47,7 @@ const RangePicker: React.FC = ({ onChange, onClose, onOpen, - disabledTime, + disabledTime: disabledTimeProps, generateDate, PickerComponent, showTime, @@ -104,6 +105,12 @@ const RangePicker: React.FC = ({ [start, end, showTime, onChangeRef, getCallbackRangeValue, setSelected] ); + const disabledTime = useNormalizeDisabledTime( + format, + disabledDateProps, + disabledTimeProps + ); + const { disabledStartTimes, disabledEndTimes } = useRangeDisabledTime({ selected, disabledTime, diff --git a/packages/zent/src/date-picker/hooks/useNormalizeDisabledTime.ts b/packages/zent/src/date-picker/hooks/useNormalizeDisabledTime.ts new file mode 100644 index 0000000000..e9fb6b3e0c --- /dev/null +++ b/packages/zent/src/date-picker/hooks/useNormalizeDisabledTime.ts @@ -0,0 +1,16 @@ +import { useCallback } from 'react'; +import { IDisabledTime, IDisabledDate } from '../types'; +import unifiedDisabledTimeFromProps from '../utils/unifiedDisabledTimeFromProps'; + +export default function useNormalizeDisabledTime( + format: string, + disabledDate: IDisabledDate, + disabledTime: IDisabledTime +) { + // eslint-disable-next-line react-hooks/exhaustive-deps + const normalizedDisabledTime = useCallback( + unifiedDisabledTimeFromProps(format, disabledDate, disabledTime), + [disabledDate, format, disabledTime] + ); + return normalizedDisabledTime; +} diff --git a/packages/zent/src/date-picker/utils/unifiedDisabledTimeFromProps.ts b/packages/zent/src/date-picker/utils/unifiedDisabledTimeFromProps.ts new file mode 100644 index 0000000000..e5ebcb5dfc --- /dev/null +++ b/packages/zent/src/date-picker/utils/unifiedDisabledTimeFromProps.ts @@ -0,0 +1,77 @@ +import { endOfDay, isAfter, isBefore, startOfDay, isSameDay } from 'date-fns'; +import { parseBase } from './index'; +import { IDisabledDate, IDisabledTime, IDisabledDateSimple } from '../types'; + +function generateNumberArray(max) { + return Array.from({ length: max + 1 }, (_, i) => i); +} + +/** + * props的DisabledDate参数 支持 {min, max} 格式 + * 内部统一转成方法-输出disabledTime + * @param format + * @param disabledDateProps + * @param disabledTime + */ +export default function unifiedDisabledDateFromProps( + format: string, + disabledDateProps: IDisabledDate, + disabledTime: IDisabledTime +): IDisabledTime { + if (typeof disabledTime === 'function') { + return disabledTime; + } + if (typeof disabledDateProps === 'object') { + const { min, max } = disabledDateProps as IDisabledDateSimple; + const disabledDate = (date: Date) => + (!!min && isBefore(endOfDay(date), parseBase(min, format))) || + (!!max && isAfter(startOfDay(date), parseBase(max, format))); + return (date: Date) => { + const isDateDisabled = disabledDate(date); + if (isDateDisabled) { + return { + disabledHours: () => generateNumberArray(23), + disabledMinutes: () => generateNumberArray(59), + disabledSeconds: () => generateNumberArray(59), + }; + } + if (!!min && isSameDay(endOfDay(date), parseBase(min, format))) { + // 如果是min当天,那么只有min之前的时间是disabled的 + const minDate = parseBase(min, format); + return { + disabledHours: () => generateNumberArray(minDate.getHours() - 1), + disabledMinutes: (hour: number) => + hour === minDate.getHours() + ? generateNumberArray(minDate.getMinutes() - 1) + : [], + disabledSeconds: (hour: number, minute: number) => + hour === minDate.getHours() && minute === minDate.getMinutes() + ? generateNumberArray(minDate.getSeconds() - 1) + : [], + }; + } + if (!!max && isSameDay(startOfDay(date), parseBase(max, format))) { + // 如果是max当天,那么只有max之后的时间是disabled的 + const maxDate = parseBase(max, format); + return { + disabledHours: () => + generateNumberArray(23).slice(maxDate.getHours() + 1), + disabledMinutes: (hour: number) => + hour === maxDate.getHours() + ? generateNumberArray(59).slice(maxDate.getMinutes() + 1) + : [], + disabledSeconds: (hour: number, minute: number) => + hour === maxDate.getHours() && minute === maxDate.getMinutes() + ? generateNumberArray(59).slice(maxDate.getSeconds() + 1) + : [], + }; + } + return { + disabledHours: () => [], + disabledMinutes: () => [], + disabledSeconds: () => [], + }; + }; + } + return disabledTime; +}