From 2828e7a7b60d17a228d41cbbf391e10bbef516a5 Mon Sep 17 00:00:00 2001 From: Netfan Date: Thu, 9 Jan 2025 12:28:33 +0800 Subject: [PATCH] fix: form `fieldMappingTime` is not working (#5333) * fix: form option `fieldMappingTime` is not working * fix: form merge support `fieldMappingTime` --- .../form-ui/src/components/form-actions.vue | 55 +------------------ packages/@core/ui-kit/form-ui/src/form-api.ts | 54 ++++++++++++++++-- .../ui-kit/form-ui/src/use-form-context.ts | 6 +- .../ui-kit/form-ui/src/vben-use-form.vue | 6 +- .../plugins/src/echarts/use-echarts.ts | 2 +- .../plugins/src/vxe-table/use-vxe-grid.vue | 10 ++-- .../src/views/examples/vxe-table/form.vue | 7 ++- 7 files changed, 72 insertions(+), 68 deletions(-) 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 b9a878e8a..fb90a5e42 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 @@ -3,12 +3,7 @@ import { computed, toRaw, unref, watch } from 'vue'; import { useSimpleLocale } from '@vben-core/composables'; import { VbenExpandableArrow } from '@vben-core/shadcn-ui'; -import { - cn, - formatDate, - isFunction, - triggerWindowResize, -} from '@vben-core/shared/utils'; +import { cn, isFunction, triggerWindowResize } from '@vben-core/shared/utils'; import { COMPONENT_MAP } from '../config'; import { injectFormProps } from '../use-form-context'; @@ -58,7 +53,7 @@ async function handleSubmit(e: Event) { return; } - const values = handleRangeTimeValue(toRaw(form.values)); + const values = toRaw(await unref(rootProps).formApi?.getValues()); await unref(rootProps).handleSubmit?.(values); } @@ -67,13 +62,7 @@ async function handleReset(e: Event) { e?.stopPropagation(); const props = unref(rootProps); - const values = toRaw(form.values); - // 清理时间字段 - props.fieldMappingTime && - props.fieldMappingTime.forEach(([_, [startTimeKey, endTimeKey]]) => { - delete values[startTimeKey]; - delete values[endTimeKey]; - }); + const values = toRaw(props.formApi?.getValues()); if (isFunction(props.handleReset)) { await props.handleReset?.(values); @@ -82,44 +71,6 @@ async function handleReset(e: Event) { } } -function handleRangeTimeValue(values: Record) { - const fieldMappingTime = unref(rootProps).fieldMappingTime; - - if (!fieldMappingTime || !Array.isArray(fieldMappingTime)) { - return values; - } - - fieldMappingTime.forEach( - ([field, [startTimeKey, endTimeKey], format = 'YYYY-MM-DD']) => { - if (startTimeKey && endTimeKey && values[field] === null) { - delete values[startTimeKey]; - delete values[endTimeKey]; - } - - if (!values[field]) { - delete values[field]; - return; - } - - const [startTime, endTime] = values[field]; - const [startTimeFormat, endTimeFormat] = Array.isArray(format) - ? format - : [format, format]; - - values[startTimeKey] = startTime - ? formatDate(startTime, startTimeFormat) - : undefined; - values[endTimeKey] = endTime - ? formatDate(endTime, endTimeFormat) - : undefined; - - delete values[field]; - }, - ); - - return values; -} - watch( () => collapsed.value, () => { diff --git a/packages/@core/ui-kit/form-ui/src/form-api.ts b/packages/@core/ui-kit/form-ui/src/form-api.ts index 9fc98a3c8..173e1ba1d 100644 --- a/packages/@core/ui-kit/form-ui/src/form-api.ts +++ b/packages/@core/ui-kit/form-ui/src/form-api.ts @@ -15,6 +15,7 @@ import { Store } from '@vben-core/shared/store'; import { bindMethods, createMerge, + formatDate, isDate, isDayjsObject, isFunction, @@ -94,7 +95,7 @@ export class FormApi { async getValues() { const form = await this.getForm(); - return form.values; + return this.handleRangeTimeValue(form.values); } async isFieldValid(fieldName: string) { @@ -117,12 +118,11 @@ export class FormApi { try { const results = await Promise.all( chain.map(async (api) => { - const form = await api.getForm(); const validateResult = await api.validate(); if (!validateResult.valid) { return; } - const rawValues = toRaw(form.values || {}); + const rawValues = toRaw((await api.getValues()) || {}); return rawValues; }), ); @@ -147,7 +147,9 @@ export class FormApi { if (!this.isMounted) { Object.assign(this.form, formActions); this.stateHandler.setConditionTrue(); - this.setLatestSubmissionValues({ ...toRaw(this.form.values) }); + this.setLatestSubmissionValues({ + ...toRaw(this.handleRangeTimeValue(this.form.values)), + }); this.isMounted = true; } } @@ -253,7 +255,7 @@ export class FormApi { e?.stopPropagation(); const form = await this.getForm(); await form.submitForm(); - const rawValues = toRaw(form.values || {}); + const rawValues = toRaw(await this.getValues()); await this.state?.handleSubmit?.(rawValues); return rawValues; @@ -342,6 +344,48 @@ export class FormApi { return this.form; } + private handleRangeTimeValue = (originValues: Record) => { + const values = { ...originValues }; + const fieldMappingTime = this.state?.fieldMappingTime; + + if (!fieldMappingTime || !Array.isArray(fieldMappingTime)) { + return values; + } + + fieldMappingTime.forEach( + ([field, [startTimeKey, endTimeKey], format = 'YYYY-MM-DD']) => { + if (startTimeKey && endTimeKey && values[field] === null) { + Reflect.deleteProperty(values, startTimeKey); + Reflect.deleteProperty(values, endTimeKey); + // delete values[startTimeKey]; + // delete values[endTimeKey]; + } + + if (!values[field]) { + Reflect.deleteProperty(values, field); + // delete values[field]; + return; + } + + const [startTime, endTime] = values[field]; + const [startTimeFormat, endTimeFormat] = Array.isArray(format) + ? format + : [format, format]; + + values[startTimeKey] = startTime + ? formatDate(startTime, startTimeFormat) + : undefined; + values[endTimeKey] = endTime + ? formatDate(endTime, endTimeFormat) + : undefined; + + // delete values[field]; + Reflect.deleteProperty(values, field); + }, + ); + return values; + }; + private updateState() { const currentSchema = this.state?.schema ?? []; const prevSchema = this.prevState?.schema ?? []; diff --git a/packages/@core/ui-kit/form-ui/src/use-form-context.ts b/packages/@core/ui-kit/form-ui/src/use-form-context.ts index 879a64c6b..8e37300e5 100644 --- a/packages/@core/ui-kit/form-ui/src/use-form-context.ts +++ b/packages/@core/ui-kit/form-ui/src/use-form-context.ts @@ -2,7 +2,7 @@ import type { ZodRawShape } from 'zod'; import type { ComputedRef } from 'vue'; -import type { FormActions, VbenFormProps } from './types'; +import type { ExtendedFormApi, FormActions, VbenFormProps } from './types'; import { computed, unref, useSlots } from 'vue'; @@ -13,8 +13,10 @@ import { useForm } from 'vee-validate'; import { object } from 'zod'; import { getDefaultsForSchema } from 'zod-defaults'; +type ExtendFormProps = VbenFormProps & { formApi: ExtendedFormApi }; + export const [injectFormProps, provideFormProps] = - createContext<[ComputedRef | VbenFormProps, FormActions]>( + createContext<[ComputedRef | ExtendFormProps, FormActions]>( 'VbenFormProps', ); diff --git a/packages/@core/ui-kit/form-ui/src/vben-use-form.vue b/packages/@core/ui-kit/form-ui/src/vben-use-form.vue index 8f0efea9f..a5a7f660c 100644 --- a/packages/@core/ui-kit/form-ui/src/vben-use-form.vue +++ b/packages/@core/ui-kit/form-ui/src/vben-use-form.vue @@ -53,8 +53,10 @@ function handleKeyDownEnter(event: KeyboardEvent) { forward.value.formApi.validateAndSubmitForm(); } -const handleValuesChangeDebounced = useDebounceFn((newVal) => { - forward.value.handleValuesChange?.(cloneDeep(newVal)); +const handleValuesChangeDebounced = useDebounceFn(async () => { + forward.value.handleValuesChange?.( + cloneDeep(await forward.value.formApi.getValues()), + ); state.value.submitOnChange && forward.value.formApi?.validateAndSubmitForm(); }, 300); diff --git a/packages/effects/plugins/src/echarts/use-echarts.ts b/packages/effects/plugins/src/echarts/use-echarts.ts index 0fd7c4b68..ec5786e8b 100644 --- a/packages/effects/plugins/src/echarts/use-echarts.ts +++ b/packages/effects/plugins/src/echarts/use-echarts.ts @@ -109,7 +109,7 @@ function useEcharts(chartRef: Ref) { return { renderEcharts, resize, - chartInstance + chartInstance, }; } diff --git a/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue b/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue index 707ea59eb..cbae6f298 100644 --- a/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue +++ b/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue @@ -8,6 +8,8 @@ import type { VxeToolbarPropTypes, } from 'vxe-table'; +import type { SetupContext } from 'vue'; + import type { VbenFormProps } from '@vben-core/form-ui'; import type { ExtendedVxeGridApi, VxeGridProps } from './types'; @@ -68,18 +70,18 @@ const { const { isMobile } = usePreferences(); -const slots = useSlots(); +const slots: SetupContext['slots'] = useSlots(); const [Form, formApi] = useTableForm({ compact: true, handleSubmit: async () => { - const formValues = formApi.form.values; + const formValues = await formApi.getValues(); formApi.setLatestSubmissionValues(toRaw(formValues)); props.api.reload(formValues); }, handleReset: async () => { await formApi.resetForm(); - const formValues = formApi.form.values; + const formValues = await formApi.getValues(); formApi.setLatestSubmissionValues(formValues); props.api.reload(formValues); }, @@ -246,7 +248,7 @@ async function init() { const autoLoad = defaultGridOptions.proxyConfig?.autoLoad; const enableProxyConfig = options.value.proxyConfig?.enabled; if (enableProxyConfig && autoLoad) { - props.api.grid.commitProxy?.('_init', formApi.form?.values ?? {}); + props.api.grid.commitProxy?.('_init', (await formApi.getValues()) ?? {}); // props.api.reload(formApi.form?.values ?? {}); } diff --git a/playground/src/views/examples/vxe-table/form.vue b/playground/src/views/examples/vxe-table/form.vue index dd9e2a376..cda65168b 100644 --- a/playground/src/views/examples/vxe-table/form.vue +++ b/playground/src/views/examples/vxe-table/form.vue @@ -5,6 +5,7 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import { Page } from '@vben/common-ui'; import { message } from 'ant-design-vue'; +import dayjs from 'dayjs'; import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { getExampleTableApi } from '#/api'; @@ -21,6 +22,7 @@ interface RowType { const formOptions: VbenFormProps = { // 默认展开 collapsed: false, + fieldMappingTime: [['date', ['start', 'end']]], schema: [ { component: 'Input', @@ -58,8 +60,9 @@ const formOptions: VbenFormProps = { label: 'Color', }, { - component: 'DatePicker', - fieldName: 'datePicker', + component: 'RangePicker', + defaultValue: [dayjs().subtract(-7, 'days'), dayjs()], + fieldName: 'date', label: 'Date', }, ],