Skip to content

Commit 5b8fce3

Browse files
author
fanny
committed
city--->msite
1 parent b806e66 commit 5b8fce3

19 files changed

+984
-24
lines changed

src/NOTE.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,8 @@ Visual 相关属性包括:background / color / transition / list-style 等
8383
### 规范———————
8484
变量用驼峰
8585
数据库字段 下划线
86-
css样式 下划线
86+
css样式 下划线
87+
88+
#### html5标签
89+
https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/figure
90+
https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/hgroup

src/components/common/loading.vue

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@
99
</template>
1010

1111
<script>
12-
export default {
13-
data () {
14-
return {
15-
positionY: 0,
16-
timer: null
17-
}
18-
},
19-
mounted () {
20-
this.timer = setInterval(() => {
21-
this.positionY ++
22-
}, 600)
23-
},
24-
beforeDestory () {
25-
clearInterval(this.timer)
12+
export default {
13+
data () {
14+
return {
15+
positionY: 0,
16+
timer: null
2617
}
18+
},
19+
mounted () {
20+
this.timer = setInterval(() => {
21+
this.positionY++
22+
}, 600)
23+
},
24+
beforeDestory () {
25+
clearInterval(this.timer)
2726
}
27+
}
2828
</script>
2929
<style lang="scss">
3030
@import '../../style/loading.scss';

src/components/common/mixin.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { getStyle } from '../../config/mUtils'
2+
3+
export const loadMore = {
4+
directives: {
5+
'load-more': {
6+
bind: (el, binding) => {
7+
let windowHeight = window.screen.height
8+
let height
9+
let setTop
10+
let paddingBottom
11+
let marginBottom
12+
let requestFram
13+
let oldScrollTop
14+
let scrollEl
15+
let heightEl
16+
let scrollType = el.attributes.type && el.attributes.type.value
17+
let scrollReduce = 2
18+
if (scrollType === 2) {
19+
scrollEl = el
20+
heightEl = el.children[0]
21+
} else {
22+
scrollEl = document.body
23+
heightEl = el
24+
}
25+
26+
el.addEventListener('touchstart', () => {
27+
let moveHeight = heightEl.clientHeight
28+
if (scrollType === 2) {
29+
height = moveHeight
30+
}
31+
setTop = el.offsetTop
32+
paddingBottom = getStyle(el, 'paddingBottom')
33+
marginBottom = getStyle(el, 'marginBottom')
34+
}, false)
35+
36+
el.addEventListener('touchmove', () => {
37+
loadMore()
38+
}, false)
39+
40+
el.addEventListener('touchend', () => {
41+
oldScrollTop = scrollEl.scrollTop || document.documentElement.scrollTop || window.pageYOffset
42+
moveEnd()
43+
}, false)
44+
45+
const moveEnd = () => {
46+
requestFram = requestAnimationFrame(() => {
47+
let tempTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop
48+
if (tempTop !== oldScrollTop) {
49+
oldScrollTop = tempTop
50+
moveEnd()
51+
} else {
52+
cancelAnimationFrame(requestFram)
53+
height = heightEl.clientHeight
54+
loadMore()
55+
}
56+
})
57+
}
58+
const loadMore = () => {
59+
let tempTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop
60+
if (tempTop + windowHeight >= height + setTop + paddingBottom + marginBottom - scrollReduce) {
61+
binding.value()
62+
}
63+
}
64+
}
65+
}
66+
}
67+
}
68+
69+
export const getImgPath = {
70+
methods: {
71+
// 传递过来的图片地址需要处理后才能正常使用
72+
getImgPath (path) {
73+
let suffix
74+
if (!path) {
75+
return '//elm.cangdu.org/img/default.jpg'
76+
}
77+
if (path.indexOf('jpeg') !== -1) {
78+
suffix = '.jpeg'
79+
} else {
80+
suffix = '.png'
81+
}
82+
let url = '/' + path.substr(0, 1) + '/' + path.substr(1, 2) + '/' + path.substr(3) + suffix
83+
return 'https://fuss10.elemecdn.com' + url
84+
}
85+
}
86+
}

src/components/common/ratingStar.vue

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<template>
2+
<div class="rating_container">
3+
<section class="star_container">
4+
<svg class="grey_fill" v-for="num in 5" :key="num">
5+
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#star"></use>
6+
</svg>
7+
</section>
8+
<div class="star_overflow" :style="'width:' + rating * 2 / 5 + 'rem'">
9+
<section class="star_container">
10+
<svg class="orange_fill" v-for="num in 5" :key="num">
11+
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#star"></use>
12+
</svg>
13+
</section>
14+
</div>
15+
</div>
16+
</template>
17+
<script>
18+
export default {
19+
props: ['rating']
20+
}
21+
</script>
22+
<style lang="scss">
23+
@import '../../style/rating.scss';
24+
</style>

src/components/common/shoplist.vue

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
<template>
2+
<div class="shoplist_container">
3+
<ul v-load-more="loadmore" v-if="shopListArr.length" type="1">
4+
<router-link v-for="item in shopListArr" tag="li" :key="item.id" class="shop_li" :to="{path: 'shop', query: {geohash: geohash, id: item.id}}">
5+
<section>
6+
<img :src="imageBaseUrl + item.image_path" class="shop_img">
7+
</section>
8+
<hgroup class="shop_right">
9+
<headedr class="shop_detail_header"><!--preminum额外费用-->
10+
<h4 :class="item.is_premium ? 'preminum' : ''" class="shop_title ellipsis">{{item.name}}</h4>
11+
<ul class="shop_detal_ul">
12+
<li v-for="item in item.supports" :key="item.id" class="supports">{{item.icon_name}}</li>
13+
</ul>
14+
</headedr>
15+
<h5 class="rating_order_num">
16+
<section class="rating_order_num_left">
17+
<section class="rating_section">
18+
<rating-star :rating="item.rating"></rating-star>
19+
<span class="rating_num">{{item.rating}}</span>
20+
</section>
21+
<section class="order_section">
22+
月售{{item.recent_order_num}}单
23+
</section>
24+
</section>
25+
<section class="rating_order_num_right">
26+
<span class="delivery_style delivery_left" v-if="item.delivery_mode">{{item.delivery_mode.text}}</span>
27+
<span class="delivery_style delivery_right" v-if="zhunshi(item.supports)">准时达</span>
28+
</section>
29+
</h5>
30+
<h5 class="fee_distance">
31+
<p class="fee">
32+
¥{{item.minimum_order_amount}}起送<span class="segmentation">/</span>{{item.piecewise_agent_fee.tips}}
33+
</p>
34+
<p class="distance_time">
35+
<span v-if="Number(item.distance)">{{item.distance > 1000 ? (item.distance/1000).toFixed(2) + 'km': item.distance + 'm'}}
36+
<span class="segemtation">/</span>
37+
</span>
38+
<span v-else>{{item.distance}}</span>
39+
<span class="segemtation">/</span>
40+
<span class="order_time">{{item.order_load_time}}</span>
41+
</p>
42+
</h5>
43+
</hgroup>
44+
</router-link>
45+
</ul>
46+
<ul v-else class="animation_opacity">
47+
<li class="list_back_li" v-for="item in 10" :key="item">
48+
<img :src="imageUrl" class="list_back_svg">
49+
</li>
50+
</ul>
51+
<p class="empty_data" v-if="touched">没有更多了</p>
52+
<aside class="return_top" @click="backTop" v-if="showBackStatus">
53+
<svg class="back_top_svg">
54+
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#backtop"></use>
55+
</svg>
56+
</aside>
57+
<div ref="abc" style="background-color: red;"></div>
58+
<transition name="loading">
59+
<loading v-show="showLoading"></loading>
60+
</transition>
61+
</div>
62+
</template>
63+
<script>
64+
import {mapState} from 'vuex'
65+
import {imgBaseUrl} from '@/config/env'
66+
import {showBack, animate} from '@/config/mUtils'
67+
import {loadMore, getImgPath} from './mixin'
68+
import loading from './loading'
69+
import ratingStar from './ratingStar'
70+
import urls from '../../config/urls'
71+
export default {
72+
data () {
73+
return {
74+
imageUrl: '../images/shopback.svg',
75+
offset: 0, // 批次加载店铺列表,每次加载20个 limit = 20
76+
shopListArr: [], // 店铺列表数据
77+
preventRepeatReuqest: false, // 到达底部加载数据,防止重复加载
78+
showBackStatus: false, // 显示返回顶部按钮
79+
showLoading: true, // 显示加载动画
80+
touchend: false, // 没有更多数据
81+
imgBaseUrl: imgBaseUrl
82+
}
83+
},
84+
mounted () {
85+
this.initData()
86+
},
87+
components: {
88+
loading,
89+
ratingStar
90+
},
91+
props: ['restaurantCategoryId', 'restaurantCategoryIds', 'sortByType', 'deliveryMode', 'supportIds', 'confirmSelect', 'geohash'],
92+
mixins: [loadMore, getImgPath],
93+
computed: {
94+
...mapState([
95+
'latitude', 'longitude'
96+
])
97+
},
98+
methods: {
99+
async initData () {
100+
let res = await this.getShopList((this.latitude, this.longitude, this.offset, this.restaurantCategoryId))
101+
this.shopListArr = [...res]
102+
if (res.length < 20) {
103+
this.touchend = true
104+
}
105+
this.hideLoading()
106+
// 开始监听scrollTop的值,达到一定程度后显示返回顶部按钮
107+
showBack(callbackStatus => {
108+
this.showBackStatus = callbackStatus
109+
})
110+
},
111+
getShopList (latitude, longitude, offset, restaurantCategoryId = '', restaurantCategoryIds = '', orderBy = '', deliveryMode = '', supportIds = []) {
112+
let supportStr = ''
113+
supportIds.forEach(item => {
114+
if (item.status) {
115+
supportStr += '&support_ids[]=' + item.id
116+
}
117+
})
118+
let query = '?latitude=' + latitude + '&longitude=' + longitude + '&offset=' + offset + '&limit=20' + '&restaurant_category_id=' + restaurantCategoryId + 'restaurant_category_ids[]' + restaurantCategoryIds
119+
query += '&order_by=' + orderBy + '&delivery_mode[]=' + deliveryMode + supportStr
120+
this.$axios.get(urls.getShopList + query).then((res) => {
121+
return res
122+
})
123+
},
124+
async loadMore () {
125+
if (this.touchend) {
126+
return
127+
}
128+
// 防止重复请求
129+
if (this.preventRepeatReuqest) {
130+
return
131+
}
132+
this.showLoading = true
133+
this.preventRepeatReuqest = true
134+
// 数据的定位加20位
135+
this.offset += 20
136+
let res = await this.getShopList(this.latitude, this.longitude, this.offset, this.restaurantCategoryId)
137+
this.hideLoading()
138+
this.shopListArr = [...this.shopListArr, ...res]
139+
// 当获取数据小于20,说明没有更多数据,不需要再次请求数据
140+
if (res.length < 20) {
141+
this.touchend = true
142+
return
143+
}
144+
this.preventRepeatReuqest = false
145+
},
146+
// 返回顶部
147+
backTop () {
148+
animate(document.body, {scrollTop: '0'}, 400, 'ease-out')
149+
},
150+
// 监听父级传来的数据发生变化时,触发此函数重新根据属性值获取数据
151+
async listenPropChange () {
152+
this.showLoading = true
153+
this.offset = 0
154+
let res = await this.getShopList(this.latitude, this.longitude, this.offset, '', this.restaurantCategoryIds, this.sortByType, this.deliveryMode, this.supportIds)
155+
this.hideLoading()
156+
// 考虑到本地模拟数据是引用类型,所以返回一个新的数组
157+
this.shopListArr = [...res]
158+
},
159+
// 开发环境与编译环境loading隐藏方式不同
160+
hideLoading () {
161+
this.showLoading = false
162+
},
163+
zhunshi (supports) {
164+
let zhunStatus
165+
if ((supports instanceof Array) && supports.length) {
166+
supports.forEach(item => {
167+
if (item.icon_name === '') {
168+
zhunStatus = true
169+
}
170+
})
171+
} else {
172+
zhunStatus = false
173+
}
174+
return zhunStatus
175+
}
176+
},
177+
watch: {
178+
// 监听父级传来的restaurantCategoryIds,当值发生变化的时候重新获取餐馆数据,作用于排序和筛选
179+
restaurantCategoryIds: function (value) {
180+
this.listenPropChange()
181+
},
182+
// 监听父级传来的排序方式
183+
sortByType: function (value) {
184+
this.listenPropChange()
185+
},
186+
// 监听父级的确认按钮是否被点击,并且返回一个自定义事件通知父级,已经接收到数据,此时父级才可以清除已选状态
187+
confirmSelect: function (value) {
188+
this.listenPropChange()
189+
}
190+
}
191+
}
192+
</script>
193+
<style lang="scss">
194+
@import '../../style/shoplist.scss';
195+
</style>

0 commit comments

Comments
 (0)