Skip to content

Commit d4a4a78

Browse files
authored
fix(Calendar): fx multiple scene errors when value is combined with switch-mode (#832)
* fix(Calendar): fix multiple scene errors when value is combined with switch-mode * fix: fix unit test * fix: fix cr
1 parent 7aa1eb4 commit d4a4a78

File tree

2 files changed

+67
-22
lines changed

2 files changed

+67
-22
lines changed

src/calendar/CalendarTemplate.tsx

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import classNames from 'classnames';
1010

1111
import parseTNode from '../_util/parseTNode';
1212
import { Button, ButtonProps } from '../button';
13-
import { TDateType, CalendarValue } from './type';
13+
import { TDateType, CalendarValue, TCalendarValue } from './type';
1414
import { usePrefixClass } from '../hooks/useClass';
1515
import useDefaultProps from '../hooks/useDefaultProps';
1616
import { calendarDefaultProps } from './defaultProps';
@@ -46,27 +46,67 @@ const CalendarTemplate = forwardRef<HTMLDivElement, CalendarProps>((_props, ref)
4646
});
4747
const firstDayOfWeek = props.firstDayOfWeek || 0;
4848

49-
useEffect(() => {
50-
if (Array.isArray(props.value)) {
51-
setSelectedDate(props.value?.map((item) => new Date(item)));
52-
} else if (props.value) {
53-
setSelectedDate(new Date(props.value));
54-
} else {
55-
setSelectedDate(props.type === 'multiple' ? [new Date()] : new Date());
56-
}
57-
}, [props.type, props.value]);
58-
5949
const getYearMonthDay = (date: Date) => ({
6050
year: date.getFullYear(),
6151
month: date.getMonth(),
6252
date: date.getDate(),
6353
});
6454

65-
const today = new Date();
66-
const minDate = props.minDate ? new Date(props.minDate) : today;
67-
const maxDate = props.maxDate
68-
? new Date(props.maxDate)
69-
: new Date(today.getFullYear(), today.getMonth() + 6, today.getDate());
55+
const today = useMemo(() => new Date(), []);
56+
const minDate = useMemo(() => (props.minDate ? new Date(props.minDate) : today), [props.minDate, today]);
57+
const maxDate = useMemo(
58+
() =>
59+
props.maxDate ? new Date(props.maxDate) : new Date(today.getFullYear(), today.getMonth() + 6, today.getDate()),
60+
[props.maxDate, today],
61+
);
62+
63+
const dateTypeHandler = useMemo(() => {
64+
const now = minDate;
65+
66+
const createRangePair = (baseDate: Date): [Date, Date] =>
67+
props.allowSameDay ? [baseDate, baseDate] : [baseDate, new Date(baseDate.getTime() + 24 * 3600 * 1000)];
68+
69+
const convertToDateArray = (value: TCalendarValue[]): Date[] => value.map((item) => new Date(item));
70+
71+
return {
72+
// 初始化空日期
73+
initialize: {
74+
single: () => now,
75+
multiple: () => [now],
76+
range: () => createRangePair(now),
77+
},
78+
// 转换已有值
79+
transform: {
80+
single: (value: TCalendarValue): Date => new Date(value),
81+
82+
multiple: (value: TCalendarValue[]): Date[] => {
83+
const dates = convertToDateArray(value);
84+
return dates.length ? dates : [now];
85+
},
86+
range: (value: TCalendarValue[]): Date[] => {
87+
const dates = convertToDateArray(value);
88+
// 传入值为空数组或只有一个值时
89+
if (dates.length <= 1) {
90+
return createRangePair(dates[0] || now);
91+
}
92+
return dates;
93+
},
94+
},
95+
};
96+
}, [props.allowSameDay, minDate]);
97+
98+
useEffect(() => {
99+
if (!props.value) {
100+
setSelectedDate(dateTypeHandler.initialize[props.type]?.());
101+
} else {
102+
const d =
103+
props.type === 'single'
104+
? dateTypeHandler.transform.single?.(props.value as TCalendarValue)
105+
: dateTypeHandler.transform[props.type]?.(props.value as TCalendarValue[]);
106+
107+
setSelectedDate(d);
108+
}
109+
}, [props.type, props.value, dateTypeHandler]);
70110

71111
const days = useMemo(() => {
72112
const raw = local.weekdays;
@@ -251,13 +291,18 @@ const CalendarTemplate = forwardRef<HTMLDivElement, CalendarProps>((_props, ref)
251291
switch (props.type) {
252292
case 'range': {
253293
if (Array.isArray(selectedDate)) {
254-
if (selectedDate.length === 1 && selected >= selectedDate[0]) {
255-
newSelected = selectedDate[0] > selected ? [selected] : [selectedDate[0], selected];
294+
if (selectedDate.length === 1) {
295+
const firstDate = selectedDate[0];
296+
if (selected.getTime() === new Date(firstDate).getTime()) {
297+
newSelected = props.allowSameDay ? [firstDate, selected] : [selected];
298+
} else if (selected < firstDate) {
299+
newSelected = [selected];
300+
} else {
301+
newSelected = [firstDate, selected];
302+
}
256303
} else {
257304
newSelected = [selected];
258305
}
259-
} else {
260-
newSelected = [selected];
261306
}
262307
break;
263308
}

src/calendar/__tests__/calendar.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ describe('Calendar', () => {
164164
const minDate = new Date(2022, 0, 1);
165165
const maxDate = new Date(2022, 1, 1);
166166

167-
const value = new Date(2022, 0, 15);
167+
const value = [new Date(2022, 0, 15)];
168168
const { rerender } = render(
169169
<Calendar visible value={value} minDate={minDate} maxDate={maxDate} onSelect={onSelect} />,
170170
);
@@ -266,7 +266,7 @@ describe('Calendar', () => {
266266

267267
it(':select', () => {
268268
const onSelect = vi.fn();
269-
const value = new Date(2022, 0, 1);
269+
const value = [new Date(2022, 0, 1)];
270270
const minDate = new Date(2022, 0, 1);
271271
const maxDate = new Date(2022, 1, 1);
272272

0 commit comments

Comments
 (0)