api-select.vue 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <script setup lang="ts">
  2. import { computed, onMounted, ref, unref } from 'vue';
  3. import { useDebounceFn } from '@vueuse/core';
  4. import { get } from '@/utils/zt/lodashChunk';
  5. import { isFunction } from '@/utils/zt/is';
  6. import { basicApiSelectProps } from './props';
  7. import type { ApiSelectProps } from './type';
  8. const debouncedFn = useDebounceFn(() => {
  9. fetchApi();
  10. }, 1000);
  11. const props = withDefaults(defineProps<ApiSelectProps>(), {
  12. immediate: true,
  13. resultFeild: 'data',
  14. clearable: true
  15. });
  16. const fetchLoading = ref(false);
  17. const basicProps = ref(basicApiSelectProps);
  18. const options = ref<Recordable[]>([]);
  19. const modelVlaue = defineModel<Array<string | number> | string | number | null>();
  20. const isFirstReq = ref(false);
  21. const searchText = ref('');
  22. const bindValue = computed(() => {
  23. return {
  24. ...props,
  25. ...basicProps
  26. };
  27. });
  28. async function fetchApi() {
  29. const api = props.api;
  30. if (!api || !isFunction(api)) return;
  31. const params = {
  32. ...props.params
  33. };
  34. if (unref(bindValue).filterFeild && unref(searchText)) {
  35. params[String(unref(bindValue).filterFeild)] = unref(searchText);
  36. console.log(params, 'apiselect请求参数');
  37. }
  38. const res = await api(params);
  39. options.value = get(res, props.resultFeild);
  40. fetchLoading.value = false;
  41. }
  42. onMounted(() => {
  43. if (unref(bindValue).immediate) {
  44. fetchApi();
  45. }
  46. });
  47. function handleFocus() {
  48. if (!unref(bindValue).immediate && !unref(isFirstReq)) {
  49. fetchApi();
  50. isFirstReq.value = true;
  51. }
  52. if (!unref(options).length && unref(bindValue).immediate) {
  53. fetchApi();
  54. }
  55. }
  56. function handleScroll(e: Event) {
  57. const currentTarget = e.currentTarget as HTMLElement;
  58. if (currentTarget.scrollTop + currentTarget.offsetHeight >= currentTarget.scrollHeight) {
  59. // console.log('到底了');
  60. }
  61. }
  62. function handleSearch(value: string) {
  63. fetchLoading.value = true;
  64. searchText.value = value;
  65. debouncedFn();
  66. }
  67. function handleClear() {
  68. searchText.value = '';
  69. fetchApi();
  70. }
  71. function handleBlur() {
  72. searchText.value = '';
  73. }
  74. </script>
  75. <template>
  76. <NSelect
  77. v-bind="bindValue"
  78. v-model:value="modelVlaue"
  79. :options="options"
  80. :label-field="labelFeild"
  81. :value-field="valueFeild"
  82. :loading="fetchLoading"
  83. @focus="handleFocus"
  84. @scroll="handleScroll"
  85. @search="handleSearch"
  86. @clear="handleClear"
  87. @blur="handleBlur"
  88. ></NSelect>
  89. </template>
  90. <style scoped></style>