import { CalendarOutlined } from '@ant-design/icons'; import moment, { Moment } from 'moment'; import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import styled from '@emotion/styled'; import { useDisclosure } from '@chakra-ui/react'; import Button from '../button'; import Checkbox from '../checkbox'; import Col from '../col'; import DatePicker, { RangePickerProps } from '../date-picker'; import Divider from '../divider'; import Input from '../input'; import Popover, { PopoverProps } from '../popover'; import Row from '../row'; import Select from '../select'; import defaultLocale from '../locale/en_US'; import { ConfigContext } from '../config-provider'; const { Option } = Select; const { RangePicker } = DatePicker; const SelectWrapper = styled.div` margin: 20px 0; `; export type CompareType = 'lastTerm' | 'yesterDay' | 'lastWeek' | 'lastMonth' | 'lastYear'; export type DateType = 'dateTime' | 'date' | 'all'; export type DateValue = 'dateTime' | 'date'; export type RangeType = | 'custom' | 'currentHour' | 'lastHour' | 'lastThreeHours' | 'today' | 'yesterday' | 'sevenDaysAgo' | 'thirtyDaysAgo' | 'ninetyDaysAgo' | 'lastMonth' | 'lastYear' | 'thisWeek' | 'thisMonth' | 'thisQuarter' | 'thisYear'; const formatShowTime = (type: DateType) => { if (type === 'dateTime') { return 'YYYY-MM-DD HH:mm:ss'; } return 'YYYY-MM-DD'; }; // 根据范围返回时间 const changeRangeType = (value: RangeType) => { let newPickerValue: [Moment, Moment]; switch (value) { case 'currentHour': newPickerValue = [moment().startOf('hour'), moment().endOf('hour')]; break; case 'lastHour': newPickerValue = [ moment().subtract(1, 'hour').startOf('hour'), moment().subtract(1, 'hour').endOf('hour'), ]; break; case 'lastThreeHours': newPickerValue = [ moment().subtract(3, 'hour').startOf('hour'), moment().subtract(1, 'hour').endOf('hour'), ]; break; case 'today': newPickerValue = [moment().startOf('day'), moment().endOf('day')]; break; case 'yesterday': newPickerValue = [ moment().subtract(1, 'days').startOf('days'), moment().subtract(1, 'days').endOf('days'), ]; break; case 'sevenDaysAgo': newPickerValue = [ moment().subtract(7, 'days').startOf('days'), moment().subtract(1, 'days').endOf('days'), ]; break; case 'thirtyDaysAgo': newPickerValue = [ moment().subtract(30, 'days').startOf('days'), moment().subtract(1, 'days').endOf('days'), ]; break; case 'ninetyDaysAgo': newPickerValue = [ moment().subtract(90, 'days').startOf('days'), moment().subtract(1, 'days').endOf('days'), ]; break; case 'lastMonth': newPickerValue = [ moment() .month(moment().month() - 1) .startOf('month'), moment() .month(moment().month() - 1) .endOf('month'), ]; break; case 'lastYear': newPickerValue = [ moment() .year(moment().year() - 1) .startOf('year'), moment() .year(moment().year() - 1) .endOf('year'), ]; break; case 'thisWeek': newPickerValue = [moment().weekday(1).startOf('day'), moment().endOf('day')]; break; case 'thisMonth': newPickerValue = [moment().startOf('month'), moment().endOf('day')]; break; case 'thisQuarter': newPickerValue = [moment().startOf('quarter'), moment().endOf('day')]; break; case 'thisYear': newPickerValue = [moment().startOf('year'), moment().endOf('day')]; break; default: newPickerValue = [moment().startOf('day'), moment().endOf('day')]; break; } return newPickerValue; }; interface OkProps { dateType: DateType; dateValue: DateValue; value: [Moment, Moment]; compareType: CompareType | boolean; compareValue?: [Moment, Moment] | null; } export interface DateValueType { type: DateType; value?: DateValue; } export interface PopoverPickerProps { /** 确定回调,回调参数: type value compareType compareValue */ onOk?: (values: OkProps) => void; /** False 禁用, true 开启, CompareType 开启比较并设置对应值 */ defaultCompareType?: CompareType | boolean; /** 选择器类型 */ defaultDateValueType?: DateValueType; /** 继承 RangePickerProps */ rangePickerProps?: Omit; /** 继承 RangePickerProps */ popoverProps?: PopoverProps; } export const PopoverRangePicker: FC = ({ onOk, defaultDateValueType, defaultCompareType, rangePickerProps, popoverProps, }) => { const { locale: { PopoverRangePicker: locale } = { PopoverRangePicker: defaultLocale.PopoverRangePicker, }, } = React.useContext(ConfigContext); const { isOpen, onOpen, onClose } = useDisclosure(); const [showTime, setShowTime] = useState('date'); const [defaultDateType, setDefaultDateType] = useState('date'); const [rangeType, setRangeType] = useState('custom'); const [pickerValue, setPickerValue] = useState<[Moment, Moment] | null>([ moment().startOf('day'), moment().endOf('day'), ]); // 显示比较 const [compareChecked, setCompareChecked] = useState(true); const [compareType, setCompareType] = useState('lastTerm'); // 计算比较时间 const pickerCompareValue = useMemo(() => { if (compareType && pickerValue) { let compareValue: [Moment, Moment]; const diffValue = moment(pickerValue[1]).valueOf() - moment(pickerValue[0]).valueOf(); switch (compareType) { case 'lastTerm': compareValue = [ moment(moment(pickerValue[0]).valueOf() - diffValue - 1), moment(moment(pickerValue[0]).valueOf() - 1), ]; break; case 'yesterDay': compareValue = [ moment(pickerValue[0]).subtract(1, 'days'), moment(moment(pickerValue[0]).subtract(1, 'days').valueOf() + diffValue), ]; break; case 'lastWeek': compareValue = [ moment(pickerValue[0]).subtract(1, 'weeks'), moment(moment(pickerValue[0]).subtract(1, 'weeks').valueOf() + diffValue), ]; break; case 'lastMonth': compareValue = [ moment(pickerValue[0]).subtract(1, 'months'), moment(moment(pickerValue[0]).subtract(1, 'months').valueOf() + diffValue), ]; break; case 'lastYear': compareValue = [ moment(pickerValue[0]).subtract(1, 'years'), moment(moment(pickerValue[0]).subtract(1, 'years').valueOf() + diffValue), ]; break; default: compareValue = [ moment(moment(pickerValue[0]).valueOf() - diffValue), moment(moment(pickerValue[0]).valueOf() - 1), ]; break; } return compareValue; } }, [compareType, pickerValue]); // 禁用对比的时间 const compareSelectDisable = useCallback( (value: CompareType) => { if (pickerValue) { let flag = true; const diffValue = pickerValue[1]?.diff(pickerValue[0], 'day'); switch (value) { case 'yesterDay': if (diffValue <= 1) { flag = false; } break; case 'lastWeek': if (diffValue <= 7) { flag = false; } break; case 'lastMonth': if (diffValue <= 31) { flag = false; } break; case 'lastYear': if (diffValue <= 365) { flag = false; } break; default: flag = true; break; } return flag; } return false; }, [pickerValue], ); const handleChangePickerValue = useCallback( value => { if (typeof compareType !== 'boolean') setCompareType('lastTerm'); setRangeType('custom'); if (showTime === 'date') { setPickerValue([value[0], value[1].endOf('day')]); } else { setPickerValue(value); } }, [showTime, compareType], ); // 提交 const handleOnOK = useCallback(() => { if (pickerValue && onOk) { onOk({ dateType: defaultDateType, dateValue: showTime, value: pickerValue, compareType, compareValue: compareChecked ? pickerCompareValue : null, }); } }, [ compareChecked, compareType, defaultDateType, onOk, pickerCompareValue, pickerValue, showTime, ]); const Footer = useMemo( () => ( <> ), [handleOnOK, locale?.cancel, locale?.ok, onClose], ); // 处理初始化比较类型 对象 | 布尔 useEffect(() => { if (typeof defaultCompareType === 'boolean') { setCompareChecked(false); if (defaultCompareType) { setCompareType(true); return; } setCompareType(false); return; } if (typeof defaultCompareType === 'string') { setCompareType(defaultCompareType); } }, [defaultCompareType]); useEffect(() => { if (rangePickerProps?.value) setPickerValue(rangePickerProps?.value as [Moment, Moment]); }, [rangePickerProps?.value]); useEffect(() => { if (typeof defaultDateValueType === 'object') { setDefaultDateType(defaultDateValueType.type); if (defaultDateValueType.type === 'date') { return setShowTime('date'); } if (defaultDateValueType.type === 'dateTime') { return setShowTime('dateTime'); } if (defaultDateValueType.type === 'all') { if (defaultDateValueType?.value) setShowTime(defaultDateValueType?.value); } } }, [defaultDateValueType]); return ( {locale?.type} {defaultDateType === 'all' ? ( ) : ( )} {locale?.range} {locale?.date} {compareType && ( { if (e.target.checked) { setCompareType('lastTerm'); } else { setCompareType(true); } setCompareChecked(e.target.checked); }} > {locale?.compare} {/* {compareChecked && pickerCompareValue && (
{`(${pickerCompareValue[0].format( formatShowTime(showTime), )} ~ ${pickerCompareValue[1].format(formatShowTime(showTime))})`}
)} */}
{compareChecked && ( )}
)} {Footer} } visible={isOpen} onVisibleChange={vis => { if (vis) { onOpen(); } else { onClose(); } }} placement="bottomLeft" {...popoverProps} > {pickerValue && ( )}
); };