plugin-ui-for-kzt 0.0.29 → 0.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/BaseBadge/BaseBadge.vue.d.ts +2 -2
- package/dist/components/BaseButton/BaseButton.vue.d.ts +1 -1
- package/dist/components/BaseInput/BaseInput.vue.d.ts +1 -1
- package/dist/components/BaseInputCalendar/BaseInputCalendar.vue.d.ts +2 -2
- package/dist/components/BaseInputCurrency/BaseInputCurrency.vue.d.ts +1 -1
- package/dist/components/BasePagination/BasePagination.vue.d.ts +1 -1
- package/dist/components/BaseSegmentedButtons/BaseSegmentedButtons.vue.d.ts +1 -1
- package/dist/components/BaseSelect/BaseSelect.vue.d.ts +5 -2
- package/dist/components/BaseTag/BaseTag.vue.d.ts +1 -1
- package/dist/components/BaseToast/BaseToast.vue.d.ts +1 -1
- package/dist/components/BaseTooltip/BaseTooltip.vue.d.ts +1 -1
- package/dist/index.js +1 -1
- package/example/App.vue +1 -1
- package/package.json +1 -1
- package/src/components/BaseSelect/BaseSelect.vue +9 -0
- package/src/components/BaseSelect/README.md +110 -1
package/example/App.vue
CHANGED
|
@@ -175,7 +175,7 @@
|
|
|
175
175
|
</div>
|
|
176
176
|
</template>
|
|
177
177
|
<script setup lang="ts">
|
|
178
|
-
import { ref,
|
|
178
|
+
import { ref, computed, onMounted } from 'vue'
|
|
179
179
|
import BaseSelect from '../src/components/BaseSelect/BaseSelect.vue'
|
|
180
180
|
import BaseTooltip from '../src/components/BaseTooltip/BaseTooltip.vue'
|
|
181
181
|
import BaseUpload from '../src/components/BaseUpload/BaseUpload.vue'
|
package/package.json
CHANGED
|
@@ -149,6 +149,9 @@ const emit = defineEmits<{
|
|
|
149
149
|
(e: 'update:modelValue', value: TSelectValue): void
|
|
150
150
|
(e: 'change', value: TSelectValue): void
|
|
151
151
|
(e: 'error'): void
|
|
152
|
+
(e: 'search', query: string): void
|
|
153
|
+
(e: 'open'): void
|
|
154
|
+
(e: 'clear'): void
|
|
152
155
|
}>();
|
|
153
156
|
|
|
154
157
|
const actualValue = ref<TSelectValue>(props.modelValue ?? '');
|
|
@@ -180,6 +183,8 @@ function handleInputChange(event: Event) {
|
|
|
180
183
|
const target = event.target as HTMLInputElement;
|
|
181
184
|
const inputValue = target.value;
|
|
182
185
|
searchQuery.value = inputValue;
|
|
186
|
+
|
|
187
|
+
emit('search', inputValue);
|
|
183
188
|
|
|
184
189
|
if (inputValue) {
|
|
185
190
|
const exactMatch = props.options?.find((option: ICoreSelectOption) =>
|
|
@@ -201,6 +206,7 @@ function handleIconClick(event: Event) {
|
|
|
201
206
|
event.stopPropagation();
|
|
202
207
|
if (actualOption.value) {
|
|
203
208
|
handleInput('');
|
|
209
|
+
emit('clear');
|
|
204
210
|
} else {
|
|
205
211
|
dropdownVisible.value = !dropdownVisible.value;
|
|
206
212
|
}
|
|
@@ -225,6 +231,9 @@ watch(() => props.error, (error) => {
|
|
|
225
231
|
});
|
|
226
232
|
|
|
227
233
|
watch(dropdownVisible, (isVisible) => {
|
|
234
|
+
if (isVisible) {
|
|
235
|
+
emit('open');
|
|
236
|
+
}
|
|
228
237
|
if (!isVisible) {
|
|
229
238
|
if (searchQuery.value && !actualOption.value) {
|
|
230
239
|
emit('error');
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
### ✅
|
|
7
|
+
### ✅ Примеры использования
|
|
8
8
|
|
|
9
|
+
#### Базовый пример
|
|
9
10
|
```vue
|
|
10
11
|
<base-select
|
|
11
12
|
v-model="selected"
|
|
@@ -21,6 +22,99 @@
|
|
|
21
22
|
/>
|
|
22
23
|
```
|
|
23
24
|
|
|
25
|
+
#### Server-side поиск (рекомендуемый подход)
|
|
26
|
+
```vue
|
|
27
|
+
<template>
|
|
28
|
+
<base-select
|
|
29
|
+
id="employee-select"
|
|
30
|
+
v-model="selectedEmployee"
|
|
31
|
+
:options="employeeOptions"
|
|
32
|
+
searchable
|
|
33
|
+
placeholder="Найти сотрудника..."
|
|
34
|
+
label="Выберите сотрудника"
|
|
35
|
+
:error="employeeError"
|
|
36
|
+
@search="handleEmployeeSearch"
|
|
37
|
+
@open="handleEmployeeOpen"
|
|
38
|
+
@clear="handleEmployeeClear"
|
|
39
|
+
@error="handleSearchError"
|
|
40
|
+
/>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script setup>
|
|
44
|
+
import { ref } from 'vue'
|
|
45
|
+
import axios from 'axios'
|
|
46
|
+
|
|
47
|
+
const selectedEmployee = ref('')
|
|
48
|
+
const employeeOptions = ref([])
|
|
49
|
+
const employeeError = ref('')
|
|
50
|
+
const searchTimeout = ref(null)
|
|
51
|
+
|
|
52
|
+
// Дебаунс поиска для оптимизации запросов
|
|
53
|
+
const debounceSearch = (callback, delay) => {
|
|
54
|
+
if (searchTimeout.value) {
|
|
55
|
+
clearTimeout(searchTimeout.value)
|
|
56
|
+
}
|
|
57
|
+
searchTimeout.value = setTimeout(callback, delay)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Загрузка сотрудников с сервера
|
|
61
|
+
const fetchEmployees = async (query = '') => {
|
|
62
|
+
try {
|
|
63
|
+
const params = {
|
|
64
|
+
limit: 100,
|
|
65
|
+
skip: 0
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (query?.trim()) {
|
|
69
|
+
params.name = query.trim()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const response = await axios.get('/api/employees', { params })
|
|
73
|
+
const employees = response.data.content || []
|
|
74
|
+
|
|
75
|
+
employeeOptions.value = employees.map(item => ({
|
|
76
|
+
id: item.employeeId,
|
|
77
|
+
name: `${item.lastName} ${item.firstName} ${item.middleName}`.trim(),
|
|
78
|
+
}))
|
|
79
|
+
|
|
80
|
+
employeeError.value = ''
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error('Failed to fetch employees:', error)
|
|
83
|
+
employeeOptions.value = []
|
|
84
|
+
employeeError.value = 'Ошибка загрузки данных'
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Обработчик поиска с дебаунсом
|
|
89
|
+
const handleEmployeeSearch = (query) => {
|
|
90
|
+
debounceSearch(() => {
|
|
91
|
+
if (query.length >= 2 || query.length === 0) {
|
|
92
|
+
fetchEmployees(query)
|
|
93
|
+
}
|
|
94
|
+
}, 700) // Дебаунс 700мс
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Загрузка при открытии если данных нет
|
|
98
|
+
const handleEmployeeOpen = () => {
|
|
99
|
+
if (employeeOptions.value.length === 0) {
|
|
100
|
+
fetchEmployees()
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Очистка выбора
|
|
105
|
+
const handleEmployeeClear = () => {
|
|
106
|
+
selectedEmployee.value = ''
|
|
107
|
+
employeeError.value = ''
|
|
108
|
+
fetchEmployees() // Загружаем исходный список
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Обработка ошибок поиска
|
|
112
|
+
const handleSearchError = () => {
|
|
113
|
+
employeeError.value = 'Элемент не найден'
|
|
114
|
+
}
|
|
115
|
+
</script>
|
|
116
|
+
```
|
|
117
|
+
|
|
24
118
|
---
|
|
25
119
|
|
|
26
120
|
### ⚙️ Пропсы
|
|
@@ -55,6 +149,9 @@
|
|
|
55
149
|
- `size?: 'small' | 'medium' | 'large'`
|
|
56
150
|
Управляет размерами шрифта, паддингов и иконок.
|
|
57
151
|
|
|
152
|
+
- `searchable?: boolean`
|
|
153
|
+
**Включает режим поиска. При `true` заменяет обычный заголовок на поле ввода для поиска. Идеально подходит для server-side поиска больших наборов данных.
|
|
154
|
+
|
|
58
155
|
- `multiple?: boolean`
|
|
59
156
|
Поддержка множественного выбора (не реализовано в текущем компоненте, зарезервировано).
|
|
60
157
|
|
|
@@ -71,6 +168,18 @@
|
|
|
71
168
|
- `change`
|
|
72
169
|
Также эмитится при выборе. Полезно для побочных эффектов.
|
|
73
170
|
|
|
171
|
+
- `search`
|
|
172
|
+
Эмитится при вводе в поисковое поле (только при `searchable: true`). Возвращает строку поискового запроса. Используется для server-side поиска.
|
|
173
|
+
|
|
174
|
+
- `open`
|
|
175
|
+
Эмитится при открытии выпадающего меню. Полезно для первоначальной загрузки данных при server-side поиске.
|
|
176
|
+
|
|
177
|
+
- `clear`
|
|
178
|
+
Эмитится при очистке выбранного значения через иконку крестика (только при `searchable: true`).
|
|
179
|
+
|
|
180
|
+
- `error`
|
|
181
|
+
Эмитится когда пользователь вводит текст, но не выбирает ни одну опцию из списка. Полезно для валидации поиска.
|
|
182
|
+
|
|
74
183
|
---
|
|
75
184
|
|
|
76
185
|
### 🧩 Слоты
|