日期范围选择组件

This commit is contained in:
2025-09-25 00:10:24 +08:00
parent dd1136d1e6
commit d99d3d87a9
4 changed files with 374 additions and 258 deletions

View File

@@ -6,7 +6,7 @@ import { PickerCommon, PickerCommonRef } from '@/components/Picker'
import dayjs from 'dayjs'
import styles from './index.module.scss'
export interface DialogCalendarCardProps {
value?: Date
value?: Date | Date[]
searchType?: 'single' | 'range' | 'multiple'
onChange?: (date: Date | Date[]) => void
visible: boolean
@@ -22,7 +22,7 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
value,
onChange,
}) => {
const [selected, setSelected] = useState<Date>(value || new Date())
const [selected, setSelected] = useState<Date | Date[]>(value || new Date())
const calendarRef = useRef<CalendarUIRef>(null);
const [type, setType] = useState<'year' | 'month' | 'time'>('year');
const [selectedHour, setSelectedHour] = useState(8)
@@ -32,6 +32,11 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
const [pendingJump, setPendingJump] = useState<{ year: number; month: number } | null>(null)
const handleConfirm = () => {
if (type === 'year') {
if (searchType === 'range') {
if (onChange) onChange(selected);
onClose();
return;
}
// 年份选择完成后,进入月份选择
setType('time')
} else if (type === 'month') {
@@ -40,7 +45,13 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
if (value) {
const year = value[0] as number
const month = value[1] as number
setSelected(new Date(year, month - 1, 1))
if (searchType === 'range') {
const delta = calculateMonthDifference(selected as Date, new Date(year, month - 1, 1))
console.log('xxxxx', calendarRef.current)
calendarRef.current?.gotoMonth(delta)
} else {
setSelected(new Date(year, month - 1, 1))
}
setPendingJump({ year, month })
}
setType('year')
@@ -54,18 +65,31 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
setSelectedMinute(minute)
const hours = hour.toString().padStart(2, '0')
const minutes = minute.toString().padStart(2, '0')
const finalDate = new Date(dayjs(selected).format('YYYY-MM-DD') + ' ' + hours + ':' + minutes)
const finalDate = new Date(dayjs(selected as Date).format('YYYY-MM-DD') + ' ' + hours + ':' + minutes)
if (onChange) onChange(finalDate)
}
onClose()
}
}
const calculateMonthDifference = (date1, date2) => {
if (!(date1 instanceof Date) || !(date2 instanceof Date)) {
throw new Error('Both arguments must be Date objects');
}
let months = (date2.getFullYear() - date1.getFullYear()) * 12;
months -= date1.getMonth();
months += date2.getMonth();
return months;
}
const handleChange = (d: Date | Date[]) => {
console.log('handleChange', d)
if (searchType === 'range') {
if (Array.isArray(d)) {
if (d.length === 2) {
onChange?.(d as Date[])
setSelected(d as Date[])
return
}
}
@@ -77,6 +101,7 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
}
}
const onHeaderClick = (date: Date) => {
console.log('onHeaderClick', date)
setSelected(date)
setType('month')
}
@@ -101,8 +126,8 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
useEffect(() => {
if (visible && value) {
setSelected(value || new Date())
setSelectedHour(value ? dayjs(value).hour() : 8)
setSelectedMinute(value ? dayjs(value).minute() : 0)
setSelectedHour(value ? dayjs(value as Date).hour() : 8)
setSelectedMinute(value ? dayjs(value as Date).minute() : 0)
}
}, [value, visible])
@@ -132,32 +157,32 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
{
type === 'year' &&
<View className={styles['calendar-container']}>
<CalendarUI
ref={calendarRef}
type={searchType}
value={selected}
onChange={handleChange}
showQuickActions={false}
onHeaderClick={onHeaderClick}
/></View>
<CalendarUI
ref={calendarRef}
type={searchType}
value={selected}
onChange={handleChange}
showQuickActions={false}
onHeaderClick={onHeaderClick}
/></View>
}
{
{
type === 'month' && <PickerCommon
ref={pickerRef}
onChange={handleDateTimePickerChange}
type="month"
value={[selected.getFullYear(), selected.getMonth() + 1]}
value={[(selected as Date).getFullYear(), (selected as Date).getMonth() + 1]}
/>
}
{
}
{
type === 'time' && <PickerCommon
ref={hourMinutePickerRef}
type="hour"
value={[selectedHour, selectedMinute]}
/>
ref={hourMinutePickerRef}
type="hour"
value={[selectedHour, selectedMinute]}
/>
}
}
</CommonPopup>
)
}