日期范围选择
import { useMemo, useCallback, useEffect } from 'react';import moment, { Moment, DurationInputArg2 } from 'moment';import { useSetState } from '../index';const formatType = 'YYYY-MM-DD HH:mm:ss';const formatDate = (date: string | Moment | undefined | null, formatString = formatType) =>moment(date).format(formatString);export type RangeType = 'none' | 'same' | number | undefined;export interface RangeDateCfg {/** 开始 结束时间 只有在 type === 'range' 有用 */start?: string | null;end?: string | null;/** 区间 或 单个 时间 */type: 'range' | 'date';/** 范围 */range?: RangeType;/** 计算单位 */unit?: DurationInputArg2;/** 格式化参数 */formatStr?: string;}export interface RangeDateState<T> {range: RangeType;date: T;}const getDateByType = (dateStr: string | string[]) => {if (!Array.isArray(dateStr)) {return [dateStr, dateStr];}return dateStr;};const useRangeDate = <T = string | string[]>(state: RangeDateCfg = {} as RangeDateCfg) => {const { start, end, type = 'range', range } = state;const initDate = ((type === 'range' ? [] : '') as unknown) as T;/** none: 表示任何都不选择 */const [rangeDate, setRangeDate] = useSetState<RangeDateState<T>>({range,date: initDate,});/** 处理计算格式 && 格式化参数 */const unit = useMemo(() => state.unit ?? 'days', [state.unit]);const fmtStr = useMemo(() => state.formatStr ?? 'YYYY-MM-DD', [state.formatStr]);useEffect(() => {if (range !== undefined && range !== 'none') {console.log(unit, ';unit');const newDate = moment().subtract(range, unit).format(fmtStr);setRangeDate({ date: (newDate as unknown) as T });}}, [range]);useEffect(() => {/** same: 表示和 开始 及 结束重叠 */if (start && end && type === 'range') {setRangeDate({ range: 'same', date: ([start, end] as unknown) as T });}}, [start, end]);/** setRange: 暂时不支持回调 */const setRange = useCallback((val: RangeType, unitType?: DurationInputArg2, fStr?: string) => {/** 当 type === 'range', same 回填初始状态 */if (val === 'same') {setRangeDate({ range: val, date: ([start, end] as unknown) as T });return;}const u = unitType ?? unit;const newFstr = fStr ?? fmtStr;const sDate = formatDate(moment().subtract(val, u), fmtStr);const eDate = formatDate(moment(), newFstr);const fillDate = type === 'date' ? sDate : [sDate, eDate];setRangeDate({ range: val, date: (fillDate as unknown) as T });},[setRangeDate, start, end],);const changeDate = useCallback(<R>(_: R, dateStr: string | string[]) => {const [startStr, endStr] = getDateByType(dateStr);const isSame =type === 'range'? startStr === start && endStr === end: startStr === formatDate(moment().subtract(range, unit), fmtStr);const newDate = type === 'range' ? [startStr, endStr] : startStr;setRangeDate({date: newDate as any,range: isSame ? range ?? 'same' : 'none',});},[setRangeDate, start, end],);return [rangeDate, { changeDate, setRange, setRangeDate }] as const;};export default useRangeDate;
