stellar-ui-v2 1.40.20 → 1.40.21

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.
@@ -1,590 +1,590 @@
1
- <template>
2
- <view class="ste-search-root" :style="[cmpStyleVar, cmpBackground, cmpRootPadding]" @click="onClick">
3
- <view class="content">
4
- <view class="icon-box">
5
- <ste-icon code="&#xe695;" :color="prefixIconColor" size="44" />
6
- </view>
7
- <view class="input-box" v-if="!hiddenInput">
8
- <ste-input
9
- rootClass="ste-search-input"
10
- placeholder-class="search-input-placeholder"
11
- :disabled="disabled"
12
- :placeholder="cmpPlaceholder"
13
- v-model="dataValue"
14
- @input="onInput"
15
- @confirm="onSearch"
16
- @focus="onFocus"
17
- @blur="onBlur"
18
- @clear="onClear"
19
- :focus="focus"
20
- :clearable="clearable"
21
- :fontColor="inputTextColor"
22
- background="transparent"
23
- :cursor="cursorNumber"
24
- :allowSpace="allowSpace"
25
- >
26
- <template #prefix>
27
- <slot name="prefix"></slot>
28
- </template>
29
- <template #suffix>
30
- <slot name="suffix"></slot>
31
- </template>
32
- </ste-input>
33
- <swiper
34
- v-if="cmpShowSwitch"
35
- class="placeholder-list"
36
- :current="switchIndex"
37
- :autoplay="internalAutoplay"
38
- :interval="interval"
39
- circular
40
- vertical
41
- @change="onSwitchChange"
42
- >
43
- <swiper-item class="placeholder-item" v-for="(item, i) in hotWords" :key="i">
44
- {{ item }}
45
- </swiper-item>
46
- </swiper>
47
- </view>
48
- <view v-if="!cmpHiddenLine" class="secrch-line" :class="disabled ? 'disabled' : ''" />
49
- <view v-if="!hiddenBtn" class="search-button" :class="disabled ? 'disabled' : ''" :style="[cmpbtnBackground]" @click="onSearch">
50
- {{ btnText }}
51
- </view>
52
- </view>
53
- <view class="nav-box" data-test="nav-box" v-if="type === 'nav'" />
54
- <!-- 输入建议 -->
55
- <view
56
- v-if="suggestionList.length > 0"
57
- class="suggestions-box"
58
- :class="showSuggestionsBox == null ? '' : showSuggestionsBox ? 'show' : 'hide'"
59
- >
60
- <scroll-view scroll-y class="scroll-box">
61
- <view class="item" @click="handleSuggestionClick(item)" v-for="(item, key) in suggestionList" :key="key">
62
- {{ item.label }}
63
- </view>
64
- </scroll-view>
65
- </view>
66
- </view>
67
- </template>
68
-
69
- <script>
70
- import utils from '../../utils/utils.js';
71
- import SteInput from '../ste-input/ste-input.vue';
72
- /**
73
- * ste-search 搜索
74
- * @description 搜索组件
75
- * @tutorial https://stellar-ui.intecloud.com.cn/?projectName=stellar-ui&menu=%E7%BB%84%E4%BB%B6&active=ste-search
76
- * @property {String} type 组件类型
77
- * @value default 正常搜索{String}
78
- * @value nav 导航栏{String}
79
- * @property {String} value 当前值(支持v-model双向绑定)
80
- * @property {String} placeholder 占位提示符
81
- * @property {String[]} hotWords 热词列表,默认值,[]
82
- * @property {Number} interval 热词列表自动切换时间间隔,默认值,3000
83
- * @property {Boolean} autoplay 热词列表自动切换,默认值,true
84
- * @property {Boolean} disabled 是否禁用状态,默认值,false
85
- * @property {Boolean} hiddenLine 是否隐藏分割线 ,默认值,false
86
- * @property {Boolean} hiddenBtn 是否隐藏搜索按钮 ,默认值,false
87
- * @property {String} btnText 搜索按钮文字 ,默认值 搜索
88
- * @property {Boolean} hiddenInput 是否隐藏输入框,默认值,false
89
- * @property {Boolean} clearable 是否可清空,默认值,true
90
- * @property {Boolean} allowSpace 是否允许输入空格,默认值,true
91
- * @property {Number} height 高度,单位rpx,默认值,64
92
- * @property {Number} radius 圆角弧度,单位rpx,默认值,32
93
- * @property {String} borderColor 边框颜色,默认值,#EEEEEE66
94
- * @property {String} background 背景,默认值,#FFFFFF
95
- * @property {String} prefixIconColor 前置图标颜色,默认值,#BBBBBB
96
- * @property {String} placeholderColor 占位符文本颜色,默认值,#BBBBBB
97
- * @property {String} inputTextColor 输入框文本颜色,默认值,#000000
98
- * @property {String} clearIconColor 清除图标颜色,默认值,#BBBBBB
99
- * @property {String} btnTextColor 搜索按钮文本颜色 ,默认值,#0090FF
100
- * @property {String} btnBackground 搜索按钮背景
101
- * @property {Boolean} focus 是否聚焦(双向绑定),默认值,false
102
- * @event {Function} input 输入事件
103
- * @event {Function} focus 聚焦焦点事件
104
- * @event {Function} blur 失去焦点事件
105
- * @event {Function} search 确定搜索时触发
106
- * @event {Function} clear 点击清除按钮后触发
107
- * @event {Function} click 点击事件
108
- */
109
- export default {
110
- group: '表单组件',
111
- title: 'Search 搜索',
112
- name: 'ste-search',
113
- components: { 'ste-input': SteInput },
114
- props: {
115
- // 组件类型,"default":正常搜索,"nav":导航栏
116
- type: {
117
- type: [String, null],
118
- default: () => 'default'
119
- },
120
- // 当前值(支持v-model双向绑定)
121
- value: {
122
- type: [String, null],
123
- default: () => ''
124
- },
125
- // 占位提示符
126
- placeholder: {
127
- type: [String, null],
128
- default: () => ''
129
- },
130
- // 热词列表
131
- hotWords: {
132
- type: [Array, null],
133
- default: () => []
134
- },
135
- // 热词列表自动切换时间间隔`
136
- interval: {
137
- type: [Number, null],
138
- default: () => 3000
139
- },
140
- // 热词列表是否自动切换
141
- autoplay: {
142
- type: [Boolean, null],
143
- default: () => true
144
- },
145
- // 是否禁用状态
146
- disabled: {
147
- type: [Boolean, null],
148
- default: () => false
149
- },
150
- // 是否隐藏分割线
151
- hiddenLine: {
152
- type: [Boolean, null],
153
- default: () => false
154
- },
155
- // 是否隐藏搜索按钮
156
- hiddenBtn: {
157
- type: [Boolean, null],
158
- default: () => false
159
- },
160
- // 搜索按钮文字
161
- btnText: {
162
- type: [String, null],
163
- default: () => '搜索'
164
- },
165
- // 是否隐藏输入框
166
- hiddenInput: {
167
- type: [Boolean, null],
168
- default: () => false
169
- },
170
- // 是否可清空
171
- clearable: {
172
- type: [Boolean, null],
173
- default: () => true
174
- },
175
- // 是否允许输入空格
176
- allowSpace: {
177
- type: [Boolean, null],
178
- default: () => true
179
- },
180
- // 边框颜色
181
- borderColor: {
182
- type: [String, null],
183
- default: () => '#dddddd'
184
- },
185
- // 背景
186
- background: {
187
- type: [String, null],
188
- default: () => '#ffffff'
189
- },
190
- // 前置图标颜色
191
- prefixIconColor: {
192
- type: [String, null],
193
- default: () => '#bbbbbb'
194
- },
195
- // 占位符字体颜色
196
- placeholderColor: {
197
- type: [String, null],
198
- default: () => '#bbbbbb'
199
- },
200
- // 输入框文字颜色
201
- inputTextColor: {
202
- type: [String, null],
203
- default: () => '#000000'
204
- },
205
- // 清除图标颜色
206
- clearIconColor: {
207
- type: [String, null],
208
- default: () => '#bbbbbb'
209
- },
210
- // 搜索按钮背景
211
- btnBackground: {
212
- type: [String, null]
213
- },
214
- // 搜索按钮文字颜色
215
- btnTextColor: {
216
- type: [String, null],
217
- default: () => '#0090FF'
218
- },
219
- // 高度
220
- height: {
221
- type: [Number, null],
222
- default: () => 64
223
- },
224
- // 圆角弧度
225
- radius: {
226
- type: [Number, null],
227
- default: () => 32
228
- },
229
- // 聚焦
230
- focus: {
231
- type: [Boolean, null],
232
- default: () => false
233
- },
234
- suggestionList: {
235
- type: [Array, null],
236
- default: () => []
237
- }
238
- },
239
- model: {
240
- prop: 'value',
241
- event: 'input'
242
- },
243
- data() {
244
- return {
245
- dataValue: '',
246
- switchIndex: 0,
247
- showSuggestionsBox: null,
248
- cursorNumber: 0,
249
- curSuggestion: '',
250
- internalAutoplay: this.autoplay
251
- };
252
- },
253
- computed: {
254
- cmpStyleVar() {
255
- return {
256
- '--search-root-height': utils.formatPx(this.height),
257
- '--search-root-radius': utils.formatPx(this.radius),
258
- '--search-btn-text-color': this.btnTextColor,
259
- '--search-placeholder-color': this.placeholderColor,
260
- '--search-input-color': this.inputTextColor,
261
- '--search-border-color': this.borderColor
262
- };
263
- },
264
- cmpPlaceholder() {
265
- return this.hotWords?.length ? '' : this.placeholder;
266
- },
267
- cmpHiddenLine() {
268
- return this.hiddenLine || this.hiddenBtn;
269
- },
270
- cmpShowClear() {
271
- return this.clearable && this.dataValue;
272
- },
273
- cmpShowSwitch() {
274
- return this.hotWords?.length && !this.dataValue;
275
- },
276
- cmpBackground() {
277
- return utils.bg2style(this.background);
278
- },
279
- cmpbtnBackground() {
280
- return utils.bg2style(this.btnBackground);
281
- },
282
- cmpRootPadding() {
283
- return this.hiddenBtn && this.hiddenInput ? {} : { padding: '0 8rpx 0 16rpx' };
284
- }
285
- },
286
- watch: {
287
- value: {
288
- handler(val) {
289
- this.dataValue = val;
290
- },
291
- immediate: true
292
- },
293
- hotWords() {
294
- this.switchIndex = 0;
295
- },
296
- autoplay(val) {
297
- this.internalAutoplay = val;
298
- }
299
- },
300
- // #ifdef MP-WEIXIN
301
- mounted() {
302
- // 监听应用显示/隐藏(小程序前后台切换)
303
- this.appShowHandler = () => {
304
- this.internalAutoplay = this.autoplay;
305
- };
306
- this.appHideHandler = () => {
307
- this.internalAutoplay = false;
308
- };
309
- uni.onAppShow(this.appShowHandler);
310
- uni.onAppHide(this.appHideHandler);
311
- },
312
- beforeDestroy() {
313
- // 移除监听
314
- if (this.appShowHandler) {
315
- uni.offAppShow(this.appShowHandler);
316
- }
317
- if (this.appHideHandler) {
318
- uni.offAppHide(this.appHideHandler);
319
- }
320
- },
321
- // #endif
322
- methods: {
323
- onInput() {
324
- if (this.disabled) return;
325
- this.$emit('input', this.dataValue);
326
- },
327
- onFocus() {
328
- if (this.disabled) return;
329
- this.$emit('focus', this.dataValue);
330
-
331
- this.showSuggestionsBox = true;
332
- },
333
- onBlur() {
334
- this.$emit('update:focus', false);
335
- this.$emit('blur', this.dataValue);
336
- },
337
- onSearch() {
338
- if (this.disabled) return;
339
- let searchValue = this.dataValue;
340
- if (!searchValue && this.hotWords.length) {
341
- searchValue = this.hotWords[this.switchIndex];
342
- }
343
- this.$emit('search', searchValue);
344
- },
345
- onSwitchChange(v) {
346
- this.switchIndex = v.detail.current;
347
- },
348
- onClick() {
349
- if (this.disabled) return;
350
- let searchValue = this.dataValue;
351
- if (!searchValue && this.hotWords.length) {
352
- searchValue = this.hotWords[this.switchIndex];
353
- }
354
- this.$emit('click', searchValue);
355
- },
356
- onClear() {
357
- if (this.disabled) return;
358
- this.dataValue = '';
359
- this.$emit('input', this.dataValue);
360
- this.$emit('clear');
361
- },
362
- handleSuggestionClick(item) {
363
- this.dataValue = item.label;
364
- this.$emit('input', item.label);
365
- this.$emit('selectSuggestion', item);
366
- this.showSuggestionsBox = false;
367
-
368
- setTimeout(() => {
369
- this.cursorNumber = item.label.length;
370
- }, 50);
371
- }
372
- }
373
- };
374
- </script>
375
-
376
- <style lang="scss" scoped>
377
- .ste-search-root {
378
- width: 100%;
379
- height: var(--search-root-height);
380
- background-color: #fff;
381
- background-repeat: no-repeat;
382
- background-size: 100% 100%;
383
- border-radius: var(--search-root-radius);
384
- border: 1rpx solid var(--search-border-color);
385
- position: relative;
386
-
387
- &,
388
- view,
389
- input {
390
- box-sizing: border-box;
391
- }
392
-
393
- .content {
394
- width: 100%;
395
- height: 100%;
396
- display: flex;
397
- flex-direction: row;
398
- align-items: center;
399
- justify-content: center;
400
- position: relative;
401
-
402
- .icon-box {
403
- width: 28rpx;
404
- height: 28rpx;
405
- flex-shrink: 0;
406
- display: flex;
407
- align-items: center;
408
- justify-content: center;
409
-
410
- .image {
411
- width: 100%;
412
- height: 100%;
413
- }
414
-
415
- & + .input-box {
416
- margin-left: 16rpx;
417
- }
418
- }
419
-
420
- .input-box {
421
- position: relative;
422
- flex: 1;
423
- height: 100%;
424
-
425
- ::v-deep .search-input {
426
- height: 100%;
427
-
428
- font-size: 28rpx;
429
- color: var(--search-input-color);
430
- // #ifdef MP-ALIPAY
431
- background-color: rgba(0, 0, 0, 0);
432
- // #endif
433
-
434
- .content {
435
- padding: 0;
436
- height: 100%;
437
- }
438
-
439
- rch-input-placeholder {
440
- color: var(--search-placeholder-color);
441
- font-family: Alibaba PuHuiTi 2, Alibaba PuHuiTi 20;
442
- font-weight: normal;
443
- }
444
- }
445
-
446
- .placeholder-list {
447
- width: 100%;
448
- height: 100%;
449
- pointer-events: none;
450
- position: absolute;
451
- top: 0;
452
- left: 0;
453
-
454
- .placeholder-item {
455
- font-size: 28rpx;
456
- color: var(--search-placeholder-color);
457
- font-family: Alibaba PuHuiTi 2, Alibaba PuHuiTi 20;
458
- font-weight: normal;
459
- display: flex;
460
- align-items: center;
461
- }
462
- }
463
-
464
- .clear-icon {
465
- width: 48rpx;
466
- height: 100%;
467
- display: flex;
468
- align-items: center;
469
- justify-content: flex-end;
470
- position: absolute;
471
- right: 8rpx;
472
- top: 50%;
473
- z-index: 2;
474
- transform: translateY(-50%);
475
- }
476
- }
477
-
478
- .secrch-line {
479
- margin-left: 16rpx;
480
- width: 2rpx;
481
- flex-shrink: 0;
482
- height: 24rpx;
483
- background-color: var(--search-btn-text-color);
484
-
485
- &.disabled {
486
- background: #bbbbbb;
487
- }
488
- }
489
-
490
- .search-button {
491
- padding: 0 16rpx;
492
- height: 40rpx;
493
- font-size: 28rpx;
494
- line-height: 40rpx;
495
- flex-shrink: 0;
496
- text-align: center;
497
- font-family: Alibaba PuHuiTi 2, Alibaba PuHuiTi 20;
498
- font-weight: normal;
499
- color: var(--search-btn-text-color);
500
- border-radius: 20rpx;
501
- background-repeat: no-repeat;
502
- background-size: 100% 100%;
503
-
504
- &.disabled {
505
- color: #bbbbbb;
506
- }
507
- }
508
- }
509
-
510
- .nav-box {
511
- position: absolute;
512
- width: 100%;
513
- height: 100%;
514
- top: 0;
515
- left: 0;
516
- z-index: 2;
517
- }
518
-
519
- .suggestions-box {
520
- z-index: 999;
521
- position: absolute;
522
- left: 0;
523
- top: 100%;
524
- overflow-y: hidden;
525
- opacity: 0;
526
- max-height: 0;
527
-
528
- margin: 20rpx 0;
529
- width: 100%;
530
-
531
- background-color: #ffffff;
532
- box-shadow: 0 4rpx 24rpx 0 rgba(0, 0, 0, 0.1);
533
- border-radius: 8rpx;
534
- padding: 16rpx 0;
535
-
536
- .scroll-box {
537
- width: 100%;
538
- max-height: calc(400rpx - 32rpx);
539
- }
540
-
541
- .item {
542
- padding-left: 16rpx;
543
- width: 100%;
544
- height: 60rpx;
545
- display: flex;
546
- align-items: center;
547
- font-size: 28rpx;
548
- color: #bbbbbb;
549
-
550
- &:focus {
551
- background-color: red;
552
- }
553
- }
554
-
555
- &.show {
556
- opacity: 1;
557
- max-height: 400rpx;
558
- animation: suggestions-show 0.2s ease-out;
559
- }
560
-
561
- &.hide {
562
- animation: suggestions-hide 0.2s ease-out;
563
- }
564
- }
565
-
566
- @keyframes suggestions-show {
567
- 0% {
568
- opacity: 0;
569
- max-height: 0;
570
- }
571
-
572
- 100% {
573
- opacity: 1;
574
- max-height: 400rpx;
575
- }
576
- }
577
-
578
- @keyframes suggestions-hide {
579
- 0% {
580
- opacity: 1;
581
- max-height: 400rpx;
582
- }
583
-
584
- 100% {
585
- opacity: 0;
586
- max-height: 0;
587
- }
588
- }
589
- }
590
- </style>
1
+ <template>
2
+ <view class="ste-search-root" :style="[cmpStyleVar, cmpBackground, cmpRootPadding]" @click="onClick">
3
+ <view class="content">
4
+ <view class="icon-box">
5
+ <ste-icon code="&#xe695;" :color="prefixIconColor" size="44" />
6
+ </view>
7
+ <view class="input-box" v-if="!hiddenInput">
8
+ <ste-input
9
+ rootClass="ste-search-input"
10
+ placeholder-class="search-input-placeholder"
11
+ :disabled="disabled"
12
+ :placeholder="cmpPlaceholder"
13
+ v-model="dataValue"
14
+ @input="onInput"
15
+ @confirm="onSearch"
16
+ @focus="onFocus"
17
+ @blur="onBlur"
18
+ @clear="onClear"
19
+ :focus="focus"
20
+ :clearable="clearable"
21
+ :fontColor="inputTextColor"
22
+ background="transparent"
23
+ :cursor="cursorNumber"
24
+ :allowSpace="allowSpace"
25
+ >
26
+ <template #prefix>
27
+ <slot name="prefix"></slot>
28
+ </template>
29
+ <template #suffix>
30
+ <slot name="suffix"></slot>
31
+ </template>
32
+ </ste-input>
33
+ <swiper
34
+ v-if="cmpShowSwitch"
35
+ class="placeholder-list"
36
+ :current="switchIndex"
37
+ :autoplay="internalAutoplay"
38
+ :interval="interval"
39
+ circular
40
+ vertical
41
+ @change="onSwitchChange"
42
+ >
43
+ <swiper-item class="placeholder-item" v-for="(item, i) in hotWords" :key="i">
44
+ {{ item }}
45
+ </swiper-item>
46
+ </swiper>
47
+ </view>
48
+ <view v-if="!cmpHiddenLine" class="secrch-line" :class="disabled ? 'disabled' : ''" />
49
+ <view v-if="!hiddenBtn" class="search-button" :class="disabled ? 'disabled' : ''" :style="[cmpbtnBackground]" @click="onSearch">
50
+ {{ btnText }}
51
+ </view>
52
+ </view>
53
+ <view class="nav-box" data-test="nav-box" v-if="type === 'nav'" />
54
+ <!-- 输入建议 -->
55
+ <view
56
+ v-if="suggestionList.length > 0"
57
+ class="suggestions-box"
58
+ :class="showSuggestionsBox == null ? '' : showSuggestionsBox ? 'show' : 'hide'"
59
+ >
60
+ <scroll-view scroll-y class="scroll-box">
61
+ <view class="item" @click="handleSuggestionClick(item)" v-for="(item, key) in suggestionList" :key="key">
62
+ {{ item.label }}
63
+ </view>
64
+ </scroll-view>
65
+ </view>
66
+ </view>
67
+ </template>
68
+
69
+ <script>
70
+ import utils from '../../utils/utils.js';
71
+ import SteInput from '../ste-input/ste-input.vue';
72
+ /**
73
+ * ste-search 搜索
74
+ * @description 搜索组件
75
+ * @tutorial https://stellar-ui.intecloud.com.cn/?projectName=stellar-ui&menu=%E7%BB%84%E4%BB%B6&active=ste-search
76
+ * @property {String} type 组件类型
77
+ * @value default 正常搜索{String}
78
+ * @value nav 导航栏{String}
79
+ * @property {String} value 当前值(支持v-model双向绑定)
80
+ * @property {String} placeholder 占位提示符
81
+ * @property {String[]} hotWords 热词列表,默认值,[]
82
+ * @property {Number} interval 热词列表自动切换时间间隔,默认值,3000
83
+ * @property {Boolean} autoplay 热词列表自动切换,默认值,true
84
+ * @property {Boolean} disabled 是否禁用状态,默认值,false
85
+ * @property {Boolean} hiddenLine 是否隐藏分割线 ,默认值,false
86
+ * @property {Boolean} hiddenBtn 是否隐藏搜索按钮 ,默认值,false
87
+ * @property {String} btnText 搜索按钮文字 ,默认值 搜索
88
+ * @property {Boolean} hiddenInput 是否隐藏输入框,默认值,false
89
+ * @property {Boolean} clearable 是否可清空,默认值,true
90
+ * @property {Boolean} allowSpace 是否允许输入空格,默认值,true
91
+ * @property {Number} height 高度,单位rpx,默认值,64
92
+ * @property {Number} radius 圆角弧度,单位rpx,默认值,32
93
+ * @property {String} borderColor 边框颜色,默认值,#EEEEEE66
94
+ * @property {String} background 背景,默认值,#FFFFFF
95
+ * @property {String} prefixIconColor 前置图标颜色,默认值,#BBBBBB
96
+ * @property {String} placeholderColor 占位符文本颜色,默认值,#BBBBBB
97
+ * @property {String} inputTextColor 输入框文本颜色,默认值,#000000
98
+ * @property {String} clearIconColor 清除图标颜色,默认值,#BBBBBB
99
+ * @property {String} btnTextColor 搜索按钮文本颜色 ,默认值,#0090FF
100
+ * @property {String} btnBackground 搜索按钮背景
101
+ * @property {Boolean} focus 是否聚焦(双向绑定),默认值,false
102
+ * @event {Function} input 输入事件
103
+ * @event {Function} focus 聚焦焦点事件
104
+ * @event {Function} blur 失去焦点事件
105
+ * @event {Function} search 确定搜索时触发
106
+ * @event {Function} clear 点击清除按钮后触发
107
+ * @event {Function} click 点击事件
108
+ */
109
+ export default {
110
+ group: '表单组件',
111
+ title: 'Search 搜索',
112
+ name: 'ste-search',
113
+ components: { 'ste-input': SteInput },
114
+ props: {
115
+ // 组件类型,"default":正常搜索,"nav":导航栏
116
+ type: {
117
+ type: [String, null],
118
+ default: () => 'default'
119
+ },
120
+ // 当前值(支持v-model双向绑定)
121
+ value: {
122
+ type: [String, null],
123
+ default: () => ''
124
+ },
125
+ // 占位提示符
126
+ placeholder: {
127
+ type: [String, null],
128
+ default: () => ''
129
+ },
130
+ // 热词列表
131
+ hotWords: {
132
+ type: [Array, null],
133
+ default: () => []
134
+ },
135
+ // 热词列表自动切换时间间隔`
136
+ interval: {
137
+ type: [Number, null],
138
+ default: () => 3000
139
+ },
140
+ // 热词列表是否自动切换
141
+ autoplay: {
142
+ type: [Boolean, null],
143
+ default: () => true
144
+ },
145
+ // 是否禁用状态
146
+ disabled: {
147
+ type: [Boolean, null],
148
+ default: () => false
149
+ },
150
+ // 是否隐藏分割线
151
+ hiddenLine: {
152
+ type: [Boolean, null],
153
+ default: () => false
154
+ },
155
+ // 是否隐藏搜索按钮
156
+ hiddenBtn: {
157
+ type: [Boolean, null],
158
+ default: () => false
159
+ },
160
+ // 搜索按钮文字
161
+ btnText: {
162
+ type: [String, null],
163
+ default: () => '搜索'
164
+ },
165
+ // 是否隐藏输入框
166
+ hiddenInput: {
167
+ type: [Boolean, null],
168
+ default: () => false
169
+ },
170
+ // 是否可清空
171
+ clearable: {
172
+ type: [Boolean, null],
173
+ default: () => true
174
+ },
175
+ // 是否允许输入空格
176
+ allowSpace: {
177
+ type: [Boolean, null],
178
+ default: () => true
179
+ },
180
+ // 边框颜色
181
+ borderColor: {
182
+ type: [String, null],
183
+ default: () => '#dddddd'
184
+ },
185
+ // 背景
186
+ background: {
187
+ type: [String, null],
188
+ default: () => '#ffffff'
189
+ },
190
+ // 前置图标颜色
191
+ prefixIconColor: {
192
+ type: [String, null],
193
+ default: () => '#bbbbbb'
194
+ },
195
+ // 占位符字体颜色
196
+ placeholderColor: {
197
+ type: [String, null],
198
+ default: () => '#bbbbbb'
199
+ },
200
+ // 输入框文字颜色
201
+ inputTextColor: {
202
+ type: [String, null],
203
+ default: () => '#000000'
204
+ },
205
+ // 清除图标颜色
206
+ clearIconColor: {
207
+ type: [String, null],
208
+ default: () => '#bbbbbb'
209
+ },
210
+ // 搜索按钮背景
211
+ btnBackground: {
212
+ type: [String, null]
213
+ },
214
+ // 搜索按钮文字颜色
215
+ btnTextColor: {
216
+ type: [String, null],
217
+ default: () => '#0090FF'
218
+ },
219
+ // 高度
220
+ height: {
221
+ type: [Number, null],
222
+ default: () => 64
223
+ },
224
+ // 圆角弧度
225
+ radius: {
226
+ type: [Number, null],
227
+ default: () => 32
228
+ },
229
+ // 聚焦
230
+ focus: {
231
+ type: [Boolean, null],
232
+ default: () => false
233
+ },
234
+ suggestionList: {
235
+ type: [Array, null],
236
+ default: () => []
237
+ }
238
+ },
239
+ model: {
240
+ prop: 'value',
241
+ event: 'input'
242
+ },
243
+ data() {
244
+ return {
245
+ dataValue: '',
246
+ switchIndex: 0,
247
+ showSuggestionsBox: null,
248
+ cursorNumber: 0,
249
+ curSuggestion: '',
250
+ internalAutoplay: this.autoplay
251
+ };
252
+ },
253
+ computed: {
254
+ cmpStyleVar() {
255
+ return {
256
+ '--search-root-height': utils.formatPx(this.height),
257
+ '--search-root-radius': utils.formatPx(this.radius),
258
+ '--search-btn-text-color': this.btnTextColor,
259
+ '--search-placeholder-color': this.placeholderColor,
260
+ '--search-input-color': this.inputTextColor,
261
+ '--search-border-color': this.borderColor
262
+ };
263
+ },
264
+ cmpPlaceholder() {
265
+ return this.hotWords?.length ? '' : this.placeholder;
266
+ },
267
+ cmpHiddenLine() {
268
+ return this.hiddenLine || this.hiddenBtn;
269
+ },
270
+ cmpShowClear() {
271
+ return this.clearable && this.dataValue;
272
+ },
273
+ cmpShowSwitch() {
274
+ return this.hotWords?.length && !this.dataValue;
275
+ },
276
+ cmpBackground() {
277
+ return utils.bg2style(this.background);
278
+ },
279
+ cmpbtnBackground() {
280
+ return utils.bg2style(this.btnBackground);
281
+ },
282
+ cmpRootPadding() {
283
+ return this.hiddenBtn && this.hiddenInput ? {} : { padding: '0 8rpx 0 16rpx' };
284
+ }
285
+ },
286
+ watch: {
287
+ value: {
288
+ handler(val) {
289
+ this.dataValue = val;
290
+ },
291
+ immediate: true
292
+ },
293
+ hotWords() {
294
+ this.switchIndex = 0;
295
+ },
296
+ autoplay(val) {
297
+ this.internalAutoplay = val;
298
+ }
299
+ },
300
+ // #ifdef MP-WEIXIN
301
+ mounted() {
302
+ // 监听应用显示/隐藏(小程序前后台切换)
303
+ this.appShowHandler = () => {
304
+ this.internalAutoplay = this.autoplay;
305
+ };
306
+ this.appHideHandler = () => {
307
+ this.internalAutoplay = false;
308
+ };
309
+ uni.onAppShow(this.appShowHandler);
310
+ uni.onAppHide(this.appHideHandler);
311
+ },
312
+ beforeDestroy() {
313
+ // 移除监听
314
+ if (this.appShowHandler) {
315
+ uni.offAppShow(this.appShowHandler);
316
+ }
317
+ if (this.appHideHandler) {
318
+ uni.offAppHide(this.appHideHandler);
319
+ }
320
+ },
321
+ // #endif
322
+ methods: {
323
+ onInput() {
324
+ if (this.disabled) return;
325
+ this.$emit('input', this.dataValue);
326
+ },
327
+ onFocus() {
328
+ if (this.disabled) return;
329
+ this.$emit('focus', this.dataValue);
330
+
331
+ this.showSuggestionsBox = true;
332
+ },
333
+ onBlur() {
334
+ this.$emit('update:focus', false);
335
+ this.$emit('blur', this.dataValue);
336
+ },
337
+ onSearch() {
338
+ if (this.disabled) return;
339
+ let searchValue = this.dataValue;
340
+ if (!searchValue && this.hotWords.length) {
341
+ searchValue = this.hotWords[this.switchIndex];
342
+ }
343
+ this.$emit('search', searchValue);
344
+ },
345
+ onSwitchChange(v) {
346
+ this.switchIndex = v.detail.current;
347
+ },
348
+ onClick() {
349
+ if (this.disabled) return;
350
+ let searchValue = this.dataValue;
351
+ if (!searchValue && this.hotWords.length) {
352
+ searchValue = this.hotWords[this.switchIndex];
353
+ }
354
+ this.$emit('click', searchValue);
355
+ },
356
+ onClear() {
357
+ if (this.disabled) return;
358
+ this.dataValue = '';
359
+ this.$emit('input', this.dataValue);
360
+ this.$emit('clear');
361
+ },
362
+ handleSuggestionClick(item) {
363
+ this.dataValue = item.label;
364
+ this.$emit('input', item.label);
365
+ this.$emit('selectSuggestion', item);
366
+ this.showSuggestionsBox = false;
367
+
368
+ setTimeout(() => {
369
+ this.cursorNumber = item.label.length;
370
+ }, 50);
371
+ }
372
+ }
373
+ };
374
+ </script>
375
+
376
+ <style lang="scss" scoped>
377
+ .ste-search-root {
378
+ width: 100%;
379
+ height: var(--search-root-height);
380
+ background-color: #fff;
381
+ background-repeat: no-repeat;
382
+ background-size: 100% 100%;
383
+ border-radius: var(--search-root-radius);
384
+ border: 1rpx solid var(--search-border-color);
385
+ position: relative;
386
+
387
+ &,
388
+ view,
389
+ input {
390
+ box-sizing: border-box;
391
+ }
392
+
393
+ .content {
394
+ width: 100%;
395
+ height: 100%;
396
+ display: flex;
397
+ flex-direction: row;
398
+ align-items: center;
399
+ justify-content: center;
400
+ position: relative;
401
+
402
+ .icon-box {
403
+ width: 28rpx;
404
+ height: 28rpx;
405
+ flex-shrink: 0;
406
+ display: flex;
407
+ align-items: center;
408
+ justify-content: center;
409
+
410
+ .image {
411
+ width: 100%;
412
+ height: 100%;
413
+ }
414
+
415
+ & + .input-box {
416
+ margin-left: 16rpx;
417
+ }
418
+ }
419
+
420
+ .input-box {
421
+ position: relative;
422
+ flex: 1;
423
+ height: 100%;
424
+
425
+ ::v-deep .search-input {
426
+ height: 100%;
427
+
428
+ font-size: 28rpx;
429
+ color: var(--search-input-color);
430
+ // #ifdef MP-ALIPAY
431
+ background-color: rgba(0, 0, 0, 0);
432
+ // #endif
433
+
434
+ .content {
435
+ padding: 0;
436
+ height: 100%;
437
+ }
438
+
439
+ rch-input-placeholder {
440
+ color: var(--search-placeholder-color);
441
+ font-family: Alibaba PuHuiTi 2, Alibaba PuHuiTi 20;
442
+ font-weight: normal;
443
+ }
444
+ }
445
+
446
+ .placeholder-list {
447
+ width: 100%;
448
+ height: 100%;
449
+ pointer-events: none;
450
+ position: absolute;
451
+ top: 0;
452
+ left: 0;
453
+
454
+ .placeholder-item {
455
+ font-size: 28rpx;
456
+ color: var(--search-placeholder-color);
457
+ font-family: Alibaba PuHuiTi 2, Alibaba PuHuiTi 20;
458
+ font-weight: normal;
459
+ display: flex;
460
+ align-items: center;
461
+ }
462
+ }
463
+
464
+ .clear-icon {
465
+ width: 48rpx;
466
+ height: 100%;
467
+ display: flex;
468
+ align-items: center;
469
+ justify-content: flex-end;
470
+ position: absolute;
471
+ right: 8rpx;
472
+ top: 50%;
473
+ z-index: 2;
474
+ transform: translateY(-50%);
475
+ }
476
+ }
477
+
478
+ .secrch-line {
479
+ margin-left: 16rpx;
480
+ width: 2rpx;
481
+ flex-shrink: 0;
482
+ height: 24rpx;
483
+ background-color: var(--search-btn-text-color);
484
+
485
+ &.disabled {
486
+ background: #bbbbbb;
487
+ }
488
+ }
489
+
490
+ .search-button {
491
+ padding: 0 16rpx;
492
+ height: 40rpx;
493
+ font-size: 28rpx;
494
+ line-height: 40rpx;
495
+ flex-shrink: 0;
496
+ text-align: center;
497
+ font-family: Alibaba PuHuiTi 2, Alibaba PuHuiTi 20;
498
+ font-weight: normal;
499
+ color: var(--search-btn-text-color);
500
+ border-radius: 20rpx;
501
+ background-repeat: no-repeat;
502
+ background-size: 100% 100%;
503
+
504
+ &.disabled {
505
+ color: #bbbbbb;
506
+ }
507
+ }
508
+ }
509
+
510
+ .nav-box {
511
+ position: absolute;
512
+ width: 100%;
513
+ height: 100%;
514
+ top: 0;
515
+ left: 0;
516
+ z-index: 2;
517
+ }
518
+
519
+ .suggestions-box {
520
+ z-index: 999;
521
+ position: absolute;
522
+ left: 0;
523
+ top: 100%;
524
+ overflow-y: hidden;
525
+ opacity: 0;
526
+ max-height: 0;
527
+
528
+ margin: 20rpx 0;
529
+ width: 100%;
530
+
531
+ background-color: #ffffff;
532
+ box-shadow: 0 4rpx 24rpx 0 rgba(0, 0, 0, 0.1);
533
+ border-radius: 8rpx;
534
+ padding: 16rpx 0;
535
+
536
+ .scroll-box {
537
+ width: 100%;
538
+ max-height: calc(400rpx - 32rpx);
539
+ }
540
+
541
+ .item {
542
+ padding-left: 16rpx;
543
+ width: 100%;
544
+ height: 60rpx;
545
+ display: flex;
546
+ align-items: center;
547
+ font-size: 28rpx;
548
+ color: #bbbbbb;
549
+
550
+ &:focus {
551
+ background-color: red;
552
+ }
553
+ }
554
+
555
+ &.show {
556
+ opacity: 1;
557
+ max-height: 400rpx;
558
+ animation: suggestions-show 0.2s ease-out;
559
+ }
560
+
561
+ &.hide {
562
+ animation: suggestions-hide 0.2s ease-out;
563
+ }
564
+ }
565
+
566
+ @keyframes suggestions-show {
567
+ 0% {
568
+ opacity: 0;
569
+ max-height: 0;
570
+ }
571
+
572
+ 100% {
573
+ opacity: 1;
574
+ max-height: 400rpx;
575
+ }
576
+ }
577
+
578
+ @keyframes suggestions-hide {
579
+ 0% {
580
+ opacity: 1;
581
+ max-height: 400rpx;
582
+ }
583
+
584
+ 100% {
585
+ opacity: 0;
586
+ max-height: 0;
587
+ }
588
+ }
589
+ }
590
+ </style>