Skip to content

Commit 06f97ac

Browse files
committed
fix(Calendar): fix multiple scene errors when value is combined with switch-mode
1 parent 51c0e2c commit 06f97ac

File tree

1 file changed

+65
-20
lines changed

1 file changed

+65
-20
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 || today;
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, today]);
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
}

0 commit comments

Comments
 (0)