RemoteSelect.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <script setup lang="ts">
  2. import type { FetchDataCallback, FetchSelectedDataCallback, PageParameters, SelectPageKey } from 'v-selectpage';
  3. import { SelectPageList } from 'v-selectpage';
  4. const props = withDefaults(defineProps<{
  5. load(page: number, size: number, query?: Record<string, any>): Promise<{ data: any[]; total: number }>;
  6. query?: Record<string, any>;
  7. keyProp?: string;
  8. labelProp?: string;
  9. }>(), {
  10. keyProp: 'id',
  11. labelProp: 'name',
  12. });
  13. const emits = defineEmits<{
  14. update: [ value: any ]
  15. }>();
  16. const attrs = useAttrs() as {
  17. multiple?: boolean;
  18. };
  19. const [ modelValue, modifiers ] = defineModel<any, 'complex'>('value', {
  20. get(v: any) {
  21. if ( !v || !v?.length ) return [];
  22. if ( !Array.isArray(v) ) v = [ v ];
  23. return v;
  24. },
  25. set(v: SelectPageKey[]) {
  26. return v[ 0 ];
  27. },
  28. });
  29. async function fetchData(data: PageParameters, callback: FetchDataCallback) {
  30. const { search: keyword, pageNumber, pageSize } = data;
  31. try {
  32. const { data, total } = await props.load(pageNumber, pageSize, { ...props.query, keyword });
  33. callback(data, total);
  34. } catch ( e ) {
  35. callback([], 0);
  36. }
  37. }
  38. async function fetchSelectedData(keys: SelectPageKey[], callback: FetchSelectedDataCallback) {
  39. if ( attrs.multiple ) {
  40. callback(keys.map(key => (
  41. {
  42. [ props.labelProp ]: key,
  43. [ props.labelProp ]: key,
  44. }
  45. )));
  46. } else {
  47. try {
  48. const { data } = await props.load(1, 1, { keyword: keys[ 0 ] });
  49. callback(data);
  50. } catch ( e ) {
  51. callback([]);
  52. }
  53. }
  54. }
  55. function onSelect(items: Record<string, unknown>[]) {
  56. emits('update', attrs.multiple ? items : items?.[ 0 ]);
  57. }
  58. </script>
  59. <template>
  60. <SelectPageList
  61. language="zh-chs"
  62. :key-prop="props.keyProp" :label-prop="props.labelProp"
  63. v-model="modelValue" @fetch-data="fetchData"
  64. @fetch-selected-data="fetchSelectedData"
  65. @selection-change="onSelect"
  66. />
  67. </template>
  68. <style lang="scss">
  69. .v-dropdown-trigger {
  70. width: 100%;
  71. .sp-trigger-container {
  72. padding: 3px 6px;
  73. border-radius: 6px;
  74. &.sp-opened,
  75. &:hover {
  76. border-color: #6bceff !important;
  77. }
  78. &.sp-opened,
  79. &:focus {
  80. border-color: #6bceff !important;
  81. box-shadow: 0 0 0 2px rgba(5, 205, 255, 0.06);
  82. border-inline-end-width: 1px;
  83. outline: 0;
  84. }
  85. }
  86. .sp-placeholder {
  87. color: #e0e0e0 !important;
  88. }
  89. }
  90. </style>