Browse Source

fix: improve request logic in api-component

* 修复某些情况下updateParam设置的参数可能不会提交给api的问题
* 修复在上一个请求尚未完成前如果params发生了变更,将不会再触发新的api请求
---------

Co-authored-by: Netfan <netfan@foxmail.com>
lghuahua 1 week ago
parent
commit
986eacae9a

+ 25 - 8
packages/effects/common-ui/src/components/api-component/api-component.vue

@@ -3,11 +3,11 @@ import type { Component } from 'vue';
 
 import type { AnyPromiseFunction } from '@vben/types';
 
-import { computed, ref, unref, useAttrs, watch } from 'vue';
+import { computed, nextTick, ref, unref, useAttrs, watch } from 'vue';
 
 import { LoaderCircle } from '@vben/icons';
 
-import { get, isEqual, isFunction } from '@vben-core/shared/utils';
+import { cloneDeep, get, isEqual, isFunction } from '@vben-core/shared/utils';
 
 import { objectOmit } from '@vueuse/core';
 
@@ -104,6 +104,8 @@ const refOptions = ref<OptionsItem[]>([]);
 const loading = ref(false);
 // 首次是否加载过了
 const isFirstLoaded = ref(false);
+// 标记是否有待处理的请求
+const hasPendingRequest = ref(false);
 
 const getOptions = computed(() => {
   const { labelField, valueField, childrenField, numberToString } = props;
@@ -146,18 +148,26 @@ const bindProps = computed(() => {
 });
 
 async function fetchApi() {
-  let { api, beforeFetch, afterFetch, params, resultField } = props;
+  const { api, beforeFetch, afterFetch, resultField } = props;
 
-  if (!api || !isFunction(api) || loading.value) {
+  if (!api || !isFunction(api)) {
     return;
   }
+
+  // 如果正在加载,标记有待处理的请求并返回
+  if (loading.value) {
+    hasPendingRequest.value = true;
+    return;
+  }
+
   refOptions.value = [];
   try {
     loading.value = true;
+    let finalParams = unref(mergedParams);
     if (beforeFetch && isFunction(beforeFetch)) {
-      params = (await beforeFetch(params)) || params;
+      finalParams = (await beforeFetch(cloneDeep(finalParams))) || finalParams;
     }
-    let res = await api(params);
+    let res = await api(finalParams);
     if (afterFetch && isFunction(afterFetch)) {
       res = (await afterFetch(res)) || res;
     }
@@ -177,6 +187,13 @@ async function fetchApi() {
     isFirstLoaded.value = false;
   } finally {
     loading.value = false;
+    // 如果有待处理的请求,立即触发新的请求
+    if (hasPendingRequest.value) {
+      hasPendingRequest.value = false;
+      // 使用 nextTick 确保状态更新完成后再触发新请求
+      await nextTick();
+      fetchApi();
+    }
   }
 }
 
@@ -190,7 +207,7 @@ async function handleFetchForVisible(visible: boolean) {
   }
 }
 
-const params = computed(() => {
+const mergedParams = computed(() => {
   return {
     ...props.params,
     ...unref(innerParams),
@@ -198,7 +215,7 @@ const params = computed(() => {
 });
 
 watch(
-  params,
+  mergedParams,
   (value, oldValue) => {
     if (isEqual(value, oldValue)) {
       return;