ApiComplete.vue
2.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<script setup lang="ts">
import { AutoComplete } from 'ant-design-vue';
import get from 'lodash-es/get';
import omit from 'lodash-es/omit';
import { computed, ref, unref, watch, watchEffect } from 'vue';
import { isFunction } from '/@/utils/is';
type OptionsItem = { text: string; value: string };
const props = withDefaults(
defineProps<{
value?: string;
api?: (arg?: Recordable) => Promise<OptionsItem[]>;
onSearchQuery?: boolean;
params?: Recordable;
resultField?: string;
valueField?: string;
labelField?: string;
immediate?: boolean;
}>(),
{
valueField: 'value',
labelField: 'label',
immediate: true,
}
);
const emit = defineEmits(['update:value', 'options-change']);
const loading = ref(false);
const isFirstLoad = ref(true);
const options = ref<OptionsItem[]>([]);
const getOptions = computed(() => {
const { labelField, valueField } = props;
return unref(options).reduce((prev, next: Recordable) => {
if (next) {
const value = next[valueField];
prev.push({
...omit(next, [labelField, valueField]),
text: next[labelField],
value,
});
}
return prev;
}, [] as OptionsItem[]);
});
const fetch = async () => {
const api = props.api;
if (!api || !isFunction(api)) return;
options.value = [];
try {
loading.value = true;
const res = await api(props.params);
if (Array.isArray(res)) {
options.value = res;
emitChange();
return;
}
if (props.resultField) {
options.value = get(res, props.resultField) || [];
}
emitChange();
} catch (error) {
console.warn(error);
} finally {
loading.value = false;
}
};
function emitChange() {
emit('options-change', unref(getOptions));
}
const handleChange = (value: any) => {
emit('update:value', value);
};
watchEffect(() => {
props.immediate && fetch();
});
watch(
() => props.params,
() => {
!unref(isFirstLoad) && fetch();
},
{ deep: true }
);
</script>
<template>
<AutoComplete :value="value" @change="handleChange" :options="getOptions" />
</template>