Kaynağa Gözat

feat(BasicForm->Components): add beforeFetch & afterFetch to apicomp && perf the code (#3786)

* fix(apitree): fix the error way to use resultfield

* feat: add before & after Fetch fn in apiComp
Electrolux 1 yıl önce
ebeveyn
işleme
7ae2ec03a7

+ 34 - 14
src/components/Form/src/components/ApiCascader.vue

@@ -69,6 +69,14 @@
     displayRenderArray: {
       type: Array,
     },
+    beforeFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
+    afterFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
   });
 
   const emit = defineEmits(['change', 'defaultChange']);
@@ -112,19 +120,25 @@
     }, [] as Option[]);
   }
 
-  async function initialFetch() {
-    const api = props.api;
+  async function fetch() {
+    let { api, beforeFetch, initFetchParams, afterFetch, resultField } = props;
     if (!api || !isFunction(api)) return;
     apiData.value = [];
     loading.value = true;
     try {
-      const res = await api(props.initFetchParams);
+      if (beforeFetch && isFunction(beforeFetch)) {
+        initFetchParams = (await beforeFetch(initFetchParams)) || initFetchParams;
+      }
+      let res = await api(initFetchParams);
+      if (afterFetch && isFunction(afterFetch)) {
+        res = (await afterFetch(res)) || res;
+      }
       if (Array.isArray(res)) {
         apiData.value = res;
         return;
       }
-      if (props.resultField) {
-        apiData.value = get(res, props.resultField) || [];
+      if (resultField) {
+        apiData.value = get(res, resultField) || [];
       }
     } catch (error) {
       console.warn(error);
@@ -136,20 +150,26 @@
   const loadData: CascaderProps['loadData'] = async (selectedOptions) => {
     const targetOption = selectedOptions[selectedOptions.length - 1];
     targetOption.loading = true;
-
-    const api = props.api;
+    let { api, beforeFetch, afterFetch, resultField, apiParamKey } = props;
     if (!api || !isFunction(api)) return;
     try {
-      const res = await api({
-        [props.apiParamKey]: Reflect.get(targetOption, 'value'),
-      });
+      let param = {
+        [apiParamKey]: Reflect.get(targetOption, 'value'),
+      };
+      if (beforeFetch && isFunction(beforeFetch)) {
+        param = (await beforeFetch(param)) || param;
+      }
+      let res = await api(param);
+      if (afterFetch && isFunction(afterFetch)) {
+        res = (await afterFetch(res)) || res;
+      }
       if (Array.isArray(res)) {
         const children = generatorOptions(res);
         targetOption.children = children;
         return;
       }
-      if (props.resultField) {
-        const children = generatorOptions(get(res, props.resultField) || []);
+      if (resultField) {
+        const children = generatorOptions(get(res, resultField) || []);
         targetOption.children = children;
       }
     } catch (e) {
@@ -162,7 +182,7 @@
   watch(
     () => props.immediate,
     () => {
-      props.immediate && initialFetch();
+      props.immediate && fetch();
     },
     {
       immediate: true,
@@ -172,7 +192,7 @@
   watch(
     () => props.initFetchParams,
     () => {
-      !unref(isFirstLoad) && initialFetch();
+      !unref(isFirstLoad) && fetch();
     },
     { deep: true },
   );

+ 18 - 4
src/components/Form/src/components/ApiRadioGroup.vue

@@ -57,6 +57,14 @@
     labelField: propTypes.string.def('label'),
     valueField: propTypes.string.def('value'),
     immediate: propTypes.bool.def(true),
+    beforeFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
+    afterFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
   });
 
   const emit = defineEmits(['options-change', 'change', 'update:value']);
@@ -95,19 +103,25 @@
   );
 
   async function fetch() {
-    const api = props.api;
+    let { api, beforeFetch, afterFetch, params, resultField } = props;
     if (!api || !isFunction(api)) return;
     options.value = [];
     try {
       loading.value = true;
-      const res = await api(props.params);
+      if (beforeFetch && isFunction(beforeFetch)) {
+        params = (await beforeFetch(params)) || params;
+      }
+      let res = await api(params);
+      if (afterFetch && isFunction(afterFetch)) {
+        res = (await afterFetch(res)) || res;
+      }
       if (Array.isArray(res)) {
         options.value = res;
         emitChange();
         return;
       }
-      if (props.resultField) {
-        options.value = get(res, props.resultField) || [];
+      if (resultField) {
+        options.value = get(res, resultField) || [];
       }
       emitChange();
     } catch (error) {

+ 18 - 4
src/components/Form/src/components/ApiSelect.vue

@@ -54,6 +54,14 @@
       type: Array<OptionsItem>,
       default: [],
     },
+    beforeFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
+    afterFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
   });
 
   const emit = defineEmits(['options-change', 'change', 'update:value']);
@@ -103,20 +111,26 @@
   );
 
   async function fetch() {
-    const api = props.api;
+    let { api, beforeFetch, afterFetch, params, resultField } = props;
     if (!api || !isFunction(api) || loading.value) return;
     optionsRef.value = [];
     try {
       loading.value = true;
-      const res = await api(props.params);
+      if (beforeFetch && isFunction(beforeFetch)) {
+        params = (await beforeFetch(params)) || params;
+      }
+      let res = await api(params);
+      if (afterFetch && isFunction(afterFetch)) {
+        res = (await afterFetch(res)) || res;
+      }
       isFirstLoaded.value = true;
       if (Array.isArray(res)) {
         optionsRef.value = res;
         emitChange();
         return;
       }
-      if (props.resultField) {
-        optionsRef.value = get(res, props.resultField) || [];
+      if (resultField) {
+        optionsRef.value = get(res, resultField) || [];
       }
       emitChange();
     } catch (error) {

+ 20 - 7
src/components/Form/src/components/ApiTransfer.vue

@@ -32,7 +32,14 @@
     dataSource: { type: Array as PropType<Array<TransferItem>> },
     immediate: propTypes.bool.def(true),
     alwaysLoad: propTypes.bool.def(false),
-    afterFetch: { type: Function },
+    beforeFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
+    afterFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
     resultField: propTypes.string.def(''),
     labelField: propTypes.string.def('title'),
     valueField: propTypes.string.def('key'),
@@ -98,23 +105,29 @@
   );
 
   async function fetch() {
-    const api = props.api;
+    let { api, beforeFetch, afterFetch, params, resultField, dataSource } = props;
     if (!api || !isFunction(api)) {
-      if (Array.isArray(props.dataSource)) {
-        _dataSource.value = props.dataSource;
+      if (Array.isArray(dataSource)) {
+        _dataSource.value = dataSource;
       }
       return;
     }
     _dataSource.value = [];
     try {
-      const res = await api(props.params);
+      if (beforeFetch && isFunction(beforeFetch)) {
+        params = (await beforeFetch(params)) || params;
+      }
+      let res = await api(params);
+      if (afterFetch && isFunction(afterFetch)) {
+        res = (await afterFetch(res)) || res;
+      }
       if (Array.isArray(res)) {
         _dataSource.value = res;
         emitChange();
         return;
       }
-      if (props.resultField) {
-        _dataSource.value = get(res, props.resultField) || [];
+      if (resultField) {
+        _dataSource.value = get(res, resultField) || [];
       }
       emitChange();
     } catch (error) {

+ 23 - 13
src/components/Form/src/components/ApiTree.vue

@@ -7,10 +7,10 @@
 </template>
 
 <script lang="ts" setup>
-  import { type Recordable, type AnyFunction } from '@vben/types';
+  import { type Recordable } from '@vben/types';
   import { type PropType, computed, watch, ref, onMounted, unref, useAttrs } from 'vue';
   import { Tree, TreeProps } from 'ant-design-vue';
-  import { isArray, isFunction } from '@/utils/is';
+  import { isFunction } from '@/utils/is';
   import { get } from 'lodash-es';
   import { DataNode } from 'ant-design-vue/es/tree';
   import { useRuleFormItem } from '@/hooks/component/useFormItem';
@@ -22,7 +22,14 @@
     params: { type: Object },
     immediate: { type: Boolean, default: true },
     resultField: { type: String, default: '' },
-    afterFetch: { type: Function as PropType<AnyFunction> },
+    beforeFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
+    afterFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
     value: {
       type: Array as PropType<TreeProps['selectedKeys']>,
     },
@@ -72,25 +79,28 @@
   });
 
   async function fetch() {
-    const { api, afterFetch } = props;
+    let { api, beforeFetch, afterFetch, params, resultField } = props;
     if (!api || !isFunction(api)) return;
     loading.value = true;
     treeData.value = [];
-    let result;
+    let res;
     try {
-      result = await api(props.params);
+      if (beforeFetch && isFunction(beforeFetch)) {
+        params = (await beforeFetch(params)) || params;
+      }
+      res = await api(params);
+      if (afterFetch && isFunction(afterFetch)) {
+        res = (await afterFetch(res)) || res;
+      }
     } catch (e) {
       console.error(e);
     }
-    if (afterFetch && isFunction(afterFetch)) {
-      result = afterFetch(result);
-    }
     loading.value = false;
-    if (!result) return;
-    if (!isArray(result)) {
-      result = get(result, props.resultField);
+    if (!res) return;
+    if (resultField) {
+      res = get(res, resultField) || [];
     }
-    treeData.value = (result as (Recordable & { key: string | number })[]) || [];
+    treeData.value = (res as (Recordable & { key: string | number })[]) || [];
     isFirstLoaded.value = true;
     emit('options-change', treeData.value);
   }

+ 21 - 7
src/components/Form/src/components/ApiTreeSelect.vue

@@ -34,6 +34,14 @@
     labelField: propTypes.string.def('title'),
     valueField: propTypes.string.def('value'),
     childrenField: propTypes.string.def('children'),
+    beforeFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
+    afterFetch: {
+      type: Function as PropType<Fn>,
+      default: null,
+    },
   });
 
   const emit = defineEmits(['options-change', 'change', 'load-data']);
@@ -88,22 +96,28 @@
   }
 
   async function fetch() {
-    const { api } = props;
+    let { api, beforeFetch, afterFetch, params, resultField } = props;
     if (!api || !isFunction(api) || loading.value) return;
     loading.value = true;
     treeData.value = [];
-    let result;
+    let res;
     try {
-      result = await api(props.params);
+      if (beforeFetch && isFunction(beforeFetch)) {
+        params = (await beforeFetch(params)) || params;
+      }
+      res = await api(params);
+      if (afterFetch && isFunction(afterFetch)) {
+        res = (await afterFetch(res)) || res;
+      }
     } catch (e) {
       console.error(e);
     }
     loading.value = false;
-    if (!result) return;
-    if (!isArray(result)) {
-      result = get(result, props.resultField);
+    if (!res) return;
+    if (resultField) {
+      res = get(res, resultField) || [];
     }
-    treeData.value = (result as Recordable<any>[]) || [];
+    treeData.value = (res as Recordable<any>[]) || [];
     isFirstLoaded.value = true;
     emit('options-change', treeData.value);
   }