import React , { useMemo , useState } from 'react' ; import dayjs , { Dayjs } from '../../dayjs' ; import { useDevice } from '../../providers' ; import { FormEventDetail } from '../../types' ; import { getToken } from '../../utils' ; import { Button } from '../button' ; import { Box } from '../layout' ; import { TimePanel , TimePanelProps } from '../time-picker/time-panel' ; import { DateTableProvider } from './date-context' ; import { DateTable } from './date-table' ; import { CheckDateFn , DateLocale , DatePanelMode } from './date-types' ; import { MonthTable } from './month-table' ; import { YearTable } from './year-table' ; const defaultGetVisibleMonth = ( { startValue , endValue } ) => { const value = endValue || startValue ; if ( value ) { return value . clone ( ) ; } return dayjs ( ) ; } ; const defaultGetDisabledDate = ( ) => false ; const getDateLocale = ( ) : DateLocale => { const localeData = dayjs . localeData ( ) ; let weekdays = localeData . weekdaysMin ( ) as string [ ] ; const firstDayOfWeek = localeData . firstDayOfWeek ( ) ; if ( firstDayOfWeek ) { const part1 = weekdays . slice ( firstDayOfWeek ) ; const part2 = weekdays . slice ( 0 , firstDayOfWeek ) ; weekdays = part1 . concat ( part2 ) ; } return { weekdays , months : localeData . months ( ) , } ; } ; export interface DateCardProps { /**
     * 日期格式
     */ format ? : string ; /**
     * 是否有时间
     */ hasTime ? : boolean ; /**
     * 默认显示的月份
     */ getDefaultVisibleMonth ? : ( props : DateCardProps ) => Dayjs ; /**
     * 开始日期
     */ startValue ? : Dayjs ; /**
     * 结束日期
     */ endValue ? : Dayjs ; /**
     * 时间值
     */ timeValue ? : Dayjs ; /**
     * 传递给时间面板的属性
     */ timeProps ? : TimePanelProps ; /**
     * 点选某个日期时的回调
     */ onSelect ? : ( date : Dayjs , data ? : FormEventDetail ) => void ; /**
     * 设置日期值是否禁用
     */ getDisabledDate ? : CheckDateFn ; /**
     * 点击确认按钮时的回调
     */ onOk ? : ( ) => void ; } export function DateCard ( props ) { const { format , hasTime , timeProps , startValue , endValue , timeValue , getDefaultVisibleMonth = defaultGetVisibleMonth , getDisabledDate = defaultGetDisabledDate , onSelect , onOk , } = props ; const device = useDevice ( ) ; const [ mode , setMode ] = useState < 'date' | 'month' | 'year' > ( 'date' ) ; const [ visibleMonth , setVisibleMonth ] = useState ( ( ) => getDefaultVisibleMonth ( { startValue , endValue , } ) ) ; const today = dayjs ( ) ; const dateLocale = useMemo ( ( ) => { return getDateLocale ( ) ; } , [ ] ) ; const context = { format , today , timeValue , check : ( fn ) => { return fn ( { format , today , startValue , endValue , visibleMonth } ) ; } , onSelectDate : ( date , payload ) => { if ( ! date . isSame ( visibleMonth , 'month' ) ) { setVisibleMonth ( date ) ; } onSelect ( date , payload ) ; } , onSelectMonth : ( date ) => { setVisibleMonth ( date ) ; } , onSelectYear : ( date ) => { setVisibleMonth ( visibleMonth . year ( date . year ( ) ) ) ; } , onChangeMode : ( nextMode ) => { if ( nextMode !== mode ) { setMode ( nextMode ) ; } } , getDisabledDate , } ; const handleTimeChange = ( date ) => { const existValue = timeValue || dayjs ( ) ; const fixedDate = existValue . hour ( date . hour ( ) ) . minute ( date . minute ( ) ) . second ( date . second ( ) ) ; onSelect ( fixedDate ) ; } ; let panelDirection = 'row' ; let timeRows = 9 ; let timeBoxProps = { } ; if ( device . alias === 's' ) { panelDirection = 'column' ; timeRows = 3 ; timeBoxProps = { borderTop : 'solid' , borderTopColor : 'emphasis.30' , } ; } const timePanelMode = timeProps ?. mode || 'simple' ; const timePanelWidth = timePanelMode === 'simple' ? getToken ( 'DatePicker.simpleTimeCardWidth' ) : getToken ( 'DatePicker.normalTimeCardWidth' ) ; return ( < DateTableProvider value = { context } > < Box display = "flex" flexDirection = { panelDirection as any } py = "l" > < Box > { mode === 'date' && < DateTable visibleMonth = { visibleMonth } locale = { dateLocale } / > } { mode === 'month' && < MonthTable visibleMonth = { visibleMonth } locale = { dateLocale } / > } { mode === 'year' && < YearTable visibleMonth = { visibleMonth } locale = { dateLocale } / > } < /Box> { hasTime && mode === 'date' && ( < Box width = { timePanelWidth } { ... timeBoxProps } > < TimePanel rows = { timeRows } value = { timeValue } mode = "simple" onChange = { handleTimeChange } { ... timeProps } /> < /Box>)} < /Box> { hasTime && < DatePanelFooter onOk = { onOk } />} < /DateTableProvider>); } interface DatePanelFooterProps { onOk ? : React . MouseEventHandler < HTMLButtonElement > ; } function DatePanelFooter ( props ) { const { onOk } = props ; const device = useDevice ( ) ; return ( < Box px = "m" pb = "m" textAlign = "right" > < Button fill = { device . alias === 's' } size = { device . alias === 's' ? 'medium' : 'small' } type = "primary" onClick = { onOk } > 确认 < /Button> < /Box>); }