Procházet zdrojové kódy

fix: form `fieldMappingTime` is not working (#5333)

* fix: form option `fieldMappingTime` is not working

* fix: form merge support `fieldMappingTime`
Netfan před 4 měsíci
rodič
revize
2828e7a7b6

+ 3 - 52
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<string, any>) {
-  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,
   () => {

+ 49 - 5
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<string, any>) => {
+    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 ?? [];

+ 4 - 2
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> | VbenFormProps, FormActions]>(
+  createContext<[ComputedRef<ExtendFormProps> | ExtendFormProps, FormActions]>(
     'VbenFormProps',
   );
 

+ 4 - 2
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);
 

+ 1 - 1
packages/effects/plugins/src/echarts/use-echarts.ts

@@ -109,7 +109,7 @@ function useEcharts(chartRef: Ref<EchartsUIType>) {
   return {
     renderEcharts,
     resize,
-    chartInstance
+    chartInstance,
   };
 }
 

+ 6 - 4
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 ?? {});
   }
 

+ 5 - 2
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',
     },
   ],