import React, { useState, useEffect, useRef } from 'react' import { View, Text, ScrollView } from '@tarojs/components' import { CommonPopup } from '../index' import styles from './index.module.scss' export interface TimePickerProps { visible: boolean onClose: () => void onConfirm: (year: number, month: number) => void defaultYear?: number defaultMonth?: number minYear?: number maxYear?: number } const TimePicker: React.FC = ({ visible, onClose, onConfirm, defaultYear = new Date().getFullYear(), defaultMonth = new Date().getMonth() + 1, minYear = 2020, maxYear = 2030 }) => { const [selectedYear, setSelectedYear] = useState(defaultYear) const [selectedMonth, setSelectedMonth] = useState(defaultMonth) const [yearScrollTop, setYearScrollTop] = useState(0) const [monthScrollTop, setMonthScrollTop] = useState(0) const yearScrollRef = useRef(null) const monthScrollRef = useRef(null) // 计算当前选项在数组中的索引 const getYearIndex = (year: number) => year - minYear const getMonthIndex = (month: number) => month - 1 // 生成选择器的选项数据 const yearOptions = Array.from({ length: maxYear - minYear + 1 }, (_, index) => ({ text: `${minYear + index}年`, value: minYear + index })) const monthOptions = Array.from({ length: 12 }, (_, index) => ({ text: `${index + 1}月`, value: index + 1 })) // 计算滚动位置 - 确保每次只显示一个选项 const calculateScrollTop = (index: number) => { const itemHeight = 48 // 每个选项的高度 const containerHeight = 216 // 容器高度 const centerOffset = (containerHeight - itemHeight) / 2 return index * itemHeight - centerOffset } // 获取当前可见的选项数量 const getVisibleItemCount = () => { const containerHeight = 216 const itemHeight = 48 return Math.floor(containerHeight / itemHeight) } useEffect(() => { if (visible) { setSelectedYear(defaultYear) setSelectedMonth(defaultMonth) // 设置初始滚动位置 const yearScrollTop = calculateScrollTop(getYearIndex(defaultYear)) const monthScrollTop = calculateScrollTop(getMonthIndex(defaultMonth)) setYearScrollTop(yearScrollTop) setMonthScrollTop(monthScrollTop) } }, [visible, defaultYear, defaultMonth]) // 处理年份滚动 const handleYearScroll = (event: any) => { const scrollTop = event.detail.scrollTop const itemHeight = 48 const containerHeight = 216 const centerOffset = (containerHeight - itemHeight) / 2 // 计算当前选中的年份索引 const currentIndex = Math.round((scrollTop + centerOffset) / itemHeight) const clampedIndex = Math.max(0, Math.min(currentIndex, yearOptions.length - 1)) const newYear = minYear + clampedIndex if (newYear !== selectedYear) { setSelectedYear(newYear) } } // 处理年份滚动结束,自动对齐 const handleYearScrollEnd = () => { const yearIndex = getYearIndex(selectedYear) const alignedScrollTop = calculateScrollTop(yearIndex) // 使用setTimeout确保滚动动画完成后再对齐 setTimeout(() => { setYearScrollTop(alignedScrollTop) }, 100) } // 处理月份滚动 const handleMonthScroll = (event: any) => { const scrollTop = event.detail.scrollTop const itemHeight = 48 const containerHeight = 216 const centerOffset = (containerHeight - itemHeight) / 2 // 计算当前选中的月份索引 const currentIndex = Math.round((scrollTop + centerOffset) / itemHeight) const clampedIndex = Math.max(0, Math.min(currentIndex, monthOptions.length - 1)) const newMonth = clampedIndex + 1 if (newMonth !== selectedMonth) { setSelectedMonth(newMonth) } } // 处理月份滚动结束,自动对齐 const handleMonthScrollEnd = () => { const monthIndex = getMonthIndex(selectedMonth) const alignedScrollTop = calculateScrollTop(monthIndex) // 使用setTimeout确保滚动动画完成后再对齐 setTimeout(() => { setMonthScrollTop(alignedScrollTop) }, 100) } const handleConfirm = () => { onConfirm(selectedYear, selectedMonth) onClose() } if (!visible) return null return ( {/* 拖拽手柄 */} {/* 时间选择器 */} {/* 自定义多列选择器 */} {/* 选中项指示器 */} {/* 年份列 */} {yearOptions.map((option, index) => ( {option.text} ))} {/* 月份列 */} {monthOptions.map((option, index) => ( {option.text} ))} ) } export default TimePicker