import React, { useState, useEffect, useRef, useImperativeHandle } from 'react' import { CalendarCard } from '@nutui/nutui-react-taro' import { View, Text, Image } from '@tarojs/components' import images from '@/config/images' import styles from './index.module.scss' import { getMonth, getWeekend, getWeekendOfCurrentWeek } from '@/utils/timeUtils' import { PopupPicker } from '@/components/Picker/index' interface NutUICalendarProps { type?: 'single' | 'range' | 'multiple' value?: string | Date | String[] | Date[] defaultValue?: string | string[] onChange?: (value: Date | Date[]) => void, isBorder?: boolean showQuickActions?: boolean, onHeaderClick?: (date: Date) => void } export interface CalendarUIRef { jumpTo: (year: number, month: number) => void } const NutUICalendar = React.forwardRef(({ type = 'single', value, onChange, isBorder = false, showQuickActions = true, onHeaderClick }, ref) => { // 根据类型初始化选中值 // const getInitialValue = (): Date | Date[] => { // console.log(value,defaultValue,'today') // if (typeof value === 'string' && value) { // return new Date(value) // } // if (Array.isArray(value) && value.length > 0) { // return value.map(item => new Date(item)) // } // if (typeof defaultValue === 'string' && defaultValue) { // return new Date(defaultValue) // } // if (Array.isArray(defaultValue) && defaultValue.length > 0) { // return defaultValue.map(item => new Date(item)) // } // const today = new Date(); // if (type === 'multiple') { // return [today] // } // return today // } const startOfMonth = (date: Date) => new Date(date.getFullYear(), date.getMonth(), 1) const [selectedValue, setSelectedValue] = useState() const [current, setCurrent] = useState(startOfMonth(new Date())) const calendarRef = useRef(null) const [visible, setvisible] = useState(false) console.log('current', current) // 当外部 value 变化时更新内部状态 useEffect(() => { if (Array.isArray(value) && value.length > 0) { setSelectedValue(value.map(item => new Date(item))) setCurrent(new Date(value[0])) } if ((typeof value === 'string' || value instanceof Date) && value) { setSelectedValue(new Date(value)) setCurrent(new Date(value)) } }, [value]) useImperativeHandle(ref, () => ({ jumpTo: (year: number, month: number) => { calendarRef.current?.jumpTo(year, month) } })) const handleDateChange = (newValue: any) => { console.log('xxxxxxxxxxxxxxxxxxxxxx', newValue) setSelectedValue(newValue) onChange?.(newValue as any) } const formatHeader = (date: Date) => `${getMonth(date)}` const handlePageChange = (data: { year: number; month: number }) => { // 月份切换时的处理逻辑,如果需要的话 console.log('月份切换:', data) } const gotoMonth = (delta: number) => { const base = current instanceof Date ? new Date(current) : new Date() base.setMonth(base.getMonth() + delta) const next = startOfMonth(base) setCurrent(next) // 同步底部 CalendarCard 的月份 try { calendarRef.current?.jump?.(delta) } catch (e) { console.warn('CalendarCardRef jump 调用失败', e) } handlePageChange({ year: next.getFullYear(), month: next.getMonth() + 1 }) } const handleHeaderClick = () => { onHeaderClick && onHeaderClick(current) setvisible(true) } const syncMonthTo = (anchor: Date) => { // 计算从 current 到目标 anchor 所在月份的偏移,调用 jump(delta) const monthsDelta = (anchor.getFullYear() - current.getFullYear()) * 12 + (anchor.getMonth() - current.getMonth()) if (monthsDelta !== 0) { gotoMonth(monthsDelta) } } const renderDay = (day: any) => { const { date, month, year} = day; const today = new Date() if (date === today.getDate() && month === today.getMonth() + 1 && year === today.getFullYear()) { return ( {date} ) } return date } const selectWeekend = () => { const [start, end] = getWeekend() setSelectedValue([start, end]) syncMonthTo(start) onChange?.([start, end]) } const selectWeek = () => { const dayList = getWeekendOfCurrentWeek(7) setSelectedValue(dayList) syncMonthTo(dayList[0]) onChange?.(dayList) } const selectMonth = () => { const dayList = getWeekendOfCurrentWeek(30) setSelectedValue(dayList) syncMonthTo(dayList[0]) onChange?.(dayList) } const handleMonthChange = (value: any) => { const [year, month] = value; const newDate = new Date(year, month - 1, 1); setCurrent(newDate); calendarRef.current?.jumpTo(year, month) } return ( {/* 快速操作行 */} { showQuickActions && 本周末 一周内 一个月 } {/* 自定义头部显示周一到周日 */} {formatHeader(current as Date)} gotoMonth(1)} /> gotoMonth(-1)}> gotoMonth(1)}> {[ '周日', '周一', '周二', '周三', '周四', '周五', '周六'].map((day) => ( {day} ))} {/* NutUI CalendarCard 组件 */} { visible && handleMonthChange(value)}/> } ) }) export default NutUICalendar