import React, { useMemo, useState } from 'react' import { View, Text, Image } from '@tarojs/components' import styles from './index.module.scss' import images from '@/config/images' interface CalendarCardProps { value?: Date minDate?: Date maxDate?: Date onChange?: (date: Date) => void onNext?: (date: Date) => void onHeaderClick?: (date: Date) => void } const startOfMonth = (date: Date) => new Date(date.getFullYear(), date.getMonth(), 1) const endOfMonth = (date: Date) => new Date(date.getFullYear(), date.getMonth() + 1, 0) const addMonths = (date: Date, delta: number) => new Date(date.getFullYear(), date.getMonth() + delta, 1) const formatHeader = (date: Date) => `${date.getMonth() + 1}月 ${date.getFullYear()}` const CalendarCard: React.FC = ({ value, minDate, maxDate, onChange, onHeaderClick }) => { const today = new Date() const [current, setCurrent] = useState(value || startOfMonth(today)) const [selected, setSelected] = useState(value || today) const firstDay = useMemo(() => startOfMonth(current), [current]) const lastDay = useMemo(() => endOfMonth(current), [current]) const days = useMemo(() => { const startWeekday = firstDay.getDay() // 0 周日 const prevPadding = startWeekday // 周日为第一列 const total = prevPadding + lastDay.getDate() const rows = Math.ceil(total / 7) const grid: (Date | null)[] = [] for (let i = 0; i < rows * 7; i++) { const day = i - prevPadding + 1 if (day < 1 || day > lastDay.getDate()) { grid.push(null) } else { grid.push(new Date(current.getFullYear(), current.getMonth(), day)) } } return grid }, [firstDay, lastDay, current]) const isDisabled = (d: Date) => { if (minDate && d < minDate) return true if (maxDate && d > maxDate) return true return false } const gotoMonth = (delta: number) => setCurrent(prev => addMonths(prev, delta)) const handleHeaderClick = () => { onHeaderClick && onHeaderClick(current) } const handleSelectDay = (d: Date | null) => { if (!d || isDisabled(d)) return setSelected(d) onChange && onChange(d) } return ( {formatHeader(current)} gotoMonth(1)} /> gotoMonth(-1)} /> gotoMonth(1)} /> {['周日','周一','周二','周三','周四','周五','周六'].map((w) => ( {w} ))} {days.map((d, idx) => { const isSelected = !!(d && selected && d.toDateString() === new Date(selected.getFullYear(), selected.getMonth(), selected.getDate()).toDateString()) return ( handleSelectDay(d)} > {d ? {d.getDate()} : null} ) })} ) } export default CalendarCard