From 1ba88a00d3c7bb0f16a73feaa5ffcf7c1635e0ea Mon Sep 17 00:00:00 2001
From: Sanakey <714737083@qq.com>
Date: 星期五, 02 八月 2024 17:44:27 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/v2' into onbus-crm

---
 src/components/Form/src/components/ApiSelect.vue |   80 ++++++++++++++++++++++++++++++++++++---
 1 files changed, 73 insertions(+), 7 deletions(-)

diff --git a/src/components/Form/src/components/ApiSelect.vue b/src/components/Form/src/components/ApiSelect.vue
index df59336..16648e4 100644
--- a/src/components/Form/src/components/ApiSelect.vue
+++ b/src/components/Form/src/components/ApiSelect.vue
@@ -3,6 +3,7 @@
     @dropdown-visible-change="handleFetch"
     v-bind="$attrs"
     @change="handleChange"
+    @search="debounceSearchFn"
     :options="getOptions"
     v-model:value="state"
   >
@@ -20,18 +21,33 @@
     </template>
   </Select>
 </template>
+
 <script lang="ts" setup>
-  import { PropType, ref, computed, unref, watch } from 'vue';
+  import { computed, PropType, ref, unref, watch } from 'vue';
   import { Select } from 'ant-design-vue';
   import type { SelectValue } from 'ant-design-vue/es/select';
-  import { isFunction } from '@/utils/is';
+  import { isEmpty, isFunction } from '@/utils/is';
   import { useRuleFormItem } from '@/hooks/component/useFormItem';
-  import { get, omit, isEqual } from 'lodash-es';
+  import { assignIn, get, isEqual, omit } from 'lodash-es';
   import { LoadingOutlined } from '@ant-design/icons-vue';
   import { useI18n } from '@/hooks/web/useI18n';
   import { propTypes } from '@/utils/propTypes';
+  import { useDebounceFn } from '@vueuse/core';
 
   type OptionsItem = { label?: string; value?: string; disabled?: boolean; [name: string]: any };
+
+  type ApiSearchOption = {
+    // 灞曠ず鎼滅储
+    show?: boolean;
+    // 寰呮悳绱㈠瓧娈靛悕
+    searchName?: string;
+    // 鏄惁鍏佽绌烘悳绱�
+    emptySearch?: boolean;
+    // 鎼滅储鍓嶇疆鏂规硶
+    beforeFetch?: (value?: string) => Promise<string>;
+    // 鎷︽埅鏂规硶
+    interceptFetch?: (value?: string) => Promise<boolean>;
+  };
 
   defineOptions({ name: 'ApiSelect', inheritAttrs: false });
 
@@ -39,7 +55,7 @@
     value: { type: [Array, Object, String, Number] as PropType<SelectValue> },
     numberToString: propTypes.bool,
     api: {
-      type: Function as PropType<(arg?: any) => Promise<OptionsItem[] | Recordable<any>>>,
+      type: Function as PropType<(arg?: any) => Promise<OptionsItem[] | Recordable>>,
       default: null,
     },
     // api params
@@ -53,6 +69,10 @@
     options: {
       type: Array<OptionsItem>,
       default: [],
+    },
+    apiSearch: {
+      type: Object as PropType<ApiSearchOption>,
+      default: () => null,
     },
     beforeFetch: {
       type: Function as PropType<Fn>,
@@ -72,6 +92,7 @@
   // 棣栨鏄惁鍔犺浇杩囦簡
   const isFirstLoaded = ref(false);
   const emitData = ref<OptionsItem[]>([]);
+  const searchParams = ref<any>({});
   const { t } = useI18n();
 
   // Embedded in the form, just use the hook binding to perform form verification
@@ -110,16 +131,29 @@
     { deep: true, immediate: props.immediate },
   );
 
+  watch(
+    () => searchParams.value,
+    (value, oldValue) => {
+      if (isEmpty(value) || isEqual(value, oldValue)) return;
+      (async () => {
+        await fetch();
+        searchParams.value = {};
+      })();
+    },
+    { deep: true, immediate: props.immediate },
+  );
+
   async function fetch() {
     let { api, beforeFetch, afterFetch, params, resultField } = props;
     if (!api || !isFunction(api) || loading.value) return;
     optionsRef.value = [];
     try {
       loading.value = true;
+      let apiParams = assignIn({}, params, searchParams.value);
       if (beforeFetch && isFunction(beforeFetch)) {
-        params = (await beforeFetch(params)) || params;
+        apiParams = (await beforeFetch(apiParams)) || apiParams;
       }
-      let res = await api(params);
+      let res = await api(apiParams);
       if (afterFetch && isFunction(afterFetch)) {
         res = (await afterFetch(res)) || res;
       }
@@ -147,11 +181,43 @@
       if (props.alwaysLoad) {
         await fetch();
       } else if (!props.immediate && !unref(isFirstLoaded)) {
-        await fetch();
+        // 鍔ㄦ�佹悳绱㈡煡璇㈡椂锛屽厑璁告帶鍒跺垵濮嬩笉鍔犺浇鏁版嵁
+        if (!(!!props.apiSearch && !!props.apiSearch.show && !props.apiSearch.emptySearch)) {
+          await fetch();
+        } else {
+          optionsRef.value = [];
+          emitChange();
+        }
       }
     }
   }
 
+  let debounceSearchFn = useDebounceFn(handleSearch, 500);
+
+  async function handleSearch(value: any) {
+    if (!props.apiSearch) {
+      return;
+    }
+    const { show, searchName, beforeFetch, interceptFetch } = props.apiSearch;
+    if (!show || !searchName) {
+      return;
+    }
+
+    value = value || undefined;
+    if (beforeFetch && isFunction(beforeFetch)) {
+      value = (await beforeFetch(value)) || value;
+    }
+
+    if (interceptFetch && isFunction(interceptFetch)) {
+      if (!(await interceptFetch(value))) {
+        return;
+      }
+    }
+    searchParams.value = {
+      [searchName]: value,
+    };
+  }
+
   function emitChange() {
     emit('options-change', unref(getOptions));
   }

--
Gitblit v1.8.0