From 7785870f605a014f869e4e5bce62729dd91abc51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C5=AB=20y=C4=81ng?= Date: Wed, 25 Feb 2026 11:49:10 +0800 Subject: [PATCH 01/11] feat(DateRangePicker): add switch timepanel mode --- packages/components/date-picker/date-picker.en-US.md | 2 +- packages/components/date-picker/date-picker.md | 2 +- packages/components/date-picker/type.ts | 10 ++++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/components/date-picker/date-picker.en-US.md b/packages/components/date-picker/date-picker.en-US.md index d3d0efd7c4..b885da20b6 100644 --- a/packages/components/date-picker/date-picker.en-US.md +++ b/packages/components/date-picker/date-picker.en-US.md @@ -61,7 +61,7 @@ defaultTime | Array | ["00:00:00", "23:59:59"] | Time selector default value。T disableDate | Object / Array / Function | - | Typescript: `DisableRangeDate` `type DisableRangeDate = Array \| DisableDateObj \| ((context: { date: DateRangeValue; partial: DateRangePickerPartial }) => boolean)` `interface DisableDateObj { from?: string; to?: string; before?: string; after?: string }` `type DateRangePickerPartial = 'start' \| 'end'`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/packages/components/date-picker/type.ts) | N disableTime | Function | - | disable time config function。Typescript: `(times: Array, context: { partial: DateRangePickerPartial }) => Partial<{ hour: Array, minute: Array, second: Array }>` | N disabled | Boolean | - | \- | N -enableTimePicker | Boolean | false | \- | N +enableTimePicker | Boolean / Object | false | Typescript: `boolean \| TimePanelConfig` `interface TimePanelConfig { mode?: TimePanelMode }` `type TimePanelMode = 'parallel' \| 'switch' `。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/packages/components/date-picker/type.ts) | N firstDayOfWeek | Number | - | options: 1/2/3/4/5/6/7 | N format | String | - | \- | N label | TNode | - | Typescript: `string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/packages/components/common.ts) | N diff --git a/packages/components/date-picker/date-picker.md b/packages/components/date-picker/date-picker.md index b0301a4c94..68c2c9181b 100644 --- a/packages/components/date-picker/date-picker.md +++ b/packages/components/date-picker/date-picker.md @@ -60,7 +60,7 @@ defaultTime | Array | ["00:00:00", "23:59:59"] | 时间选择器默认值,当 disableDate | Object / Array / Function | - | 禁用日期,示例:['A', 'B'] 表示日期 A 和日期 B 会被禁用。{ from: 'A', to: 'B' } 表示在 A 到 B 之间的日期会被禁用(包含A和B)。{ before: 'A', after: 'B' } 表示在 A 之前和在 B 之后的日期都会被禁用。其中 A = '2021-01-01',B = '2021-02-01'。值类型为 Function 则表示返回值为 true 的日期会被禁用。TS 类型:`DisableRangeDate` `type DisableRangeDate = Array \| DisableDateObj \| ((context: { date: DateRangeValue; partial: DateRangePickerPartial }) => boolean)` `interface DisableDateObj { from?: string; to?: string; before?: string; after?: string }` `type DateRangePickerPartial = 'start' \| 'end'`。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/packages/components/date-picker/type.ts) | N disableTime | Function | - | 禁用时间项的配置函数,仅在日期区间选择器中开启时间展示时可用。TS 类型:`(times: Array, context: { partial: DateRangePickerPartial }) => Partial<{ hour: Array, minute: Array, second: Array }>` | N disabled | Boolean | - | 是否禁用组件 | N -enableTimePicker | Boolean | false | 是否显示时间选择 | N +enableTimePicker | Boolean / Object | false | 是否显示时间选择, 默认不展示,设置为 true 时,默认模式为 parallel ,与日期面板并列展示,可以通过配置 mode 为 switch 调整展示方式。TS 类型:`boolean \| TimePanelConfig` `interface TimePanelConfig { mode?: TimePanelMode }` `type TimePanelMode = 'parallel' \| 'switch' `。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/packages/components/date-picker/type.ts) | N firstDayOfWeek | Number | - | 第一天从星期几开始。可选项:1/2/3/4/5/6/7 | N format | String | - | 用于格式化日期,[详细文档](https://day.js.org/docs/en/display/format) | N label | TNode | - | 左侧文本。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/packages/components/common.ts) | N diff --git a/packages/components/date-picker/type.ts b/packages/components/date-picker/type.ts index 687c5d18a0..d0a55e32a6 100644 --- a/packages/components/date-picker/type.ts +++ b/packages/components/date-picker/type.ts @@ -217,10 +217,10 @@ export interface TdDateRangePickerProps { */ disabled?: boolean; /** - * 是否显示时间选择 + * 是否显示时间选择, 默认不展示,设置为 true 时,默认模式为 parallel ,与日期面板并列展示,可以通过配置 mode 为 switch 调整展示方式 * @default false */ - enableTimePicker?: boolean; + enableTimePicker?: boolean | TimePanelConfig; /** * 第一天从星期几开始 */ @@ -559,6 +559,12 @@ export type DisableRangeDate = export type DateRangePickerPartial = 'start' | 'end'; +export interface TimePanelConfig { + mode?: TimePanelMode; +} + +export type TimePanelMode = 'parallel' | 'switch'; + export interface PresetRange { [range: string]: DateRange | (() => DateRange); } From d6ed1e7f79187dc87901db2ee8e681f82d23dbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C5=AB=20y=C4=81ng?= Date: Wed, 25 Feb 2026 18:13:54 +0800 Subject: [PATCH 02/11] feat(DateRangePicker): add new time panel display mode --- packages/common | 2 +- .../date-picker/DateRangePicker.tsx | 20 +-- .../date-picker/_example/date-presets-alt.tsx | 7 +- .../date-picker/_example/date-range.tsx | 2 + .../components/date-picker/base/Footer.tsx | 28 ++-- .../components/date-picker/hooks/useRange.tsx | 16 ++- .../date-picker/panel/ExtraContent.tsx | 2 + .../date-picker/panel/PanelContent.tsx | 5 +- .../date-picker/panel/RangePanel.tsx | 132 +++++++++++------ .../date-picker/panel/SinglePanel.tsx | 5 +- test/snap/__snapshots__/csr.test.jsx.snap | 133 +++++++++++++++--- test/snap/__snapshots__/ssr.test.jsx.snap | 4 +- 12 files changed, 266 insertions(+), 90 deletions(-) diff --git a/packages/common b/packages/common index 44ffa8f6dc..34819ff725 160000 --- a/packages/common +++ b/packages/common @@ -1 +1 @@ -Subproject commit 44ffa8f6dc450b453388db2c623006f00b59bfc8 +Subproject commit 34819ff725ec52b48835cbcd8c3ebc00dd61b524 diff --git a/packages/components/date-picker/DateRangePicker.tsx b/packages/components/date-picker/DateRangePicker.tsx index e8c5cb3e6c..0ffed00205 100644 --- a/packages/components/date-picker/DateRangePicker.tsx +++ b/packages/components/date-picker/DateRangePicker.tsx @@ -72,6 +72,7 @@ const DateRangePicker = forwardRef((origin setIsFirstValueSelected, cacheValue, setCacheValue, + isSwitchTimeMode, } = useRange(props); const { format, timeFormat, valueType } = getDefaultFormat({ @@ -144,7 +145,7 @@ const DateRangePicker = forwardRef((origin const { year: defaultYear, month: defaultMonth } = initYearMonthTime({ value, mode, format, enableTimePicker }); setYear(defaultYear); setMonth(defaultMonth); - } else if (value.length === 2 && !enableTimePicker) { + } else if (value.length === 2 && (!enableTimePicker || isSwitchTimeMode)) { handleSyncPanelValue(value); } else { setYear(value.map((v: string) => parseToDayjs(v, format).year())); @@ -191,7 +192,7 @@ const DateRangePicker = forwardRef((origin setInputValue(nextValue); // 有时间选择器走 confirm 逻辑 - if (enableTimePicker) return; + if (enableTimePicker && !isSwitchTimeMode) return; // 确保两端都是有效值 const notValidIndex = nextValue.findIndex((v) => !v || !isValidDate(v, format)); @@ -212,8 +213,9 @@ const DateRangePicker = forwardRef((origin } // 首次点击不关闭、确保两端都有有效值并且无时间选择器时点击后自动关闭 - if (!isFirstValueSelected || !activeIndex) { + if (!isFirstValueSelected || !activeIndex || isSwitchTimeMode) { let nextIndex = notValidIndex; + if (isSwitchTimeMode && activeIndex === 1) return; if (nextIndex === -1) nextIndex = activeIndex ? 0 : 1; setActiveIndex(nextIndex); setIsFirstValueSelected(!!nextValue[0]); @@ -254,13 +256,13 @@ const DateRangePicker = forwardRef((origin } // time-picker 点击 - function onTimePickerChange(val: string) { + function onTimePickerChange(val: string, context?: { activeIndex: 0 | 1 }) { const { hours, minutes, seconds, milliseconds, meridiem } = extractTimeObj(val); - + const currentIndex = context.activeIndex ?? activeIndex; const nextInputValue = [...inputValue]; - const changedInputValue = inputValue[activeIndex]; + const changedInputValue = inputValue[currentIndex]; const currentDate = !dayjs(changedInputValue, format).isValid() - ? dayjs().year(year[activeIndex]).month(month[activeIndex]) + ? dayjs().year(year[currentIndex]).month(month[currentIndex]) : dayjs(changedInputValue, format); // am pm 12小时制转化 24小时制 let nextHours = hours; @@ -268,10 +270,10 @@ const DateRangePicker = forwardRef((origin if (/pm/i.test(meridiem) && nextHours < 12) nextHours += 12; const nextDate = currentDate.hour(nextHours).minute(minutes).second(seconds).millisecond(milliseconds).toDate(); - nextInputValue[activeIndex] = nextDate; + nextInputValue[currentIndex] = nextDate; const nextTime = [...time]; - nextTime[activeIndex] = val; + nextTime[currentIndex] = val; setTime(nextTime); setIsSelected(true); diff --git a/packages/components/date-picker/_example/date-presets-alt.tsx b/packages/components/date-picker/_example/date-presets-alt.tsx index 6a5553fda5..aebb5ce382 100644 --- a/packages/components/date-picker/_example/date-presets-alt.tsx +++ b/packages/components/date-picker/_example/date-presets-alt.tsx @@ -17,7 +17,12 @@ export default function YearDatePicker() { setRange1(val)} /> - setRange2(val)} enableTimePicker /> + setRange2(val)} + enableTimePicker={{ mode: 'switch' }} + /> ); } diff --git a/packages/components/date-picker/_example/date-range.tsx b/packages/components/date-picker/_example/date-range.tsx index 2590476e0c..a1439d74e9 100644 --- a/packages/components/date-picker/_example/date-range.tsx +++ b/packages/components/date-picker/_example/date-range.tsx @@ -24,6 +24,8 @@ export default function YearDatePicker() { + {/* 可以通过 enableTimePicker 的 mode 属性控制时间选择器的显示方式 */} + ); } diff --git a/packages/components/date-picker/base/Footer.tsx b/packages/components/date-picker/base/Footer.tsx index c3a48c8620..06cb487440 100644 --- a/packages/components/date-picker/base/Footer.tsx +++ b/packages/components/date-picker/base/Footer.tsx @@ -1,17 +1,18 @@ import React from 'react'; import classNames from 'classnames'; -import { isFunction } from 'lodash-es'; +import { isFunction, isObject } from 'lodash-es'; import { useLocaleReceiver } from '../../locale/LocalReceiver'; import Button from '../../button'; import useConfig from '../../hooks/useConfig'; import { TdDatePickerProps, TdDateRangePickerProps, DateValue, DateMultipleValue } from '../type'; -interface DatePickerFooterProps - extends Pick { +interface DatePickerFooterProps extends Pick { presets?: TdDatePickerProps['presets'] | TdDateRangePickerProps['presets']; onPresetClick?: Function; onConfirmClick?: Function; selectedValue?: DateValue | DateMultipleValue; + onTimePanelChange?: () => void; + enableTimePicker?: TdDateRangePickerProps['enableTimePicker'] | TdDatePickerProps['enableTimePicker']; } const DatePickerFooter = (props: DatePickerFooterProps) => { @@ -28,6 +29,7 @@ const DatePickerFooter = (props: DatePickerFooterProps) => { onPresetClick, selectedValue, needConfirm, + onTimePanelChange, } = props; const footerClass = classNames( @@ -35,6 +37,9 @@ const DatePickerFooter = (props: DatePickerFooterProps) => { `${classPrefix}-date-picker__footer--${presetsPlacement}`, ); + // 在日期区间选择器下,可能存在两种时间选择面板的展示方式:并列展示(parallel)和切换展示(switch) + const isSwitchMode = isObject(enableTimePicker) && enableTimePicker?.mode === 'switch'; + const renderPresets = () => { if (presets) { if (React.isValidElement(presets)) return presets; @@ -58,11 +63,18 @@ const DatePickerFooter = (props: DatePickerFooterProps) => { return (
{renderPresets()}
- {enableTimePicker && needConfirm && ( - - )} +
+ {isSwitchMode && ( + + )} + {enableTimePicker && needConfirm && ( + + )} +
); }; diff --git a/packages/components/date-picker/hooks/useRange.tsx b/packages/components/date-picker/hooks/useRange.tsx index 3c95088a99..78380d1863 100644 --- a/packages/components/date-picker/hooks/useRange.tsx +++ b/packages/components/date-picker/hooks/useRange.tsx @@ -1,4 +1,5 @@ -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { isObject } from 'lodash-es'; import { CalendarIcon as TdCalendarIcon } from 'tdesign-icons-react'; import classNames from 'classnames'; @@ -22,6 +23,11 @@ export default function useRange(props: TdDateRangePickerProps) { const isMountedRef = useRef(false); const inputRef = useRef(null); + const isSwitchTimeMode = useMemo( + () => isObject(props.enableTimePicker) && props.enableTimePicker.mode === 'switch', + [props.enableTimePicker], + ); + const { value, onChange, @@ -92,7 +98,12 @@ export default function useRange(props: TdDateRangePickerProps) { onChange: (newVal: string[], { e, position }) => { const index = position === 'first' ? 0 : 1; - props.onInput?.({ input: newVal[index], value, partial: PARTIAL_MAP[position], e: e as React.FormEvent }); + props.onInput?.({ + input: newVal[index], + value, + partial: PARTIAL_MAP[position], + e: e as React.FormEvent, + }); setInputValue(newVal); // 跳过不符合格式化的输入框内容 @@ -197,5 +208,6 @@ export default function useRange(props: TdDateRangePickerProps) { setIsFirstValueSelected, cacheValue, setCacheValue, + isSwitchTimeMode, }; } diff --git a/packages/components/date-picker/panel/ExtraContent.tsx b/packages/components/date-picker/panel/ExtraContent.tsx index 2159008c32..30fc8f7350 100644 --- a/packages/components/date-picker/panel/ExtraContent.tsx +++ b/packages/components/date-picker/panel/ExtraContent.tsx @@ -10,6 +10,7 @@ export interface ExtraContentProps > { selectedValue?: DateValue | DateMultipleValue; presets?: TdDatePickerProps['presets'] | TdDateRangePickerProps['presets']; + onTimeModeChange?: () => void; } export default function ExtraContent(props: ExtraContentProps) { @@ -27,6 +28,7 @@ export default function ExtraContent(props: ExtraContentProps) { presetsPlacement={presetsPlacement} selectedValue={selectedValue} needConfirm={needConfirm} + onTimePanelChange={props.onTimeModeChange} /> ) : null; } diff --git a/packages/components/date-picker/panel/PanelContent.tsx b/packages/components/date-picker/panel/PanelContent.tsx index cd0ce0679d..9c674f2c9d 100644 --- a/packages/components/date-picker/panel/PanelContent.tsx +++ b/packages/components/date-picker/panel/PanelContent.tsx @@ -1,4 +1,5 @@ import React, { useCallback } from 'react'; +import { isBoolean, isObject } from 'lodash-es'; import { getDefaultFormat } from '@tdesign/common-js/date-picker/format'; import DateHeader from '../base/Header'; import DateTable from '../base/Table'; @@ -62,7 +63,9 @@ export default function PanelContent(props: PanelContentProps) { const { timeFormat } = getDefaultFormat({ mode, format, enableTimePicker }); - const showTimePicker = enableTimePicker && mode === 'date'; + const showTimePicker = + (isBoolean(enableTimePicker) && enableTimePicker) || + (isObject(enableTimePicker) && enableTimePicker.mode !== 'switch' && mode === 'date'); const defaultTime = '00:00:00'; diff --git a/packages/components/date-picker/panel/RangePanel.tsx b/packages/components/date-picker/panel/RangePanel.tsx index 04a812ffaa..d5d58ae325 100644 --- a/packages/components/date-picker/panel/RangePanel.tsx +++ b/packages/components/date-picker/panel/RangePanel.tsx @@ -1,6 +1,6 @@ -import React, { forwardRef } from 'react'; +import React, { forwardRef, useState, useEffect } from 'react'; import classNames from 'classnames'; -import { isFunction } from 'lodash-es'; +import { isFunction, isObject } from 'lodash-es'; import { getDefaultFormat, parseToDayjs } from '@tdesign/common-js/date-picker/format'; import useConfig from '../../hooks/useConfig'; import { StyledProps } from '../../common'; @@ -10,6 +10,7 @@ import useTableData from '../hooks/useTableData'; import useDisableDate from '../hooks/useDisableDate'; import useDefaultProps from '../../hooks/useDefaultProps'; import { parseToDateTime } from '../utils'; +import { TimePickerPanel } from '../../time-picker'; import type { TdDateRangePickerProps } from '../type'; import type { TdTimePickerProps } from '../../time-picker'; @@ -33,12 +34,15 @@ export interface RangePanelProps extends TdDateRangePickerProps, StyledProps { onPresetClick?: any; onYearChange?: (year: number, context: { partial: 'start' | 'end' }) => void; onMonthChange?: (month: number, context: { partial: 'start' | 'end' }) => void; - onTimePickerChange?: TdTimePickerProps['onChange']; + onTimePickerChange?: (value: string, context?: { activeIndex: 0 | 1 }) => void; } const RangePanel = forwardRef((originalProps, ref) => { const { classPrefix, datePicker: globalDatePickerConfig } = useConfig(); const panelName = `${classPrefix}-date-range-picker__panel`; + + const [isDateRangeContent, toggleDateRangeContent] = useState(true); + const props = useDefaultProps(originalProps, { mode: 'date', panelPreselection: true, @@ -69,9 +73,11 @@ const RangePanel = forwardRef((originalProps, r onClick, onConfirmClick, disableTime, + onTimePickerChange, + popupVisible, } = props; - const { format } = getDefaultFormat({ + const { format, timeFormat } = getDefaultFormat({ mode: props.mode, format: props.format, enableTimePicker: props.enableTimePicker, @@ -91,6 +97,11 @@ const RangePanel = forwardRef((originalProps, r : undefined, }); + useEffect(() => { + if (!popupVisible) { + toggleDateRangeContent(true); + } + }, [popupVisible]); const disableTimeOptions: TdTimePickerProps['disableTime'] = (h, m, s, ms) => { if (!isFunction(disableTime)) { return {}; @@ -140,8 +151,7 @@ const RangePanel = forwardRef((originalProps, r mode, format, firstDayOfWeek, - - popupVisible: props.popupVisible, + popupVisible, enableTimePicker: props.enableTimePicker, timePickerProps: { disableTime: disableTimeOptions, @@ -156,29 +166,16 @@ const RangePanel = forwardRef((originalProps, r onTimePickerChange: props.onTimePickerChange, }; - return ( -
onClick?.({ e })} - > - {['top', 'left'].includes(presetsPlacement) ? ( - - ) : null} -
- {!enableTimePicker ? ( - [ + const onTimeModeChange = () => { + toggleDateRangeContent((prev) => !prev); + }; + + const renderPanelContent = () => { + // 没有开启时间选择,或者开启时间选择但模式是切换(switch),则日期面板和时间面板分开展示 + if (!enableTimePicker || (isObject(enableTimePicker) && enableTimePicker.mode === 'switch')) { + if (isDateRangeContent) + return ( + <> ((originalProps, r tableData={startTableData} value={value} {...panelContentProps} - />, + /> ((originalProps, r tableData={endTableData} internalYear={year} {...panelContentProps} - />, - ] - ) : ( - + + ); + + return ( + <> + onTimePickerChange(val, { activeIndex: 0 })} + /> + onTimePickerChange(val, { activeIndex: 1 })} /> - )} -
+ + ); + } + return ( + + ); + }; + + return ( +
onClick?.({ e })} + > + {['top', 'left'].includes(presetsPlacement) ? ( + + ) : null} +
{renderPanelContent()}
{['bottom', 'right'].includes(presetsPlacement) ? ( ((originalProps, r enableTimePicker={enableTimePicker} onPresetClick={onPresetClick} onConfirmClick={onConfirmClick} + onTimeModeChange={onTimeModeChange} presetsPlacement={presetsPlacement} needConfirm={needConfirm} /> diff --git a/packages/components/date-picker/panel/SinglePanel.tsx b/packages/components/date-picker/panel/SinglePanel.tsx index be828f6d96..8e6aac84ad 100644 --- a/packages/components/date-picker/panel/SinglePanel.tsx +++ b/packages/components/date-picker/panel/SinglePanel.tsx @@ -6,18 +6,19 @@ import useConfig from '../../hooks/useConfig'; import { StyledProps } from '../../common'; import PanelContent from './PanelContent'; import ExtraContent from './ExtraContent'; -import type { DateValue, TdDatePickerProps } from '../type'; +import type { DateValue, TdDatePickerProps, TdDateRangePickerProps } from '../type'; import type { TdTimePickerProps } from '../../time-picker'; import useTableData from '../hooks/useTableData'; import useDisableDate from '../hooks/useDisableDate'; import useDefaultProps from '../../hooks/useDefaultProps'; import { parseToDateTime } from '../utils'; -export interface SinglePanelProps extends TdDatePickerProps, StyledProps { +export interface SinglePanelProps extends Omit, StyledProps { year?: number; month?: number; time?: string; popupVisible?: boolean; + enableTimePicker?: TdDateRangePickerProps['enableTimePicker'] | TdDatePickerProps['enableTimePicker']; onPanelClick?: (context: { e: React.MouseEvent }) => void; onCellClick?: (date: Date, context: { e: React.MouseEvent }) => void; onCellMouseEnter?: (date: Date) => void; diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap index 79ee6ef014..3d6056a351 100644 --- a/test/snap/__snapshots__/csr.test.jsx.snap +++ b/test/snap/__snapshots__/csr.test.jsx.snap @@ -35788,6 +35788,95 @@ exports[`csr snapshot test > csr test packages/components/date-picker/_example/d
+
+
+
+
+
+
+
+ +
+
+
+ - +
+
+
+ +
+
+ + + + + + + + + +
+
+
+
+
`; @@ -39196,16 +39285,18 @@ exports[`csr snapshot test > csr test packages/components/date-picker/_example/p
-
- +
- 确定 - + + 确定 + +
@@ -41899,16 +41990,18 @@ exports[`csr snapshot test > csr test packages/components/date-picker/_example/p
-
- +
- 确定 - + + 确定 + +
@@ -150767,7 +150860,7 @@ exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/c exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/date-presets-alt.tsx 1`] = `"
-
-
"`; -exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/date-range.tsx 1`] = `"
-
-
"`; +exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/date-range.tsx 1`] = `"
-
-
-
"`; exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/date-time.tsx 1`] = `"
"`; @@ -150779,7 +150872,7 @@ exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/m exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/multiple.tsx 1`] = `"
2024-10-01
2024-10-24
2024-50周
2024-51周
2022
2023
2024
"`; -exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/panel.tsx 1`] = `"
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
"`; +exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/panel.tsx 1`] = `"
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
"`; exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/quarter.tsx 1`] = `"
-
"`; diff --git a/test/snap/__snapshots__/ssr.test.jsx.snap b/test/snap/__snapshots__/ssr.test.jsx.snap index dce5e8cc0c..6784da113b 100644 --- a/test/snap/__snapshots__/ssr.test.jsx.snap +++ b/test/snap/__snapshots__/ssr.test.jsx.snap @@ -290,7 +290,7 @@ exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/c exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/date-presets-alt.tsx 1`] = `"
-
-
"`; -exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/date-range.tsx 1`] = `"
-
-
"`; +exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/date-range.tsx 1`] = `"
-
-
-
"`; exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/date-time.tsx 1`] = `"
"`; @@ -302,7 +302,7 @@ exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/m exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/multiple.tsx 1`] = `"
2024-10-01
2024-10-24
2024-50周
2024-51周
2022
2023
2024
"`; -exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/panel.tsx 1`] = `"
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
"`; +exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/panel.tsx 1`] = `"
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
"`; exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/quarter.tsx 1`] = `"
-
"`; From 351f14d2f832266a099d98f3023229bd2b4bb84a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C5=AB=20y=C4=81ng?= Date: Wed, 25 Feb 2026 18:30:51 +0800 Subject: [PATCH 03/11] fix: fix i18n --- packages/components/date-picker/base/Footer.tsx | 3 ++- packages/components/date-picker/panel/ExtraContent.tsx | 2 ++ packages/components/date-picker/panel/RangePanel.tsx | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/components/date-picker/base/Footer.tsx b/packages/components/date-picker/base/Footer.tsx index 06cb487440..26538ba2a3 100644 --- a/packages/components/date-picker/base/Footer.tsx +++ b/packages/components/date-picker/base/Footer.tsx @@ -13,6 +13,7 @@ interface DatePickerFooterProps extends Pick void; enableTimePicker?: TdDateRangePickerProps['enableTimePicker'] | TdDatePickerProps['enableTimePicker']; + isDateRangeContent?: boolean; } const DatePickerFooter = (props: DatePickerFooterProps) => { @@ -66,7 +67,7 @@ const DatePickerFooter = (props: DatePickerFooterProps) => {
{isSwitchMode && ( )} {enableTimePicker && needConfirm && ( diff --git a/packages/components/date-picker/panel/ExtraContent.tsx b/packages/components/date-picker/panel/ExtraContent.tsx index 30fc8f7350..bfc8aa3530 100644 --- a/packages/components/date-picker/panel/ExtraContent.tsx +++ b/packages/components/date-picker/panel/ExtraContent.tsx @@ -11,6 +11,7 @@ export interface ExtraContentProps selectedValue?: DateValue | DateMultipleValue; presets?: TdDatePickerProps['presets'] | TdDateRangePickerProps['presets']; onTimeModeChange?: () => void; + isDateRangeContent?: boolean; } export default function ExtraContent(props: ExtraContentProps) { @@ -29,6 +30,7 @@ export default function ExtraContent(props: ExtraContentProps) { selectedValue={selectedValue} needConfirm={needConfirm} onTimePanelChange={props.onTimeModeChange} + isDateRangeContent={props.isDateRangeContent} /> ) : null; } diff --git a/packages/components/date-picker/panel/RangePanel.tsx b/packages/components/date-picker/panel/RangePanel.tsx index d5d58ae325..8c3cd87a81 100644 --- a/packages/components/date-picker/panel/RangePanel.tsx +++ b/packages/components/date-picker/panel/RangePanel.tsx @@ -254,6 +254,7 @@ const RangePanel = forwardRef((originalProps, r presetsPlacement={presetsPlacement} needConfirm={needConfirm} onTimeModeChange={onTimeModeChange} + isDateRangeContent={isDateRangeContent} /> ) : null}
{renderPanelContent()}
@@ -265,6 +266,7 @@ const RangePanel = forwardRef((originalProps, r onPresetClick={onPresetClick} onConfirmClick={onConfirmClick} onTimeModeChange={onTimeModeChange} + isDateRangeContent={isDateRangeContent} presetsPlacement={presetsPlacement} needConfirm={needConfirm} /> From 08e12343eb159efb4e4564ff4ff62c246329e03e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C5=AB=20y=C4=81ng?= Date: Thu, 26 Feb 2026 15:51:44 +0800 Subject: [PATCH 04/11] chore: optimize --- packages/common | 2 +- .../components/date-picker/DateRangePicker.tsx | 5 ++++- .../components/date-picker/panel/RangePanel.tsx | 14 +++++++++----- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/common b/packages/common index 34819ff725..72b0e54f1a 160000 --- a/packages/common +++ b/packages/common @@ -1 +1 @@ -Subproject commit 34819ff725ec52b48835cbcd8c3ebc00dd61b524 +Subproject commit 72b0e54f1ab56ee513c865b98355feecb6fb2757 diff --git a/packages/components/date-picker/DateRangePicker.tsx b/packages/components/date-picker/DateRangePicker.tsx index 36c4ac17fe..8de76b2818 100644 --- a/packages/components/date-picker/DateRangePicker.tsx +++ b/packages/components/date-picker/DateRangePicker.tsx @@ -201,7 +201,7 @@ const DateRangePicker = forwardRef((origin setCacheValue(nextValue); setInputValue(nextValue); - // 有时间选择器走 confirm 逻辑 + // 有时间选择器且非 switch mode,走 confirm 逻辑 if (enableTimePicker && !isSwitchTimeMode) return; // 确保两端都是有效值 @@ -335,6 +335,8 @@ const DateRangePicker = forwardRef((origin } } + if (isSwitchTimeMode && nextValue.every(Boolean)) handlePopupInvisible(); + // 首次点击不关闭、确保两端都有有效值并且无时间选择器时点击后自动关闭 if (!isFirstValueSelected || !activeIndex) { let nextIndex = notValidIndex; @@ -472,6 +474,7 @@ const DateRangePicker = forwardRef((origin onMonthChange, onTimePickerChange, disableTime, + isSwitchTimeMode, }; return ( diff --git a/packages/components/date-picker/panel/RangePanel.tsx b/packages/components/date-picker/panel/RangePanel.tsx index 6035467e2a..d33969b522 100644 --- a/packages/components/date-picker/panel/RangePanel.tsx +++ b/packages/components/date-picker/panel/RangePanel.tsx @@ -9,6 +9,7 @@ import ExtraContent from './ExtraContent'; import useTableData from '../hooks/useTableData'; import useDisableDate from '../hooks/useDisableDate'; import useDefaultProps from '../../hooks/useDefaultProps'; + import { parseToDateTime } from '../utils'; import { TimePickerPanel } from '../../time-picker'; @@ -25,6 +26,7 @@ export interface RangePanelProps extends Omit }) => void; onCellClick?: (date: Date, context: { e: React.MouseEvent; partial: 'start' | 'end' }) => void; onCellMouseEnter?: (date: Date, context: { partial: 'start' | 'end' }) => void; @@ -50,6 +52,7 @@ const RangePanel = forwardRef((originalProps, r presetsPlacement: 'bottom', needConfirm: true, }); + const { value = [], hoverValue = [], @@ -75,6 +78,7 @@ const RangePanel = forwardRef((originalProps, r disableTime, onTimePickerChange, popupVisible, + isSwitchTimeMode, } = props; const { format, timeFormat } = getDefaultFormat({ @@ -98,10 +102,11 @@ const RangePanel = forwardRef((originalProps, r }); useEffect(() => { - if (!popupVisible) { + if (popupVisible && isSwitchTimeMode) { toggleDateRangeContent(true); } - }, [popupVisible]); + }, [popupVisible, isSwitchTimeMode]); + const disableTimeOptions: TdTimePickerProps['disableTime'] = (h, m, s, ms) => { if (!isFunction(disableTime)) { return {}; @@ -172,7 +177,7 @@ const RangePanel = forwardRef((originalProps, r const renderPanelContent = () => { // 没有开启时间选择,或者开启时间选择但模式是切换(switch),则日期面板和时间面板分开展示 - if (!enableTimePicker || (isObject(enableTimePicker) && enableTimePicker.mode === 'switch')) { + if (!enableTimePicker || isSwitchTimeMode) { if (isDateRangeContent) return ( <> @@ -239,8 +244,7 @@ const RangePanel = forwardRef((originalProps, r style={style} className={classNames(panelName, className, { [`${panelName}--direction-row`]: ['left', 'right'].includes(presetsPlacement), - [`${panelName}--switch-mode`]: - enableTimePicker && isObject(enableTimePicker) && enableTimePicker.mode === 'switch', + [`${panelName}--switch-mode`]: isSwitchTimeMode, })} onClick={(e) => onClick?.({ e })} > From 1b1becaa07ef11119491c52360abde0ea31b9f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C5=AB=20y=C4=81ng?= Date: Thu, 26 Feb 2026 15:58:36 +0800 Subject: [PATCH 05/11] chore: fix lint --- packages/components/date-picker/panel/RangePanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/date-picker/panel/RangePanel.tsx b/packages/components/date-picker/panel/RangePanel.tsx index d33969b522..bb864f48e7 100644 --- a/packages/components/date-picker/panel/RangePanel.tsx +++ b/packages/components/date-picker/panel/RangePanel.tsx @@ -1,6 +1,6 @@ import React, { forwardRef, useState, useEffect } from 'react'; import classNames from 'classnames'; -import { isFunction, isObject } from 'lodash-es'; +import { isFunction } from 'lodash-es'; import { getDefaultFormat, parseToDayjs } from '@tdesign/common-js/date-picker/format'; import useConfig from '../../hooks/useConfig'; import { StyledProps } from '../../common'; From e749e5cf3dd0932ac362d7437c690ca6985e107e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C5=AB=20y=C4=81ng?= Date: Thu, 26 Feb 2026 16:22:56 +0800 Subject: [PATCH 06/11] chore: optimize --- packages/components/date-picker/DateRangePicker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/date-picker/DateRangePicker.tsx b/packages/components/date-picker/DateRangePicker.tsx index 8de76b2818..1fb198bfba 100644 --- a/packages/components/date-picker/DateRangePicker.tsx +++ b/packages/components/date-picker/DateRangePicker.tsx @@ -225,7 +225,7 @@ const DateRangePicker = forwardRef((origin // 首次点击不关闭、确保两端都有有效值并且无时间选择器时点击后自动关闭 if (!isFirstValueSelected || !activeIndex || isSwitchTimeMode) { let nextIndex = notValidIndex; - if (isSwitchTimeMode && activeIndex === 1) return; + if (isSwitchTimeMode && activeIndex === 1 && isFirstValueSelected) return; if (nextIndex === -1) nextIndex = activeIndex ? 0 : 1; setActiveIndex(nextIndex); setIsFirstValueSelected(!!nextValue[0]); From 28aa4c2d510d9af998e4895eb75dad6db09f9236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C5=AB=20y=C4=81ng?= Date: Thu, 26 Feb 2026 16:45:45 +0800 Subject: [PATCH 07/11] chore: optimize --- packages/components/date-picker/base/Footer.tsx | 7 +++---- .../components/date-picker/panel/ExtraContent.tsx | 14 ++++++++++++-- .../components/date-picker/panel/PanelContent.tsx | 7 +++---- .../components/date-picker/panel/RangePanel.tsx | 5 +++++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/packages/components/date-picker/base/Footer.tsx b/packages/components/date-picker/base/Footer.tsx index 26538ba2a3..c369d19069 100644 --- a/packages/components/date-picker/base/Footer.tsx +++ b/packages/components/date-picker/base/Footer.tsx @@ -14,6 +14,7 @@ interface DatePickerFooterProps extends Pick void; enableTimePicker?: TdDateRangePickerProps['enableTimePicker'] | TdDatePickerProps['enableTimePicker']; isDateRangeContent?: boolean; + isSwitchTimeMode?: boolean; } const DatePickerFooter = (props: DatePickerFooterProps) => { @@ -31,6 +32,7 @@ const DatePickerFooter = (props: DatePickerFooterProps) => { selectedValue, needConfirm, onTimePanelChange, + isSwitchTimeMode, } = props; const footerClass = classNames( @@ -38,9 +40,6 @@ const DatePickerFooter = (props: DatePickerFooterProps) => { `${classPrefix}-date-picker__footer--${presetsPlacement}`, ); - // 在日期区间选择器下,可能存在两种时间选择面板的展示方式:并列展示(parallel)和切换展示(switch) - const isSwitchMode = isObject(enableTimePicker) && enableTimePicker?.mode === 'switch'; - const renderPresets = () => { if (presets) { if (React.isValidElement(presets)) return presets; @@ -65,7 +64,7 @@ const DatePickerFooter = (props: DatePickerFooterProps) => {
{renderPresets()}
- {isSwitchMode && ( + {isSwitchTimeMode && ( diff --git a/packages/components/date-picker/panel/ExtraContent.tsx b/packages/components/date-picker/panel/ExtraContent.tsx index bfc8aa3530..d2190898f0 100644 --- a/packages/components/date-picker/panel/ExtraContent.tsx +++ b/packages/components/date-picker/panel/ExtraContent.tsx @@ -12,11 +12,20 @@ export interface ExtraContentProps presets?: TdDatePickerProps['presets'] | TdDateRangePickerProps['presets']; onTimeModeChange?: () => void; isDateRangeContent?: boolean; + isSwitchTimeMode?: boolean; } export default function ExtraContent(props: ExtraContentProps) { - const { presets, enableTimePicker, presetsPlacement, onPresetClick, onConfirmClick, selectedValue, needConfirm } = - props; + const { + presets, + enableTimePicker, + presetsPlacement, + onPresetClick, + onConfirmClick, + selectedValue, + needConfirm, + isSwitchTimeMode, + } = props; const showPanelFooter = (enableTimePicker && needConfirm) || presets; @@ -31,6 +40,7 @@ export default function ExtraContent(props: ExtraContentProps) { needConfirm={needConfirm} onTimePanelChange={props.onTimeModeChange} isDateRangeContent={props.isDateRangeContent} + isSwitchTimeMode={isSwitchTimeMode} /> ) : null; } diff --git a/packages/components/date-picker/panel/PanelContent.tsx b/packages/components/date-picker/panel/PanelContent.tsx index 9c674f2c9d..d65a024711 100644 --- a/packages/components/date-picker/panel/PanelContent.tsx +++ b/packages/components/date-picker/panel/PanelContent.tsx @@ -24,6 +24,7 @@ export interface PanelContentProps { popupVisible?: boolean; tableData: any[]; internalYear?: Array; + isSwitchTimeMode?: boolean; onMonthChange: SinglePanelProps['onMonthChange'] | RangePanelProps['onMonthChange']; onYearChange: SinglePanelProps['onYearChange'] | RangePanelProps['onYearChange']; onJumperClick: SinglePanelProps['onJumperClick'] | RangePanelProps['onJumperClick']; @@ -46,7 +47,6 @@ export default function PanelContent(props: PanelContentProps) { enableTimePicker, timePickerProps, firstDayOfWeek, - partial = 'start', time, tableData, @@ -56,6 +56,7 @@ export default function PanelContent(props: PanelContentProps) { onCellMouseEnter, onCellMouseLeave, onTimePickerChange, + isSwitchTimeMode, } = props; const onMonthChange = useEventCallback(props.onMonthChange); @@ -63,9 +64,7 @@ export default function PanelContent(props: PanelContentProps) { const { timeFormat } = getDefaultFormat({ mode, format, enableTimePicker }); - const showTimePicker = - (isBoolean(enableTimePicker) && enableTimePicker) || - (isObject(enableTimePicker) && enableTimePicker.mode !== 'switch' && mode === 'date'); + const showTimePicker = enableTimePicker && !isSwitchTimeMode && mode === 'date'; const defaultTime = '00:00:00'; diff --git a/packages/components/date-picker/panel/RangePanel.tsx b/packages/components/date-picker/panel/RangePanel.tsx index bb864f48e7..de09a8250c 100644 --- a/packages/components/date-picker/panel/RangePanel.tsx +++ b/packages/components/date-picker/panel/RangePanel.tsx @@ -158,6 +158,7 @@ const RangePanel = forwardRef((originalProps, r firstDayOfWeek, popupVisible, enableTimePicker: props.enableTimePicker, + isSwitchTimeMode, timePickerProps: { disableTime: disableTimeOptions, ...props.timePickerProps, @@ -213,6 +214,7 @@ const RangePanel = forwardRef((originalProps, r format={timeFormat} value={time[0]} onChange={(val) => onTimePickerChange(val, { activeIndex: 0 })} + {...props.timePickerProps} /> ((originalProps, r format={timeFormat} value={time[1]} onChange={(val) => onTimePickerChange(val, { activeIndex: 1 })} + {...props.timePickerProps} /> ); @@ -259,6 +262,7 @@ const RangePanel = forwardRef((originalProps, r needConfirm={needConfirm} onTimeModeChange={onTimeModeChange} isDateRangeContent={isDateRangeContent} + isSwitchTimeMode={isSwitchTimeMode} /> ) : null}
{renderPanelContent()}
@@ -271,6 +275,7 @@ const RangePanel = forwardRef((originalProps, r onConfirmClick={onConfirmClick} onTimeModeChange={onTimeModeChange} isDateRangeContent={isDateRangeContent} + isSwitchTimeMode={isSwitchTimeMode} presetsPlacement={presetsPlacement} needConfirm={needConfirm} /> From 402b2cf2db1782636f348d93c4a5387d002eb400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C5=AB=20y=C4=81ng?= Date: Thu, 26 Feb 2026 16:52:43 +0800 Subject: [PATCH 08/11] chore: fix lint --- packages/components/date-picker/base/Footer.tsx | 2 +- packages/components/date-picker/panel/PanelContent.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/components/date-picker/base/Footer.tsx b/packages/components/date-picker/base/Footer.tsx index c369d19069..439dcd7c1c 100644 --- a/packages/components/date-picker/base/Footer.tsx +++ b/packages/components/date-picker/base/Footer.tsx @@ -1,6 +1,6 @@ import React from 'react'; import classNames from 'classnames'; -import { isFunction, isObject } from 'lodash-es'; +import { isFunction } from 'lodash-es'; import { useLocaleReceiver } from '../../locale/LocalReceiver'; import Button from '../../button'; import useConfig from '../../hooks/useConfig'; diff --git a/packages/components/date-picker/panel/PanelContent.tsx b/packages/components/date-picker/panel/PanelContent.tsx index d65a024711..1958cfcdcd 100644 --- a/packages/components/date-picker/panel/PanelContent.tsx +++ b/packages/components/date-picker/panel/PanelContent.tsx @@ -1,5 +1,4 @@ import React, { useCallback } from 'react'; -import { isBoolean, isObject } from 'lodash-es'; import { getDefaultFormat } from '@tdesign/common-js/date-picker/format'; import DateHeader from '../base/Header'; import DateTable from '../base/Table'; From 5ca3a5cbcbb6fa6d58ac258a304078db81a107ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C5=AB=20y=C4=81ng?= Date: Thu, 26 Feb 2026 18:07:40 +0800 Subject: [PATCH 09/11] feat: rangepicker panel add timepicker switch model --- .../date-picker/DateRangePickerPanel.tsx | 20 ++++++++++--------- .../components/date-picker/_example/panel.tsx | 7 +++++++ .../date-picker/hooks/useRangeValue.ts | 9 ++++++++- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/components/date-picker/DateRangePickerPanel.tsx b/packages/components/date-picker/DateRangePickerPanel.tsx index a7d0524af3..8f29498d8e 100644 --- a/packages/components/date-picker/DateRangePickerPanel.tsx +++ b/packages/components/date-picker/DateRangePickerPanel.tsx @@ -50,6 +50,7 @@ const DateRangePickerPanel = forwardRef dayjs(v).toDate()), trigger: 'time-hour' as DatePickerTimeChangeTrigger, }); @@ -346,8 +348,8 @@ const DateRangePickerPanel = forwardRef; }); diff --git a/packages/components/date-picker/_example/panel.tsx b/packages/components/date-picker/_example/panel.tsx index 9970229cad..14b395589b 100644 --- a/packages/components/date-picker/_example/panel.tsx +++ b/packages/components/date-picker/_example/panel.tsx @@ -34,6 +34,13 @@ export default function PanelExample() {
+
+ +
); } diff --git a/packages/components/date-picker/hooks/useRangeValue.ts b/packages/components/date-picker/hooks/useRangeValue.ts index 332720b5c2..dcfdef98e3 100644 --- a/packages/components/date-picker/hooks/useRangeValue.ts +++ b/packages/components/date-picker/hooks/useRangeValue.ts @@ -1,4 +1,5 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useMemo } from 'react'; +import { isObject } from 'lodash-es'; import { isValidDate, formatDate, @@ -47,6 +48,11 @@ export default function useRange(props: TdDateRangePickerProps) { const [year, setYear] = useState>(() => initYearMonthTime({ value, mode: props.mode, format }).year); const [cacheValue, setCacheValue] = useState(() => formatDate(value, { format })); // 缓存选中值,panel 点击时更改 + const isSwitchTimeMode = useMemo( + () => isObject(props.enableTimePicker) && props.enableTimePicker.mode === 'switch', + [props.enableTimePicker], + ); + // 输入框响应 value 变化 useEffect(() => { if (!value) { @@ -73,5 +79,6 @@ export default function useRange(props: TdDateRangePickerProps) { setIsFirstValueSelected, cacheValue, setCacheValue, + isSwitchTimeMode, }; } From 9ee3c2a452e0378b68f3468dba00982459ffe658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?w=C5=AB=20y=C4=81ng?= Date: Thu, 26 Feb 2026 18:14:44 +0800 Subject: [PATCH 10/11] chore: update snapshot --- test/snap/__snapshots__/csr.test.jsx.snap | 1309 ++++++++++++++++++++- test/snap/__snapshots__/ssr.test.jsx.snap | 2 +- 2 files changed, 1309 insertions(+), 2 deletions(-) diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap index 3d6056a351..edbb2283ab 100644 --- a/test/snap/__snapshots__/csr.test.jsx.snap +++ b/test/snap/__snapshots__/csr.test.jsx.snap @@ -42007,6 +42007,1313 @@ exports[`csr snapshot test > csr test packages/components/date-picker/_example/p
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + +
+
+
+
+
+
+
+
+ + + + + + +
+
+
+
+
+
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 一 + + 二 + + 三 + + 四 + + 五 + + 六 + + 日 +
+
+ 30 +
+
+
+ 1 +
+
+
+ 2 +
+
+
+ 3 +
+
+
+ 4 +
+
+
+ 5 +
+
+
+ 6 +
+
+
+ 7 +
+
+
+ 8 +
+
+
+ 9 +
+
+
+ 10 +
+
+
+ 11 +
+
+
+ 12 +
+
+
+ 13 +
+
+
+ 14 +
+
+
+ 15 +
+
+
+ 16 +
+
+
+ 17 +
+
+
+ 18 +
+
+
+ 19 +
+
+
+ 20 +
+
+
+ 21 +
+
+
+ 22 +
+
+
+ 23 +
+
+
+ 24 +
+
+
+ 25 +
+
+
+ 26 +
+
+
+ 27 +
+
+
+ 28 +
+
+
+ 29 +
+
+
+ 30 +
+
+
+ 31 +
+
+
+ 1 +
+
+
+ 2 +
+
+
+ 3 +
+
+
+ 4 +
+
+
+ 5 +
+
+
+ 6 +
+
+
+ 7 +
+
+
+ 8 +
+
+
+ 9 +
+
+
+ 10 +
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + +
+
+
+
+
+
+
+
+ + + + + + +
+
+
+
+
+
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 一 + + 二 + + 三 + + 四 + + 五 + + 六 + + 日 +
+
+ 28 +
+
+
+ 29 +
+
+
+ 30 +
+
+
+ 31 +
+
+
+ 1 +
+
+
+ 2 +
+
+
+ 3 +
+
+
+ 4 +
+
+
+ 5 +
+
+
+ 6 +
+
+
+ 7 +
+
+
+ 8 +
+
+
+ 9 +
+
+
+ 10 +
+
+
+ 11 +
+
+
+ 12 +
+
+
+ 13 +
+
+
+ 14 +
+
+
+ 15 +
+
+
+ 16 +
+
+
+ 17 +
+
+
+ 18 +
+
+
+ 19 +
+
+
+ 20 +
+
+
+ 21 +
+
+
+ 22 +
+
+
+ 23 +
+
+
+ 24 +
+
+
+ 25 +
+
+
+ 26 +
+
+
+ 27 +
+
+
+ 28 +
+
+
+ 29 +
+
+
+ 30 +
+
+
+ 31 +
+
+
+ 1 +
+
+
+ 2 +
+
+
+ 3 +
+
+
+ 4 +
+
+
+ 5 +
+
+
+ 6 +
+
+
+ 7 +
+
+
+
+
+
+ +
+
`; @@ -150872,7 +152179,7 @@ exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/m exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/multiple.tsx 1`] = `"
2024-10-01
2024-10-24
2024-50周
2024-51周
2022
2023
2024
"`; -exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/panel.tsx 1`] = `"
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
"`; +exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/panel.tsx 1`] = `"
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
"`; exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/quarter.tsx 1`] = `"
-
"`; diff --git a/test/snap/__snapshots__/ssr.test.jsx.snap b/test/snap/__snapshots__/ssr.test.jsx.snap index 6784da113b..4ddae9b59e 100644 --- a/test/snap/__snapshots__/ssr.test.jsx.snap +++ b/test/snap/__snapshots__/ssr.test.jsx.snap @@ -302,7 +302,7 @@ exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/m exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/multiple.tsx 1`] = `"
2024-10-01
2024-10-24
2024-50周
2024-51周
2022
2023
2024
"`; -exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/panel.tsx 1`] = `"
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
"`; +exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/panel.tsx 1`] = `"
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
00:00:00
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
"`; exports[`ssr snapshot test > ssr test packages/components/date-picker/_example/quarter.tsx 1`] = `"
-
"`; From dfd931ae25c464ad810660c94d417f6f49028cd9 Mon Sep 17 00:00:00 2001 From: tdesign-bot Date: Thu, 26 Feb 2026 10:30:28 +0000 Subject: [PATCH 11/11] chore: stash changelog [ci skip] --- packages/tdesign-react/.changelog/pr-4141.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 packages/tdesign-react/.changelog/pr-4141.md diff --git a/packages/tdesign-react/.changelog/pr-4141.md b/packages/tdesign-react/.changelog/pr-4141.md new file mode 100644 index 0000000000..704f13a485 --- /dev/null +++ b/packages/tdesign-react/.changelog/pr-4141.md @@ -0,0 +1,6 @@ +--- +pr_number: 4141 +contributor: uyarn +--- + +- feat(DateRangePicker): 日期时间范围选择器新增交互模式,通过 `enableTimePicker.mode` API 配置,具体可参考示例代码 @uyarn ([#4141](https://github.com/Tencent/tdesign-react/pull/4141))