@kaiyinchem/ky-uniui 1.0.3

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.
@@ -0,0 +1,642 @@
1
+ <!--底部弹出组件,2020-10-16 zzc-->
2
+ <template>
3
+ <view v-if="showPopup" class="uni-popup" :class="[popupstyle, noFixed ? 'noFixed' : '']">
4
+ <uni-transition
5
+ v-if="maskShow"
6
+ class="uni-mask--hook"
7
+ :mode-class="['fade']"
8
+ :styles="maskClass"
9
+ :duration="duration"
10
+ :show="showTrans"
11
+ @click="onTap"
12
+ />
13
+ <uni-transition
14
+ :class="{ hasTabbar }"
15
+ :mode-class="ani"
16
+ :styles="transClass"
17
+ :duration="duration"
18
+ :show="showTrans"
19
+ @click="onTap"
20
+ >
21
+ <view class="uni-popup__wrapper-box" @click.stop="clear">
22
+ <!--start-->
23
+ <view
24
+ :class="position"
25
+ :style="{width: position !== 'center' ? false : width + 'rpx' }"
26
+ class="lmy-pop white-bg radius">
27
+
28
+ <!--通用头部-->
29
+ <view v-if="title" :class="{ noClose, 'white-bg': type === 'pop', txtLeft: titleAlign === 'left' }" class="pop-top">
30
+ <text v-if="showTopBtn" class="pop-close" @click="close">取消</text>
31
+ <text class="pop-title">{{ title }}</text>
32
+ <text v-if="!noClose && !showTopBtn && position !== 'top'" class="pop-close iconfont" @click="close">&#xe634;</text>
33
+ <button v-if="!noClose && showTopBtn" :disabled="disabled" :class="{ disabled }" class="pop-top-btn" @click="confirm">{{ confirmText }}</button>
34
+ </view>
35
+
36
+ <!--############## 一般提示框部分 ##############-->
37
+ <view v-if="type === 'dialog'" :class="{noPadding: noPadding || (!hasSlots && !content)}" class="pop-content">
38
+ <text v-if="!hasSlots && content" :class="{txtCenter: textAlign === 'center'}" class="msg-content">{{ content }}</text>
39
+ <view v-if="hasSlots" class="msg-content pop-scroll">
40
+ <slot></slot>
41
+ </view>
42
+ </view>
43
+ <!--##############end 一般提示框部分 ##############-->
44
+
45
+
46
+ <!--############## 底部弹出层 ##############-->
47
+ <view v-if="type === 'pop'" class="pop-content" :style="{ padding: 0 }">
48
+ <view v-if="$slots.header" class="pop-header">
49
+ <slot name="header"></slot>
50
+ </view>
51
+ <view :class="{ noPadding }" class="pop-scroll">
52
+ <slot></slot>
53
+ </view>
54
+ <view v-if="$slots.footer" :class="{'white-bg': !noFooterBg}" class="pop-footer">
55
+ <slot name="footer"></slot>
56
+ <view :style="{height: $safeBottom - 15 + 'px'}"></view>
57
+ </view>
58
+ <!--iPhoneX等机型手势条底部高度-->
59
+ <view v-if="!$slots.footer" :style="{height: $safeBottom - 15 + 'px'}"></view>
60
+ </view>
61
+ <!--############## end 底部弹出层 ##############-->
62
+
63
+
64
+ <!--############## 输入框提示框 ##############-->
65
+ <view v-if="type === 'input'" class="pop-content">
66
+ <view class="pop-input">
67
+ <!--由于不支持动态设置type,只能这样了-->
68
+ <input
69
+ v-if="inputType === 'text'"
70
+ :placeholder="placeholder"
71
+ :focus="true"
72
+ :value="value"
73
+ class="input-item"
74
+ type="text"
75
+ cursor-spacing="20"
76
+ @input="getInputVal"/>
77
+ <input
78
+ v-if="inputType === 'number'"
79
+ :placeholder="placeholder"
80
+ :focus="true"
81
+ :value="value"
82
+ class="input-item"
83
+ type="number"
84
+ cursor-spacing="20"
85
+ @input="getInputVal"
86
+ />
87
+ <input
88
+ v-if="inputType === 'digit'"
89
+ :placeholder="placeholder"
90
+ :focus="true"
91
+ :value="value"
92
+ class="input-item"
93
+ type="digit"
94
+ cursor-spacing="20"
95
+ @input="getInputVal"
96
+ />
97
+ </view>
98
+ <slot></slot>
99
+ </view>
100
+ <!--############## end 输入框提示框 ##############-->
101
+
102
+ <view v-if="(!noButton && type === 'dialog') || type === 'input'" class="pop-btngroup">
103
+ <ky-btn
104
+ v-if="!noCancel"
105
+ :disabled="disabled"
106
+ class="pop-btns cancel"
107
+ radius="0"
108
+ color="#999999!important"
109
+ type="default"
110
+ @click="cancel"
111
+ >
112
+ {{ cancelText }}
113
+ </ky-btn>
114
+ <ky-btn
115
+ :disabled="disabled"
116
+ class="pop-btns confirm"
117
+ color="#00b2a9!important"
118
+ radius="0"
119
+ type="default"
120
+ @click="confirm"
121
+ >
122
+ {{ confirmText }}
123
+ </ky-btn>
124
+ </view>
125
+ </view>
126
+ <!--end-->
127
+ </view>
128
+ </uni-transition>
129
+ </view>
130
+ </template>
131
+
132
+ <script>
133
+ export default {
134
+ emits: ['change', 'update:value', 'confirm', 'cancel', 'input'],
135
+ props: {
136
+ // 弹窗方式, top, bottom, center, relative
137
+ position: {
138
+ type: String,
139
+ default: 'center',
140
+ },
141
+ // 弹窗类型 pop: 非居中弹出, dialog: 居中弹窗, input: 输入框
142
+ type: {
143
+ type: String,
144
+ default: 'pop',
145
+ },
146
+ title: {
147
+ type: String,
148
+ default: '',
149
+ },
150
+ noClose: {
151
+ type: Boolean,
152
+ default: false,
153
+ },
154
+ content: {
155
+ type: String,
156
+ default: '',
157
+ },
158
+ noCancel: {
159
+ type: Boolean,
160
+ default: false,
161
+ },
162
+ cancelText: {
163
+ type: String,
164
+ default: '取消',
165
+ },
166
+ confirmText: {
167
+ type: String,
168
+ default: '确定',
169
+ },
170
+ // 输入框类型
171
+ inputType: {
172
+ type: String,
173
+ default: 'text',
174
+ },
175
+ value: {
176
+ type: [String, Number, Boolean],
177
+ default: ''
178
+ },
179
+ placeholder: {
180
+ type: String,
181
+ default: '请输入'
182
+ },
183
+ width: {
184
+ type: String,
185
+ default: '630'
186
+ },
187
+ noButton: {
188
+ type: Boolean,
189
+ default: false,
190
+ },
191
+ // 右上角确定按钮
192
+ showTopBtn: {
193
+ type: Boolean,
194
+ default: false
195
+ },
196
+ // 按钮禁用
197
+ disabled: {
198
+ type: Boolean,
199
+ default: false
200
+ },
201
+ maskClick: {
202
+ type: Boolean,
203
+ default: true
204
+ },
205
+ noPadding: {
206
+ type: Boolean,
207
+ default: false
208
+ },
209
+ noFooterBg: {
210
+ type: Boolean,
211
+ default: false
212
+ },
213
+ // 开启动画
214
+ animation: {
215
+ type: Boolean,
216
+ default: true
217
+ },
218
+
219
+ // 文本对齐方式
220
+ textAlign: {
221
+ type: String,
222
+ default: 'left'
223
+ },
224
+ // 是否自动关窗口
225
+ autoClose: {
226
+ type: Boolean,
227
+ default: true
228
+ },
229
+ // 是否有tabbar
230
+ hasTabbar: {
231
+ type: Boolean,
232
+ default: false
233
+ },
234
+ // 是否固定定位
235
+ noFixed: {
236
+ type: Boolean,
237
+ default: false
238
+ },
239
+ titleAlign: {
240
+ type: String,
241
+ default: 'center'
242
+ }
243
+ },
244
+ data() {
245
+ return {
246
+ inputVal: '',
247
+ duration: 300,
248
+ ani: [],
249
+ showPopup: false,
250
+ showTrans: false,
251
+ maskClass: {
252
+ 'position': 'fixed',
253
+ 'bottom': 0,
254
+ 'top': 0,
255
+ 'left': 0,
256
+ 'right': 0,
257
+ 'backgroundColor': 'rgba(0, 0, 0, 0.5)'
258
+ },
259
+ transClass: {
260
+ 'position': 'fixed',
261
+ 'left': 0,
262
+ 'right': 0,
263
+ },
264
+ maskShow: true,
265
+ popupstyle: 'top',
266
+ config: {
267
+ top:'top',
268
+ bottom:'bottom',
269
+ center:'center',
270
+ message:'top',
271
+ dialog:'center',
272
+ share:'bottom',
273
+ }
274
+ }
275
+ },
276
+ computed: {
277
+ hasSlots() {
278
+ return Object.keys(this.$slots).length
279
+ },
280
+ $safeBottom() {
281
+ return uni.getSystemInfoSync().safeAreaInsets.bottom
282
+ }
283
+ },
284
+ watch: {
285
+ value(v) {
286
+ this.inputVal = v;
287
+ if (this.type !== 'input') {
288
+ if (!v) {
289
+ this.close()
290
+ } else {
291
+ this.open()
292
+ }
293
+ }
294
+ },
295
+ position: {
296
+ handler: function(newVal) {
297
+ this[this.config[newVal]]()
298
+ },
299
+ immediate: true
300
+ },
301
+ },
302
+ mounted() {
303
+ this.inputVal = this.value;
304
+ },
305
+ methods: {
306
+ clear(e) {
307
+ e.stopPropagation()
308
+ },
309
+ open() {
310
+ this.showPopup = true
311
+ this.$nextTick(() => {
312
+ new Promise(resolve => {
313
+ clearTimeout(this.timer)
314
+ this.timer = setTimeout(() => {
315
+ this.showTrans = true
316
+ // fixed by mehaotian 兼容 app 端
317
+ this.$nextTick(() => {
318
+ resolve();
319
+ })
320
+ }, 50);
321
+ }).then(res => {
322
+ // 自定义打开事件
323
+ clearTimeout(this.msgtimer)
324
+ this.msgtimer = setTimeout(() => {
325
+ this.customOpen && this.customOpen()
326
+ }, 100)
327
+ this.$emit('change', {
328
+ show: true,
329
+ position: this.position
330
+ })
331
+ })
332
+ })
333
+ if (this.type !== 'input') {
334
+ this.$emit('input', true)
335
+ }
336
+ },
337
+ close() {
338
+ this.showTrans = false
339
+ this.$nextTick(() => {
340
+ this.$emit('change', {
341
+ show: false,
342
+ position: this.position
343
+ })
344
+ clearTimeout(this.timer)
345
+ // 自定义关闭事件
346
+ this.customOpen && this.customClose()
347
+ this.timer = setTimeout(() => {
348
+ this.showPopup = false
349
+ if (this.type !== 'input') {
350
+ this.$emit('input', false)
351
+ }
352
+ }, 300)
353
+ })
354
+ },
355
+ cancel() {
356
+ this.$emit('cancel', true)
357
+ this.close()
358
+ },
359
+ confirm() {
360
+ if (this.type === 'input' && this.inputVal === '') {
361
+ this.$toast('内容不能为空')
362
+ return
363
+ }
364
+ this.$emit('confirm', this.type === 'input' ? this.inputVal : true)
365
+ if (this.autoClose) {
366
+ this.close()
367
+ }
368
+ },
369
+ getInputVal({ detail }) {
370
+ this.$emit('input', detail.value)
371
+ },
372
+ onPopChange(e) {
373
+ if (this.type !== 'input') {
374
+ setTimeout(() => {
375
+ this.$emit('update:value', e.show)
376
+ this.$emit('input', e.show)
377
+ })
378
+ }
379
+ },
380
+
381
+ onTap() {
382
+ if (!this.maskClick || this.noClose || this.noCancel) return
383
+ this.close()
384
+ },
385
+ /**
386
+ * 顶部弹出样式处理
387
+ */
388
+ top() {
389
+ this.popupstyle = 'top'
390
+ this.ani = ['slide-top']
391
+ this.transClass = {
392
+ 'position': 'fixed',
393
+ 'left': 0,
394
+ 'right': 0,
395
+ }
396
+ },
397
+ /**
398
+ * 底部弹出样式处理
399
+ */
400
+ bottom() {
401
+ this.popupstyle = 'bottom'
402
+ this.ani = ['slide-bottom']
403
+ this.transClass = {
404
+ 'position': 'fixed',
405
+ 'left': 0,
406
+ 'right': 0,
407
+ 'bottom': 0
408
+ }
409
+ },
410
+ /**
411
+ * 中间弹出样式处理
412
+ */
413
+ center() {
414
+ this.popupstyle = 'center'
415
+ this.ani = ['zoom-out', 'fade']
416
+ this.transClass = {
417
+ 'position': 'fixed',
418
+ /* #ifndef APP-NVUE */
419
+ 'display': 'flex',
420
+ 'flexDirection': 'column',
421
+ /* #endif */
422
+ 'bottom': 0,
423
+ 'left': 0,
424
+ 'right': 0,
425
+ 'top': 0,
426
+ 'justifyContent': 'center',
427
+ 'alignItems': 'center'
428
+ }
429
+ }
430
+ }
431
+ }
432
+ </script>
433
+
434
+ <style scoped lang="scss">
435
+ .hasTabbar {
436
+ padding-bottom: calc(env(safe-area-inset-bottom) / 2)!important;
437
+ }
438
+ .lmy-pop {
439
+ width: 100%;
440
+ &.center {
441
+ width: 630rpx;
442
+ border-radius: 6rpx;
443
+ overflow: hidden;
444
+ }
445
+ &.bottom {
446
+ border-radius: 0!important;
447
+ .pop-content {
448
+ padding: 0;
449
+ overflow: hidden;
450
+ }
451
+ }
452
+ &.top {
453
+ border-radius: 0!important;
454
+ }
455
+ .pop-top {
456
+ padding: 24rpx 36rpx;
457
+ display: flex;
458
+ align-items: center;
459
+ justify-content: space-between;
460
+ border-bottom: 1px solid var(--border-1);
461
+ .pop-top-btn {
462
+ padding: 0;
463
+ margin: 0;
464
+ border: 0;
465
+ color: var(--color-primary);
466
+ height: auto;
467
+ font-size: 28rpx;
468
+ line-height: initial;
469
+ background: none;
470
+ &:after {
471
+ display: none;
472
+ }
473
+ &.disabled {
474
+ color: var(--color-gray);
475
+ }
476
+ }
477
+ &.white-bg {
478
+ background: var(--bg-white);
479
+ }
480
+ &.noClose {
481
+ justify-content: center;
482
+ }
483
+ &.txtLeft {
484
+ justify-content: space-between;
485
+ }
486
+ .pop-title {
487
+ font-size: 32rpx;
488
+ }
489
+ .pop-close {
490
+ color: var(--color-gray);
491
+ }
492
+ }
493
+ .pop-content {
494
+ padding: 36rpx;
495
+ background: var(--bg-white);
496
+ &.noPadding {
497
+ padding: 0;
498
+ }
499
+ .msg-content {
500
+ display: flex;
501
+ align-items: center;
502
+ min-height: 120rpx;
503
+ padding: 0;
504
+ font-size: 30rpx;
505
+ &.txtCenter {
506
+ text-align: center;
507
+ justify-content: center;
508
+ }
509
+ }
510
+ }
511
+ .pop-btngroup {
512
+ display: flex;
513
+ align-items: center;
514
+ position: relative;
515
+ border-top: 1px solid var(--border-1);;
516
+ .pop-btns {
517
+ flex: 1;
518
+ position: relative;
519
+ &.confirm {
520
+ &:after {
521
+ content: '';
522
+ display: block;
523
+ position: absolute;
524
+ height: 100%;
525
+ width: 1px;
526
+ background: var(--border-1);
527
+ left: 0;
528
+ top: 0;
529
+ bottom: 0;
530
+ margin: auto;
531
+ }
532
+ }
533
+ }
534
+ }
535
+ .pop-input {
536
+ .input-item {
537
+ display: block;
538
+ height: 90rpx;
539
+ background: var(--border-1);
540
+ border-radius: 12rpx;
541
+ text-indent: 24rpx;
542
+ }
543
+ }
544
+ .pop-scroll {
545
+ max-height: 70vh;
546
+ overflow-y: auto;
547
+ padding: 24rpx;
548
+ position: relative;
549
+ &.noPadding {
550
+ padding: 0;
551
+ }
552
+ }
553
+ .pop-footer {
554
+ padding: 24rpx;
555
+ background: var(--bg-gray);
556
+ }
557
+ }
558
+ :deep(.pop-btngroup) .btn-main { font-weight: bold; }
559
+ .uni-popup {
560
+ position: fixed;
561
+ /* #ifndef APP-NVUE */
562
+ z-index: 99;
563
+ /* #endif */
564
+ &.noFixed {
565
+ position: relative;
566
+ }
567
+ }
568
+
569
+ .uni-popup__mask {
570
+ position: absolute;
571
+ top: 0;
572
+ bottom: 0;
573
+ left: 0;
574
+ right: 0;
575
+ background-color: $uni-bg-color-mask;
576
+ opacity: 0;
577
+ }
578
+
579
+ .mask-ani {
580
+ transition-property: opacity;
581
+ transition-duration: 0.2s;
582
+ }
583
+
584
+ .uni-top-mask {
585
+ opacity: 1;
586
+ }
587
+
588
+ .uni-bottom-mask {
589
+ opacity: 1;
590
+ }
591
+
592
+ .uni-center-mask {
593
+ opacity: 1;
594
+ }
595
+
596
+ .uni-popup__wrapper {
597
+ /* #ifndef APP-NVUE */
598
+ display: block;
599
+ /* #endif */
600
+ position: absolute;
601
+ }
602
+
603
+ .top {
604
+ /* #ifdef H5 */
605
+ top: var(--window-top);
606
+ /* #endif */
607
+ /* #ifndef H5 */
608
+ top: 0;
609
+ /* #endif */
610
+ }
611
+
612
+ .bottom {
613
+ bottom: 0;
614
+ }
615
+
616
+ .uni-popup__wrapper-box {
617
+ /* #ifndef APP-NVUE */
618
+ display: block;
619
+ /* #endif */
620
+ position: relative;
621
+ }
622
+
623
+ .content-ani {
624
+ // transition: transform 0.3s;
625
+ transition-property: transform, opacity;
626
+ transition-duration: 0.2s;
627
+ }
628
+
629
+
630
+ .uni-top-content {
631
+ transform: translateY(0);
632
+ }
633
+
634
+ .uni-bottom-content {
635
+ transform: translateY(0);
636
+ }
637
+
638
+ .uni-center-content {
639
+ transform: scale(1);
640
+ opacity: 1;
641
+ }
642
+ </style>