@opendesign-plus-test/components 0.0.1-rc.52 → 0.0.1-rc.54
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/chunk-OElCookieNotice.cjs.js +1 -1
- package/dist/chunk-OElCookieNotice.es.js +66 -46
- package/dist/components/OHeaderSearch.vue.d.ts +814 -534
- package/dist/components/search/OSearchInput.vue.d.ts +1001 -0
- package/dist/components/search/composables/useImageSearch.d.ts +48 -0
- package/dist/components/search/composables/useKeywordHighlight.d.ts +2 -0
- package/dist/components/search/composables/useSearchHistory.d.ts +14 -0
- package/dist/components/search/index.d.ts +587 -0
- package/dist/components/search/internal/HighlightText.vue.d.ts +9 -0
- package/dist/components/search/internal/SearchImageInput.vue.d.ts +716 -0
- package/dist/components/search/internal/SearchPanel.vue.d.ts +100 -0
- package/dist/components/search/types.d.ts +20 -0
- package/dist/components.cjs.js +43 -43
- package/dist/components.css +1 -1
- package/dist/components.es.js +11851 -10799
- package/dist/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/assets/svg-icons/icon-delete-hover.svg +4 -0
- package/src/assets/svg-icons/icon-delete.svg +5 -1
- package/src/assets/svg-icons/icon-image-close.svg +4 -0
- package/src/assets/svg-icons/icon-image-upload.svg +3 -0
- package/src/assets/svg-icons/icon-image-zoomin.svg +3 -0
- package/src/assets/svg-icons/icon-refresh.svg +3 -0
- package/src/components/OHeaderSearch.vue +448 -418
- package/src/components/meeting/OMeetingForm.vue +1 -5
- package/src/components/meeting/OMeetingMyCalendar.vue +3 -6
- package/src/components/meeting/components/OMeetingCalendarList.vue +13 -9
- package/src/components/search/OSearchInput.vue +503 -0
- package/src/components/search/composables/useImageSearch.ts +157 -0
- package/src/components/search/composables/useKeywordHighlight.ts +30 -0
- package/src/components/search/composables/useSearchHistory.ts +75 -0
- package/src/components/search/index.ts +23 -0
- package/src/components/search/internal/HighlightText.vue +37 -0
- package/src/components/search/internal/SearchImageInput.vue +498 -0
- package/src/components/search/internal/SearchPanel.vue +431 -0
- package/src/components/search/types.ts +25 -0
- package/src/i18n/en.ts +10 -0
- package/src/i18n/zh.ts +10 -0
- package/src/index.ts +1 -0
- package/vite.config.ts +4 -0
|
@@ -302,10 +302,7 @@ watch(
|
|
|
302
302
|
(data) => {
|
|
303
303
|
if (data) {
|
|
304
304
|
const propData = getPropData() as unknown as CycleSubItemT;
|
|
305
|
-
|
|
306
|
-
console.log(props.subId, propData.sub_id);
|
|
307
|
-
const sub = propData?.cycle_sub?.find((v) => v.sub_id === props.subId || propData.sub_id) || {} as unknown as CycleSubItemT;
|
|
308
|
-
console.log(2, sub);
|
|
305
|
+
const sub = propData?.cycle_sub?.find((v) => v.sub_id === (props.subId || propData.sub_id)) || {} as unknown as CycleSubItemT;
|
|
309
306
|
const { mid, date, start, end, sub_id } = sub;
|
|
310
307
|
Object.assign(
|
|
311
308
|
form.value,
|
|
@@ -321,7 +318,6 @@ watch(
|
|
|
321
318
|
}
|
|
322
319
|
: {},
|
|
323
320
|
);
|
|
324
|
-
console.log(form.value);
|
|
325
321
|
} else {
|
|
326
322
|
const today = dayjs().format('YYYY-MM-DD');
|
|
327
323
|
const now = dayjs().format('HH:mm');
|
|
@@ -340,21 +340,18 @@ const confirmHandleItem = async () => {
|
|
|
340
340
|
return;
|
|
341
341
|
}
|
|
342
342
|
flag = await props.cancelSubMeetingRequest(row.sub_id);
|
|
343
|
-
message.success({
|
|
344
|
-
content: `${ t('meeting.meetingCancel', [row.topic]) }`,
|
|
345
|
-
});
|
|
346
343
|
} else {
|
|
347
344
|
if (!props.deleteMeetingRequest) {
|
|
348
345
|
return;
|
|
349
346
|
}
|
|
350
347
|
flag = await props.deleteMeetingRequest(row.id);
|
|
351
|
-
message.success({
|
|
352
|
-
content: `${ t('meeting.meetingCancel', [row.topic]) }`,
|
|
353
|
-
});
|
|
354
348
|
}
|
|
355
349
|
if (typeof flag === 'boolean' && !flag) {
|
|
356
350
|
return;
|
|
357
351
|
}
|
|
352
|
+
message.success({
|
|
353
|
+
content: `${ t('meeting.meetingCancel', [row.topic]) }`,
|
|
354
|
+
});
|
|
358
355
|
cancelHandleItem();
|
|
359
356
|
reloadAll.value = true;
|
|
360
357
|
getList();
|
|
@@ -45,7 +45,7 @@ const i18n = computed(() => {
|
|
|
45
45
|
// -------------------- 监听尺寸变化 --------------------
|
|
46
46
|
const meetInfoRef = ref<HTMLDivElement[]>();
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
let resizeObserver: ResizeObserver | null = null;
|
|
49
49
|
watch(
|
|
50
50
|
[() => props.list, () => isClient],
|
|
51
51
|
() => {
|
|
@@ -56,15 +56,19 @@ watch(
|
|
|
56
56
|
}
|
|
57
57
|
if (isClient) {
|
|
58
58
|
nextTick(() => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
if (!resizeObserver) {
|
|
60
|
+
resizeObserver = new ResizeObserver((entries) => {
|
|
61
|
+
for (let entry of entries) {
|
|
62
|
+
const { height } = entry.contentRect;
|
|
63
|
+
entry.target.classList.remove('hidden-divider');
|
|
64
|
+
if (height >= 30) {
|
|
65
|
+
entry.target.classList.add('hidden-divider');
|
|
66
|
+
}
|
|
65
67
|
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
+
});
|
|
69
|
+
} else {
|
|
70
|
+
resizeObserver.disconnect();
|
|
71
|
+
}
|
|
68
72
|
meetInfoRef.value?.forEach((targetDiv) => {
|
|
69
73
|
resizeObserver!.observe(targetDiv);
|
|
70
74
|
});
|
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, ref, toRef, watch } from 'vue';
|
|
3
|
+
import { onClickOutside, useDebounceFn } from '@vueuse/core';
|
|
4
|
+
|
|
5
|
+
import SearchImageInput from './internal/SearchImageInput.vue';
|
|
6
|
+
import SearchPanel from './internal/SearchPanel.vue';
|
|
7
|
+
import { useSearchHistory } from './composables/useSearchHistory';
|
|
8
|
+
import { useI18n } from '@/i18n';
|
|
9
|
+
import type {
|
|
10
|
+
OSearchPayload,
|
|
11
|
+
OSearchRecommendItem,
|
|
12
|
+
OSearchUploadImageFn,
|
|
13
|
+
} from './types';
|
|
14
|
+
|
|
15
|
+
export interface OSearchInputPropsT {
|
|
16
|
+
modelValue?: string;
|
|
17
|
+
imageUrl?: string;
|
|
18
|
+
size?: 'small' | 'medium' | 'large';
|
|
19
|
+
placeholder?: string;
|
|
20
|
+
imagePlaceholder?: string;
|
|
21
|
+
|
|
22
|
+
/** ---- Image search ---- */
|
|
23
|
+
enableImageSearch?: boolean;
|
|
24
|
+
uploadImage?: OSearchUploadImageFn;
|
|
25
|
+
maxImageSize?: number;
|
|
26
|
+
imageUploadTooltip?: string;
|
|
27
|
+
allowedImageTypes?: string[];
|
|
28
|
+
|
|
29
|
+
/** ---- Recommendation lists (controlled by parent) ---- */
|
|
30
|
+
suggestItems?: OSearchRecommendItem[];
|
|
31
|
+
onestepItems?: OSearchRecommendItem[];
|
|
32
|
+
suggestTitle?: string;
|
|
33
|
+
onestepTitle?: string;
|
|
34
|
+
noDataText?: string;
|
|
35
|
+
/** When true, show "no data" placeholder for empty suggest while typing */
|
|
36
|
+
showSuggestEmpty?: boolean;
|
|
37
|
+
highlightKeyword?: boolean;
|
|
38
|
+
debounce?: number;
|
|
39
|
+
|
|
40
|
+
/** ---- History ---- */
|
|
41
|
+
enableHistory?: boolean;
|
|
42
|
+
historyItems?: string[];
|
|
43
|
+
maxHistoryCount?: number;
|
|
44
|
+
storeHistory?: boolean;
|
|
45
|
+
storageKey?: string;
|
|
46
|
+
historyTitle?: string;
|
|
47
|
+
/** Auto-record history on search; default true */
|
|
48
|
+
autoSaveHistory?: boolean;
|
|
49
|
+
|
|
50
|
+
/** ---- "Did you mean" list (below input) ---- */
|
|
51
|
+
suggestList?: string[];
|
|
52
|
+
suggestListLabel?: string;
|
|
53
|
+
|
|
54
|
+
/** ---- Misc ---- */
|
|
55
|
+
clearable?: boolean;
|
|
56
|
+
closeOnSearch?: boolean;
|
|
57
|
+
closeOnClickOutside?: boolean;
|
|
58
|
+
/** Show dropdown on focus even when empty (history) */
|
|
59
|
+
openOnFocus?: boolean;
|
|
60
|
+
/** Always show image as inline thumbnail inside the input; never expand preview below */
|
|
61
|
+
alwaysInlineThumbnail?: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const props = withDefaults(defineProps<OSearchInputPropsT>(), {
|
|
65
|
+
modelValue: '',
|
|
66
|
+
imageUrl: '',
|
|
67
|
+
size: 'large',
|
|
68
|
+
enableImageSearch: false,
|
|
69
|
+
maxImageSize: 10 * 1024 * 1024,
|
|
70
|
+
suggestItems: () => [],
|
|
71
|
+
onestepItems: () => [],
|
|
72
|
+
showSuggestEmpty: true,
|
|
73
|
+
highlightKeyword: true,
|
|
74
|
+
debounce: 300,
|
|
75
|
+
enableHistory: true,
|
|
76
|
+
historyItems: () => [],
|
|
77
|
+
maxHistoryCount: 6,
|
|
78
|
+
storeHistory: false,
|
|
79
|
+
storageKey: 'search-history',
|
|
80
|
+
autoSaveHistory: true,
|
|
81
|
+
suggestList: () => [],
|
|
82
|
+
clearable: true,
|
|
83
|
+
closeOnSearch: true,
|
|
84
|
+
closeOnClickOutside: true,
|
|
85
|
+
openOnFocus: true,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const emit = defineEmits<{
|
|
89
|
+
(e: 'update:modelValue', val: string): void;
|
|
90
|
+
(e: 'update:imageUrl', url: string): void;
|
|
91
|
+
(e: 'update:historyItems', items: string[]): void;
|
|
92
|
+
(e: 'focus'): void;
|
|
93
|
+
(e: 'blur'): void;
|
|
94
|
+
(e: 'input', val: string): void;
|
|
95
|
+
(e: 'clear'): void;
|
|
96
|
+
(e: 'search', payload: OSearchPayload): void;
|
|
97
|
+
(e: 'recommend-click', item: OSearchRecommendItem): void;
|
|
98
|
+
(e: 'onestep-click', item: OSearchRecommendItem): void;
|
|
99
|
+
(e: 'history-click', val: string): void;
|
|
100
|
+
(e: 'suggest-list-click', val: string): void;
|
|
101
|
+
(e: 'delete-history', items: string[]): void;
|
|
102
|
+
(e: 'delete-history-item', val: string): void;
|
|
103
|
+
(e: 'image-upload-start', file: File): void;
|
|
104
|
+
(e: 'image-upload-success', url: string, file: File): void;
|
|
105
|
+
(e: 'image-upload-error', error: unknown, file: File): void;
|
|
106
|
+
(e: 'image-validate-error', reason: 'size' | 'type', file: File): void;
|
|
107
|
+
}>();
|
|
108
|
+
|
|
109
|
+
const { t } = useI18n();
|
|
110
|
+
|
|
111
|
+
type SuggestSegment = { text: string; em: boolean };
|
|
112
|
+
function parseSuggest(raw: string): SuggestSegment[] {
|
|
113
|
+
const segments: SuggestSegment[] = [];
|
|
114
|
+
const re = /<em>(.*?)<\/em>/g;
|
|
115
|
+
let last = 0;
|
|
116
|
+
let m: RegExpExecArray | null;
|
|
117
|
+
while ((m = re.exec(raw)) !== null) {
|
|
118
|
+
if (m.index > last) segments.push({ text: raw.slice(last, m.index), em: false });
|
|
119
|
+
segments.push({ text: m[1], em: true });
|
|
120
|
+
last = m.index + m[0].length;
|
|
121
|
+
}
|
|
122
|
+
if (last < raw.length) segments.push({ text: raw.slice(last), em: false });
|
|
123
|
+
return segments;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const inputRef = ref<InstanceType<typeof SearchImageInput>>();
|
|
127
|
+
const wrapperRef = ref<HTMLElement | null>(null);
|
|
128
|
+
|
|
129
|
+
const innerValue = computed({
|
|
130
|
+
get: () => props.modelValue,
|
|
131
|
+
set: (val: string) => emit('update:modelValue', val),
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const isFocus = ref(false);
|
|
135
|
+
const isPreviewOpen = ref(false);
|
|
136
|
+
const justClosedPreview = ref(false);
|
|
137
|
+
const hasInternalImage = ref(false);
|
|
138
|
+
|
|
139
|
+
const showDropdown = computed(() => {
|
|
140
|
+
if (!isFocus.value) return false;
|
|
141
|
+
if (props.imageUrl || hasInternalImage.value) return false;
|
|
142
|
+
const hasSuggest =
|
|
143
|
+
!!innerValue.value &&
|
|
144
|
+
(props.suggestItems.length > 0 || props.onestepItems.length > 0 || props.showSuggestEmpty);
|
|
145
|
+
const hasHistory = props.enableHistory && history.items.value.length > 0 && !innerValue.value;
|
|
146
|
+
if (hasSuggest) return true;
|
|
147
|
+
if (props.openOnFocus && hasHistory) return true;
|
|
148
|
+
return false;
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// history
|
|
152
|
+
const historyItemsRef = toRef(props, 'historyItems');
|
|
153
|
+
const storageKeyRef = toRef(props, 'storageKey');
|
|
154
|
+
const storeHistoryRef = toRef(props, 'storeHistory');
|
|
155
|
+
const maxHistoryRef = toRef(props, 'maxHistoryCount');
|
|
156
|
+
|
|
157
|
+
const history = useSearchHistory({
|
|
158
|
+
initial: historyItemsRef,
|
|
159
|
+
storageKey: storageKeyRef,
|
|
160
|
+
storeHistory: storeHistoryRef,
|
|
161
|
+
maxHistoryCount: maxHistoryRef,
|
|
162
|
+
onChange: (items) => emit('update:historyItems', items),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// debounced input event
|
|
166
|
+
const emitInputDebounced = useDebounceFn((val: string) => {
|
|
167
|
+
emit('input', val);
|
|
168
|
+
}, () => props.debounce);
|
|
169
|
+
|
|
170
|
+
watch(innerValue, (val) => {
|
|
171
|
+
emitInputDebounced(val);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// click outside
|
|
175
|
+
onClickOutside(wrapperRef, () => {
|
|
176
|
+
if (!props.closeOnClickOutside) return;
|
|
177
|
+
if (isPreviewOpen.value || justClosedPreview.value) return;
|
|
178
|
+
isFocus.value = false;
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const handleFocus = () => {
|
|
182
|
+
isFocus.value = true;
|
|
183
|
+
emit('focus');
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const handleBlur = () => {
|
|
187
|
+
emit('blur');
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const runSearch = async () => {
|
|
191
|
+
if (inputRef.value?.getIsUploading?.()) {
|
|
192
|
+
await inputRef.value.awaitUpload?.();
|
|
193
|
+
}
|
|
194
|
+
const keyword = innerValue.value.trim();
|
|
195
|
+
const imageUrl = inputRef.value?.getUploadedUrl?.() || props.imageUrl;
|
|
196
|
+
|
|
197
|
+
if (!keyword && !imageUrl) return;
|
|
198
|
+
|
|
199
|
+
if (props.autoSaveHistory && keyword) {
|
|
200
|
+
history.push(keyword);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (props.closeOnSearch) {
|
|
204
|
+
isFocus.value = false;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
emit('search', { keyword, imageUrl: imageUrl || undefined });
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const handleClear = () => {
|
|
211
|
+
innerValue.value = '';
|
|
212
|
+
emit('clear');
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const handleSuggestClick = (item: OSearchRecommendItem) => {
|
|
216
|
+
emit('recommend-click', item);
|
|
217
|
+
innerValue.value = item.key;
|
|
218
|
+
runSearch();
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
const handleOnestepClick = (item: OSearchRecommendItem) => {
|
|
222
|
+
emit('onestep-click', item);
|
|
223
|
+
if (item.path) {
|
|
224
|
+
const url = item.path;
|
|
225
|
+
if (typeof window !== 'undefined') window.open(url, '_blank', 'noopener,noreferrer');
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const handleHistoryClick = (val: string) => {
|
|
230
|
+
emit('history-click', val);
|
|
231
|
+
innerValue.value = val;
|
|
232
|
+
runSearch();
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const handleHistoryRemove = (val: string) => {
|
|
236
|
+
history.remove(val);
|
|
237
|
+
emit('delete-history-item', val);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const handleHistoryClear = () => {
|
|
241
|
+
const removed = [...history.items.value];
|
|
242
|
+
history.clearAll();
|
|
243
|
+
emit('delete-history', removed);
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const handleSuggestListClick = (val: string) => {
|
|
247
|
+
const text = val.replace(/<[^>]+>/g, '');
|
|
248
|
+
emit('suggest-list-click', text);
|
|
249
|
+
innerValue.value = text;
|
|
250
|
+
runSearch();
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
const onPreviewChange = (visible: boolean) => {
|
|
254
|
+
isPreviewOpen.value = visible;
|
|
255
|
+
if (!visible) {
|
|
256
|
+
justClosedPreview.value = true;
|
|
257
|
+
setTimeout(() => {
|
|
258
|
+
justClosedPreview.value = false;
|
|
259
|
+
}, 100);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const showInlineThumbnail = computed(() =>
|
|
264
|
+
!!props.imageUrl && (props.alwaysInlineThumbnail || !isFocus.value)
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
const onImageUploadStart = (file: File) => {
|
|
268
|
+
hasInternalImage.value = true;
|
|
269
|
+
emit('image-upload-start', file);
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const onImageUploadSuccess = (url: string, file: File) => {
|
|
273
|
+
hasInternalImage.value = false;
|
|
274
|
+
emit('image-upload-success', url, file);
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
const onImageClear = () => {
|
|
278
|
+
hasInternalImage.value = false;
|
|
279
|
+
emit('update:imageUrl', '');
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
defineExpose({
|
|
283
|
+
focus: () => inputRef.value?.focus?.(),
|
|
284
|
+
blur: () => inputRef.value?.blur?.(),
|
|
285
|
+
search: runSearch,
|
|
286
|
+
saveHistory: (val?: string) => history.push(val ?? innerValue.value),
|
|
287
|
+
});
|
|
288
|
+
</script>
|
|
289
|
+
|
|
290
|
+
<template>
|
|
291
|
+
<div ref="wrapperRef" class="o-search-input" :class="{ 'is-focus': isFocus }">
|
|
292
|
+
<div class="o-search-input-box">
|
|
293
|
+
<SearchImageInput
|
|
294
|
+
ref="inputRef"
|
|
295
|
+
v-model="innerValue"
|
|
296
|
+
:image-url="imageUrl"
|
|
297
|
+
:placeholder="placeholder"
|
|
298
|
+
:image-placeholder="imagePlaceholder"
|
|
299
|
+
:size="size"
|
|
300
|
+
:enable-image-search="enableImageSearch"
|
|
301
|
+
:upload-image="uploadImage"
|
|
302
|
+
:max-image-size="maxImageSize"
|
|
303
|
+
:image-upload-tooltip="imageUploadTooltip"
|
|
304
|
+
:allowed-image-types="allowedImageTypes"
|
|
305
|
+
:expanded="isFocus && !props.alwaysInlineThumbnail"
|
|
306
|
+
:inline-thumbnail="showInlineThumbnail"
|
|
307
|
+
:clearable="clearable"
|
|
308
|
+
class="o-search-input-field"
|
|
309
|
+
@update:imageUrl="(url: string) => emit('update:imageUrl', url)"
|
|
310
|
+
@focus="handleFocus"
|
|
311
|
+
@blur="handleBlur"
|
|
312
|
+
@enter="runSearch"
|
|
313
|
+
@clear="handleClear"
|
|
314
|
+
@image-clear="onImageClear"
|
|
315
|
+
@image-upload-start="onImageUploadStart"
|
|
316
|
+
@image-upload-success="onImageUploadSuccess"
|
|
317
|
+
@image-upload-error="(error: unknown, file: File) => emit('image-upload-error', error, file)"
|
|
318
|
+
@image-validate-error="(reason: 'size' | 'type', file: File) => emit('image-validate-error', reason, file)"
|
|
319
|
+
@preview-change="onPreviewChange"
|
|
320
|
+
>
|
|
321
|
+
<template #prefix><slot name="input-prefix" /></template>
|
|
322
|
+
<template #suffix="slotProps"><slot name="input-suffix" v-bind="slotProps" /></template>
|
|
323
|
+
<template v-if="$slots['image-preview']" #preview="slotProps">
|
|
324
|
+
<slot name="image-preview" v-bind="slotProps" />
|
|
325
|
+
</template>
|
|
326
|
+
</SearchImageInput>
|
|
327
|
+
|
|
328
|
+
<Transition name="o-search-input-dropdown">
|
|
329
|
+
<div v-if="showDropdown" class="o-search-input-dropdown">
|
|
330
|
+
<slot name="dropdown" :keyword="modelValue">
|
|
331
|
+
<SearchPanel
|
|
332
|
+
:keyword="modelValue"
|
|
333
|
+
:onestep-items="onestepItems"
|
|
334
|
+
:onestep-title="onestepTitle"
|
|
335
|
+
:suggest-items="suggestItems"
|
|
336
|
+
:suggest-title="suggestTitle"
|
|
337
|
+
:history-items="enableHistory ? history.items.value : []"
|
|
338
|
+
:history-title="historyTitle"
|
|
339
|
+
:no-data-text="noDataText"
|
|
340
|
+
:highlight-keyword="highlightKeyword"
|
|
341
|
+
:hide-on-keyword="true"
|
|
342
|
+
:show-suggest-empty="showSuggestEmpty"
|
|
343
|
+
history-layout="list"
|
|
344
|
+
@onestep-click="handleOnestepClick"
|
|
345
|
+
@suggest-click="handleSuggestClick"
|
|
346
|
+
@history-click="handleHistoryClick"
|
|
347
|
+
@history-remove="handleHistoryRemove"
|
|
348
|
+
@history-clear="handleHistoryClear"
|
|
349
|
+
>
|
|
350
|
+
<template v-if="$slots['onestep-header']" #onestep-header="slotProps">
|
|
351
|
+
<slot name="onestep-header" v-bind="slotProps" />
|
|
352
|
+
</template>
|
|
353
|
+
<template v-if="$slots['onestep-content']" #onestep-content="slotProps">
|
|
354
|
+
<slot name="onestep-content" v-bind="slotProps" />
|
|
355
|
+
</template>
|
|
356
|
+
<template v-if="$slots['suggest-header']" #suggest-header="slotProps">
|
|
357
|
+
<slot name="suggest-header" v-bind="slotProps" />
|
|
358
|
+
</template>
|
|
359
|
+
<template v-if="$slots['suggest-content']" #suggest-content="slotProps">
|
|
360
|
+
<slot name="suggest-content" v-bind="slotProps" />
|
|
361
|
+
</template>
|
|
362
|
+
<template v-if="$slots['history-header']" #history-header="slotProps">
|
|
363
|
+
<slot name="history-header" v-bind="slotProps" />
|
|
364
|
+
</template>
|
|
365
|
+
<template v-if="$slots['history-content']" #history-content="slotProps">
|
|
366
|
+
<slot name="history-content" v-bind="slotProps" />
|
|
367
|
+
</template>
|
|
368
|
+
</SearchPanel>
|
|
369
|
+
</slot>
|
|
370
|
+
</div>
|
|
371
|
+
</Transition>
|
|
372
|
+
</div>
|
|
373
|
+
|
|
374
|
+
<div v-if="suggestList?.length" class="o-search-input-suggest-list-row">
|
|
375
|
+
<slot name="suggest-list" :items="suggestList">
|
|
376
|
+
<span class="o-search-input-suggest-list-label">{{ suggestListLabel ?? t('search.suggestListLabel') }}</span>
|
|
377
|
+
<ul class="o-search-input-suggest-list">
|
|
378
|
+
<li
|
|
379
|
+
v-for="(item, idx) in suggestList"
|
|
380
|
+
:key="item + idx"
|
|
381
|
+
class="o-search-input-suggest-list-item"
|
|
382
|
+
@click="handleSuggestListClick(item)"
|
|
383
|
+
>
|
|
384
|
+
<template v-for="seg in parseSuggest(item)" :key="seg.text + String(seg.em)">
|
|
385
|
+
<em v-if="seg.em">{{ seg.text }}</em>
|
|
386
|
+
<template v-else>{{ seg.text }}</template>
|
|
387
|
+
</template>
|
|
388
|
+
</li>
|
|
389
|
+
</ul>
|
|
390
|
+
</slot>
|
|
391
|
+
</div>
|
|
392
|
+
</div>
|
|
393
|
+
</template>
|
|
394
|
+
|
|
395
|
+
<style lang="scss" scoped>
|
|
396
|
+
.o-search-input {
|
|
397
|
+
position: relative;
|
|
398
|
+
width: 100%;
|
|
399
|
+
background-color: var(--o-color-fill2);
|
|
400
|
+
border-radius: var(--o-radius-xs);
|
|
401
|
+
|
|
402
|
+
:deep(.o-input.o_box-large) {
|
|
403
|
+
--_box-height: 48px;
|
|
404
|
+
}
|
|
405
|
+
:deep(.o-search-image-input-icon) {
|
|
406
|
+
font-size: 24px;
|
|
407
|
+
}
|
|
408
|
+
:deep(.o-search-image-input-upload-btn) {
|
|
409
|
+
width: 24px;
|
|
410
|
+
height: 24px;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
@include respond-to('pad_v-pc_s') {
|
|
414
|
+
:deep(.o-input.o_box-large) {
|
|
415
|
+
--_box-height: 40px;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
@include respond-to('<=pad_v') {
|
|
420
|
+
:deep(.o-input.o_box-large) {
|
|
421
|
+
--_box-height: 32px;
|
|
422
|
+
}
|
|
423
|
+
:deep(.o-search-image-input-icon) {
|
|
424
|
+
font-size: 16px;
|
|
425
|
+
}
|
|
426
|
+
:deep(.o-search-image-input-upload-btn) {
|
|
427
|
+
width: 16px;
|
|
428
|
+
height: 16px;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.o-search-input-box {
|
|
434
|
+
position: relative;
|
|
435
|
+
width: 100%;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.o-search-input-field {
|
|
439
|
+
width: 100%;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.o-search-input-dropdown {
|
|
443
|
+
position: absolute;
|
|
444
|
+
top: calc(100% + 4px);
|
|
445
|
+
left: 0;
|
|
446
|
+
right: 0;
|
|
447
|
+
z-index: 10;
|
|
448
|
+
padding: var(--o-gap-4);
|
|
449
|
+
background-color: var(--o-color-fill2);
|
|
450
|
+
border-radius: var(--o-radius-xs);
|
|
451
|
+
box-shadow: var(--o-shadow-2);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.o-search-input-dropdown-enter-active,
|
|
455
|
+
.o-search-input-dropdown-leave-active {
|
|
456
|
+
transition: opacity var(--o-duration-m1), transform var(--o-duration-m1);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.o-search-input-dropdown-enter-from,
|
|
460
|
+
.o-search-input-dropdown-leave-to {
|
|
461
|
+
opacity: 0;
|
|
462
|
+
transform: translateY(-4px);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.o-search-input-suggest-list-row {
|
|
466
|
+
display: flex;
|
|
467
|
+
margin-top: 8px;
|
|
468
|
+
align-items: center;
|
|
469
|
+
flex-wrap: wrap;
|
|
470
|
+
@include tip1;
|
|
471
|
+
color: var(--o-color-info1);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.o-search-input-suggest-list-label {
|
|
475
|
+
color: var(--o-color-info3);
|
|
476
|
+
margin-right: 4px;
|
|
477
|
+
@include tip1;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
.o-search-input-suggest-list {
|
|
481
|
+
display: flex;
|
|
482
|
+
flex-wrap: wrap;
|
|
483
|
+
align-items: center;
|
|
484
|
+
padding: 0;
|
|
485
|
+
margin: 0;
|
|
486
|
+
list-style: none;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.o-search-input-suggest-list-item {
|
|
490
|
+
margin-right: 8px;
|
|
491
|
+
cursor: pointer;
|
|
492
|
+
color: var(--o-color-primary1);
|
|
493
|
+
|
|
494
|
+
:deep(em) {
|
|
495
|
+
color: var(--o-color-primary1);
|
|
496
|
+
font-style: normal;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
@include hover {
|
|
500
|
+
text-decoration: underline;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
</style>
|