feat: 增加双击自动填充数据,以及自动设置是否全天的bug
parent
53c4256f10
commit
5843bf5fd9
|
|
@ -0,0 +1,123 @@
|
||||||
|
<docs>
|
||||||
|
---
|
||||||
|
order: 7
|
||||||
|
title:
|
||||||
|
zh-CN: 自动填充和整天模式
|
||||||
|
en-US: Auto Fill and Whole Day Mode
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
RangePicker 支持两个新功能:
|
||||||
|
1. `autoFill`:双击日期时自动设置为开始和结束日期
|
||||||
|
2. `isWholeDay`:在 showTime 模式下,自动设置开始时间为 00:00:00,结束时间为 23:59:59
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
RangePicker supports two new features:
|
||||||
|
1. `autoFill`: Double-click a date to automatically set it as both start and end date
|
||||||
|
2. `isWholeDay`: In showTime mode, automatically set start time to 00:00:00 and end time to 23:59:59
|
||||||
|
|
||||||
|
</docs>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-space direction="vertical" :size="12">
|
||||||
|
<div>
|
||||||
|
<h4>Auto Fill 功能</h4>
|
||||||
|
<p>双击日期会自动设置为开始和结束日期</p>
|
||||||
|
<a-range-picker :auto-fill="true" @change="onAutoFillChange" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4>Whole Day 功能</h4>
|
||||||
|
<p>在 showTime 模式下,自动设置整天时间</p>
|
||||||
|
<a-range-picker
|
||||||
|
show-time
|
||||||
|
:is-whole-day="true"
|
||||||
|
format="YYYY/MM/DD HH:mm:ss"
|
||||||
|
@change="onWholeDayChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4>组合使用</h4>
|
||||||
|
<p>同时启用 autoFill 和 isWholeDay</p>
|
||||||
|
<a-range-picker
|
||||||
|
show-time
|
||||||
|
:auto-fill="true"
|
||||||
|
:is-whole-day="true"
|
||||||
|
format="YYYY/MM/DD HH:mm:ss"
|
||||||
|
@change="onCombinedChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
|
|
||||||
|
type RangeValue = [Dayjs, Dayjs];
|
||||||
|
|
||||||
|
const onAutoFillChange = (
|
||||||
|
values: RangeValue,
|
||||||
|
dateStrings: [string, string],
|
||||||
|
currentPreset?: any,
|
||||||
|
) => {
|
||||||
|
if (values) {
|
||||||
|
console.log(
|
||||||
|
'Auto Fill - From: ',
|
||||||
|
values[0].format('YYYY-MM-DD'),
|
||||||
|
', to: ',
|
||||||
|
values[1].format('YYYY-MM-DD'),
|
||||||
|
);
|
||||||
|
console.log('Auto Fill - From: ', dateStrings[0], ', to: ', dateStrings[1]);
|
||||||
|
if (currentPreset) {
|
||||||
|
console.log('Auto Fill - Selected preset: ', currentPreset.label);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Auto Fill - Clear');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onWholeDayChange = (
|
||||||
|
values: RangeValue,
|
||||||
|
dateStrings: [string, string],
|
||||||
|
currentPreset?: any,
|
||||||
|
) => {
|
||||||
|
if (values) {
|
||||||
|
console.log(
|
||||||
|
'Whole Day - From: ',
|
||||||
|
values[0].format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
', to: ',
|
||||||
|
values[1].format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
);
|
||||||
|
console.log('Whole Day - From: ', dateStrings[0], ', to: ', dateStrings[1]);
|
||||||
|
if (currentPreset) {
|
||||||
|
console.log('Whole Day - Selected preset: ', currentPreset.label);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Whole Day - Clear');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCombinedChange = (
|
||||||
|
values: RangeValue,
|
||||||
|
dateStrings: [string, string],
|
||||||
|
currentPreset?: any,
|
||||||
|
) => {
|
||||||
|
if (values) {
|
||||||
|
console.log(
|
||||||
|
'Combined - From: ',
|
||||||
|
values[0].format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
', to: ',
|
||||||
|
values[1].format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
);
|
||||||
|
console.log('Combined - From: ', dateStrings[0], ', to: ', dateStrings[1]);
|
||||||
|
if (currentPreset) {
|
||||||
|
console.log('Combined - Selected preset: ', currentPreset.label);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Combined - Clear');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<Suffix />
|
<Suffix />
|
||||||
<statusVue />
|
<statusVue />
|
||||||
<placementVue />
|
<placementVue />
|
||||||
|
<AutoFillWholeDay />
|
||||||
</demo-sort>
|
</demo-sort>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -36,6 +37,7 @@ import Suffix from './suffix.vue';
|
||||||
import Bordered from './bordered.vue';
|
import Bordered from './bordered.vue';
|
||||||
import RangePicker from './range-picker.vue';
|
import RangePicker from './range-picker.vue';
|
||||||
import placementVue from './placement.vue';
|
import placementVue from './placement.vue';
|
||||||
|
import AutoFillWholeDay from './auto-fill-whole-day.vue';
|
||||||
import statusVue from './status.vue';
|
import statusVue from './status.vue';
|
||||||
import CN from '../index.zh-CN.md';
|
import CN from '../index.zh-CN.md';
|
||||||
import US from '../index.en-US.md';
|
import US from '../index.en-US.md';
|
||||||
|
|
@ -62,6 +64,7 @@ export default defineComponent({
|
||||||
SelectInRnage,
|
SelectInRnage,
|
||||||
Bordered,
|
Bordered,
|
||||||
RangePicker,
|
RangePicker,
|
||||||
|
AutoFillWholeDay,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -40,25 +40,31 @@ const onChange = (date: Dayjs) => {
|
||||||
console.log('Clear');
|
console.log('Clear');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const onRangeChange = (dates: RangeValue, dateStrings: string[]) => {
|
const onRangeChange = (values: RangeValue, dateStrings: [string, string], currentPreset?: any) => {
|
||||||
if (dates) {
|
if (values) {
|
||||||
console.log('From: ', dates[0], ', to: ', dates[1]);
|
console.log('From: ', values[0], ', to: ', values[1]);
|
||||||
console.log('From: ', dateStrings[0], ', to: ', dateStrings[1]);
|
console.log('From: ', dateStrings[0], ', to: ', dateStrings[1]);
|
||||||
|
if (currentPreset) {
|
||||||
|
console.log('Selected preset key: ', currentPreset.key);
|
||||||
|
console.log('Selected preset label: ', currentPreset.label);
|
||||||
|
} else {
|
||||||
|
console.log('Manual selection (no preset)');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('Clear');
|
console.log('Clear');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const presets = ref([
|
const presets = ref([
|
||||||
{ label: 'Yesterday', value: dayjs().add(-1, 'd') },
|
{ label: 'Yesterday', value: dayjs().add(-1, 'd'), key: 'yesterday' },
|
||||||
{ label: 'Last Week', value: dayjs().add(-7, 'd') },
|
{ label: 'Last Week', value: dayjs().add(-7, 'd'), key: 'lastweek' },
|
||||||
{ label: 'Last Month', value: dayjs().add(-1, 'month') },
|
{ label: 'Last Month', value: dayjs().add(-1, 'month'), key: 'lastmonth' },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const rangePresets = ref([
|
const rangePresets = ref([
|
||||||
{ label: 'Last 7 Days', value: [dayjs().add(-7, 'd'), dayjs()] },
|
{ label: 'Last 7 Days', value: [dayjs().add(-7, 'd'), dayjs()], key: 'last7days' },
|
||||||
{ label: 'Last 14 Days', value: [dayjs().add(-14, 'd'), dayjs()] },
|
{ label: 'Last 14 Days', value: [dayjs().add(-14, 'd'), dayjs()], key: 'last14days' },
|
||||||
{ label: 'Last 30 Days', value: [dayjs().add(-30, 'd'), dayjs()] },
|
{ label: 'Last 30 Days', value: [dayjs().add(-30, 'd'), dayjs()], key: 'last30days' },
|
||||||
{ label: 'Last 90 Days', value: [dayjs().add(-90, 'd'), dayjs()] },
|
{ label: 'Last 90 Days', value: [dayjs().add(-90, 'd'), dayjs()], key: 'last90days' },
|
||||||
]);
|
]);
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import useConfigInject from '../../config-provider/hooks/useConfigInject';
|
||||||
import classNames from '../../_util/classNames';
|
import classNames from '../../_util/classNames';
|
||||||
import type { CommonProps, RangePickerProps } from './props';
|
import type { CommonProps, RangePickerProps } from './props';
|
||||||
import { commonProps, rangePickerProps } from './props';
|
import { commonProps, rangePickerProps } from './props';
|
||||||
import type { PanelMode, RangeValue } from '../../vc-picker/interface';
|
import type { PanelMode, RangeValue, RangePickerOnChange } from '../../vc-picker/interface';
|
||||||
import type { RangePickerSharedProps } from '../../vc-picker/RangePicker';
|
import type { RangePickerSharedProps } from '../../vc-picker/RangePicker';
|
||||||
import { FormItemInputContext, useInjectFormItemContext } from '../../form/FormItemContext';
|
import { FormItemInputContext, useInjectFormItemContext } from '../../form/FormItemContext';
|
||||||
import omit from '../../_util/omit';
|
import omit from '../../_util/omit';
|
||||||
|
|
@ -84,13 +84,18 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
|
||||||
pickerRef.value?.blur();
|
pickerRef.value?.blur();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const maybeToStrings = (dates: DateType[]) => {
|
const maybeToStrings = (dates: RangeValue<DateType>) => {
|
||||||
return props.valueFormat ? generateConfig.toString(dates, props.valueFormat) : dates;
|
return props.valueFormat ? generateConfig.toString(dates, props.valueFormat) : dates;
|
||||||
};
|
};
|
||||||
const onChange = (dates: RangeValue<DateType>, dateStrings: [string, string]) => {
|
const onChange: RangePickerOnChange<DateType> = (values, formatStrings) => {
|
||||||
const values = maybeToStrings(dates);
|
const [startValue, endValue, currentPreset] = values;
|
||||||
emit('update:value', values);
|
const [startStr, endStr] = formatStrings;
|
||||||
emit('change', values, dateStrings);
|
const dates: RangeValue<DateType> = [startValue, endValue];
|
||||||
|
const dateStrings: [string, string] = [startStr, endStr];
|
||||||
|
|
||||||
|
const processedValues = maybeToStrings(dates);
|
||||||
|
emit('update:value', processedValues);
|
||||||
|
emit('change', processedValues, dateStrings, currentPreset);
|
||||||
formItemContext.onFieldChange();
|
formItemContext.onFieldChange();
|
||||||
};
|
};
|
||||||
const onOpenChange = (open: boolean) => {
|
const onOpenChange = (open: boolean) => {
|
||||||
|
|
@ -109,7 +114,7 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
|
||||||
emit('panelChange', values, modes);
|
emit('panelChange', values, modes);
|
||||||
};
|
};
|
||||||
const onOk = (dates: DateType[]) => {
|
const onOk = (dates: DateType[]) => {
|
||||||
const value = maybeToStrings(dates);
|
const value = props.valueFormat ? generateConfig.toString(dates, props.valueFormat) : dates;
|
||||||
emit('ok', value);
|
emit('ok', value);
|
||||||
};
|
};
|
||||||
const onCalendarChange: RangePickerSharedProps<DateType>['onCalendarChange'] = (
|
const onCalendarChange: RangePickerSharedProps<DateType>['onCalendarChange'] = (
|
||||||
|
|
|
||||||
|
|
@ -269,8 +269,13 @@ export interface RangePickerProps<DateType> {
|
||||||
onChange?: (
|
onChange?: (
|
||||||
value: RangeValue<DateType> | RangeValue<string> | null,
|
value: RangeValue<DateType> | RangeValue<string> | null,
|
||||||
dateString: [string, string],
|
dateString: [string, string],
|
||||||
|
currentPreset?: any,
|
||||||
) => void;
|
) => void;
|
||||||
'onUpdate:value'?: (value: RangeValue<DateType> | RangeValue<string> | null) => void;
|
'onUpdate:value'?: (value: RangeValue<DateType> | RangeValue<string> | null) => void;
|
||||||
|
/** 双击日期时自动设置为开始和结束日期 */
|
||||||
|
autoFill?: boolean;
|
||||||
|
/** 在 showTime 模式下,是否设置为整天(开始时间 00:00:00,结束时间 23:59:59) */
|
||||||
|
isWholeDay?: boolean;
|
||||||
onCalendarChange?: (
|
onCalendarChange?: (
|
||||||
values: RangeValue<DateType> | RangeValue<string>,
|
values: RangeValue<DateType> | RangeValue<string>,
|
||||||
formatString: [string, string],
|
formatString: [string, string],
|
||||||
|
|
|
||||||
|
|
@ -961,6 +961,7 @@ const genPickerStyle: GenerateStyle<PickerToken> = token => {
|
||||||
controlItemBgHover,
|
controlItemBgHover,
|
||||||
presetsWidth,
|
presetsWidth,
|
||||||
presetsMaxWidth,
|
presetsMaxWidth,
|
||||||
|
fontWeightStrong,
|
||||||
} = token;
|
} = token;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
@ -1326,6 +1327,12 @@ const genPickerStyle: GenerateStyle<PickerToken> = token => {
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
background: controlItemBgHover,
|
background: controlItemBgHover,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[`&${componentCls}-preset-active`]: {
|
||||||
|
background: controlItemBgActive,
|
||||||
|
color: colorPrimary,
|
||||||
|
fontWeight: fontWeightStrong,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,18 @@
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import type { PresetDate } from './interface';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'PresetPanel',
|
name: 'PresetPanel',
|
||||||
props: {
|
props: {
|
||||||
prefixCls: String,
|
prefixCls: String,
|
||||||
presets: {
|
presets: {
|
||||||
type: Array,
|
type: Array as () => PresetDate<any>[],
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
|
currentPreset: {
|
||||||
|
type: Object as () => PresetDate<any> | null,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
onClick: Function,
|
onClick: Function,
|
||||||
onHover: Function,
|
onHover: Function,
|
||||||
},
|
},
|
||||||
|
|
@ -19,21 +24,24 @@ export default defineComponent({
|
||||||
return (
|
return (
|
||||||
<div class={`${props.prefixCls}-presets`}>
|
<div class={`${props.prefixCls}-presets`}>
|
||||||
<ul>
|
<ul>
|
||||||
{props.presets.map(({ label, value }, index) => (
|
{props.presets.map(preset => (
|
||||||
<li
|
<li
|
||||||
key={index}
|
key={preset.key}
|
||||||
|
class={{
|
||||||
|
[`${props.prefixCls}-preset-active`]: props.currentPreset?.key === preset.key,
|
||||||
|
}}
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
props.onClick(value);
|
props.onClick(preset.value, preset);
|
||||||
}}
|
}}
|
||||||
onMouseenter={() => {
|
onMouseenter={() => {
|
||||||
props.onHover?.(value);
|
props.onHover?.(preset.value);
|
||||||
}}
|
}}
|
||||||
onMouseleave={() => {
|
onMouseleave={() => {
|
||||||
props.onHover?.(null);
|
props.onHover?.(null);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{label}
|
{preset.label}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import type {
|
||||||
RangeValue,
|
RangeValue,
|
||||||
EventValue,
|
EventValue,
|
||||||
PresetDate,
|
PresetDate,
|
||||||
|
RangePickerOnChange,
|
||||||
} from './interface';
|
} from './interface';
|
||||||
import type { PickerBaseProps, PickerDateProps, PickerTimeProps } from './Picker';
|
import type { PickerBaseProps, PickerDateProps, PickerTimeProps } from './Picker';
|
||||||
import type { SharedTimeProps } from './panels/TimePanel';
|
import type { SharedTimeProps } from './panels/TimePanel';
|
||||||
|
|
@ -108,7 +109,7 @@ export type RangePickerSharedProps<DateType> = {
|
||||||
separator?: VueNode;
|
separator?: VueNode;
|
||||||
allowEmpty?: [boolean, boolean];
|
allowEmpty?: [boolean, boolean];
|
||||||
mode?: [PanelMode, PanelMode];
|
mode?: [PanelMode, PanelMode];
|
||||||
onChange?: (values: RangeValue<DateType>, formatString: [string, string]) => void;
|
onChange?: RangePickerOnChange<DateType>;
|
||||||
onCalendarChange?: (
|
onCalendarChange?: (
|
||||||
values: RangeValue<DateType>,
|
values: RangeValue<DateType>,
|
||||||
formatString: [string, string],
|
formatString: [string, string],
|
||||||
|
|
@ -133,6 +134,10 @@ export type RangePickerSharedProps<DateType> = {
|
||||||
nextIcon?: VueNode;
|
nextIcon?: VueNode;
|
||||||
superPrevIcon?: VueNode;
|
superPrevIcon?: VueNode;
|
||||||
superNextIcon?: VueNode;
|
superNextIcon?: VueNode;
|
||||||
|
/** 双击日期时自动设置为开始和结束日期 */
|
||||||
|
autoFill?: boolean;
|
||||||
|
/** 在 showTime 模式下,是否设置为整天(开始时间 00:00:00,结束时间 23:59:59) */
|
||||||
|
isWholeDay?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type OmitPickerProps<Props> = Omit<
|
type OmitPickerProps<Props> = Omit<
|
||||||
|
|
@ -258,6 +263,8 @@ function RangerPicker<DateType>() {
|
||||||
'nextIcon',
|
'nextIcon',
|
||||||
'superPrevIcon',
|
'superPrevIcon',
|
||||||
'superNextIcon',
|
'superNextIcon',
|
||||||
|
'autoFill',
|
||||||
|
'isWholeDay',
|
||||||
] as any,
|
] as any,
|
||||||
setup(props, { attrs, expose }) {
|
setup(props, { attrs, expose }) {
|
||||||
const needConfirmButton = computed(
|
const needConfirmButton = computed(
|
||||||
|
|
@ -319,6 +326,31 @@ function RangerPicker<DateType>() {
|
||||||
: reorderValues(values, props.generateConfig),
|
: reorderValues(values, props.generateConfig),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ========================= Current Preset =========================
|
||||||
|
const [currentPreset, setCurrentPreset] = useState<PresetDate<RangeValue<DateType>> | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 检查当前值是否匹配某个 preset
|
||||||
|
const checkAndSetPreset = (values: RangeValue<DateType>) => {
|
||||||
|
if (!values || !values[0] || !values[1]) {
|
||||||
|
setCurrentPreset(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const matchedPreset = presetList.value.find(preset => {
|
||||||
|
if (!preset.value || !preset.value[0] || !preset.value[1]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
isEqual(props.generateConfig, values[0], preset.value[0]) &&
|
||||||
|
isEqual(props.generateConfig, values[1], preset.value[1])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
setCurrentPreset(matchedPreset || null);
|
||||||
|
};
|
||||||
|
|
||||||
// =========================== View Date ===========================
|
// =========================== View Date ===========================
|
||||||
// Config view panel
|
// Config view panel
|
||||||
const [startViewDate, endViewDate, setViewDate] = useRangeViewDates({
|
const [startViewDate, endViewDate, setViewDate] = useRangeViewDates({
|
||||||
|
|
@ -491,7 +523,11 @@ function RangerPicker<DateType>() {
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function triggerChange(newValue: RangeValue<DateType>, sourceIndex: 0 | 1) {
|
function triggerChange(
|
||||||
|
newValue: RangeValue<DateType>,
|
||||||
|
sourceIndex: 0 | 1,
|
||||||
|
fromPreset = false,
|
||||||
|
) {
|
||||||
let values = newValue;
|
let values = newValue;
|
||||||
let startValue = getValue(values, 0);
|
let startValue = getValue(values, 0);
|
||||||
let endValue = getValue(values, 1);
|
let endValue = getValue(values, 1);
|
||||||
|
|
@ -541,8 +577,33 @@ function RangerPicker<DateType>() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle isWholeDay: set time to 00:00:00 for start and 23:59:59 for end when showTime is true
|
||||||
|
if (props.isWholeDay && showTime && values && values[0] && values[1]) {
|
||||||
|
const startDate = values[0];
|
||||||
|
const endDate = values[1];
|
||||||
|
|
||||||
|
// Set start time to 00:00:00
|
||||||
|
const startWithTime = generateConfig.setHour(
|
||||||
|
generateConfig.setMinute(generateConfig.setSecond(startDate, 0), 0),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set end time to 23:59:59
|
||||||
|
const endWithTime = generateConfig.setHour(
|
||||||
|
generateConfig.setMinute(generateConfig.setSecond(endDate, 59), 59),
|
||||||
|
23,
|
||||||
|
);
|
||||||
|
|
||||||
|
values = [startWithTime, endWithTime];
|
||||||
|
}
|
||||||
|
|
||||||
setSelectedValue(values);
|
setSelectedValue(values);
|
||||||
|
|
||||||
|
// 如果不是通过 preset 触发的,清除 currentPreset
|
||||||
|
if (!fromPreset) {
|
||||||
|
setCurrentPreset(null);
|
||||||
|
}
|
||||||
|
|
||||||
const startStr =
|
const startStr =
|
||||||
values && values[0]
|
values && values[0]
|
||||||
? formatValue(values[0], { generateConfig, locale, format: formatList.value[0] })
|
? formatValue(values[0], { generateConfig, locale, format: formatList.value[0] })
|
||||||
|
|
@ -577,7 +638,10 @@ function RangerPicker<DateType>() {
|
||||||
(!isEqual(generateConfig, getValue(mergedValue.value, 0), startValue) ||
|
(!isEqual(generateConfig, getValue(mergedValue.value, 0), startValue) ||
|
||||||
!isEqual(generateConfig, getValue(mergedValue.value, 1), endValue))
|
!isEqual(generateConfig, getValue(mergedValue.value, 1), endValue))
|
||||||
) {
|
) {
|
||||||
onChange(values, [startStr, endStr]);
|
onChange(
|
||||||
|
[startValue, endValue, currentPreset.value],
|
||||||
|
[startStr, endStr, currentPreset.value?.key || null],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -720,7 +784,7 @@ function RangerPicker<DateType>() {
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
triggerChange(selectedValue.value, index);
|
triggerChange(selectedValue.value, index, false);
|
||||||
resetText();
|
resetText();
|
||||||
},
|
},
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
|
|
@ -824,6 +888,11 @@ function RangerPicker<DateType>() {
|
||||||
setSelectedValue(mergedValue.value);
|
setSelectedValue(mergedValue.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 当 mergedValue 变化时,检查是否匹配某个 preset
|
||||||
|
watch(mergedValue, newValue => {
|
||||||
|
checkAndSetPreset(newValue);
|
||||||
|
});
|
||||||
|
|
||||||
// ============================ Warning ============================
|
// ============================ Warning ============================
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
|
|
@ -889,6 +958,37 @@ function RangerPicker<DateType>() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle isWholeDay: set default time values for start and end
|
||||||
|
if (props.isWholeDay && showTime) {
|
||||||
|
const now = generateConfig.getNow();
|
||||||
|
let defaultTime: DateType;
|
||||||
|
|
||||||
|
if (mergedActivePickerIndex.value === 0) {
|
||||||
|
// Start time: 00:00:00
|
||||||
|
defaultTime = generateConfig.setHour(
|
||||||
|
generateConfig.setMinute(generateConfig.setSecond(now, 0), 0),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// End time: 23:59:59
|
||||||
|
defaultTime = generateConfig.setHour(
|
||||||
|
generateConfig.setMinute(generateConfig.setSecond(now, 59), 59),
|
||||||
|
23,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof showTime === 'object') {
|
||||||
|
panelShowTime = {
|
||||||
|
...showTime,
|
||||||
|
defaultValue: defaultTime,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
panelShowTime = {
|
||||||
|
defaultValue: defaultTime,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let panelDateRender: DateRender<DateType> | null = null;
|
let panelDateRender: DateRender<DateType> | null = null;
|
||||||
if (dateRender) {
|
if (dateRender) {
|
||||||
panelDateRender = ({ current: date, today }) =>
|
panelDateRender = ({ current: date, today }) =>
|
||||||
|
|
@ -971,7 +1071,7 @@ function RangerPicker<DateType>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const onContextSelect = (date: DateType, type: 'key' | 'mouse' | 'submit') => {
|
const onContextSelect = (date: DateType, type: 'key' | 'mouse' | 'submit') => {
|
||||||
const values = updateValues(selectedValue.value, date, mergedActivePickerIndex.value);
|
let values = updateValues(selectedValue.value, date, mergedActivePickerIndex.value);
|
||||||
const currentIndex = mergedActivePickerIndex.value;
|
const currentIndex = mergedActivePickerIndex.value;
|
||||||
const isDoubleClick = isDoubleClickRef.value;
|
const isDoubleClick = isDoubleClickRef.value;
|
||||||
const shouldSwitch = type === 'mouse' && needConfirmButton.value && isDoubleClick;
|
const shouldSwitch = type === 'mouse' && needConfirmButton.value && isDoubleClick;
|
||||||
|
|
@ -979,13 +1079,28 @@ function RangerPicker<DateType>() {
|
||||||
// Reset double click state
|
// Reset double click state
|
||||||
isDoubleClickRef.value = false;
|
isDoubleClickRef.value = false;
|
||||||
|
|
||||||
|
// Handle autoFill: when double-clicking and autoFill is enabled, set the same date for both start and end
|
||||||
|
if (props.autoFill && isDoubleClick && type === 'mouse') {
|
||||||
|
values = [date, date];
|
||||||
|
}
|
||||||
|
|
||||||
if (type === 'submit' || (type !== 'key' && !needConfirmButton.value) || shouldSwitch) {
|
if (type === 'submit' || (type !== 'key' && !needConfirmButton.value) || shouldSwitch) {
|
||||||
// triggerChange will also update selected values
|
// triggerChange will also update selected values
|
||||||
triggerChange(values, mergedActivePickerIndex.value);
|
triggerChange(values, mergedActivePickerIndex.value, false);
|
||||||
|
|
||||||
// If double click, switch to next input
|
// If autoFill is enabled and we have both values, close the panel
|
||||||
// But check if both inputs are complete, if so don't switch to avoid animation before popup closes
|
if (
|
||||||
if (shouldSwitch) {
|
props.autoFill &&
|
||||||
|
isDoubleClick &&
|
||||||
|
type === 'mouse' &&
|
||||||
|
values &&
|
||||||
|
values[0] &&
|
||||||
|
values[1]
|
||||||
|
) {
|
||||||
|
triggerOpen(false, mergedActivePickerIndex.value);
|
||||||
|
} else if (shouldSwitch) {
|
||||||
|
// If double click, switch to next input
|
||||||
|
// But check if both inputs are complete, if so don't switch to avoid animation before popup closes
|
||||||
const startValue = getValue(values, 0);
|
const startValue = getValue(values, 0);
|
||||||
const endValue = getValue(values, 1);
|
const endValue = getValue(values, 1);
|
||||||
const bothValuesComplete = startValue && endValue;
|
const bothValuesComplete = startValue && endValue;
|
||||||
|
|
@ -1074,7 +1189,7 @@ function RangerPicker<DateType>() {
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
if (getValue(selectedValue.value, mergedActivePickerIndex.value)) {
|
if (getValue(selectedValue.value, mergedActivePickerIndex.value)) {
|
||||||
// triggerChangeOld(selectedValue.value);
|
// triggerChangeOld(selectedValue.value);
|
||||||
triggerChange(selectedValue.value, mergedActivePickerIndex.value);
|
triggerChange(selectedValue.value, mergedActivePickerIndex.value, false);
|
||||||
if (onOk) {
|
if (onOk) {
|
||||||
onOk(selectedValue.value);
|
onOk(selectedValue.value);
|
||||||
}
|
}
|
||||||
|
|
@ -1129,8 +1244,10 @@ function RangerPicker<DateType>() {
|
||||||
<PresetPanel
|
<PresetPanel
|
||||||
prefixCls={prefixCls}
|
prefixCls={prefixCls}
|
||||||
presets={presetList.value}
|
presets={presetList.value}
|
||||||
onClick={nextValue => {
|
currentPreset={currentPreset.value}
|
||||||
triggerChange(nextValue, null);
|
onClick={(nextValue, preset) => {
|
||||||
|
setCurrentPreset(preset);
|
||||||
|
triggerChange(nextValue, null, true);
|
||||||
triggerOpen(false, mergedActivePickerIndex.value);
|
triggerOpen(false, mergedActivePickerIndex.value);
|
||||||
}}
|
}}
|
||||||
onHover={hoverValue => {
|
onHover={hoverValue => {
|
||||||
|
|
@ -1207,7 +1324,7 @@ function RangerPicker<DateType>() {
|
||||||
values = updateValues(values, null, 1);
|
values = updateValues(values, null, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerChange(values, null);
|
triggerChange(values, null, false);
|
||||||
triggerOpen(false, mergedActivePickerIndex.value);
|
triggerOpen(false, mergedActivePickerIndex.value);
|
||||||
}}
|
}}
|
||||||
class={`${prefixCls}-clear`}
|
class={`${prefixCls}-clear`}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ export default function usePresets<T>(
|
||||||
return {
|
return {
|
||||||
label,
|
label,
|
||||||
value: newValues,
|
value: newValues,
|
||||||
|
key: label, // 添加 key 属性
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,4 +112,11 @@ export type CustomFormat<DateType> = (value: DateType) => string;
|
||||||
export interface PresetDate<T> {
|
export interface PresetDate<T> {
|
||||||
label: VueNode;
|
label: VueNode;
|
||||||
value: T;
|
value: T;
|
||||||
|
key: string; // 重要,需要用key来高亮选中状态
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 扩展的 onChange 回调类型,values 和 formatString 都包含第三个 preset 元素
|
||||||
|
export type RangePickerOnChange<DateType> = (
|
||||||
|
values: [DateType | null, DateType | null, PresetDate<RangeValue<DateType>> | null],
|
||||||
|
formatString: [string, string, string | null],
|
||||||
|
) => void;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue