uview-plus 3.3.52 → 3.3.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/changelog.md +8 -0
- package/components/u-cate-tab/u-cate-tab.vue +313 -0
- package/components/u-checkbox/u-checkbox.vue +1 -1
- package/components/u-popup/u-popup.vue +2 -0
- package/components/u-qrcode/u-qrcode.vue +25 -16
- package/components/u-radio/u-radio.vue +1 -1
- package/libs/css/flex.scss +1 -1
- package/package.json +1 -1
package/changelog.md
CHANGED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="u-cate-tab">
|
|
3
|
+
<view class="u-cate-tab__wrap">
|
|
4
|
+
<scroll-view class="u-cate-tab__view u-cate-tab__menu-scroll-view"
|
|
5
|
+
scroll-y scroll-with-animation :scroll-top="scrollTop"
|
|
6
|
+
:scroll-into-view="itemId">
|
|
7
|
+
<view v-for="(item, index) in tabList" :key="index" class="u-cate-tab__item"
|
|
8
|
+
:class="[current == index ? 'u-cate-tab__item-active' : '']"
|
|
9
|
+
@tap.stop="swichMenu(index)">
|
|
10
|
+
<slot name="tabItem" :item="item">
|
|
11
|
+
<text class="u-line-1">{{item[tabKeyName]}}</text>
|
|
12
|
+
</slot>
|
|
13
|
+
</view>
|
|
14
|
+
</scroll-view>
|
|
15
|
+
<scroll-view :scroll-top="scrollRightTop" scroll-y scroll-with-animation class="u-cate-tab__right-box" @scroll="rightScroll">
|
|
16
|
+
<view class="u-cate-tab__page-view">
|
|
17
|
+
<view class="u-cate-tab__page-item" :id="'item' + index" v-for="(item , index) in tabList" :key="index">
|
|
18
|
+
<slot name="itemList" :item="item">
|
|
19
|
+
<view class="item-title">
|
|
20
|
+
<text>{{item[tabKeyName]}}</text>
|
|
21
|
+
</view>
|
|
22
|
+
<view class="item-container">
|
|
23
|
+
<template v-for="(item1, index1) in item.children" :key="index1">
|
|
24
|
+
<slot name="pageItem" :pageItem="item1">
|
|
25
|
+
<view class="thumb-box" >
|
|
26
|
+
<image class="item-menu-image" :src="item1.icon" mode=""></image>
|
|
27
|
+
<view class="item-menu-name">{{item1[itemKeyName]}}</view>
|
|
28
|
+
</view>
|
|
29
|
+
</slot>
|
|
30
|
+
</template>
|
|
31
|
+
</view>
|
|
32
|
+
</slot>
|
|
33
|
+
</view>
|
|
34
|
+
</view>
|
|
35
|
+
</scroll-view>
|
|
36
|
+
</view>
|
|
37
|
+
</view>
|
|
38
|
+
</template>
|
|
39
|
+
<script>
|
|
40
|
+
export default {
|
|
41
|
+
props: {
|
|
42
|
+
tabList: {
|
|
43
|
+
type: Array,
|
|
44
|
+
default: () => {
|
|
45
|
+
return []
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
tabKeyName: {
|
|
49
|
+
type: String,
|
|
50
|
+
default: 'name'
|
|
51
|
+
},
|
|
52
|
+
itemKeyName: {
|
|
53
|
+
type: String,
|
|
54
|
+
default: 'name'
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
watch: {
|
|
58
|
+
tabList() {
|
|
59
|
+
this.getMenuItemTop()
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
data() {
|
|
63
|
+
return {
|
|
64
|
+
scrollTop: 0, //tab标题的滚动条位置
|
|
65
|
+
oldScrollTop: 0,
|
|
66
|
+
current: 0, // 预设当前项的值
|
|
67
|
+
menuHeight: 0, // 左边菜单的高度
|
|
68
|
+
menuItemHeight: 0, // 左边菜单item的高度
|
|
69
|
+
itemId: '', // 栏目右边scroll-view用于滚动的id
|
|
70
|
+
menuItemPos: [],
|
|
71
|
+
rects: [],
|
|
72
|
+
arr: [],
|
|
73
|
+
scrollRightTop: 0, // 右边栏目scroll-view的滚动条高度
|
|
74
|
+
timer: null, // 定时器
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
onMounted() {
|
|
78
|
+
this.getMenuItemTop()
|
|
79
|
+
},
|
|
80
|
+
methods: {
|
|
81
|
+
// 点击左边的栏目切换
|
|
82
|
+
async swichMenu(index) {
|
|
83
|
+
if(this.arr.length == 0) {
|
|
84
|
+
await this.getMenuItemTop();
|
|
85
|
+
}
|
|
86
|
+
if (index == this.current) return;
|
|
87
|
+
this.scrollRightTop = this.oldScrollTop;
|
|
88
|
+
this.$nextTick(function(){
|
|
89
|
+
this.scrollRightTop = this.arr[index];
|
|
90
|
+
this.current = index;
|
|
91
|
+
this.leftMenuStatus(index);
|
|
92
|
+
})
|
|
93
|
+
},
|
|
94
|
+
// 获取一个目标元素的高度
|
|
95
|
+
getElRect(elClass, dataVal) {
|
|
96
|
+
new Promise((resolve, reject) => {
|
|
97
|
+
const query = uni.createSelectorQuery().in(this);
|
|
98
|
+
query.select('.' + elClass).fields({
|
|
99
|
+
size: true
|
|
100
|
+
}, res => {
|
|
101
|
+
// 如果节点尚未生成,res值为null,循环调用执行
|
|
102
|
+
if (!res) {
|
|
103
|
+
setTimeout(() => {
|
|
104
|
+
this.getElRect(elClass);
|
|
105
|
+
}, 10);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
this[dataVal] = res.height;
|
|
109
|
+
resolve();
|
|
110
|
+
}).exec();
|
|
111
|
+
})
|
|
112
|
+
},
|
|
113
|
+
// 观测元素相交状态
|
|
114
|
+
async observer() {
|
|
115
|
+
this.tabList.map((val, index) => {
|
|
116
|
+
let observer = uni.createIntersectionObserver(this);
|
|
117
|
+
// 检测右边scroll-view的id为itemxx的元素与u-cate-tab__right-box的相交状态
|
|
118
|
+
// 如果跟.u-cate-tab__right-box底部相交,就动态设置左边栏目的活动状态
|
|
119
|
+
observer.relativeTo('.u-cate-tab__right-box', {
|
|
120
|
+
top: 0
|
|
121
|
+
}).observe('#item' + index, res => {
|
|
122
|
+
if (res.intersectionRatio > 0) {
|
|
123
|
+
let id = res.id.substring(4);
|
|
124
|
+
this.leftMenuStatus(id);
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
},
|
|
129
|
+
// 设置左边菜单的滚动状态
|
|
130
|
+
async leftMenuStatus(index) {
|
|
131
|
+
this.current = index;
|
|
132
|
+
// 如果为0,意味着尚未初始化
|
|
133
|
+
if (this.menuHeight == 0 || this.menuItemHeight == 0) {
|
|
134
|
+
await this.getElRect('u-cate-tab__menu-scroll-view', 'menuHeight');
|
|
135
|
+
await this.getElRect('u-cate-tab__item', 'menuItemHeight');
|
|
136
|
+
}
|
|
137
|
+
// 将菜单活动item垂直居中
|
|
138
|
+
this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
|
|
139
|
+
},
|
|
140
|
+
// 获取右边菜单每个item到顶部的距离
|
|
141
|
+
getMenuItemTop() {
|
|
142
|
+
new Promise(resolve => {
|
|
143
|
+
let selectorQuery = uni.createSelectorQuery();
|
|
144
|
+
selectorQuery.selectAll('.u-cate-tab__page-item').boundingClientRect((rects) => {
|
|
145
|
+
// 如果节点尚未生成,rects值为[](因为用selectAll,所以返回的是数组),循环调用执行
|
|
146
|
+
if(!rects.length) {
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
this.getMenuItemTop();
|
|
149
|
+
}, 10);
|
|
150
|
+
return ;
|
|
151
|
+
}
|
|
152
|
+
this.rects = rects;
|
|
153
|
+
rects.forEach((rect) => {
|
|
154
|
+
// 这里减去rects[0].top,是因为第一项顶部可能不是贴到导航栏(比如有个搜索框的情况)
|
|
155
|
+
this.arr.push(rect.top - rects[0].top);
|
|
156
|
+
resolve();
|
|
157
|
+
})
|
|
158
|
+
}).exec()
|
|
159
|
+
})
|
|
160
|
+
},
|
|
161
|
+
// 右边菜单滚动
|
|
162
|
+
async rightScroll(e) {
|
|
163
|
+
this.oldScrollTop = e.detail.scrollTop;
|
|
164
|
+
// console.log(e.detail.scrollTop)
|
|
165
|
+
// console.log(JSON.stringify(this.arr))
|
|
166
|
+
if(this.arr.length == 0) {
|
|
167
|
+
await this.getMenuItemTop();
|
|
168
|
+
}
|
|
169
|
+
if(this.timer) return ;
|
|
170
|
+
if(!this.menuHeight) {
|
|
171
|
+
await this.getElRect('u-cate-tab__menu-scroll-view', 'menuHeight');
|
|
172
|
+
}
|
|
173
|
+
setTimeout(() => { // 节流
|
|
174
|
+
this.timer = null;
|
|
175
|
+
// scrollHeight为右边菜单垂直中点位置
|
|
176
|
+
let scrollHeight = e.detail.scrollTop + 1;
|
|
177
|
+
// console.log(e.detail.scrollTop)
|
|
178
|
+
for (let i = 0; i < this.arr.length; i++) {
|
|
179
|
+
let height1 = this.arr[i];
|
|
180
|
+
let height2 = this.arr[i + 1];
|
|
181
|
+
// console.log('i', i)
|
|
182
|
+
// console.log('height1', height1)
|
|
183
|
+
// console.log('height2', height2)
|
|
184
|
+
// 如果不存在height2,意味着数据循环已经到了最后一个,设置左边菜单为最后一项即可
|
|
185
|
+
if (!height2 || scrollHeight >= height1 && scrollHeight <= height2) {
|
|
186
|
+
// console.log('scrollHeight', scrollHeight)
|
|
187
|
+
// console.log('height1', height1)
|
|
188
|
+
// console.log('height2', height2)
|
|
189
|
+
this.leftMenuStatus(i);
|
|
190
|
+
return ;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}, 10)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
</script>
|
|
198
|
+
|
|
199
|
+
<style lang="scss" scoped>
|
|
200
|
+
.u-cate-tab {
|
|
201
|
+
display: flex;
|
|
202
|
+
flex-direction: column;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.u-cate-tab__wrap {
|
|
206
|
+
flex: 1;
|
|
207
|
+
display: flex;
|
|
208
|
+
overflow: hidden;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.u-search-inner {
|
|
212
|
+
background-color: rgb(234, 234, 234);
|
|
213
|
+
border-radius: 100rpx;
|
|
214
|
+
display: flex;
|
|
215
|
+
align-items: center;
|
|
216
|
+
padding: 10rpx 16rpx;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.u-search-text {
|
|
220
|
+
font-size: 26rpx;
|
|
221
|
+
color: $u-tips-color;
|
|
222
|
+
margin-left: 10rpx;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.u-cate-tab__view {
|
|
226
|
+
width: 200rpx;
|
|
227
|
+
height: 100%;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.u-cate-tab__item {
|
|
231
|
+
height: 110rpx;
|
|
232
|
+
background: #f6f6f6;
|
|
233
|
+
box-sizing: border-box;
|
|
234
|
+
display: flex;
|
|
235
|
+
align-items: center;
|
|
236
|
+
justify-content: center;
|
|
237
|
+
font-size: 26rpx;
|
|
238
|
+
color: #444;
|
|
239
|
+
font-weight: 400;
|
|
240
|
+
line-height: 1;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.u-cate-tab__item-active {
|
|
244
|
+
position: relative;
|
|
245
|
+
color: #000;
|
|
246
|
+
font-size: 30rpx;
|
|
247
|
+
font-weight: 600;
|
|
248
|
+
background: #fff;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.u-cate-tab__item-active::before {
|
|
252
|
+
content: "";
|
|
253
|
+
position: absolute;
|
|
254
|
+
border-left: 4px solid $u-primary;
|
|
255
|
+
height: 32rpx;
|
|
256
|
+
left: 0;
|
|
257
|
+
top: 39rpx;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.u-cate-tab__view {
|
|
261
|
+
height: 100%;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.u-cate-tab__right-box {
|
|
265
|
+
background-color: rgb(250, 250, 250);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.u-cate-tab__page-view {
|
|
269
|
+
padding: 16rpx;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.u-cate-tab__page-item {
|
|
273
|
+
margin-bottom: 30rpx;
|
|
274
|
+
background-color: #fff;
|
|
275
|
+
padding: 16rpx;
|
|
276
|
+
border-radius: 8rpx;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.u-cate-tab__page-item:last-child {
|
|
280
|
+
min-height: 100vh;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.item-title {
|
|
284
|
+
font-size: 26rpx;
|
|
285
|
+
color: $u-main-color;
|
|
286
|
+
font-weight: bold;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.item-menu-name {
|
|
290
|
+
font-weight: normal;
|
|
291
|
+
font-size: 24rpx;
|
|
292
|
+
color: $u-main-color;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.item-container {
|
|
296
|
+
display: flex;
|
|
297
|
+
flex-wrap: wrap;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.thumb-box {
|
|
301
|
+
width: 33.333333%;
|
|
302
|
+
display: flex;
|
|
303
|
+
align-items: center;
|
|
304
|
+
justify-content: center;
|
|
305
|
+
flex-direction: column;
|
|
306
|
+
margin-top: 20rpx;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.item-menu-image {
|
|
310
|
+
width: 120rpx;
|
|
311
|
+
height: 120rpx;
|
|
312
|
+
}
|
|
313
|
+
</style>
|
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
@afterEnter="afterEnter"
|
|
18
18
|
@click="clickHandler"
|
|
19
19
|
>
|
|
20
|
+
<!-- @click.stop不能去除,去除会导致居中模式下点击内容区域触发关闭弹窗 -->
|
|
20
21
|
<view
|
|
21
22
|
class="u-popup__content"
|
|
22
23
|
:style="[contentStyle]"
|
|
24
|
+
@click.stop="noop"
|
|
23
25
|
@touchmove.stop.prevent="noop"
|
|
24
26
|
>
|
|
25
27
|
<u-status-bar v-if="safeAreaInsetTop"></u-status-bar>
|
|
@@ -99,6 +99,10 @@ export default {
|
|
|
99
99
|
type: String,
|
|
100
100
|
default: '生成中'
|
|
101
101
|
},
|
|
102
|
+
allowPreview: {
|
|
103
|
+
type: Boolean,
|
|
104
|
+
default: false
|
|
105
|
+
},
|
|
102
106
|
},
|
|
103
107
|
emits: ['result', 'longpress'],
|
|
104
108
|
data() {
|
|
@@ -189,26 +193,31 @@ export default {
|
|
|
189
193
|
});
|
|
190
194
|
}
|
|
191
195
|
},
|
|
192
|
-
preview() {
|
|
196
|
+
preview(e) {
|
|
193
197
|
// 预览图片
|
|
194
198
|
// console.log(this.result)
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
199
|
+
if (this.allowPreview) {
|
|
200
|
+
uni.previewImage({
|
|
201
|
+
urls: [this.result],
|
|
202
|
+
longPressActions: {
|
|
203
|
+
itemList: ['保存二维码图片'],
|
|
204
|
+
success: function(data) {
|
|
205
|
+
// console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
|
|
206
|
+
switch (data.tapIndex) {
|
|
207
|
+
case 0:
|
|
208
|
+
that._saveCode();
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
fail: function(err) {
|
|
213
|
+
console.log(err.errMsg);
|
|
205
214
|
}
|
|
206
|
-
},
|
|
207
|
-
fail: function(err) {
|
|
208
|
-
console.log(err.errMsg);
|
|
209
215
|
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
this.$emit('preview', {
|
|
219
|
+
url: this.result
|
|
220
|
+
}, e)
|
|
212
221
|
},
|
|
213
222
|
longpress() {
|
|
214
223
|
this.$emit('longpress', this.result)
|
package/libs/css/flex.scss
CHANGED