import { Tooltip } from 'antd'; import moment from 'moment'; import type { CSSProperties } from 'react'; import { useMemo } from 'react'; import { useIntl } from 'umi'; export interface TimeFromNowProps { style?: CSSProperties; time: number | string | Date; format?: string; tooltip?: boolean; /** * 表示时间距离限制,超出限制则以标准时间(format配置的格式)展示,例: * ['month', 1] 表示超过两个月(包括两个月)则以标准时间展示; * ['day', 1] 表示超过两天(包括两天)则以标准时间展示。 */ limit?: ['year' | 'month' | 'day' | 'hour' | 'minute', number] | false; } const TimeFromNow = (props: TimeFromNowProps) => { const { style, time, format = 'YYYY-MM-DD HH:mm:ss', tooltip = true, limit = ['month', 1], } = props; const { formatMessage } = useIntl(); const { result, standardTime } = useMemo(() => { const targetDate = moment(time).toDate(); const now = new Date(); const timeDiff = now.getTime() - targetDate.getTime(); // 毫秒差值 // 计算时间差值 const seconds = Math.floor(timeDiff / 1000); // 秒 const minutes = Math.floor(seconds / 60); // 分钟 const hours = Math.floor(minutes / 60); // 小时 const days = Math.floor(hours / 24); // 天 const months = Math.floor(days / 30); // 月 const years = Math.floor(months / 12); // 年 const res = { /** 格式化时间 */ result: '', /** 是否为标准时间格式 */ standardTime: true, }; const fromNow = () => { if (years > 0) { return formatMessage({ id: 'component.TimeFromNow.year' }).replace( '${year}', String(years), ); } else if (months > 0) { return formatMessage({ id: 'component.TimeFromNow.month' }).replace( '${month}', String(months), ); } else if (days > 0) { return formatMessage({ id: 'component.TimeFromNow.day' }).replace('${day}', String(days)); } else if (hours > 0) { return formatMessage({ id: 'component.TimeFromNow.hour' }).replace( '${hour}', String(hours), ); } else if (minutes > 0) { return formatMessage({ id: 'component.TimeFromNow.minute' }).replace( '${minute}', String(minutes), ); } else { return formatMessage({ id: 'component.TimeFromNow.just' }); } }; if (limit === false) { res.result = fromNow(); res.standardTime = false; } else { const [limitType, limitValue] = Array.isArray(limit) ? limit : ['month', 1]; if (limitType && limitValue > 0) { const some = [ limitType === 'year' && years > limitValue, limitType === 'month' && months > limitValue, limitType === 'day' && days > limitValue, limitType === 'hour' && hours > limitValue, limitType === 'minute' && minutes > limitValue, ].some((v) => v); if (some) { res.result = moment(time).format(format); } else { res.result = fromNow(); res.standardTime = false; } } else { res.result = fromNow(); res.standardTime = false; } } return res; }, [format, formatMessage, limit, time]); return tooltip && !standardTime ? ( {result} ) : ( {result} ); }; export default TimeFromNow;