Commit d495801abedc7d8eab28f34c0704c1bd97013574
Exists in
master
Merge branch 'master' of 121.40.31.31:jp/gulu-vue
Showing
9 changed files
Show diff stats
src/components/CommodityCard/CommodityCard.vue
... | ... | @@ -3,10 +3,14 @@ |
3 | 3 | class="card" |
4 | 4 | @tap="toGoods(goods.id?goods.id:goods.pid,goods.sk_id)" |
5 | 5 | > |
6 | - <image | |
6 | + <easy-loadimage mode="widthFix" | |
7 | + :scroll-top="scrollTop" | |
8 | + :image-src="goods.imgurl?goods.imgurl:goods.pic" | |
9 | + :viewHeight="viewHeight"></easy-loadimage> | |
10 | +<!-- <image | |
7 | 11 | mode="widthFix" |
8 | 12 | :src="goods.imgurl?goods.imgurl:goods.pic" |
9 | - ></image> | |
13 | + ></image> --> | |
10 | 14 | <view class="name">{{goods.name?goods.name:goods.p_name}}</view> |
11 | 15 | <view class="info"> |
12 | 16 | <view class="priceBox"> |
... | ... | @@ -22,7 +26,10 @@ |
22 | 26 | </template> |
23 | 27 | |
24 | 28 | <script> |
29 | +import easyLoadimage from '@/components/EasyLoadimage/EasyLoadimage.vue' | |
30 | +// const MockData = require('@/static/easy-loadimage/mock-data.json') | |
25 | 31 | export default { |
32 | + components:{easyLoadimage}, | |
26 | 33 | props: { |
27 | 34 | /** |
28 | 35 | * 商品数据 |
... | ... | @@ -37,15 +44,17 @@ export default { |
37 | 44 | trade_num: String, |
38 | 45 | goodType: String, |
39 | 46 | }, |
40 | - | |
47 | + scrollTop:Number, | |
48 | + viewHeight:Number, | |
41 | 49 | }, |
42 | 50 | created () { |
43 | 51 | }, |
44 | 52 | data () { |
45 | 53 | return { |
46 | - | |
54 | + | |
47 | 55 | } |
48 | 56 | }, |
57 | + | |
49 | 58 | methods: { |
50 | 59 | toGoods (id, skId) { |
51 | 60 | console.log('---', '../frameDetail/frameDetail?pid=' + id + '&sk_id=' + skId) |
... | ... | @@ -61,6 +70,7 @@ export default { |
61 | 70 | </script> |
62 | 71 | |
63 | 72 | <style lang="scss"> |
73 | + | |
64 | 74 | image { |
65 | 75 | width: 100%; |
66 | 76 | height: 120rpx; | ... | ... |
src/components/EasyLoadimage/EasyLoadimage.vue
... | ... | @@ -0,0 +1,170 @@ |
1 | +<template> | |
2 | + <view class="easy-loadimage" :id="uid"> | |
3 | + <image class="origin-img" :src="imageSrc?imageSrc:defaultImg" :mode="mode" | |
4 | + v-if="loadImg&&!isLoadError" | |
5 | + v-show="showImg" | |
6 | + :class="{'no-transition':!openTransition,'show-transition':showTransition&&openTransition}" | |
7 | + @load="handleImgLoad" | |
8 | + @error="handleImgError"> | |
9 | + </image> | |
10 | + <view class="loadfail-img" v-else-if="isLoadError"></view> | |
11 | + <view :class="['loading-img',loadingMode]" v-show="!showImg&&!isLoadError"></view> | |
12 | + | |
13 | + </view> | |
14 | +</template> | |
15 | +<script> | |
16 | +// 生成全局唯一id | |
17 | +function generateUUID() { | |
18 | + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { | |
19 | + let r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); | |
20 | + return v.toString(16); | |
21 | + }) | |
22 | +} | |
23 | +export default{ | |
24 | + props:{ | |
25 | + imageSrc:{ | |
26 | + type: String, | |
27 | + }, | |
28 | + mode:{ | |
29 | + type: String, | |
30 | + }, | |
31 | + scrollTop:{ | |
32 | + type: Number, | |
33 | + }, | |
34 | + loadingMode:{ | |
35 | + type: String, | |
36 | + default:'looming-gray' | |
37 | + }, | |
38 | + openTransition:{ | |
39 | + type: Boolean, | |
40 | + default:true, | |
41 | + }, | |
42 | + viewHeight:{ | |
43 | + type:Number, | |
44 | + default() { | |
45 | + return uni.getSystemInfoSync().windowHeight; | |
46 | + } | |
47 | + } | |
48 | + }, | |
49 | + watch:{ | |
50 | + scrollTop(val){ | |
51 | + this.onScroll(val) | |
52 | + } | |
53 | + }, | |
54 | + data(){ | |
55 | + return { | |
56 | + uid:'', | |
57 | + loadImg:false, | |
58 | + showImg:false, | |
59 | + isLoadError:false, | |
60 | + showTransition:false | |
61 | + } | |
62 | + }, | |
63 | + methods:{ | |
64 | + init(){ | |
65 | + this.uid = 'uid-' + generateUUID(); | |
66 | + this.$nextTick(this.onScroll) | |
67 | + }, | |
68 | + handleImgLoad(e){ | |
69 | + // console.log('success'); | |
70 | + this.showImg = true; | |
71 | + // this.$nextTick(function(){ | |
72 | + // this.showTransition = true | |
73 | + // }) | |
74 | + setTimeout(()=>{ | |
75 | + this.showTransition = true | |
76 | + },50) | |
77 | + }, | |
78 | + handleImgError(e){ | |
79 | + // console.log('fail'); | |
80 | + this.isLoadError = true; | |
81 | + }, | |
82 | + onScroll(scrollTop){ | |
83 | + // 加载ing时才执行滚动监听判断是否可加载 | |
84 | + if(this.loadImg || this.isLoadError) return; | |
85 | + const id = this.uid | |
86 | + const query = uni.createSelectorQuery().in(this); | |
87 | + query.select('#'+id).boundingClientRect(data => { | |
88 | + if(!data) return; | |
89 | + if(data.top - this.viewHeight<0){ | |
90 | + this.loadImg = true; | |
91 | + } | |
92 | + }).exec() | |
93 | + }, | |
94 | + }, | |
95 | + mounted() { | |
96 | + this.init() | |
97 | + } | |
98 | +} | |
99 | +</script> | |
100 | + | |
101 | +<style scoped> | |
102 | + /* 官方优化图片tips */ | |
103 | + image{ | |
104 | + will-change: transform | |
105 | + } | |
106 | + /* 渐变过渡效果处理 */ | |
107 | + image.origin-img{ | |
108 | + width: 100%; | |
109 | + height: 100%; | |
110 | + opacity: 0.3; | |
111 | + } | |
112 | + image.origin-img.show-transition{ | |
113 | + transition: opacity 1.2s; | |
114 | + opacity: 1; | |
115 | + } | |
116 | + image.origin-img.no-transition{ | |
117 | + opacity: 1; | |
118 | + } | |
119 | + /* 加载失败、加载中的占位图样式控制 */ | |
120 | + .loadfail-img{ | |
121 | + height: 100%; | |
122 | + background: url('~@/static/easy-loadimage/loadfail.png') no-repeat center; | |
123 | + background-size: 50%; | |
124 | + } | |
125 | + .loading-img{ | |
126 | + height: 100%; | |
127 | + } | |
128 | + /* 转圈 */ | |
129 | + .spin-circle{ | |
130 | + background: url('~@/static/easy-loadimage/loading.gif') no-repeat center; | |
131 | + background-size: 100rpx; | |
132 | + } | |
133 | + /* 动态灰色若隐若现 */ | |
134 | + .looming-gray{ | |
135 | + animation: looming-gray 1s infinite linear; | |
136 | + background-color: #e3e3e3; | |
137 | + } | |
138 | + @keyframes looming-gray{ | |
139 | + 0% {background-color:#e3e3e3aa;} | |
140 | + 50% {background-color:#e3e3e3;} | |
141 | + 100% {background-color:#e3e3e3aa;} | |
142 | + } | |
143 | + /* 骨架屏1 */ | |
144 | + .skeleton-1{ | |
145 | + background-color: #e3e3e3; | |
146 | + background-image: linear-gradient(100deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0) 80%); | |
147 | + background-size: 100rpx 100%; | |
148 | + background-repeat: repeat-y; | |
149 | + background-position:0 0; | |
150 | + animation: skeleton-1 .6s infinite; | |
151 | + } | |
152 | + @keyframes skeleton-1 { | |
153 | + to { | |
154 | + background-position: 200% 0; | |
155 | + } | |
156 | + } | |
157 | + /* 骨架屏2 */ | |
158 | + .skeleton-2{ | |
159 | + background-image: linear-gradient(-90deg, #fefefe 0%, #e6e6e6 50%,#fefefe 100%); | |
160 | + background-size: 400% 400%; | |
161 | + background-position:0 0; | |
162 | + animation: skeleton-2 1.2s ease-in-out infinite; | |
163 | + } | |
164 | + @keyframes skeleton-2{ | |
165 | + to { | |
166 | + background-position: -135% 0; | |
167 | + } | |
168 | + } | |
169 | +</style> | |
170 | + | ... | ... |
src/pages/cart/cart.vue
... | ... | @@ -8,7 +8,7 @@ |
8 | 8 | <view class="cardHeader"> |
9 | 9 | <view |
10 | 10 | v-bind:class="pIsoPen? 'partentChecked' : 'partentCheck'" |
11 | - @tap="pChange(pIsoPen)" | |
11 | + @touchstart="pChange(pIsoPen)" | |
12 | 12 | > |
13 | 13 | <span class="correct"></span> |
14 | 14 | </view> |
... | ... | @@ -21,12 +21,12 @@ |
21 | 21 | <view |
22 | 22 | class="cardBody" |
23 | 23 | v-for="(item,index) in cartList" |
24 | - :key="item.cart_id" | |
24 | + :key="index" | |
25 | 25 | @longpress="delCart(item.cart_id,index)" |
26 | 26 | > |
27 | 27 | <view |
28 | 28 | v-bind:class="childIsOpen[index]? 'partentChecked':'partentCheck'" |
29 | - @tap="Change(childIsOpen[index],index)" | |
29 | + @touchstart="Change(childIsOpen[index],index)" | |
30 | 30 | > |
31 | 31 | <span class="correct"></span> |
32 | 32 | </view> |
... | ... | @@ -47,11 +47,10 @@ |
47 | 47 | @tap="toGoods(item.pid,item.sk_id)" |
48 | 48 | >{{item.p_name}}</view> |
49 | 49 | <!-- <view class="describ"> --> |
50 | - <uni-collapse accordion="true"> | |
50 | + <uni-collapse accordion="true" style="justify-content: space-around;width: 196px;"> | |
51 | 51 | <uni-collapse-item |
52 | 52 | showAnimation='true' |
53 | - :title="item.tag.prod_tag_fun[0].label+'/'+item.tag.prod_tag_fun[1].label+'/'+item.tag.prod_tag_fun[2].label+'...' || '暂无'" | |
54 | - > | |
53 | + :title="item.tag.prod_tag_fun[0].label&&item.tag.prod_tag_fun[1].label?item.tag.prod_tag_fun[0].label+'/'+item.tag.prod_tag_fun[1].label+'...':'暂无数据'"> | |
55 | 54 | <text class="describ"> |
56 | 55 | <block |
57 | 56 | v-for="tag in item.tag.prod_tag_fun" |
... | ... | @@ -127,6 +126,7 @@ export default { |
127 | 126 | |
128 | 127 | cartList() { |
129 | 128 | // console.log('cart-list', this.$store.state.cart.cartList); |
129 | + this.totalPrice=0 | |
130 | 130 | return this.$store.state.cart.cartList |
131 | 131 | }, |
132 | 132 | childIsOpen() { |
... | ... | @@ -268,24 +268,24 @@ export default { |
268 | 268 | // console.log('delcart------>cart_id',cart_id) |
269 | 269 | // console.log('cartlist====>delcart',this.$store.state.cart.cartList) |
270 | 270 | // console.log('delcart======>index',index) |
271 | - const uid = this.$store.state.user.userInfo.uid | |
272 | - const openid = this.$store.state.user.userInfo.openid | |
273 | - uni.showModal({ | |
274 | - title: '是否删除该商品', | |
275 | - // content: '是否删除该商品', | |
276 | - success: function (res) { | |
277 | - if (res.confirm) { | |
278 | - // this.$store.state.cart.cartList.splice(index,1) | |
279 | - store.dispatch('cart/delCart', { | |
280 | - uid: uid, | |
281 | - openid: openid, | |
282 | - cart_id: cart_id, // 要修改的购物车id | |
283 | - arg: index, // 由于action 传参是能接收两参数,因此将index放入对象 | |
284 | - }) | |
285 | - console.log('用户点击确定') | |
286 | - } | |
287 | - }, | |
288 | - }) | |
271 | + uni.showModal({ | |
272 | + title: '是否删除该商品', | |
273 | + // content: '是否删除该商品', | |
274 | + success: function (res) { | |
275 | + if (res.confirm) { | |
276 | + if (this.childIsOpen[index]) { | |
277 | + this.totalPrice = this.totalPrice - (this.$store.state.cart.cartList[index].nowPrice*this.$store.state.cart.cartList[index].num) | |
278 | + } | |
279 | + console.log('index===>',index) | |
280 | + store.dispatch('cart/delCart', { | |
281 | + uid: this.$store.state.user.userInfo.uid, | |
282 | + openid: this.$store.state.user.userInfo.openid, | |
283 | + cart_id: cart_id, // 要修改的购物车id | |
284 | + arg: index, // 由于action 传参是能接收两参数,因此将index放入对象 | |
285 | + }) | |
286 | + } | |
287 | + }.bind(this), | |
288 | + }) | |
289 | 289 | }, |
290 | 290 | }, |
291 | 291 | } |
... | ... | @@ -308,14 +308,14 @@ export default { |
308 | 308 | border-radius: 22px; |
309 | 309 | border: 1px solid #cfcfcf; |
310 | 310 | background-color: #ffffff; |
311 | - margin: 6px; | |
311 | + margin: 24rpx 12rpx 24rpx 24rpx; | |
312 | 312 | } |
313 | 313 | .partentChecked { |
314 | 314 | width: 18px; |
315 | 315 | height: 18px; |
316 | 316 | border-radius: 22px; |
317 | 317 | background-color: #ff6b4a; |
318 | - margin: 6px; | |
318 | + margin: 24rpx 12rpx 24rpx 24rpx; | |
319 | 319 | .correct { |
320 | 320 | display: inline-block; |
321 | 321 | position: relative; | ... | ... |
src/pages/index/index.vue
... | ... | @@ -84,6 +84,12 @@ |
84 | 84 | data-format="Object" |
85 | 85 | ></HMfilterDropdown> |
86 | 86 | <!-- 商品列表 --> |
87 | +<!-- <scroll-view | |
88 | + enable-flex | |
89 | + @scrolltolower="handleScrolltolower" | |
90 | + scroll-y | |
91 | + style="height: 1000px;margin-bottom: 20px;" | |
92 | + > --> | |
87 | 93 | <view class="goods-list"> |
88 | 94 | <view class="product-list"> |
89 | 95 | <view |
... | ... | @@ -91,11 +97,12 @@ |
91 | 97 | v-for="(goods) in goodsList" |
92 | 98 | :key="goods.id" |
93 | 99 | > |
94 | - <Card :goods="goods"></Card> | |
100 | + <Card :goods="goods" :scrollTop="scrollTop" :viewHeight="viewHeight"></Card> | |
95 | 101 | </view> |
96 | 102 | </view> |
97 | 103 | <view class="loading-text">{{loadingText}}</view> |
98 | 104 | </view> |
105 | + <!-- </scroll-view> --> | |
99 | 106 | </view> |
100 | 107 | </view> |
101 | 108 | </view> |
... | ... | @@ -121,8 +128,16 @@ export default { |
121 | 128 | filterDropdownValue: [], |
122 | 129 | filterData: [], |
123 | 130 | searchText: '', |
131 | + scrollTop: 0, | |
132 | + viewHeight: uni.getSystemInfoSync().windowHeight, | |
124 | 133 | } |
125 | 134 | }, |
135 | + onPageScroll({scrollTop}) { | |
136 | + // 传入scrollTop值并触发所有easy-loadimage组件下的滚动监听事件 | |
137 | + | |
138 | + this.scrollTop = scrollTop; | |
139 | + console.log('pagescroll====>',this.viewHeight) | |
140 | + }, | |
126 | 141 | computed: { |
127 | 142 | goodsList () { |
128 | 143 | // 也可以从 getters 获取 | ... | ... |
src/pages/user/user.vue
... | ... | @@ -36,10 +36,16 @@ |
36 | 36 | <button @tap="chatOur(2)">客服2</button> |
37 | 37 | </view> |
38 | 38 | </uni-popup> |
39 | - <view | |
40 | - v-if="isAuth" | |
41 | - class="content" | |
42 | - > | |
39 | +<!-- <scroll-view | |
40 | + enable-flex | |
41 | + @scrolltolower="handleScrolltolower" | |
42 | + scroll-y | |
43 | + style="height: 1000px;" | |
44 | + > --> | |
45 | + <view | |
46 | + v-if="isAuth" | |
47 | + class="content" | |
48 | + > | |
43 | 49 | <view class="userInfo"> |
44 | 50 | <view class="info"> |
45 | 51 | <image |
... | ... | @@ -192,24 +198,26 @@ |
192 | 198 | </view> |
193 | 199 | <!-- 商品列表 --> |
194 | 200 | <view class="goods-list"> |
195 | - <scroll-view | |
201 | +<!-- <scroll-view | |
196 | 202 | enable-flex |
197 | 203 | @scrolltolower="handleScrolltolower" |
198 | 204 | scroll-y |
199 | 205 | class="product-list" |
200 | - > | |
206 | + > --> | |
207 | + <view class="product-list"> | |
201 | 208 | <view |
202 | 209 | class="product" |
203 | 210 | v-for="(item, index) in userRecommandList" |
204 | 211 | :key="index" |
205 | 212 | > |
206 | - <Card :goods="item"></Card> | |
213 | + <Card :goods="item" :scrollTop="scrollTop" :viewHeight="viewHeight"></Card> | |
207 | 214 | </view> |
208 | - </scroll-view> | |
215 | + </view> | |
216 | + <!-- </scroll-view> --> | |
209 | 217 | <view class="loading-text">{{loadingText}}</view> |
210 | 218 | </view> |
211 | 219 | </view> |
212 | - </view> | |
220 | + </view> | |
213 | 221 | <view |
214 | 222 | v-else |
215 | 223 | class="auth" |
... | ... | @@ -224,6 +232,7 @@ |
224 | 232 | @getuserinfo="onGotUserInfo" |
225 | 233 | >授权登陆</button> |
226 | 234 | </view> |
235 | + <!-- </scroll-view> --> | |
227 | 236 | </view> |
228 | 237 | </template> |
229 | 238 | |
... | ... | @@ -241,9 +250,16 @@ export default { |
241 | 250 | return { |
242 | 251 | isAuth: true, // 是否显示授权页面, |
243 | 252 | pagesnum: 1, // 分页请求初始值 |
244 | - whichTap: 0 // 弹窗渲染选择条件 | |
253 | + whichTap: 0 ,// 弹窗渲染选择条件 | |
254 | + loadingText: '到底了', | |
255 | + scrollTop: 0, | |
256 | + viewHeight: uni.getSystemInfoSync().windowHeight, | |
245 | 257 | } |
246 | 258 | }, |
259 | + onPageScroll({scrollTop}) { | |
260 | + // 传入scrollTop值并触发所有easy-loadimage组件下的滚动监听事件 | |
261 | + this.scrollTop = scrollTop; | |
262 | + }, | |
247 | 263 | onLoad() { |
248 | 264 | // 判断是否授权 |
249 | 265 | uni.getSetting({ |
... | ... | @@ -262,6 +278,15 @@ export default { |
262 | 278 | page: this.pagesnum |
263 | 279 | }) |
264 | 280 | }, |
281 | + onReachBottom() { | |
282 | + // console.log('usr-my',this.$store.state.user.userInfo) | |
283 | + this.pagesnum++ | |
284 | + store.dispatch('userRecommand/getRecommandList', { | |
285 | + uid: this.$store.state.user.userInfo.uid, | |
286 | + openid: this.$store.state.user.userInfo.openid, | |
287 | + page: this.pagesnum | |
288 | + }) | |
289 | + }, | |
265 | 290 | computed: { |
266 | 291 | nickName() { |
267 | 292 | return this.$store.state.user.userInfo.nickName |
... | ... | @@ -332,15 +357,6 @@ export default { |
332 | 357 | uni.navigateTo({ |
333 | 358 | url: '../addOpticsData/addOpticsData' |
334 | 359 | }) |
335 | - }, | |
336 | - handleScrolltolower() { | |
337 | - // console.log('usr-my',this.$store.state.user.userInfo) | |
338 | - this.pagesnum++ | |
339 | - store.dispatch('userRecommand/getRecommandList', { | |
340 | - uid: this.$store.state.user.userInfo.uid, | |
341 | - openid: this.$store.state.user.userInfo.openid, | |
342 | - page: this.pagesnum | |
343 | - }) | |
344 | 360 | } |
345 | 361 | } |
346 | 362 | } |
... | ... | @@ -581,7 +597,6 @@ export default { |
581 | 597 | display: flex; |
582 | 598 | justify-content: space-between; |
583 | 599 | flex-wrap: wrap; |
584 | - height: 400px; | |
585 | 600 | .product { |
586 | 601 | width: 48%; |
587 | 602 | margin: 0 0 20rpx 0; | ... | ... |
src/static/easy-loadimage/loadfail.png
3.42 KB
src/static/easy-loadimage/loading.gif
16.9 KB
src/store/modules/index.js
... | ... | @@ -9,7 +9,7 @@ |
9 | 9 | |
10 | 10 | const state = { |
11 | 11 | categoryList: [], |
12 | - list: [], | |
12 | + list: [] | |
13 | 13 | }; |
14 | 14 | |
15 | 15 | const mutations = { |
... | ... | @@ -18,7 +18,7 @@ const mutations = { |
18 | 18 | }, |
19 | 19 | CATEGORY: (state, categoryList) => { |
20 | 20 | state.categoryList = categoryList; |
21 | - }, | |
21 | + } | |
22 | 22 | }; |
23 | 23 | |
24 | 24 | const actions = { |
... | ... | @@ -84,7 +84,7 @@ const actions = { |
84 | 84 | console.log("complete status === > ", res); |
85 | 85 | }, |
86 | 86 | }) |
87 | - } | |
87 | + }, | |
88 | 88 | }; |
89 | 89 | |
90 | 90 | export default { | ... | ... |
src/store/modules/userRecommand.js
... | ... | @@ -23,7 +23,8 @@ const actions = { |
23 | 23 | url: recommandList, |
24 | 24 | data: param, |
25 | 25 | success: (res) => { |
26 | - console.log(res.data.data) | |
26 | + console.log('ReccomandList请求结果',res.data) | |
27 | + // console.log(res.data.data) | |
27 | 28 | // const Res={...res.data.data.list,...data.data.list} |
28 | 29 | const data = res.data.data |
29 | 30 | for (let index = 0; index < data.length; index++) { | ... | ... |