This commit is contained in:
2025-09-25 17:39:03 +08:00
parent 4686812653
commit 19a51fc679
3 changed files with 413 additions and 312 deletions

View File

@@ -1,17 +1,19 @@
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'
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 | Date[]
searchType?: 'single' | 'range' | 'multiple'
onChange?: (date: Date | Date[]) => void
visible: boolean
onClose: () => void
title?: React.ReactNode
value?: Date | Date[];
searchType?: "single" | "range" | "multiple";
onChange?: (date: Date | Date[]) => void;
visible: boolean;
onClose: () => void;
title?: React.ReactNode;
}
const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
@@ -22,61 +24,73 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
value,
onChange,
}) => {
const [selected, setSelected] = useState<Date | Date[]>(value || new Date())
const [selected, setSelected] = useState<Date | Date[]>(value || new Date());
const [selectedBackup, setSelectedBackup] = useState<Date[]>(
Array.isArray(value) ? [...(value as Date[])] : [value as 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 [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 [pendingJump, setPendingJump] = useState<{
year: number;
month: number;
} | null>(null);
const handleConfirm = () => {
if (type === 'year') {
if (searchType === 'range') {
if (type === "year") {
if (searchType === "range") {
if (onChange) onChange(selected);
onClose();
return;
}
// 年份选择完成后,进入月份选择
setType('time')
} else if (type === 'month') {
setType("time");
} else if (type === "month") {
// 月份选择完成后,进入时间选择
const value = pickerRef.current?.getValue()
const value = pickerRef.current?.getValue();
if (value) {
const year = value[0] as number
const month = value[1] as number
if (searchType === 'range') {
const delta = calculateMonthDifference(selected as Date, new Date(year, month - 1, 1))
console.log('xxxxx', calendarRef.current)
setTimeout(() => {
calendarRef.current?.gotoMonth(delta)
}, 50)
} else {
setSelected(new Date(year, month - 1, 1))
const year = value[0] as number;
const month = value[1] as number;
setPendingJump({ year, month });
setType("year");
if (searchType === "range") {
const delta = calculateMonthDifference(
selected as Date,
new Date(year, month - 1, 1)
);
calendarRef.current?.gotoMonth(delta);
return;
}
setPendingJump({ year, month })
setSelected(new Date(year, month - 1, 1));
}
setType('year')
} else if (type === 'time') {
} else if (type === "time") {
// 时间选择完成后调用onNext回调
const value = hourMinutePickerRef.current?.getValue()
const value = hourMinutePickerRef.current?.getValue();
if (value) {
const hour = value[0] as number
const minute = value[1] as number
setSelectedHour(hour)
setSelectedMinute(minute)
const hours = hour.toString().padStart(2, '0')
const minutes = minute.toString().padStart(2, '0')
const finalDate = new Date(dayjs(selected as Date).format('YYYY-MM-DD') + ' ' + hours + ':' + minutes)
if (onChange) onChange(finalDate)
const hour = value[0] as number;
const minute = value[1] as number;
setSelectedHour(hour);
setSelectedMinute(minute);
const hours = hour.toString().padStart(2, "0");
const minutes = minute.toString().padStart(2, "0");
const finalDate = new Date(
dayjs(selected as Date).format("YYYY-MM-DD") +
" " +
hours +
":" +
minutes
);
if (onChange) onChange(finalDate);
}
onClose()
onClose();
}
}
};
const calculateMonthDifference = (date1, date2) => {
if (!(date1 instanceof Date) || !(date2 instanceof Date)) {
throw new Error('Both arguments must be Date objects');
throw new Error("Both arguments must be Date objects");
}
let months = (date2.getFullYear() - date1.getFullYear()) * 12;
@@ -84,63 +98,76 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
months += date2.getMonth();
return months;
}
};
const handleChange = (d: Date | Date[]) => {
console.log('handleChange', d)
if (searchType === 'range') {
if (searchType === "range") {
if (Array.isArray(d)) {
if (d.length === 2) {
setSelected(d as Date[])
return
return;
} else if (d.length === 1) {
debugger;
if (selectedBackup.length === 0 || selectedBackup.length === 2) {
setSelected([]);
setSelectedBackup([...d]);
} else {
setSelected(
[...selectedBackup, d[0]].sort(
(a, b) => a.getTime() - b.getTime()
)
);
setSelectedBackup([]);
}
}
return;
}
}
if (Array.isArray(d)) {
setSelected(d[0])
setSelected(d[0]);
} else {
setSelected(d)
setSelected(d);
}
}
};
const onHeaderClick = (date: Date) => {
console.log('onHeaderClick', date)
setSelected(date)
setType('month')
}
console.log("onHeaderClick", date);
setSelected(date);
setType("month");
};
const getConfirmText = () => {
if (type === 'time' || type === 'month') return '完成'
return '下一步'
}
if (type === "time" || type === "month" || searchType === "range")
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 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')
if (type === "month") {
setType("year");
} else if (type === "time") {
setType("year");
} else {
onClose()
onClose();
}
}
};
useEffect(() => {
if (visible && value) {
setSelected(value || new Date())
setSelectedHour(value ? dayjs(value as Date).hour() : 8)
setSelectedMinute(value ? dayjs(value as Date).minute() : 0)
setSelected(value || new Date());
setSelectedHour(value ? dayjs(value as Date).hour() : 8);
setSelectedMinute(value ? dayjs(value as Date).minute() : 0);
}
}, [value, visible])
}, [value, visible]);
useEffect(() => {
if (type === 'year' && pendingJump && calendarRef.current) {
calendarRef.current.jumpTo(pendingJump.year, pendingJump.month)
setPendingJump(null)
if (type === "year" && pendingJump && calendarRef.current) {
calendarRef.current.jumpTo(pendingJump.year, pendingJump.month);
setPendingJump(null);
}
}, [type, pendingJump])
}, [type, pendingJump]);
console.log([selectedHour, selectedMinute], 'selectedHour, selectedMinute');
console.log([selectedHour, selectedMinute], "selectedHour, selectedMinute");
return (
<CommonPopup
@@ -149,16 +176,15 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
showHeader={!!title}
title={title}
hideFooter={false}
cancelText='取消'
cancelText="取消"
confirmText={getConfirmText()}
onConfirm={handleConfirm}
position='bottom'
position="bottom"
round
zIndex={1000}
>
{
type === 'year' &&
<View className={styles['calendar-container']}>
{type === "year" && (
<View className={styles["calendar-container"]}>
<CalendarUI
ref={calendarRef}
type={searchType}
@@ -166,27 +192,29 @@ const DialogCalendarCard: React.FC<DialogCalendarCardProps> = ({
onChange={handleChange}
showQuickActions={false}
onHeaderClick={onHeaderClick}
/></View>
}
{
type === 'month' && <PickerCommon
/>
</View>
)}
{type === "month" && (
<PickerCommon
ref={pickerRef}
onChange={handleDateTimePickerChange}
type="month"
value={[(selected as Date).getFullYear(), (selected as Date).getMonth() + 1]}
value={[
(selected as Date).getFullYear(),
(selected as Date).getMonth() + 1,
]}
/>
}
{
type === 'time' && <PickerCommon
)}
{type === "time" && (
<PickerCommon
ref={hourMinutePickerRef}
type="hour"
value={[selectedHour, selectedMinute]}
/>
}
)}
</CommonPopup>
)
}
);
};
export default DialogCalendarCard
export default DialogCalendarCard;