diff --git a/packages/devui-vue/devui/date-picker-pro/__tests__/date-picker-pro.spec.tsx b/packages/devui-vue/devui/date-picker-pro/__tests__/date-picker-pro.spec.tsx
index 95efb3f013..657ae514fa 100644
--- a/packages/devui-vue/devui/date-picker-pro/__tests__/date-picker-pro.spec.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/__tests__/date-picker-pro.spec.tsx
@@ -2,7 +2,7 @@ import { mount } from '@vue/test-utils';
import dayjs from 'dayjs';
import DDatePickerPro from '../src/date-picker-pro';
import { nextTick, ref, getCurrentInstance } from 'vue';
-import { useNamespace } from '../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import DButton from '../../button/src/button';
import { Locale } from '../../locale';
import { getDateIndex, getSelectedDate, getSelectedIndex } from './utils';
diff --git a/packages/devui-vue/devui/date-picker-pro/__tests__/month-picker.spec.tsx b/packages/devui-vue/devui/date-picker-pro/__tests__/month-picker.spec.tsx
index 8a5af37ac1..9aa5370093 100644
--- a/packages/devui-vue/devui/date-picker-pro/__tests__/month-picker.spec.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/__tests__/month-picker.spec.tsx
@@ -2,7 +2,7 @@ import { mount } from '@vue/test-utils';
import DDatePickerPro from '../src/date-picker-pro';
import DRangeDatePickerPro from '../src/components/range-date-picker-pro';
import { nextTick, ref, getCurrentInstance } from 'vue';
-import { useNamespace } from '../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import { Locale } from '../../locale';
const ns = useNamespace('date-picker-pro', true);
diff --git a/packages/devui-vue/devui/date-picker-pro/__tests__/range-date-picker-pro.spec.tsx b/packages/devui-vue/devui/date-picker-pro/__tests__/range-date-picker-pro.spec.tsx
index 1e681ccd6a..41f9521832 100644
--- a/packages/devui-vue/devui/date-picker-pro/__tests__/range-date-picker-pro.spec.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/__tests__/range-date-picker-pro.spec.tsx
@@ -2,7 +2,7 @@ import { mount } from '@vue/test-utils';
import dayjs from 'dayjs';
import DRangeDatePickerPro from '../src/components/range-date-picker-pro';
import { nextTick, ref, getCurrentInstance } from 'vue';
-import { useNamespace } from '../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import DButton from '../../button/src/button';
import { Locale } from '../../locale';
import { getDateIndex, getSelectedDate, getSelectedIndex } from './utils';
diff --git a/packages/devui-vue/devui/date-picker-pro/__tests__/utils.ts b/packages/devui-vue/devui/date-picker-pro/__tests__/utils.ts
index 2f4ba9fedf..017f5e685c 100644
--- a/packages/devui-vue/devui/date-picker-pro/__tests__/utils.ts
+++ b/packages/devui-vue/devui/date-picker-pro/__tests__/utils.ts
@@ -6,9 +6,9 @@ export const getDateIndex = (date: Date): number => {
};
export const getSelectedIndex = (todayIndex: number, intervalDay = 1): number => {
- return todayIndex > 20 ? todayIndex : todayIndex + intervalDay;
+ return todayIndex > 20 ? todayIndex - 1 : todayIndex + intervalDay;
};
export const getSelectedDate = (todayIndex: number, date: Date, intervalDay = 1): string => {
- return todayIndex > 20 ? dayjs(date).format(DATE_FORMAT) : dayjs(date).add(intervalDay, 'day').format(DATE_FORMAT);
+ return todayIndex > 20 ? dayjs(date).subtract(1, 'day').format(DATE_FORMAT) : dayjs(date).add(intervalDay, 'day').format(DATE_FORMAT);
};
diff --git a/packages/devui-vue/devui/date-picker-pro/__tests__/year-picker.spec.tsx b/packages/devui-vue/devui/date-picker-pro/__tests__/year-picker.spec.tsx
index 659293c712..879ae46c2d 100644
--- a/packages/devui-vue/devui/date-picker-pro/__tests__/year-picker.spec.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/__tests__/year-picker.spec.tsx
@@ -2,7 +2,7 @@ import { mount } from '@vue/test-utils';
import DDatePickerPro from '../src/date-picker-pro';
import DRangeDatePickerPro from '../src/components/range-date-picker-pro';
import { nextTick, ref, getCurrentInstance } from 'vue';
-import { useNamespace } from '../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import { Locale } from '../../locale';
const ns = useNamespace('date-picker-pro', true);
diff --git a/packages/devui-vue/devui/date-picker-pro/src/components/calendar-panel.tsx b/packages/devui-vue/devui/date-picker-pro/src/components/calendar-panel.tsx
index 1a50454e5d..77b09dffbe 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/components/calendar-panel.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/src/components/calendar-panel.tsx
@@ -1,11 +1,13 @@
import { defineComponent, getCurrentInstance } from 'vue';
import type { SetupContext } from 'vue';
-import { useNamespace } from '../../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
+import { RecycleScroller } from 'vue-virtual-scroller'
import useCalendarPanel from '../composables/use-calendar-panel';
import { YearAndMonthItem, datePickerProPanelProps, DatePickerProPanelProps } from '../date-picker-pro-types';
import { createI18nTranslate } from '../../../locale/create';
import { yearListHeight, yearItemHeight, calendarListHeight, calendarItemHeight } from '../const';
import { VirtualList } from '../../../virtual-list';
+import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
export default defineComponent({
name: 'CalendarPanel',
@@ -34,7 +36,8 @@ export default defineComponent({
} = useCalendarPanel(props, ctx);
return () => {
const yearItemSlots = {
- item: (item: YearAndMonthItem) => {
+ default: (scoped: any) => {
+ const item = scoped.item;
return (
{!item.isMonth && !isListCollapse.value && (
@@ -106,13 +109,14 @@ export default defineComponent({
return (
-
+
+
+
diff --git a/packages/devui-vue/devui/date-picker-pro/src/components/date-picker-panel.tsx b/packages/devui-vue/devui/date-picker-pro/src/components/date-picker-panel.tsx
index ebcaa293c0..f3d00987b8 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/components/date-picker-panel.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/src/components/date-picker-panel.tsx
@@ -1,6 +1,6 @@
import { defineComponent, getCurrentInstance } from 'vue';
import type { SetupContext } from 'vue';
-import { useNamespace } from '../../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import CalendarPanel from './calendar-panel';
import TimerPickerPanel from './time-picker-panel';
import { Button } from '../../../button';
diff --git a/packages/devui-vue/devui/date-picker-pro/src/components/month-calendar-panel.tsx b/packages/devui-vue/devui/date-picker-pro/src/components/month-calendar-panel.tsx
index b8a8826438..393a465de3 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/components/month-calendar-panel.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/src/components/month-calendar-panel.tsx
@@ -1,6 +1,6 @@
import { defineComponent, getCurrentInstance } from 'vue';
import type { SetupContext } from 'vue';
-import { useNamespace } from '../../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import useMonthCalendarPanel from '../composables/use-month-calendar-panel';
import { datePickerProPanelProps, DatePickerProPanelProps, YearAndMonthItem } from '../date-picker-pro-types';
import { createI18nTranslate } from '../../../locale/create';
diff --git a/packages/devui-vue/devui/date-picker-pro/src/components/range-date-picker-pro.tsx b/packages/devui-vue/devui/date-picker-pro/src/components/range-date-picker-pro.tsx
index 0ba472323f..40dcb86069 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/components/range-date-picker-pro.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/src/components/range-date-picker-pro.tsx
@@ -1,4 +1,4 @@
-import { defineComponent, Transition, ref, renderSlot, useSlots, getCurrentInstance, Teleport, withModifiers } from 'vue';
+import { defineComponent, Transition, ref, renderSlot, useSlots, getCurrentInstance, Teleport, withModifiers, toRefs } from 'vue';
import type { SetupContext } from 'vue';
import { rangeDatePickerProProps, RangeDatePickerProProps } from '../range-date-picker-types';
import { FlexibleOverlay } from '../../../overlay';
@@ -6,7 +6,7 @@ import DatePickerProPanel from './date-picker-panel';
import { Input } from '../../../input';
import { IconCalendar } from './icon-calendar';
import { IconClose } from './icon-close';
-import { useNamespace } from '../../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import useRangePickerPro from '../composables/use-range-date-picker-pro';
import '../date-picker-pro.scss';
@@ -19,6 +19,7 @@ export default defineComponent({
setup(props: RangeDatePickerProProps, ctx: SetupContext) {
const app = getCurrentInstance();
const t = createI18nTranslate('DDatePickerPro', app);
+ const { position } = toRefs(props)
const ns = useNamespace('range-date-picker-pro');
const {
@@ -42,8 +43,8 @@ export default defineComponent({
onSelectedDate,
handlerClearTime,
onChangeRangeFocusType,
+ onStartInputChange,
} = useRangePickerPro(props, ctx);
- const position = ref(['bottom-start', 'top-start']);
return () => {
const vSlots = {
@@ -56,8 +57,8 @@ export default defineComponent({
(isMouseEnter.value = true)}
- onMouseout={() => (isMouseEnter.value = false)}>
+ onMouseenter={() => (isMouseEnter.value = true)}
+ onMouseleave={() => (isMouseEnter.value = false)}>
onStartInputChange(val, 'start')}
+ validate-event={false}
onFocus={withModifiers(
(e: MouseEvent) => {
onFocus('start');
@@ -98,6 +101,8 @@ export default defineComponent({
ref={endInputRef}
modelValue={displayDateValue.value[1]}
placeholder={placeholder.value[1] || t('endPlaceholder')}
+ onUpate:modelValue={(val) => onStartInputChange(val, 'end')}
+ validate-event={false}
onFocus={withModifiers(
(e: MouseEvent) => {
onFocus('end');
@@ -109,11 +114,11 @@ export default defineComponent({
disabled={pickerDisabled.value}
v-slots={{
suffix: () => (
-
-
-
+ showCloseIcon.value ?
+
+
+ : null
),
}}
/>
diff --git a/packages/devui-vue/devui/date-picker-pro/src/components/time-picker-panel.tsx b/packages/devui-vue/devui/date-picker-pro/src/components/time-picker-panel.tsx
index 42f097aae7..13e5ea1f41 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/components/time-picker-panel.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/src/components/time-picker-panel.tsx
@@ -1,6 +1,6 @@
import { defineComponent, getCurrentInstance } from 'vue';
import type { SetupContext } from 'vue';
-import { useNamespace } from '../../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import DTimeList from '../../../time-picker/src/components/popup-line';
import useTimePickerPanel from '../composables/use-time-picker-panel';
import { TimerPickerPanelProps, timerPickerPanelProps } from '../date-picker-pro-types';
diff --git a/packages/devui-vue/devui/date-picker-pro/src/components/year-calendar-panel.tsx b/packages/devui-vue/devui/date-picker-pro/src/components/year-calendar-panel.tsx
index c4a82e22e1..1d1fc332e5 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/components/year-calendar-panel.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/src/components/year-calendar-panel.tsx
@@ -1,6 +1,6 @@
import { defineComponent } from 'vue';
import type { SetupContext } from 'vue';
-import { useNamespace } from '../../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import useYearCalendarPanel from '../composables/use-year-calendar-panel';
import { datePickerProPanelProps, DatePickerProPanelProps } from '../date-picker-pro-types';
import { yearPickerHeight, yearCalendarItemHeight } from '../const';
diff --git a/packages/devui-vue/devui/date-picker-pro/src/composables/use-calendar-panel.ts b/packages/devui-vue/devui/date-picker-pro/src/composables/use-calendar-panel.ts
index a68bd21e4e..a316a35325 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/composables/use-calendar-panel.ts
+++ b/packages/devui-vue/devui/date-picker-pro/src/composables/use-calendar-panel.ts
@@ -1,10 +1,11 @@
import { ref, onBeforeMount, nextTick, watch, onMounted } from 'vue';
import type { SetupContext } from 'vue';
+import { v4 as uuidv4 } from 'uuid'
import { DAY_DURATION, calendarItemHeight } from '../const';
import { CalendarDateItem, YearAndMonthItem, UseCalendarPanelReturnType, DatePickerProPanelProps } from '../date-picker-pro-types';
import dayjs from 'dayjs';
import type { Dayjs } from 'dayjs';
-import { throttle } from 'lodash';
+import throttle from 'lodash/throttle';
import useCalendarSelected from './use-calendar-selected';
export default function useCalendarPanel(props: DatePickerProPanelProps, ctx: SetupContext): UseCalendarPanelReturnType {
@@ -68,6 +69,7 @@ export default function useCalendarPanel(props: DatePickerProPanelProps, ctx: Se
for (let year = calendarRange.value[0]; year <= calendarRange.value[1]; year++) {
const yearOption: YearAndMonthItem = {
+ id: uuidv4(),
year,
isMonth: false,
active: false,
@@ -81,6 +83,7 @@ export default function useCalendarPanel(props: DatePickerProPanelProps, ctx: Se
};
allMonthList.value.push(monthOption);
const yearMonthOption: YearAndMonthItem = {
+ id: uuidv4(),
year,
month,
isMonth: true,
@@ -121,7 +124,7 @@ export default function useCalendarPanel(props: DatePickerProPanelProps, ctx: Se
}
nextTick(() => {
const scrollEl = yearScrollRef.value;
- scrollEl?.scrollTo?.(scrollIndex);
+ scrollEl?.scrollToItem?.(scrollIndex);
});
};
@@ -149,7 +152,9 @@ export default function useCalendarPanel(props: DatePickerProPanelProps, ctx: Se
}
const toDate = getToDate(props.dateValue);
if (toDate) {
- goToShowDate(toDate.toDate());
+ nextTick(() => {
+ goToShowDate(toDate.toDate());
+ })
}
};
@@ -202,7 +207,12 @@ export default function useCalendarPanel(props: DatePickerProPanelProps, ctx: Se
const selectedMonth = activeItem?.month;
isListCollapse.value = !isListCollapse.value;
if (isListCollapse.value) {
- yearAndMonthList.value = yearAndMonthList.value.filter((child) => !child.isMonth);
+ yearAndMonthList.value = yearAndMonthList.value
+ .map((child) => {
+ child.active = false;
+ return child;
+ })
+ .filter((child) => !child.isMonth);
} else {
initCalendarData();
}
diff --git a/packages/devui-vue/devui/date-picker-pro/src/composables/use-month-calendar-panel.ts b/packages/devui-vue/devui/date-picker-pro/src/composables/use-month-calendar-panel.ts
index dfe333200c..8bdd6af904 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/composables/use-month-calendar-panel.ts
+++ b/packages/devui-vue/devui/date-picker-pro/src/composables/use-month-calendar-panel.ts
@@ -1,9 +1,9 @@
import { ref, onBeforeMount, nextTick, watch } from 'vue';
import type { SetupContext } from 'vue';
-import { useNamespace } from '../../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import { monthCalendarItemHeight } from '../const';
import { DatePickerProPanelProps, YearAndMonthItem, UseMonthCalendarPanelReturnType } from '../date-picker-pro-types';
-import { throttle } from 'lodash';
+import throttle from 'lodash/throttle';
import dayjs from 'dayjs';
import type { Dayjs } from 'dayjs';
import useCalendarSelected from './use-calendar-selected';
diff --git a/packages/devui-vue/devui/date-picker-pro/src/composables/use-range-date-picker-pro.ts b/packages/devui-vue/devui/date-picker-pro/src/composables/use-range-date-picker-pro.ts
index de461c1d91..0e8999cd12 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/composables/use-range-date-picker-pro.ts
+++ b/packages/devui-vue/devui/date-picker-pro/src/composables/use-range-date-picker-pro.ts
@@ -1,14 +1,19 @@
-import { shallowRef, ref, computed, inject, watch } from 'vue';
+import { shallowRef, ref, computed, inject, getCurrentInstance, watch, toRefs } from 'vue';
import type { SetupContext } from 'vue';
import { RangeDatePickerProProps, UseRangePickerProReturnType } from '../range-date-picker-types';
import { onClickOutside } from '@vueuse/core';
import type { Dayjs } from 'dayjs';
-import { formatDayjsToStr, isDateEquals, parserDate } from '../utils';
+import { debounce } from '@devui/shared'
+import { formatDayjsToStr, isDateEquals, parserDate, isInputDateValid } from '../utils';
import { FORM_ITEM_TOKEN, FORM_TOKEN } from '../../../form';
+import { createI18nTranslate } from '../../../locale/create';
export default function useRangePickerPro(props: RangeDatePickerProProps, ctx: SetupContext): UseRangePickerProReturnType {
const formContext = inject(FORM_TOKEN, undefined);
const formItemContext = inject(FORM_ITEM_TOKEN, undefined);
+ const { calendarRange, limitDateRange, allowClear } = toRefs(props);
+ const app = getCurrentInstance()
+ const t = createI18nTranslate('DCommon', app)
const originRef = ref();
const startInputRef = shallowRef();
@@ -22,7 +27,9 @@ export default function useRangePickerPro(props: RangeDatePickerProProps, ctx: S
const pickerDisabled = computed(() => formContext?.disabled || props.disabled);
const pickerSize = computed(() => formContext?.size || props.size);
const isValidateError = computed(() => formItemContext?.validateState === 'error');
-
+ const toggle = () => {
+ toggleChange(!isPanelShow.value)
+ }
const toggleChange = (isShow: boolean) => {
isPanelShow.value = isShow;
ctx.emit('toggleChange', isShow);
@@ -42,9 +49,16 @@ export default function useRangePickerPro(props: RangeDatePickerProProps, ctx: S
const focusHandler = function (e: MouseEvent) {
ctx.emit('focus', e);
};
-
+ const langMap: Record = {
+ 'zh-cn': 'YYYY/MM/DD',
+ 'en-us': 'MMM DD, YYYY'
+ }
+ const langTimeMap: Record = {
+ 'zh-cn': 'YYYY/MM/DD HH:mm:ss',
+ 'en-us': 'MMM DD, YYYY HH:mm:ss'
+ }
const format = computed(() => {
- return props.showTime ? props.format || 'YYYY/MM/DD HH:mm:ss' : props.format || 'YYYY/MM/DD';
+ return props.showTime ? props.format || langTimeMap[t('lang')] : props.format || langMap[t('lang')];
});
const dateValue = computed(() => {
@@ -60,8 +74,8 @@ export default function useRangePickerPro(props: RangeDatePickerProProps, ctx: S
});
const displayDateValue = computed(() => {
- const startFormatDate = formatDayjsToStr(dateValue.value[0], format.value, props.type);
- const endFormatDate = formatDayjsToStr(dateValue.value[1], format.value, props.type);
+ const startFormatDate = formatDayjsToStr(dateValue.value[0], format.value, props.type, t('lang'));
+ const endFormatDate = formatDayjsToStr(dateValue.value[1], format.value, props.type, t('lang'));
if (startFormatDate) {
return endFormatDate ? [startFormatDate, endFormatDate] : [startFormatDate, ''];
} else if (endFormatDate) {
@@ -70,19 +84,36 @@ export default function useRangePickerPro(props: RangeDatePickerProProps, ctx: S
return ['', ''];
});
- const showCloseIcon = computed(() => isMouseEnter.value && (displayDateValue.value[0] !== '' || displayDateValue.value[1] !== ''));
+
+ const showCloseIcon = computed(
+ () =>
+ !pickerDisabled.value &&
+ isMouseEnter.value &&
+ (displayDateValue.value[0] !== '' || displayDateValue.value[1] !== '') &&
+ allowClear.value
+ );
const onSelectedDate = (date: Dayjs[], isConfirm?: boolean) => {
const [startDate, endDate] = date;
const selectStart = startDate ? startDate.toDate() : startDate;
const selectEnd = endDate ? endDate.toDate() : endDate;
const [start, end] = props.modelValue;
+ const temp: any[] = []
+ if (selectStart) {
+ temp.push(selectStart)
+ if (selectEnd) {
+ temp.push(selectEnd)
+ }
+ } else if (selectEnd) {
+ temp.push('')
+ temp.push(selectEnd)
+ }
if (!isDateEquals(start, selectStart) || !isDateEquals(end, selectEnd)) {
- ctx.emit('update:modelValue', [selectStart ? selectStart : '', selectEnd ? selectEnd : '']);
+ ctx.emit('update:modelValue', temp);
}
if (isConfirm) {
// 回调参数为Date类型
- ctx.emit('confirmEvent', [selectStart ? selectStart : '', selectEnd ? selectEnd : '']);
+ ctx.emit('confirmEvent', temp);
toggleChange(false);
}
};
@@ -106,8 +137,8 @@ export default function useRangePickerPro(props: RangeDatePickerProProps, ctx: S
}
e.stopPropagation();
e.preventDefault();
- ctx.emit('update:modelValue', ['', '']);
- ctx.emit('confirmEvent', ['', '']);
+ ctx.emit('update:modelValue', []);
+ ctx.emit('confirmEvent', []);
// 当面板未关闭时,清空后focusType置位start
if (isPanelShow.value) {
onChangeRangeFocusType('start');
@@ -115,6 +146,7 @@ export default function useRangePickerPro(props: RangeDatePickerProProps, ctx: S
};
ctx.expose({
+ toggle,
focusChange: onChangeRangeFocusType,
});
@@ -125,11 +157,29 @@ export default function useRangePickerPro(props: RangeDatePickerProProps, ctx: S
onChangeRangeFocusType(type);
toggleChange(true);
};
+ const onStartInputChange = debounce((val: string, type: 'start' | 'end') => {
+ isInputDateValid(val, format.value, calendarRange.value, limitDateRange?.value, (validDate: string) => {
+ const currentDate = [...props.modelValue];
+ if (type === 'start') {
+ currentDate[0] = validDate;
+ } else {
+ currentDate[0] = currentDate[0] ?? '';
+ currentDate[1] = validDate;
+ }
+ ctx.emit('update:modelValue', currentDate)
+ });
+ }, 300);
+
+ watch(isPanelShow, (show) => {
+ if (!show) {
+ formItemContext?.validate('blur').catch(() => { })
+ }
+ });
watch(
() => props.modelValue,
() => {
- formItemContext?.validate('change').catch((err) => console.warn(err));
+ formItemContext?.validate('change').catch(() => { });
},
{ deep: true }
);
@@ -155,5 +205,6 @@ export default function useRangePickerPro(props: RangeDatePickerProProps, ctx: S
onSelectedDate,
handlerClearTime,
onChangeRangeFocusType,
+ onStartInputChange,
};
}
diff --git a/packages/devui-vue/devui/date-picker-pro/src/composables/use-time-picker-panel.ts b/packages/devui-vue/devui/date-picker-pro/src/composables/use-time-picker-panel.ts
index 61e92f9e71..0785eda16e 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/composables/use-time-picker-panel.ts
+++ b/packages/devui-vue/devui/date-picker-pro/src/composables/use-time-picker-panel.ts
@@ -19,6 +19,11 @@ export default function useTimePickerPanel(props: TimerPickerPanelProps, ctx: Se
watch(
() => [props.visible, props.bindData],
([visible, newTimeVal], [, oldTimeVal]) => {
+ const reg = /(\d{2}):(\d{2}):(\d{2})/;
+ if (typeof newTimeVal === 'string') {
+ const result = newTimeVal.match(reg);
+ newTimeVal = result![0];
+ }
if (newTimeVal && (visible || newTimeVal !== oldTimeVal)) {
timeListDom.value.setOuterTime(newTimeVal);
} else {
diff --git a/packages/devui-vue/devui/date-picker-pro/src/composables/use-year-calendar-panel.ts b/packages/devui-vue/devui/date-picker-pro/src/composables/use-year-calendar-panel.ts
index e86a94ac0f..91f5c6a5f3 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/composables/use-year-calendar-panel.ts
+++ b/packages/devui-vue/devui/date-picker-pro/src/composables/use-year-calendar-panel.ts
@@ -1,7 +1,7 @@
import { ref, onBeforeMount, nextTick, watch } from 'vue';
import type { SetupContext } from 'vue';
-import { chunk } from 'lodash';
-import { useNamespace } from '../../../shared/hooks/use-namespace';
+import chunk from 'lodash/chunk';
+import { useNamespace } from '@devui/shared/utils';
import { DatePickerProPanelProps, UseYearCalendarPanelReturnType } from '../date-picker-pro-types';
import dayjs from 'dayjs';
import type { Dayjs } from 'dayjs';
diff --git a/packages/devui-vue/devui/date-picker-pro/src/const.ts b/packages/devui-vue/devui/date-picker-pro/src/const.ts
index ff49789c38..b09c25c849 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/const.ts
+++ b/packages/devui-vue/devui/date-picker-pro/src/const.ts
@@ -9,6 +9,3 @@ export const monthCalendarItemHeight = 186; // 月选择器一个年份日历面
export const yearPickerHeight = 186; // 年选择器模式下年份虚拟列表的高度
export const yearCalendarItemHeight = 48; // 年选择器日历面板单行的高度
-
-export const DEFAULT_DATE = 'YYYY/MM/DD';
-export const DEFAULT_TIME = `${DEFAULT_DATE} HH:mm:ss`;
diff --git a/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro-types.ts b/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro-types.ts
index 62d6109fc6..aa924e1b5e 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro-types.ts
+++ b/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro-types.ts
@@ -3,6 +3,20 @@ import type { Dayjs } from 'dayjs';
import { ArrType } from '../../time-picker/src/types';
import type { InputSize } from '../../input/src/input-types';
+export type Placement =
+ | 'top'
+ | 'right'
+ | 'bottom'
+ | 'left'
+ | 'top-start'
+ | 'top-end'
+ | 'right-start'
+ | 'right-end'
+ | 'bottom-start'
+ | 'bottom-end'
+ | 'left-start'
+ | 'left-end';
+
export const datePickerProCommonProps = {
format: {
type: String,
@@ -30,6 +44,14 @@ export const datePickerProCommonProps = {
type: String,
default: 'date',
},
+ position: {
+ type: Array as PropType>,
+ default: ['bottom-start']
+ },
+ allowClear: {
+ type: Boolean,
+ default: true
+ }
};
export const datePickerProProps = {
@@ -63,6 +85,8 @@ export interface UseDatePickerProReturnType {
onFocus: (e: MouseEvent) => void;
onSelectedDate: (date: Dayjs, isConfirm?: boolean) => void;
handlerClearTime: (e: MouseEvent) => void;
+ onInputChange: (e: string) => void;
+ toggle: () => void;
}
export interface CalendarDateItem {
@@ -74,6 +98,7 @@ export interface CalendarDateItem {
}
export interface YearAndMonthItem {
+ id?: string,
year: number;
month?: number;
isMonth?: boolean;
diff --git a/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro.scss b/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro.scss
index 66236ab5b0..e0cf7c3c63 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro.scss
+++ b/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro.scss
@@ -106,14 +106,17 @@ $input-height-lg: 46px;
line-height: 30px;
cursor: pointer;
}
+
.#{$devui-prefix}-date-picker-pro__month-title {
font-size: $devui-font-size-sm;
line-height: 30px;
cursor: pointer;
}
+
&.#{$devui-prefix}-date-picker-pro__year-title-active {
background-color: $devui-base-bg;
}
+
&:hover:not(.#{$devui-prefix}-date-picker-pro__year-title-active) {
background-color: $devui-list-item-selected-bg;
}
@@ -212,6 +215,7 @@ $input-height-lg: 46px;
color: $devui-list-item-active-text;
}
}
+
&.#{$devui-prefix}-date-picker-pro__table-date-in-range {
background-color: $devui-list-item-hover-bg;
@@ -292,6 +296,7 @@ $input-height-lg: 46px;
line-height: 30px;
}
}
+
.#{$devui-prefix}-time-list {
border: none;
@@ -370,6 +375,10 @@ $input-height-lg: 46px;
.#{$devui-prefix}-range-date-picker-pro__input {
flex: 1 1;
+
+ .#{$devui-prefix}-input__inner {
+ text-align: center;
+ }
}
.#{$devui-prefix}-input {
@@ -401,6 +410,7 @@ $input-height-lg: 46px;
color: $devui-brand;
}
}
+
.#{$devui-prefix}-range-date-picker-pro__normal-input {
.#{$devui-prefix}-input__inner {
color: $devui-text;
@@ -411,6 +421,7 @@ $input-height-lg: 46px;
display: inline-block;
padding: 0 4px;
}
+
.#{$devui-prefix}-input-slot__suffix {
cursor: pointer;
}
@@ -461,6 +472,7 @@ $input-height-lg: 46px;
cursor: not-allowed;
}
}
+
&.#{$devui-prefix}-range-date-picker-pro--error {
border-color: $devui-danger-line;
background-color: $devui-danger-bg;
@@ -501,6 +513,7 @@ $input-height-lg: 46px;
padding: 4px 0;
height: 48px;
}
+
.#{$devui-prefix}-date-picker-pro__year-item-title {
width: 60px;
height: 40px;
@@ -548,6 +561,7 @@ $input-height-lg: 46px;
}
}
}
+
// 月选择器
.#{$devui-prefix}-date-picker-pro__month-calendar-panel {
height: 300px;
@@ -577,11 +591,13 @@ $input-height-lg: 46px;
&.#{$devui-prefix}-date-picker-pro__year-item-active {
background-color: $devui-base-bg;
}
+
&:hover:not(.#{$devui-prefix}-date-picker-pro__year-item-active) {
background-color: $devui-list-item-selected-bg;
}
}
}
+
.#{$devui-prefix}-date-picker-pro__month-wrapper {
height: 300px;
width: 208px;
@@ -690,4 +706,4 @@ $input-height-lg: 46px;
}
}
}
-}
+}
\ No newline at end of file
diff --git a/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro.tsx b/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro.tsx
index 459180d8a8..afee699e34 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro.tsx
+++ b/packages/devui-vue/devui/date-picker-pro/src/date-picker-pro.tsx
@@ -1,13 +1,13 @@
-import { defineComponent, Transition, ref, renderSlot, useSlots, getCurrentInstance, Teleport, withModifiers } from 'vue';
+import { defineComponent, Transition, ref, renderSlot, useSlots, getCurrentInstance, Teleport, withModifiers, toRefs } from 'vue';
import type { SetupContext } from 'vue';
import { datePickerProProps, DatePickerProProps } from './date-picker-pro-types';
import usePickerPro from './use-picker-pro';
import { Input } from '../../input';
-import { FlexibleOverlay, Placement } from '../../overlay';
+import { FlexibleOverlay } from '../../overlay';
import DatePickerProPanel from './components/date-picker-panel';
import { IconCalendar } from './components/icon-calendar';
import { IconClose } from './components/icon-close';
-import { useNamespace } from '../../shared/hooks/use-namespace';
+import { useNamespace } from '@devui/shared/utils';
import './date-picker-pro.scss';
import { createI18nTranslate } from '../../locale/create';
@@ -18,6 +18,8 @@ export default defineComponent({
setup(props: DatePickerProProps, ctx: SetupContext) {
const app = getCurrentInstance();
const t = createI18nTranslate('DDatePickerPro', app);
+ const commonT = createI18nTranslate('DCommon', app)
+ const { position } = toRefs(props);
const ns = useNamespace('date-picker-pro');
const {
@@ -37,7 +39,10 @@ export default defineComponent({
onFocus,
onSelectedDate,
handlerClearTime,
- } = usePickerPro(props, ctx, t);
+ onInputChange,
+ toggle,
+ } = usePickerPro(props, ctx, t, commonT);
+ ctx.expose({ toggle })
const position = ref(['bottom-start', 'top-start']);
return () => {
const vSlots = {
@@ -49,8 +54,8 @@ export default defineComponent({
(isMouseEnter.value = true)}
- onMouseout={() => (isMouseEnter.value = false)}>
+ onMouseenter={() => (isMouseEnter.value = true)}
+ onMouseleave={() => (isMouseEnter.value = false)}>
(
@@ -66,9 +72,10 @@ export default defineComponent({
),
suffix: () => (
-
-
-
+ showCloseIcon.value ?
+
+
+ : null
),
}}
/>
@@ -93,7 +100,7 @@ export default defineComponent({
-
+
);
};
},
diff --git a/packages/devui-vue/devui/date-picker-pro/src/range-date-picker-types.ts b/packages/devui-vue/devui/date-picker-pro/src/range-date-picker-types.ts
index 5d86df20f6..2595cc7fae 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/range-date-picker-types.ts
+++ b/packages/devui-vue/devui/date-picker-pro/src/range-date-picker-types.ts
@@ -5,7 +5,7 @@ import { datePickerProCommonProps } from './date-picker-pro-types';
export const rangeDatePickerProProps = {
modelValue: {
type: Array as PropType<(Date | string)[]>,
- default: ['', ''],
+ default: [],
},
placeholder: {
type: Array as PropType,
@@ -41,4 +41,5 @@ export interface UseRangePickerProReturnType {
onSelectedDate: (date: Dayjs[], isConfirm?: boolean) => void;
handlerClearTime: (e: MouseEvent) => void;
onChangeRangeFocusType: (type: string) => void;
+ onStartInputChange: (e: string, type: 'start' | 'end') => void;
}
diff --git a/packages/devui-vue/devui/date-picker-pro/src/use-picker-pro.ts b/packages/devui-vue/devui/date-picker-pro/src/use-picker-pro.ts
index 42c774e53f..4f0c726fd4 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/use-picker-pro.ts
+++ b/packages/devui-vue/devui/date-picker-pro/src/use-picker-pro.ts
@@ -1,19 +1,21 @@
-import { shallowRef, ref, computed, inject, watch } from 'vue';
+import { shallowRef, ref, computed, inject, watch, toRefs } from 'vue';
import type { SetupContext } from 'vue';
import { DatePickerProProps, UseDatePickerProReturnType } from './date-picker-pro-types';
import { onClickOutside } from '@vueuse/core';
import type { Dayjs } from 'dayjs';
-import { formatDayjsToStr, isDateEquals, parserDate } from './utils';
+import { debounce } from 'lodash';
+import { formatDayjsToStr, isDateEquals, parserDate, isInputDateValid } from './utils';
import { FORM_ITEM_TOKEN, FORM_TOKEN } from '../../form';
-import { DEFAULT_DATE, DEFAULT_TIME } from './const';
export default function usePickerPro(
props: DatePickerProProps,
ctx: SetupContext,
- t: (path: string) => unknown
+ t: (path: string) => unknown,
+ commonT: (path: string) => string
): UseDatePickerProReturnType {
const formContext = inject(FORM_TOKEN, undefined);
const formItemContext = inject(FORM_ITEM_TOKEN, undefined);
+ const { calendarRange, limitDateRange, allowClear } = toRefs(props)
const originRef = ref();
const inputRef = shallowRef();
@@ -26,6 +28,10 @@ export default function usePickerPro(
const pickerSize = computed(() => formContext?.size || props.size);
const isValidateError = computed(() => formItemContext?.validateState === 'error');
+ const toggle = () => {
+ toggleChange(!isPanelShow.value)
+ }
+
const toggleChange = (isShow: boolean) => {
isPanelShow.value = isShow;
ctx.emit('toggleChange', isShow);
@@ -46,9 +52,16 @@ export default function usePickerPro(
toggleChange(true);
ctx.emit('focus', e);
};
-
+ const langMap: Record = {
+ 'zh-cn': 'YYYY/MM/DD',
+ 'en-us': 'MMM DD, YYYY'
+ }
+ const langTimeMap: Record = {
+ 'zh-cn': 'YYYY/MM/DD HH:mm:ss',
+ 'en-us': 'MMM DD, YYYY HH:mm:ss'
+ }
const format = computed(() => {
- return props.showTime ? props.format || DEFAULT_TIME : props.format || DEFAULT_DATE;
+ return props.showTime ? props.format || langTimeMap[commonT('lang')] : props.format || langMap[commonT('lang')];
});
const dateValue = computed(() => {
@@ -60,14 +73,16 @@ export default function usePickerPro(
});
const displayDateValue = computed(() => {
- const formatDate = formatDayjsToStr(dateValue.value, format.value, props.type);
+ const formatDate = formatDayjsToStr(dateValue.value, format.value, props.type, commonT('lang'));
if (formatDate) {
return formatDate;
}
return '';
});
- const showCloseIcon = computed(() => isMouseEnter.value && (props.modelValue ? true : false));
+ const showCloseIcon = computed(
+ () => !pickerDisabled.value && isMouseEnter.value && (props.modelValue ? true : false) && allowClear.value
+ );
const onSelectedDate = (date: Dayjs, isConfirm?: boolean) => {
const result = date ? date.toDate() : date;
@@ -95,10 +110,16 @@ export default function usePickerPro(
}
};
+ const onInputChange = debounce((val: string) => {
+ isInputDateValid(val, format.value, calendarRange.value, limitDateRange?.value, (validDate: string) => {
+ ctx.emit('update:modelValue', validDate)
+ });
+ }, 300);
+
watch(
() => props.modelValue,
() => {
- formItemContext?.validate('change').catch((err) => console.warn(err));
+ formItemContext?.validate('change').catch(() => { });
},
{ deep: true }
);
@@ -120,5 +141,7 @@ export default function usePickerPro(
onFocus,
onSelectedDate,
handlerClearTime,
+ onInputChange,
+ toggle,
};
}
diff --git a/packages/devui-vue/devui/date-picker-pro/src/utils.ts b/packages/devui-vue/devui/date-picker-pro/src/utils.ts
index 04749caef8..32f61545ea 100644
--- a/packages/devui-vue/devui/date-picker-pro/src/utils.ts
+++ b/packages/devui-vue/devui/date-picker-pro/src/utils.ts
@@ -1,17 +1,20 @@
import dayjs from 'dayjs';
import type { Dayjs } from 'dayjs';
import { ArrType } from '../../time-picker/src/types';
-import { DEFAULT_DATE } from './const';
+import { getCurrentInstance } from 'vue';
+import { createI18nTranslate } from '../../locale/create';
-export const formatDayjsToStr = (date: Dayjs | undefined, format: string, type: string): string | null => {
+const app = getCurrentInstance()
+export const t = createI18nTranslate('DDatePickerPro', app)
+export const formatDayjsToStr = (date: Dayjs | undefined, format: string, type: string, lang: string): string | null => {
+ const monthEnArr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
if (!date) {
return null;
}
if (type === 'year') {
return date.year().toString();
} else if (type === 'month') {
- const month = date.month() + 1 < 10 ? '0' + (date.month() + 1) : date.month() + 1;
- return `${date.year()}-${month}`;
+ return lang === 'en-us' ? `${monthEnArr[date.month()]} ${date.year()}` : `${date.year()} ${t('year')} ${date.month() + 1} ${t('month')}`;
} else {
// 兼容非法格式(format),如果是非法格式,则使用默认格式(YYYY/MM/DD)
return dayjs(date.format(format)).isValid() ? date.format(format) : date.format(DEFAULT_DATE);
@@ -34,3 +37,30 @@ export const resetActiveTimeData = (list: ArrType[]): void => {
item.isActive = false;
});
};
+
+export const isInputDateValid = (
+ inputVal: string,
+ format: string,
+ calendarRange: Array,
+ limitDateRange: Array | undefined,
+ cb: (validDate: string) => void
+) => {
+ const inputDate = parserDate(inputVal);
+ const formatedDate = inputDate?.format(format);
+ const year = inputDate?.year();
+ const [startYear, endYear] = calendarRange;
+ const isInCalendarRange = year && startYear && endYear && year >= startYear && year <= endYear;
+ const [startDate, endDate] = limitDateRange ?? [];
+ const startDateTime = startDate?.valueOf();
+ const endDateTime = endDate?.valueOf();
+ const inputDateTime = inputDate?.valueOf();
+ const isInLimitDateRange =
+ inputDateTime && startDateTime && endDateTime && inputDateTime >= startDateTime && inputDateTime <= endDateTime;
+ if (inputDate && formatedDate === inputVal) {
+ if (limitDateRange?.length === 2) {
+ isInLimitDateRange && cb(formatedDate)
+ } else if (isInCalendarRange) {
+ cb(formatedDate);
+ }
+ }
+};