From f5c6870743e8e66fbfff2967e5aef5b885a752dd Mon Sep 17 00:00:00 2001 From: hiker90 Date: Thu, 19 Jan 2023 19:08:13 +0800 Subject: [PATCH] =?UTF-8?q?feat(past-time-picker):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E2=80=9C=E6=98=BE=E7=A4=BA=E7=BB=9D=E5=AF=B9=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E2=80=9D=E7=89=B9=E6=80=A7=20(#2137)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: YanHui --- src/date-picker/DatePicker.tsx | 4 +- src/past-time-picker/PastTimePicker.tsx | 42 ++++++++++++++++--- .../demos/PastTimePicker.stories.tsx | 5 +++ .../demos/PastTimePickerPage.tsx | 4 ++ src/past-time-picker/interfaces.ts | 1 + .../__tests__/utils.test.tsx | 7 +++- src/static-past-time-picker/utils.ts | 41 ++++++++++++++++++ src/time-picker/TimePicker.tsx | 4 +- src/utils/timeHelper.ts | 4 +- 9 files changed, 101 insertions(+), 11 deletions(-) diff --git a/src/date-picker/DatePicker.tsx b/src/date-picker/DatePicker.tsx index bfa0bde060..03f5ae2845 100644 --- a/src/date-picker/DatePicker.tsx +++ b/src/date-picker/DatePicker.tsx @@ -50,7 +50,7 @@ export const DatePicker: React.FC = (props: DatePickerProps) => const handleOnSelect = (currentValue: Date) => { setControlledValue(currentValue); setVisible(false); - onSelect?.(currentValue, formatDate(currentValue)); + onSelect?.(currentValue, formatDate(currentValue) as string); }; const content = ( @@ -67,7 +67,7 @@ export const DatePicker: React.FC = (props: DatePickerProps) => placeholder={placeholder} disabled={disabled} allowClear={allowClear} - value={controlledValue && formatDate(controlledValue)} + value={controlledValue && (formatDate(controlledValue) as string)} size={size} suffix={suffix} className={className} diff --git a/src/past-time-picker/PastTimePicker.tsx b/src/past-time-picker/PastTimePicker.tsx index c61c776aaf..d4edc82683 100644 --- a/src/past-time-picker/PastTimePicker.tsx +++ b/src/past-time-picker/PastTimePicker.tsx @@ -11,6 +11,7 @@ import { InputButton } from '../input'; import { PastTimePickerProps } from './interfaces'; import StaticPastTimePicker from '../static-past-time-picker'; import defaultLocale from '../static-past-time-picker/locales/zh-CN'; +import { parseStartAndEndDate, parseQuickDate } from '../static-past-time-picker/utils'; const PastTimePicker = (props: PastTimePickerProps) => { const { @@ -32,6 +33,7 @@ const PastTimePicker = (props: PastTimePickerProps) => { size, className, style, + showAbsDate = false, ...restProps } = props; @@ -110,17 +112,35 @@ const PastTimePicker = (props: PastTimePickerProps) => { return defaultString; } if (has(QUICK_MAPPING, time)) { - return get(QUICK_MAPPING, time); + const [startTime, endTime] = parseQuickDate(time); + return showAbsDate + ? `${get(QUICK_MAPPING, time)} | ${parseFnsTimeZone(startTime, 'yyyy/MM/dd')}-${parseFnsTimeZone( + endTime, + 'yyyy/MM/dd' + )}` + : `${get(QUICK_MAPPING, time)}`; } const items = time.split(':'); const times = items[1].split(',').map((str) => parseInt(str, 10)); if (items[0] === 'since') { const start = parseFnsTimeZone(times[0], 'yyyy/MM/dd'); - return `${FromText} ${start} ${toTodayText}`; + const [startTime, endTime] = parseStartAndEndDate(time); + return showAbsDate + ? `${FromText} ${start} ${toTodayText} | ${parseFnsTimeZone(startTime, 'yyyy/MM/dd')}-${parseFnsTimeZone( + endTime, + 'yyyy/MM/dd' + )}` + : `${FromText} ${start} ${toTodayText}`; } if (items[0] === 'since-lt-today') { const start = parseFnsTimeZone(times[0], 'yyyy/MM/dd'); - return `${FromText} ${start} ${toYesterdayText}`; + const [startTime, endTime] = parseStartAndEndDate(time); + return showAbsDate + ? `${FromText} ${start} ${toYesterdayText} | ${parseFnsTimeZone(startTime, 'yyyy/MM/dd')}-${parseFnsTimeZone( + endTime, + 'yyyy/MM/dd' + )}` + : `${FromText} ${start} ${toYesterdayText}`; } if (items[0] === 'abs') { @@ -129,10 +149,22 @@ const PastTimePicker = (props: PastTimePickerProps) => { return `${FromText} ${start} ${ToText} ${end}`; } if (items[0] === 'day') { + const [startTime, endTime] = parseStartAndEndDate(time); + if (times[1] === 1) { - return `${lastText} ${times[0] - times[1]} ${dayText}`; + return showAbsDate + ? `${lastText} ${times[0] - times[1]} ${dayText} | ${parseFnsTimeZone( + startTime, + 'yyyy/MM/dd' + )}-${parseFnsTimeZone(endTime, 'yyyy/MM/dd')}` + : `${lastText} ${times[0] - times[1]} ${dayText}`; } - return `${lastText} ${times[1]}-${times[0]} ${dayText}`; + return showAbsDate + ? `${lastText} ${times[1]}-${times[0]} ${dayText} | ${parseFnsTimeZone( + startTime, + 'yyyy/MM/dd' + )}-${parseFnsTimeZone(endTime, 'yyyy/MM/dd')}` + : `${lastText} ${times[1]}-${times[0]} ${dayText}`; } return defaultString; }; diff --git a/src/past-time-picker/demos/PastTimePicker.stories.tsx b/src/past-time-picker/demos/PastTimePicker.stories.tsx index f96dc91253..2c4f6f778f 100644 --- a/src/past-time-picker/demos/PastTimePicker.stories.tsx +++ b/src/past-time-picker/demos/PastTimePicker.stories.tsx @@ -94,6 +94,11 @@ export const DisabledDate = () => { return ; }; +export const ShowAbsDate = Template.bind({}); +ShowAbsDate.args = { + showAbsDate: true, +}; + const StaticTemplate: Story = (args) => ( ); diff --git a/src/past-time-picker/demos/PastTimePickerPage.tsx b/src/past-time-picker/demos/PastTimePickerPage.tsx index d5074b41fd..adfff11319 100644 --- a/src/past-time-picker/demos/PastTimePickerPage.tsx +++ b/src/past-time-picker/demos/PastTimePickerPage.tsx @@ -135,6 +135,10 @@ export default function DatePickerPage() { + {formatMessage({ defaultMessage: '显示绝对日期' })} + + + {formatMessage({ defaultMessage: '参数说明' })} diff --git a/src/past-time-picker/interfaces.ts b/src/past-time-picker/interfaces.ts index a72084d2c4..a945871887 100644 --- a/src/past-time-picker/interfaces.ts +++ b/src/past-time-picker/interfaces.ts @@ -16,4 +16,5 @@ export interface PastTimePickerProps */ value?: string; 'data-testid'?: string; + showAbsDate?: boolean; } diff --git a/src/static-past-time-picker/__tests__/utils.test.tsx b/src/static-past-time-picker/__tests__/utils.test.tsx index 081828c5a8..77366b5692 100644 --- a/src/static-past-time-picker/__tests__/utils.test.tsx +++ b/src/static-past-time-picker/__tests__/utils.test.tsx @@ -1,6 +1,6 @@ import { startOfToday, startOfYesterday } from 'date-fns'; import { TimeMode } from '../interfaces'; -import { parseFixedMode, parseStartAndEndDate, parseTimeMode } from '../utils'; +import { parseFixedMode, parseStartAndEndDate, parseTimeMode, parseQuickDate } from '../utils'; describe('test utils', () => { it('parseTimeMode', () => { @@ -20,6 +20,11 @@ describe('test utils', () => { ]); expect(parseStartAndEndDate('xxx:1656115199999')).toStrictEqual([undefined, undefined]); }); + it('parseQuickDate', () => { + expect(parseQuickDate('day:1,0')).toStrictEqual([startOfToday(), startOfToday()]); + expect(parseQuickDate('day:2,1')).toStrictEqual([startOfYesterday(), startOfYesterday()]); + expect(parseQuickDate('xxx:1656115199999')).toStrictEqual([undefined, undefined]); + }); it('parseFixedMode', () => { expect(parseFixedMode('day:2,1')).toBe('yesterday'); expect(parseFixedMode('since:1656115199999')).toBe('today'); diff --git a/src/static-past-time-picker/utils.ts b/src/static-past-time-picker/utils.ts index 24f7af9a3e..7a3d7b4af8 100644 --- a/src/static-past-time-picker/utils.ts +++ b/src/static-past-time-picker/utils.ts @@ -1,9 +1,12 @@ import has from 'lodash/has'; import { sub } from 'date-fns'; import momentTZ from 'moment-timezone'; +import moment from 'moment'; import { TimeMode } from './interfaces'; import { QUICK_MAPPING } from './constant'; +momentTZ.tz.setDefault(localStorage.getItem('timezone') || Intl.DateTimeFormat().resolvedOptions().timeZone); + export const parseTimeMode = (timeRange: string | undefined) => { if (!timeRange) { return undefined; @@ -63,6 +66,44 @@ export const parseStartAndEndDate = (timeRange: string | undefined): [Date | und return [undefined, undefined]; }; +export const parseQuickDate = (timeRange: string | undefined): [Date | undefined, Date | undefined] => { + if (!timeRange || timeRange.split(':').length !== 2) { + return [undefined, undefined]; + } + const items = timeRange.split(':'); + const times = items[1].split(',').map((str) => parseInt(str, 10)); + const today = startOfTodayInTimezone(); + + if (items[0] === 'day') { + return [sub(today, { days: times[0] - 1 }), sub(today, { days: times[1] })]; + } + if (items[0] === 'week-lt-today') { + return [moment().subtract(times[0] - 1, 'week').startOf('isoWeek').toDate(), String(times[1]) === '0' ? moment().subtract(1, 'day').endOf('day').toDate() : moment().subtract(times[0] - 1, 'week').endOf('isoWeek').toDate()]; + } + if (items[0] === 'month-lt-today') { + return [moment().subtract(times[0] - 1, 'month').startOf('month').toDate(), String(times[1]) === '0' ? moment().subtract(1, 'day').endOf('day').toDate() : moment().subtract(times[0] - 1, 'month').endOf('month').toDate()]; + } + if (items[0] === 'quarter-lt-today') { + return [moment().subtract(times[0] - 1, 'quarter').startOf('quarter').toDate(), String(times[1]) === '0' ? moment().subtract(1, 'day').endOf('day').toDate() : moment().subtract(times[0] - 1, 'quarter').endOf('quarter').toDate()]; + } + if (items[0] === 'year-lt-today') { + return [moment().subtract(times[0] - 1, 'year').startOf('year').toDate(), String(times[1]) === '0' ? moment().subtract(1, 'day').endOf('day').toDate() : moment().subtract(times[0] - 1, 'year').endOf('year').toDate()]; + } + if (items[0] === 'week') { + return [moment().subtract(times[0] - 1, 'week').startOf('isoWeek').toDate(), String(times[1]) === '0' ? moment().endOf('day').toDate() : moment().subtract(times[0] - 1, 'week').endOf('isoWeek').toDate()]; + } + if (items[0] === 'month') { + return [moment().subtract(times[0] - 1, 'month').startOf('month').toDate(), String(times[1]) === '0' ? moment().endOf('day').toDate() : moment().subtract(times[0] - 1, 'month').endOf('month').toDate()]; + } + if (items[0] === 'quarter') { + return [moment().subtract(times[0] - 1, 'quarter').startOf('quarter').toDate(), String(times[1]) === '0' ? moment().endOf('day').toDate() : moment().subtract(times[0] - 1, 'quarter').endOf('quarter').toDate()]; + } + if (items[0] === 'year') { + return [moment().subtract(times[0] - 1, 'year').startOf('year').toDate(), String(times[1]) === '0' ? moment().endOf('day').toDate() : moment().subtract(times[0] - 1, 'year').endOf('year').toDate()]; + } + return [undefined, undefined]; +} + export const parseFixedMode = (timeRange: string | undefined) => { if (!timeRange || timeRange.split(':').length !== 2) { return false; diff --git a/src/time-picker/TimePicker.tsx b/src/time-picker/TimePicker.tsx index a079b92574..322e77c7c4 100644 --- a/src/time-picker/TimePicker.tsx +++ b/src/time-picker/TimePicker.tsx @@ -54,7 +54,7 @@ export const TimePicker: React.FC = (props) => { const handleOnOk = () => { setControlledValue(time); setVisible(false); - onSelect?.(time as Date, formatTime(time as Date)); + onSelect?.(time as Date, formatTime(time as Date) as string); }; const handleVisibleChange = (current: boolean) => { @@ -100,7 +100,7 @@ export const TimePicker: React.FC = (props) => { prefix={prefix || } disabled={disabled} allowClear={allowClear} - value={time && formatTime(time)} + value={time && (formatTime(time) as string)} placeholder={placeholder ?? timeSelect} size={size} suffix={suffix} diff --git a/src/utils/timeHelper.ts b/src/utils/timeHelper.ts index d595b6e3a2..9a49fb8e52 100644 --- a/src/utils/timeHelper.ts +++ b/src/utils/timeHelper.ts @@ -3,6 +3,7 @@ import momentTZ from 'moment-timezone'; import moment from 'moment'; import { format as dateFnsFormat, utcToZonedTime } from 'date-fns-tz'; +momentTZ.tz.setDefault(localStorage.getItem('timezone') || Intl.DateTimeFormat().resolvedOptions().timeZone); // 时间日期转换时区 moment export const parseTimeZone = (data?: any, format?: string) => momentTZ(data as string, format).tz( @@ -10,7 +11,8 @@ export const parseTimeZone = (data?: any, format?: string) => ); // 时间日期转换时区 date-fns -export const parseFnsTimeZone = (date: number | Date | string, format: string) => { +export const parseFnsTimeZone = (date: number | Date | string | undefined, format: string) => { + if (!date) return date; let finalDate = date; if (isNumber(date)) { finalDate = new Date(date);