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