diff --git a/packages/@core/ui-kit/form-ui/src/components/form-actions.vue b/packages/@core/ui-kit/form-ui/src/components/form-actions.vue index 460dc18f6..0904fd6cb 100644 --- a/packages/@core/ui-kit/form-ui/src/components/form-actions.vue +++ b/packages/@core/ui-kit/form-ui/src/components/form-actions.vue @@ -52,20 +52,92 @@ async function handleSubmit(e: Event) { if (!valid) { return; } - await unref(rootProps).handleSubmit?.(toRaw(form.values)); + + const values = handleRangeTimeValue(toRaw(form.values)); + await unref(rootProps).handleSubmit?.(values); } async function handleReset(e: Event) { e?.preventDefault(); e?.stopPropagation(); const props = unref(rootProps); + + const values = toRaw(form.values); + // 清理时间字段 + props.fieldMapToTime && + props.fieldMapToTime.forEach(([_, [startTimeKey, endTimeKey]]) => { + delete values[startTimeKey]; + delete values[endTimeKey]; + }); + if (isFunction(props.handleReset)) { - await props.handleReset?.(form.values); + await props.handleReset?.(values); } else { form.resetForm(); } } +function handleRangeTimeValue(values: Record) { + const fieldMapToTime = unref(rootProps).fieldMapToTime; + + if (!fieldMapToTime) return values; + + if (!Array.isArray(fieldMapToTime)) { + return values; + } + + fieldMapToTime.forEach( + ([field, [startTimeKey, endTimeKey], format = 'YYYY-MM-DD']) => { + if (!values[field]) { + delete values[field]; + return; + } + + const [startTime, endTime] = values[field]; + const [startTimeFormat, endTimeFormat] = Array.isArray(format) + ? format + : [format, format]; + + values[startTimeKey] = startTime + ? formatTime(startTime, startTimeFormat) + : undefined; + values[endTimeKey] = endTime + ? formatTime(endTime, endTimeFormat) + : undefined; + + delete values[field]; + }, + ); + + return values; +} + +function formatTime(time: string, format: string): number | string { + const date = new Date(time); + const timestamp = (date: Date) => Math.floor(date.getTime() / 1000); + + if (format === 'timestamp') return timestamp(date); + if (format === 'timestampStartDay') + return timestamp( + new Date(date.getFullYear(), date.getMonth(), date.getDate()), + ); + + const padZero = (num: number) => num.toString().padStart(2, '0'); + const replacements: Record = { + DD: padZero(date.getDate()), + HH: padZero(date.getHours()), + MM: padZero(date.getMonth() + 1), + mm: padZero(date.getMinutes()), + ss: padZero(date.getSeconds()), + YYYY: date.getFullYear().toString(), + }; + + return format.replaceAll( + /YYYY|MM|DD|HH|mm|ss/g, + (match) => replacements[match] || match, + ); +} + watch( () => collapsed.value, () => { diff --git a/packages/@core/ui-kit/form-ui/src/types.ts b/packages/@core/ui-kit/form-ui/src/types.ts index 741167569..9d2b28074 100644 --- a/packages/@core/ui-kit/form-ui/src/types.ts +++ b/packages/@core/ui-kit/form-ui/src/types.ts @@ -206,6 +206,12 @@ export type HandleResetFn = ( values: Record, ) => Promise | void; +export type FieldMapToTime = [ + string, + [string, string], + ([string, string] | string)?, +][]; + export interface FormSchema< T extends BaseFormComponentType = BaseFormComponentType, > extends FormCommonConfig { @@ -266,6 +272,10 @@ export interface FormRenderProps< * 组件集合 */ componentMap: Record; + /** + * 表单字段映射成时间格式 + */ + fieldMapToTime?: FieldMapToTime; /** * 表单实例 */ diff --git a/playground/src/views/examples/vxe-table/form.vue b/playground/src/views/examples/vxe-table/form.vue index fad0cf58f..18a1a038f 100644 --- a/playground/src/views/examples/vxe-table/form.vue +++ b/playground/src/views/examples/vxe-table/form.vue @@ -21,6 +21,7 @@ interface RowType { const formOptions: VbenFormProps = { // 默认展开 collapsed: false, + fieldMapToTime: [['dateRangePicker', ['startTime', 'endTime'], 'YYYY-MM']], schema: [ { component: 'Input', @@ -62,6 +63,11 @@ const formOptions: VbenFormProps = { fieldName: 'datePicker', label: 'Date', }, + { + component: 'RangePicker', + fieldName: 'dateRangePicker', + label: 'DateRange', + }, ], // 控制表单是否显示折叠按钮 showCollapseButton: true,