uview-plus 3.5.16 → 3.5.20
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/changelog.md +14 -0
- package/components/u-checkbox/u-checkbox.vue +3 -2
- package/components/u-coupon/u-coupon.vue +406 -0
- package/components/u-picker-data/u-picker-data.vue +10 -4
- package/components/u-popup/popup.js +5 -2
- package/components/u-popup/props.js +15 -0
- package/components/u-popup/u-popup.vue +119 -4
- package/package.json +1 -1
package/changelog.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 3.5.20(2025-08-27)
|
|
2
|
+
improvement: 提升checkbox条件编译兼容性
|
|
3
|
+
|
|
4
|
+
## 3.5.19(2025-08-27)
|
|
5
|
+
feat: popup新增iOS风格手势控制上下高度及下滑关闭
|
|
6
|
+
|
|
7
|
+
## 3.5.18(2025-08-26)
|
|
8
|
+
feat: 新增coupon优惠券组件
|
|
9
|
+
|
|
10
|
+
## 3.5.17(2025-08-26)
|
|
11
|
+
fix: 分支合并冲突修复
|
|
12
|
+
|
|
13
|
+
feat: picker-data组件新增cancel/close/confirm事件支持
|
|
14
|
+
|
|
1
15
|
## 3.5.16(2025-08-26)
|
|
2
16
|
feat: tabbar新增支持中间凸起按钮
|
|
3
17
|
|
|
@@ -199,11 +199,12 @@
|
|
|
199
199
|
if (!this.parent) {
|
|
200
200
|
error('up-checkbox必须搭配up-checkbox-group组件使用')
|
|
201
201
|
}
|
|
202
|
+
let value = '';
|
|
202
203
|
// #ifdef VUE2
|
|
203
|
-
|
|
204
|
+
value = this.parentData.value
|
|
204
205
|
// #endif
|
|
205
206
|
// #ifdef VUE3
|
|
206
|
-
|
|
207
|
+
value = this.parentData.modelValue
|
|
207
208
|
// #endif
|
|
208
209
|
// 设置初始化时,是否默认选中的状态,父组件u-checkbox-group的value可能是array,所以额外判断
|
|
209
210
|
if (this.checked) {
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="up-coupon" :class="[`up-coupon--${shape}`, `up-coupon--${type}`, `up-coupon--${size}`, {'up-coupon--disabled': disabled}]"
|
|
3
|
+
:style="[couponStyle]" @click="handleClick">
|
|
4
|
+
<view class="up-coupon__content">
|
|
5
|
+
<!-- 左侧金额区域 -->
|
|
6
|
+
<view class="up-coupon__amount">
|
|
7
|
+
<slot name="unit" :unit="unit" :unitPosition="unitPosition" v-if="unitPosition === 'left'">
|
|
8
|
+
<text class="up-coupon__amount-unit" v-if="unitPosition === 'left'">{{ unit }}</text>
|
|
9
|
+
</slot>
|
|
10
|
+
<slot name="amount" :amount="amount">
|
|
11
|
+
<text class="up-coupon__amount-value">{{ amount }}</text>
|
|
12
|
+
</slot>
|
|
13
|
+
<slot name="unit" :unit="unit" :unitPosition="unitPosition" v-if="unitPosition === 'right'">
|
|
14
|
+
<text class="up-coupon__amount-unit" v-if="unitPosition === 'right'">{{ unit }}</text>
|
|
15
|
+
</slot>
|
|
16
|
+
<slot name="limit" :limit="limit">
|
|
17
|
+
<text class="up-coupon__amount-limit" v-if="limit">{{ limit }}</text>
|
|
18
|
+
</slot>
|
|
19
|
+
</view>
|
|
20
|
+
|
|
21
|
+
<!-- 中间描述区域 -->
|
|
22
|
+
<view class="up-coupon__info">
|
|
23
|
+
<slot name="title" :title="title">
|
|
24
|
+
<text class="up-coupon__info-title">{{ title }}</text>
|
|
25
|
+
</slot>
|
|
26
|
+
<slot name="desc" :desc="desc">
|
|
27
|
+
<text class="up-coupon__info-desc" v-if="desc">{{ desc }}</text>
|
|
28
|
+
</slot>
|
|
29
|
+
<slot name="time" :time="time">
|
|
30
|
+
<text class="up-coupon__info-time" v-if="time">{{ time }}</text>
|
|
31
|
+
</slot>
|
|
32
|
+
</view>
|
|
33
|
+
|
|
34
|
+
<!-- 右侧操作区域 -->
|
|
35
|
+
<view class="up-coupon__action u-padding-right-20">
|
|
36
|
+
<slot name="action" :actionText="actionText" :circle="circle">
|
|
37
|
+
<up-tag type="error" :bgColor="type ? 'transparent' : '#eb433d'"
|
|
38
|
+
:borderColor="type ? '#eee' : '#eb433d'" borderRadius="6px"
|
|
39
|
+
size="medium" class="up-coupon__action-text"
|
|
40
|
+
:shape="circle ? 'circle': 'circle'">{{ actionText }}</up-tag>
|
|
41
|
+
</slot>
|
|
42
|
+
</view>
|
|
43
|
+
</view>
|
|
44
|
+
|
|
45
|
+
<!-- 红包绳子效果 -->
|
|
46
|
+
<view v-if="shape === 'envelope'" class="up-coupon__rope"></view>
|
|
47
|
+
|
|
48
|
+
<!-- 默认插槽,可用于添加额外内容 -->
|
|
49
|
+
<slot></slot>
|
|
50
|
+
</view>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<script>
|
|
54
|
+
export default {
|
|
55
|
+
name: 'up-coupon',
|
|
56
|
+
props: {
|
|
57
|
+
// 金额
|
|
58
|
+
amount: {
|
|
59
|
+
type: [String, Number],
|
|
60
|
+
default: ''
|
|
61
|
+
},
|
|
62
|
+
// 金额单位
|
|
63
|
+
unit: {
|
|
64
|
+
type: String,
|
|
65
|
+
default: '¥'
|
|
66
|
+
},
|
|
67
|
+
// 单位位置
|
|
68
|
+
unitPosition: {
|
|
69
|
+
type: String,
|
|
70
|
+
default: 'left'
|
|
71
|
+
},
|
|
72
|
+
// 使用限制
|
|
73
|
+
limit: {
|
|
74
|
+
type: String,
|
|
75
|
+
default: ''
|
|
76
|
+
},
|
|
77
|
+
// 标题
|
|
78
|
+
title: {
|
|
79
|
+
type: String,
|
|
80
|
+
default: '优惠券'
|
|
81
|
+
},
|
|
82
|
+
// 描述
|
|
83
|
+
desc: {
|
|
84
|
+
type: String,
|
|
85
|
+
default: ''
|
|
86
|
+
},
|
|
87
|
+
// 有效期
|
|
88
|
+
time: {
|
|
89
|
+
type: String,
|
|
90
|
+
default: ''
|
|
91
|
+
},
|
|
92
|
+
// 操作按钮文字
|
|
93
|
+
actionText: {
|
|
94
|
+
type: String,
|
|
95
|
+
default: '使用'
|
|
96
|
+
},
|
|
97
|
+
// 形状:coupon-优惠券, envelope-红包, card-卡片
|
|
98
|
+
shape: {
|
|
99
|
+
type: String,
|
|
100
|
+
default: 'coupon'
|
|
101
|
+
},
|
|
102
|
+
// 尺寸:small, medium, large
|
|
103
|
+
size: {
|
|
104
|
+
type: String,
|
|
105
|
+
default: 'medium'
|
|
106
|
+
},
|
|
107
|
+
// 是否圆形按钮
|
|
108
|
+
circle: {
|
|
109
|
+
type: Boolean,
|
|
110
|
+
default: false
|
|
111
|
+
},
|
|
112
|
+
// 是否禁用
|
|
113
|
+
disabled: {
|
|
114
|
+
type: Boolean,
|
|
115
|
+
default: false
|
|
116
|
+
},
|
|
117
|
+
// 背景颜色
|
|
118
|
+
bgColor: {
|
|
119
|
+
type: String,
|
|
120
|
+
default: ''
|
|
121
|
+
},
|
|
122
|
+
// 文字颜色
|
|
123
|
+
color: {
|
|
124
|
+
type: String,
|
|
125
|
+
default: ''
|
|
126
|
+
},
|
|
127
|
+
// 内置背景类型
|
|
128
|
+
type: {
|
|
129
|
+
type: String,
|
|
130
|
+
default: ''
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
computed: {
|
|
134
|
+
couponStyle() {
|
|
135
|
+
const style = {};
|
|
136
|
+
if (this.bgColor) style.background = this.bgColor;
|
|
137
|
+
if (this.color) style.color = this.color;
|
|
138
|
+
return style;
|
|
139
|
+
},
|
|
140
|
+
dotCount() {
|
|
141
|
+
// 根据尺寸计算锯齿数量
|
|
142
|
+
const map = {
|
|
143
|
+
small: 8,
|
|
144
|
+
medium: 10,
|
|
145
|
+
large: 12
|
|
146
|
+
};
|
|
147
|
+
return map[this.size] || 10;
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
methods: {
|
|
151
|
+
handleClick() {
|
|
152
|
+
if (this.disabled) return;
|
|
153
|
+
this.$emit('click');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
</script>
|
|
158
|
+
|
|
159
|
+
<style lang="scss" scoped>
|
|
160
|
+
.up-coupon {
|
|
161
|
+
position: relative;
|
|
162
|
+
overflow: hidden;
|
|
163
|
+
border-radius: 8rpx;
|
|
164
|
+
background: #ffebf0;
|
|
165
|
+
color: $u-main-color;
|
|
166
|
+
|
|
167
|
+
&--coupon {
|
|
168
|
+
border-radius: 16rpx;
|
|
169
|
+
overflow: hidden;
|
|
170
|
+
|
|
171
|
+
&::before {
|
|
172
|
+
content: '';
|
|
173
|
+
position: absolute;
|
|
174
|
+
left: -24rpx;
|
|
175
|
+
top: 50%;
|
|
176
|
+
transform: translateY(-50%);
|
|
177
|
+
width: 48rpx;
|
|
178
|
+
height: 48rpx;
|
|
179
|
+
background-color: #fff;
|
|
180
|
+
border-radius: 50%;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
&::after {
|
|
184
|
+
content: '';
|
|
185
|
+
position: absolute;
|
|
186
|
+
right: -24rpx;
|
|
187
|
+
top: 50%;
|
|
188
|
+
transform: translateY(-50%);
|
|
189
|
+
width: 48rpx;
|
|
190
|
+
height: 48rpx;
|
|
191
|
+
background-color: #fff;
|
|
192
|
+
border-radius: 50%;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
&--envelope {
|
|
197
|
+
border-radius: 16rpx;
|
|
198
|
+
|
|
199
|
+
&::before {
|
|
200
|
+
content: '';
|
|
201
|
+
position: absolute;
|
|
202
|
+
left: 0;
|
|
203
|
+
top: 0;
|
|
204
|
+
right: 0;
|
|
205
|
+
height: 20rpx;
|
|
206
|
+
background: repeating-linear-gradient(-45deg, #ffd000, #ffd000 10rpx, #ffa000 10rpx, #ffa000 20rpx);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
&--card {
|
|
211
|
+
border-radius: 16rpx;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
width: 100%;
|
|
215
|
+
|
|
216
|
+
&--small {
|
|
217
|
+
// width: 520rpx;
|
|
218
|
+
height: 160rpx;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
&--medium {
|
|
222
|
+
// width: 600rpx;
|
|
223
|
+
height: 180rpx;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
&--large {
|
|
227
|
+
// width: 700rpx;
|
|
228
|
+
height: 220rpx;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
&--disabled {
|
|
232
|
+
opacity: 0.5;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
&__content {
|
|
236
|
+
display: flex;
|
|
237
|
+
flex-direction: row;
|
|
238
|
+
align-items: center;
|
|
239
|
+
justify-content: space-between;
|
|
240
|
+
height: 100%;
|
|
241
|
+
padding: 0 30rpx;
|
|
242
|
+
position: relative;
|
|
243
|
+
z-index: 2;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
&__amount {
|
|
247
|
+
display: flex;
|
|
248
|
+
flex-direction: column;
|
|
249
|
+
align-items: flex-start;
|
|
250
|
+
padding-left: 10rpx;
|
|
251
|
+
padding-right: 30rpx;
|
|
252
|
+
border-right: 1px dashed #ccc;
|
|
253
|
+
|
|
254
|
+
&-unit {
|
|
255
|
+
font-size: 24rpx;
|
|
256
|
+
font-weight: normal;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
&-value {
|
|
260
|
+
font-size: 56rpx;
|
|
261
|
+
font-weight: bold;
|
|
262
|
+
color: red;
|
|
263
|
+
line-height: 1;
|
|
264
|
+
margin: 10rpx 0;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
&-limit {
|
|
268
|
+
font-size: 24rpx;
|
|
269
|
+
opacity: 0.9;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
&__info {
|
|
274
|
+
flex: 1;
|
|
275
|
+
display: flex;
|
|
276
|
+
flex-direction: column;
|
|
277
|
+
align-items: flex-start;
|
|
278
|
+
padding-left: 30rpx;
|
|
279
|
+
|
|
280
|
+
&-title {
|
|
281
|
+
font-size: 32rpx;
|
|
282
|
+
font-weight: bold;
|
|
283
|
+
margin-bottom: 10rpx;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
&-desc {
|
|
287
|
+
font-size: 24rpx;
|
|
288
|
+
opacity: 0.9;
|
|
289
|
+
margin-bottom: 10rpx;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
&-time {
|
|
293
|
+
font-size: 20rpx;
|
|
294
|
+
opacity: 0.8;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
&__action {
|
|
299
|
+
display: flex;
|
|
300
|
+
flex-direction: row;
|
|
301
|
+
align-items: center;
|
|
302
|
+
justify-content: center;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
&__dots {
|
|
306
|
+
position: absolute;
|
|
307
|
+
left: 0;
|
|
308
|
+
top: 0;
|
|
309
|
+
bottom: 0;
|
|
310
|
+
width: 100%;
|
|
311
|
+
display: flex;
|
|
312
|
+
flex-direction: column;
|
|
313
|
+
justify-content: space-between;
|
|
314
|
+
padding: 30rpx 0;
|
|
315
|
+
z-index: 1;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
&__dot {
|
|
319
|
+
width: 32rpx;
|
|
320
|
+
height: 32rpx;
|
|
321
|
+
background-color: #fff;
|
|
322
|
+
border-radius: 50%;
|
|
323
|
+
margin: 0 -16rpx;
|
|
324
|
+
z-index: 3;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
&__rope {
|
|
328
|
+
position: absolute;
|
|
329
|
+
top: -40rpx;
|
|
330
|
+
left: 50%;
|
|
331
|
+
transform: translateX(-50%);
|
|
332
|
+
width: 80rpx;
|
|
333
|
+
height: 80rpx;
|
|
334
|
+
background: linear-gradient(to right, #ffd000, #ffa000);
|
|
335
|
+
border-radius: 40rpx 40rpx 0 0;
|
|
336
|
+
z-index: 1;
|
|
337
|
+
|
|
338
|
+
&::before {
|
|
339
|
+
content: '';
|
|
340
|
+
position: absolute;
|
|
341
|
+
top: 0;
|
|
342
|
+
left: -20rpx;
|
|
343
|
+
width: 20rpx;
|
|
344
|
+
height: 40rpx;
|
|
345
|
+
background: linear-gradient(to bottom, #ffd000, #ffa000);
|
|
346
|
+
border-radius: 10rpx 0 0 10rpx;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
&::after {
|
|
350
|
+
content: '';
|
|
351
|
+
position: absolute;
|
|
352
|
+
top: 0;
|
|
353
|
+
right: -20rpx;
|
|
354
|
+
width: 20rpx;
|
|
355
|
+
height: 40rpx;
|
|
356
|
+
background: linear-gradient(to bottom, #ffd000, #ffa000);
|
|
357
|
+
border-radius: 0 10rpx 10rpx 0;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// 不同主题样式
|
|
362
|
+
&--primary {
|
|
363
|
+
background: linear-gradient(90deg, #43afff, #3b8cff);
|
|
364
|
+
color: #fff;
|
|
365
|
+
.up-coupon__amount {
|
|
366
|
+
border-right: 1px dashed #eee;
|
|
367
|
+
}
|
|
368
|
+
.up-coupon__amount-value {
|
|
369
|
+
color: #fff;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
&--success {
|
|
374
|
+
background: linear-gradient(90deg, #67dda9, #19be6b);
|
|
375
|
+
color: #fff !important;
|
|
376
|
+
.up-coupon__amount {
|
|
377
|
+
border-right: 1px dashed #eee;
|
|
378
|
+
}
|
|
379
|
+
.up-coupon__amount-value {
|
|
380
|
+
color: #fff;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
&--warning {
|
|
385
|
+
background: linear-gradient(90deg, #ff9739, #ff6a39);
|
|
386
|
+
color: #fff;
|
|
387
|
+
.up-coupon__amount {
|
|
388
|
+
border-right: 1px dashed #eee;
|
|
389
|
+
}
|
|
390
|
+
.up-coupon__amount-value {
|
|
391
|
+
color: #fff;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
&--error {
|
|
396
|
+
background: linear-gradient(90deg, #ff7070, #ff4747);
|
|
397
|
+
color: #fff;
|
|
398
|
+
.up-coupon__amount {
|
|
399
|
+
border-right: 1px dashed #eee;
|
|
400
|
+
}
|
|
401
|
+
.up-coupon__amount-value {
|
|
402
|
+
color: #fff;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
</style>
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
:columns="optionsInner"
|
|
19
19
|
:keyName="labelKey"
|
|
20
20
|
:defaultIndex="defaultIndex"
|
|
21
|
-
@confirm="
|
|
22
|
-
@cancel="cancel"
|
|
21
|
+
@confirm="confirm"
|
|
22
|
+
@cancel="cancel"
|
|
23
|
+
@close="close">
|
|
23
24
|
</up-picker>
|
|
24
25
|
</view>
|
|
25
26
|
</template>
|
|
@@ -89,15 +90,19 @@ export default {
|
|
|
89
90
|
return [this.options];
|
|
90
91
|
}
|
|
91
92
|
},
|
|
92
|
-
emits: ['update:modelValue'],
|
|
93
|
+
emits: ['update:modelValue', 'cancel', 'close', 'confirm'],
|
|
93
94
|
methods: {
|
|
94
95
|
hideKeyboard() {
|
|
95
96
|
uni.hideKeyboard()
|
|
96
97
|
},
|
|
97
98
|
cancel() {
|
|
98
99
|
this.show = false;
|
|
100
|
+
this.$emit('cancel')
|
|
99
101
|
},
|
|
100
|
-
|
|
102
|
+
close() {
|
|
103
|
+
this.$emit('close')
|
|
104
|
+
},
|
|
105
|
+
confirm(e) {
|
|
101
106
|
const {
|
|
102
107
|
columnIndex,
|
|
103
108
|
index,
|
|
@@ -108,6 +113,7 @@ export default {
|
|
|
108
113
|
this.$emit('update:modelValue', value[0][this.valueKey]);
|
|
109
114
|
this.defaultIndex = columnIndex;
|
|
110
115
|
this.current = value[0][this.labelKey];
|
|
116
|
+
this.$emit('confirm')
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
119
|
}
|
|
@@ -21,10 +21,13 @@ export default {
|
|
|
21
21
|
safeAreaInsetBottom: true,
|
|
22
22
|
safeAreaInsetTop: false,
|
|
23
23
|
closeIconPos: 'top-right',
|
|
24
|
-
round:
|
|
24
|
+
round: '20px',
|
|
25
25
|
zoom: true,
|
|
26
26
|
bgColor: '',
|
|
27
27
|
overlayOpacity: 0.5,
|
|
28
|
-
pageInline: false
|
|
28
|
+
pageInline: false,
|
|
29
|
+
touchable: false,
|
|
30
|
+
minHeight: '200px',
|
|
31
|
+
maxHeight: '600px'
|
|
29
32
|
}
|
|
30
33
|
}
|
|
@@ -81,6 +81,21 @@ export const props = defineMixin({
|
|
|
81
81
|
pageInline:{
|
|
82
82
|
type: Boolean,
|
|
83
83
|
default: () => defProps.popup.pageInline
|
|
84
|
+
},
|
|
85
|
+
// 是否页开启手势滑动
|
|
86
|
+
touchable:{
|
|
87
|
+
type: Boolean,
|
|
88
|
+
default: () => defProps.popup.touchable
|
|
89
|
+
},
|
|
90
|
+
// 手势滑动最小高度
|
|
91
|
+
minHeight:{
|
|
92
|
+
type: [String],
|
|
93
|
+
default: () => defProps.popup.minHeight
|
|
94
|
+
},
|
|
95
|
+
// 手势滑动最大高度
|
|
96
|
+
maxHeight:{
|
|
97
|
+
type: [String],
|
|
98
|
+
default: () => defProps.popup.maxHeight
|
|
84
99
|
}
|
|
85
100
|
}
|
|
86
101
|
})
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
:opacity="overlayOpacity"
|
|
19
19
|
></u-overlay>
|
|
20
20
|
<u-transition
|
|
21
|
+
class="u-popup__content—transition"
|
|
22
|
+
:style="contentStyleWrap"
|
|
21
23
|
:show="show"
|
|
22
24
|
:customStyle="transitionStyle"
|
|
23
25
|
:mode="pageInline ? 'none' : position"
|
|
@@ -33,6 +35,18 @@
|
|
|
33
35
|
@touchmove.stop.prevent="noop"
|
|
34
36
|
>
|
|
35
37
|
<u-status-bar v-if="safeAreaInsetTop"></u-status-bar>
|
|
38
|
+
<!-- 增加触摸区域,用于处理手势 -->
|
|
39
|
+
<view
|
|
40
|
+
v-if="touchable && mode === 'bottom'"
|
|
41
|
+
class="u-popup__content__touch-area"
|
|
42
|
+
@touchstart="onTouchStart"
|
|
43
|
+
@touchmove="onTouchMove"
|
|
44
|
+
@touchend="onTouchEnd"
|
|
45
|
+
@touchcancel="onTouchEnd"
|
|
46
|
+
>
|
|
47
|
+
<!-- iOS风格的横条指示器 -->
|
|
48
|
+
<view class="u-popup__content__indicator"></view>
|
|
49
|
+
</view>
|
|
36
50
|
<slot></slot>
|
|
37
51
|
<view
|
|
38
52
|
v-if="closeable"
|
|
@@ -78,9 +92,12 @@
|
|
|
78
92
|
* @property {Boolean} safeAreaInsetBottom 是否为iPhoneX留出底部安全距离 (默认 true )
|
|
79
93
|
* @property {Boolean} safeAreaInsetTop 是否留出顶部安全距离(状态栏高度) (默认 false )
|
|
80
94
|
* @property {String} closeIconPos 自定义关闭图标位置(默认 'top-right' )
|
|
81
|
-
* @property {String | Number} round 圆角值(默认
|
|
95
|
+
* @property {String | Number} round 圆角值(默认 20px)
|
|
82
96
|
* @property {String } bgColor 背景色值(默认 '' )
|
|
83
97
|
* @property {Boolean} zoom 当mode=center时 是否开启缩放(默认 true )
|
|
98
|
+
* @property {Boolean} touchable 是否开启底部弹窗手势功能(默认 false )
|
|
99
|
+
* @property {String | Number} minHeight 最小高度,单位任意,数值默认为px(默认 '200' )
|
|
100
|
+
* @property {String | Number} maxHeight 最大高度,单位任意,数值默认为px(默认 '80%' )
|
|
84
101
|
* @property {Object} customStyle 组件的样式,对象形式
|
|
85
102
|
* @event {Function} open 弹出层打开
|
|
86
103
|
* @event {Function} close 弹出层收起
|
|
@@ -91,7 +108,13 @@
|
|
|
91
108
|
mixins: [mpMixin, mixin, props],
|
|
92
109
|
data() {
|
|
93
110
|
return {
|
|
94
|
-
overlayDuration: this.duration + 50
|
|
111
|
+
overlayDuration: this.duration + 50,
|
|
112
|
+
// 触摸相关数据
|
|
113
|
+
touchStartY: 0,
|
|
114
|
+
touchStartHeight: 0,
|
|
115
|
+
isTouching: false,
|
|
116
|
+
// 当前弹窗高度
|
|
117
|
+
currentHeight: 'auto'
|
|
95
118
|
}
|
|
96
119
|
},
|
|
97
120
|
watch: {
|
|
@@ -145,6 +168,23 @@
|
|
|
145
168
|
})
|
|
146
169
|
}
|
|
147
170
|
},
|
|
171
|
+
contentStyleWrap() {
|
|
172
|
+
const style = {}
|
|
173
|
+
|
|
174
|
+
// 处理手势滑动时的高度变化
|
|
175
|
+
if (this.mode === 'bottom' && this.touchable) {
|
|
176
|
+
if (this.currentHeight !== 'auto') {
|
|
177
|
+
style.height = this.currentHeight
|
|
178
|
+
}
|
|
179
|
+
if (this.maxHeight) {
|
|
180
|
+
style.maxHeight = addUnit(this.maxHeight)
|
|
181
|
+
}
|
|
182
|
+
if (this.minHeight) {
|
|
183
|
+
style.minHeight = addUnit(this.minHeight)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return style;
|
|
187
|
+
},
|
|
148
188
|
contentStyle() {
|
|
149
189
|
const style = {}
|
|
150
190
|
// 通过设备信息的safeAreaInsets值来判断是否需要预留顶部状态栏和底部安全局的位置
|
|
@@ -171,6 +211,7 @@
|
|
|
171
211
|
style.borderRadius = value
|
|
172
212
|
}
|
|
173
213
|
}
|
|
214
|
+
|
|
174
215
|
return deepMerge(style, addStyle(this.customStyle))
|
|
175
216
|
},
|
|
176
217
|
position() {
|
|
@@ -242,8 +283,61 @@
|
|
|
242
283
|
this.retryComputedComponentRect(grandChild)
|
|
243
284
|
}
|
|
244
285
|
}
|
|
245
|
-
}
|
|
286
|
+
},
|
|
246
287
|
// #endif
|
|
288
|
+
|
|
289
|
+
// 触摸开始
|
|
290
|
+
onTouchStart(e) {
|
|
291
|
+
if (!this.touchable || this.mode !== 'bottom') return;
|
|
292
|
+
this.isTouching = true;
|
|
293
|
+
this.touchStartY = e.touches[0].clientY;
|
|
294
|
+
// 保存当前高度
|
|
295
|
+
this.touchStartHeight = this.$el.querySelector('.u-popup__content—transition').offsetHeight;
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
// 触摸移动
|
|
299
|
+
onTouchMove(e) {
|
|
300
|
+
if (!this.isTouching || !this.touchable || this.mode !== 'bottom') return;
|
|
301
|
+
const touchY = e.touches[0].clientY;
|
|
302
|
+
const deltaY = touchY - this.touchStartY;
|
|
303
|
+
|
|
304
|
+
// 只处理向上滑动(减小高度)和向下滑动(增加高度)
|
|
305
|
+
if (deltaY !== 0) {
|
|
306
|
+
const newHeight = this.touchStartHeight - deltaY;
|
|
307
|
+
const minHeight = parseFloat(addUnit(this.minHeight)) || 200;
|
|
308
|
+
const maxHeight = this.maxHeight ?
|
|
309
|
+
(this.maxHeight.toString().includes('%') ?
|
|
310
|
+
getWindowInfo().windowHeight * (parseFloat(this.maxHeight) / 100) :
|
|
311
|
+
parseFloat(addUnit(this.maxHeight))) :
|
|
312
|
+
getWindowInfo().windowHeight * 0.8;
|
|
313
|
+
|
|
314
|
+
// 限制高度在最小值和最大值之间
|
|
315
|
+
if (newHeight >= minHeight && newHeight <= maxHeight) {
|
|
316
|
+
this.currentHeight = newHeight + 'px';
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// 阻止默认滚动行为
|
|
321
|
+
e.preventDefault();
|
|
322
|
+
},
|
|
323
|
+
|
|
324
|
+
// 触摸结束
|
|
325
|
+
onTouchEnd(e) {
|
|
326
|
+
if (!this.isTouching || !this.touchable || this.mode !== 'bottom') return;
|
|
327
|
+
this.isTouching = false;
|
|
328
|
+
|
|
329
|
+
const touchY = e.changedTouches[0].clientY;
|
|
330
|
+
const deltaY = touchY - this.touchStartY;
|
|
331
|
+
const velocity = Math.abs(deltaY) / (e.timeStamp - e.changedTouches[0].timestamp); // 简单的速度计算
|
|
332
|
+
|
|
333
|
+
// 快速向下滑动时关闭弹窗
|
|
334
|
+
if (deltaY > 100 || (deltaY > 30 && velocity > 0.5)) {
|
|
335
|
+
this.close();
|
|
336
|
+
} else {
|
|
337
|
+
// 恢复到自适应高度
|
|
338
|
+
// this.currentHeight = 'auto';
|
|
339
|
+
}
|
|
340
|
+
}
|
|
247
341
|
}
|
|
248
342
|
}
|
|
249
343
|
</script>
|
|
@@ -304,6 +398,27 @@
|
|
|
304
398
|
border-bottom-left-radius: 10px;
|
|
305
399
|
border-bottom-right-radius: 10px;
|
|
306
400
|
}
|
|
401
|
+
|
|
402
|
+
&__touch-area {
|
|
403
|
+
// position: absolute;
|
|
404
|
+
top: 0;
|
|
405
|
+
left: 0;
|
|
406
|
+
right: 0;
|
|
407
|
+
height: 42rpx;
|
|
408
|
+
z-index: 10;
|
|
409
|
+
/* #ifndef APP-NVUE */
|
|
410
|
+
display: flex;
|
|
411
|
+
/* #endif */
|
|
412
|
+
justify-content: center;
|
|
413
|
+
align-items: center;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
&__indicator {
|
|
417
|
+
width: 100px;
|
|
418
|
+
height: 5px;
|
|
419
|
+
border-radius: 100px;
|
|
420
|
+
background-color: #c0c4cc;
|
|
421
|
+
}
|
|
307
422
|
|
|
308
423
|
&__close {
|
|
309
424
|
position: absolute;
|
|
@@ -334,4 +449,4 @@
|
|
|
334
449
|
}
|
|
335
450
|
}
|
|
336
451
|
}
|
|
337
|
-
</style>
|
|
452
|
+
</style>
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "uview-plus",
|
|
3
3
|
"name": "uview-plus",
|
|
4
4
|
"displayName": "零云®uview-plus3.0重磅发布,全面的Vue3鸿蒙跨端移动组件库,组件丰富维护更新稳定。",
|
|
5
|
-
"version": "3.5.
|
|
5
|
+
"version": "3.5.20",
|
|
6
6
|
"description": "零云®uview-plus已兼容vue3支持多语言,100+全面的组件和便捷的工具会让您信手拈来。近期新增拖动排序、条码、图片裁剪、下拉刷新、虚拟列表、签名、Markdown等。",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"uview",
|