fix(web-antdv-next): normalize date picker timestamp handling

Add DatePicker and RangePicker adapter wrappers for numeric timestamp values, route direct value-format="x" usages through the adapter, and keep ShortcutDateRangePicker values as Dayjs.
pull/362/head
XuZhiqiang 2026-06-18 14:21:12 +08:00
parent 2fc5575c30
commit f152217c3c
7 changed files with 94 additions and 14 deletions

View File

@ -0,0 +1,86 @@
import type { Component } from 'vue';
import type { Recordable } from '@vben/types';
import { defineAsyncComponent, defineComponent, h, ref } from 'vue';
const RawDatePicker = defineAsyncComponent(
() => import('antdv-next/dist/date-picker/index'),
);
const RawRangePicker = defineAsyncComponent(() =>
import('antdv-next/dist/date-picker/index').then(
(res) => res.DateRangePicker,
),
);
const TIMESTAMP_VALUE_FORMATS = new Set(['x', 'X']);
function isTimestampValueFormat(valueFormat: unknown) {
return (
typeof valueFormat === 'string' && TIMESTAMP_VALUE_FORMATS.has(valueFormat)
);
}
function normalizeTimestampPickerValue(value: any, valueFormat: unknown): any {
if (!isTimestampValueFormat(valueFormat)) {
return value;
}
if (Array.isArray(value)) {
return value.map((item) => normalizeTimestampPickerValue(item, valueFormat));
}
return typeof value === 'number' ? String(value) : value;
}
function withTimestampValueFormat(
component: Component,
name: 'DatePicker' | 'RangePicker',
) {
return defineComponent({
name,
inheritAttrs: false,
setup(_, { attrs, expose, slots }) {
const innerRef = ref();
expose(
new Proxy(
{},
{
get: (_target, key) => innerRef.value?.[key],
has: (_target, key) => key in (innerRef.value || {}),
},
),
);
return () => {
const pickerAttrs: Recordable<any> = { ...attrs };
if (
'value-format' in pickerAttrs &&
!Reflect.has(pickerAttrs, 'valueFormat')
) {
pickerAttrs.valueFormat = pickerAttrs['value-format'];
}
const valueFormat = pickerAttrs.valueFormat;
for (const key of [
'value',
'defaultValue',
'pickerValue',
'defaultPickerValue',
]) {
if (Reflect.has(pickerAttrs, key)) {
pickerAttrs[key] = normalizeTimestampPickerValue(
pickerAttrs[key],
valueFormat,
);
}
}
return h(component, { ...pickerAttrs, ref: innerRef }, slots);
};
},
});
}
const DatePicker = withTimestampValueFormat(RawDatePicker, 'DatePicker');
const RangePicker = withTimestampValueFormat(RawRangePicker, 'RangePicker');
export { DatePicker, RangePicker };

View File

@ -75,6 +75,9 @@ import { message, Modal, notification } from 'antdv-next';
import { uploadFile as uploadFileApi } from '#/api/infra/file';
import { Tinymce as RichTextarea } from '#/components/tinymce';
import { FileUpload, ImageUpload } from '#/components/upload';
import { DatePicker, RangePicker } from './date-picker';
type AdapterUploadProps = UploadProps & {
aspectRatio?: string;
crop?: boolean;
@ -97,9 +100,6 @@ const Checkbox = defineAsyncComponent(
const CheckboxGroup = defineAsyncComponent(() =>
import('antdv-next/dist/checkbox/index').then((res) => res.CheckboxGroup),
);
const DatePicker = defineAsyncComponent(
() => import('antdv-next/dist/date-picker/index'),
);
const Divider = defineAsyncComponent(
() => import('antdv-next/dist/divider/index'),
);
@ -117,11 +117,6 @@ const Radio = defineAsyncComponent(() => import('antdv-next/dist/radio/index'));
const RadioGroup = defineAsyncComponent(() =>
import('antdv-next/dist/radio/index').then((res) => res.RadioGroup),
);
const RangePicker = defineAsyncComponent(() =>
import('antdv-next/dist/date-picker/index').then(
(res) => res.DateRangePicker,
),
);
const Rate = defineAsyncComponent(() => import('antdv-next/dist/rate/index'));
const Select = defineAsyncComponent(
() => import('antdv-next/dist/select/index'),
@ -794,4 +789,4 @@ async function initComponentAdapter() {
});
}
export { initComponentAdapter };
export { DatePicker, initComponentAdapter, RangePicker };

View File

@ -91,7 +91,6 @@ onMounted(() => {
<DateRangePicker
v-model:value="times"
:format="rangePickerProps.format"
:value-format="rangePickerProps.valueFormat"
:placeholder="rangePickerProps.placeholder"
:presets="rangePickerProps.presets"
class="!w-full !max-w-96"

View File

@ -8,7 +8,6 @@ import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import {
DatePicker,
Form,
Input,
message,
@ -16,6 +15,7 @@ import {
RadioGroup,
} from 'antdv-next';
import { DatePicker } from '#/adapter/component/date-picker';
import {
createDemo01Contact,
getDemo01Contact,

View File

@ -8,7 +8,6 @@ import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import {
DatePicker,
Form,
Input,
message,
@ -16,6 +15,7 @@ import {
RadioGroup,
} from 'antdv-next';
import { DatePicker } from '#/adapter/component/date-picker';
import {
createDemo03Student,
getDemo03Student,

View File

@ -8,7 +8,6 @@ import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import {
DatePicker,
Form,
Input,
message,
@ -17,6 +16,7 @@ import {
Tabs,
} from 'antdv-next';
import { DatePicker } from '#/adapter/component/date-picker';
import {
createDemo03Student,
getDemo03Student,

View File

@ -8,7 +8,6 @@ import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import {
DatePicker,
Form,
Input,
message,
@ -17,6 +16,7 @@ import {
Tabs,
} from 'antdv-next';
import { DatePicker } from '#/adapter/component/date-picker';
import {
createDemo03Student,
getDemo03Student,