修改日历组件

This commit is contained in:
筱野
2025-09-07 20:26:32 +08:00
parent f503bf53ac
commit 549f704c53
22 changed files with 1057 additions and 563 deletions

View File

@@ -0,0 +1,151 @@
import React, { useState, useEffect, useRef } from 'react'
import CommonPopup from '@/components/CommonPopup'
import { View } from '@tarojs/components'
import CalendarUI, { CalendarUIRef } from '@/components/Picker/CalendarUI/CalendarUI'
import { PickerCommon, PickerCommonRef } from '@/components/Picker'
import dayjs from 'dayjs'
import styles from './index.module.scss'
export interface DialogCalendarCardProps {
value?: Date
onChange?: (date: Date) => void
visible: boolean
onClose: () => void
title?: React.ReactNode
}
const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
visible,
onClose,
title,
value,
onChange,
}) => {
const [selected, setSelected] = useState<Date>(value || new Date())
const calendarRef = useRef<CalendarUIRef>(null);
const [type, setType] = useState<'year' | 'month' | 'time'>('year');
const [selectedHour, setSelectedHour] = useState(8)
const [selectedMinute, setSelectedMinute] = useState(0)
const pickerRef = useRef<PickerCommonRef>(null);
const hourMinutePickerRef = useRef<PickerCommonRef>(null);
const [pendingJump, setPendingJump] = useState<{ year: number; month: number } | null>(null)
const handleConfirm = () => {
if (type === 'year') {
// 年份选择完成后,进入月份选择
setType('time')
} else if (type === 'month') {
// 月份选择完成后,进入时间选择
const value = pickerRef.current?.getValue()
if (value) {
const year = value[0] as number
const month = value[1] as number
setSelected(new Date(year, month - 1, 1))
setPendingJump({ year, month })
}
setType('year')
} else if (type === 'time') {
// 时间选择完成后调用onNext回调
const value = hourMinutePickerRef.current?.getValue()
if (value) {
const hour = value[0] as number
const minute = value[1] as number
setSelectedHour(hour)
setSelectedMinute(minute)
const finalDate = new Date(dayjs(selected).format('YYYY-MM-DD') + ' ' + hour + ':' + minute)
if (onChange) onChange(finalDate)
}
onClose()
}
}
const handleChange = (d: Date | Date[]) => {
if (Array.isArray(d)) {
setSelected(d[0])
} else {
setSelected(d)
}
}
const onHeaderClick = (date: Date) => {
setSelected(date)
setType('month')
}
const getConfirmText = () => {
if (type === 'time' || type === 'month') return '完成'
return '下一步'
}
const handleDateTimePickerChange = (value: (string | number)[]) => {
const year = value[0] as number
const month = value[1] as number
setSelected(new Date(year, month - 1, 1))
}
const dialogClose = () => {
if (type === 'month') {
setType('year')
} else if (type === 'time') {
setType('year')
} else {
onClose()
}
}
useEffect(() => {
if (visible && value) {
setSelected(value || new Date())
setSelectedHour(value ? dayjs(value).hour() : 8)
setSelectedMinute(value ? dayjs(value).minute() : 0)
}
}, [value, visible])
useEffect(() => {
if (type === 'year' && pendingJump && calendarRef.current) {
calendarRef.current.jumpTo(pendingJump.year, pendingJump.month)
setPendingJump(null)
}
}, [type, pendingJump])
return (
<CommonPopup
visible={visible}
onClose={dialogClose}
showHeader={!!title}
title={title}
hideFooter={false}
cancelText='取消'
confirmText={getConfirmText()}
onConfirm={handleConfirm}
position='bottom'
round
zIndex={1000}
>
{
type === 'year' &&
<View className={styles['calendar-container']}>
<CalendarUI
ref={calendarRef}
value={selected}
onChange={handleChange}
showQuickActions={false}
onHeaderClick={onHeaderClick}
/></View>
}
{
type === 'month' && <PickerCommon
ref={pickerRef}
onChange={handleDateTimePickerChange}
type="month"
value={[selected.getFullYear(), selected.getMonth() + 1]}
/>
}
{
type === 'time' && <PickerCommon
ref={hourMinutePickerRef}
type="hour"
value={[selectedHour, selectedMinute]}
/>
}
</CommonPopup>
)
}
export default DialogCalendarCard