Commit 96d13733 authored by lixy's avatar lixy

旅游、车型详情定位

parent 1cbd37e1
...@@ -79,6 +79,7 @@ input[disabled] { ...@@ -79,6 +79,7 @@ input[disabled] {
background: #fff; background: #fff;
color: #333; color: #333;
width:100%; width:100%;
border-bottom: 1px solid #dfdfdf;
} }
.ellipsis { .ellipsis {
overflow: hidden;white-space: nowrap;text-overflow:ellipsis;word-wrap:break-word;word-break:break-all; overflow: hidden;white-space: nowrap;text-overflow:ellipsis;word-wrap:break-word;word-break:break-all;
...@@ -201,4 +202,5 @@ img { ...@@ -201,4 +202,5 @@ img {
} }
.bt-line{ .bt-line{
border-bottom: 1px solid #dfdfdf; border-bottom: 1px solid #dfdfdf;
padding-bottom: 17px;
} }
...@@ -172,7 +172,7 @@ ...@@ -172,7 +172,7 @@
transform: translateY(-50%); transform: translateY(-50%);
} }
.banner{ .banner{
height:px2rem(500px); height:250px;
overflow: hidden; overflow: hidden;
} }
img{ img{
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
@next="next" @next="next"
@change="changeBanner" @change="changeBanner"
@click="bannerClick"/> @click="bannerClick"/>
<div class="main-padding">{{ totalCount }}个活动</div>
<ul <ul
v-if="dataDetail.length" v-if="dataDetail.length"
id="scroll-area" id="scroll-area"
...@@ -49,7 +48,7 @@ ...@@ -49,7 +48,7 @@
class="loading">加载中……</p> class="loading">加载中……</p>
<p <p
v-if="touchend" v-if="touchend"
class="empty_data">——没有更多了——</p> class="empty_data">——{{ totalCount }}个活动——</p>
<go-top/> <go-top/>
<Footer v-if="touchend"/> <Footer v-if="touchend"/>
</div> </div>
......
<template>
<div class="cartcontrol">
<svg
v-show="food.count>0"
class="inner"
fill="rgb(35, 149, 255)"
@click.stop.prevent="decreaseCart"><use xlink:href="#cart-minus"/></svg>
<div
v-show="food.count>0"
class="cart-count">{{ food.count }}</div>
<svg
width="24"
height="24"
fill="rgb(35, 149, 255)"
@click="addCart"><use xlink:href="#cart-add"/></svg>
</div>
</template>
<script>
import Vue from "vue";
export default {
props: ['food'],
methods: {
addCart(event) {
if (!this.food.count) {
Vue.set(this.food, "count", 1);
} else {
this.food.count++;
}
this.$emit("add", event.target);
},
decreaseCart(event) {
if (this.food.count) {
this.food.count--;
}
}
}
};
</script>
<style lang="scss">
.cartcontrol {
display: flex;
align-items: center;
.inner {
width: 24px;
height: 24px;
}
.cart-count {
display: inline-block;
vertical-align: top;
width: 25px;
text-align: center;
font-size: 15px;
color: #333;
}
.cart-add {
display: inline-block;
padding: 6px;
line-height: 24px;
font-size: 24px;
color: rgb(0, 160, 220);
}
}
</style>
<template>
<div class="goods-page">
<div class="menu-wrapper">
<ul>
<li
v-for="(item, index) in goods"
:key="index"
:class="{'current':currentIndex === index}"
class="menu-item"
@click="selectMenu(index,$event)">
<span class="text">
<!-- <span v-show="item.type>0" class="icon" :class="classMap[item.type]"></span> -->
{{ item.name }}
</span>
</li>
</ul>
</div>
<div class="foods-wrapper">
<ul>
<li
v-for="(item, index) in goods"
:key="index"
class="food-list food-list-hook">
<h1
:id="'a'+index"
class="title">{{ item.name }}</h1>
<ul>
<li
v-for="(food, index) in item.foods"
:key="index"
class="food-item border-1px">
<div class="icon">
<img :src="food.icon" >
</div>
<div class="content">
<h2 class="name">{{ food.name }}</h2>
<p class="desc">{{ food.description }}</p>
<div class="extra">
<span class="count">月售{{ food.sellCount }}</span><span>好评率{{ food.rating }}%</span>
</div>
<div class="price">
<span class="now"><b>{{ food.price }}</b></span>
<cartcontrol :food="food" />
</div>
</div>
</li>
</ul>
</li>
</ul>
</div>
<shopcart
ref="shopcart"
:select-foods="selectFoods"
:delivery-price="seller.deliveryPrice"
:min-price="seller.minPrice"/>
</div>
</template>
<script>
import shopcart from "./shopcart";
import cartcontrol from "./cartcontrol";
import * as shoppingApi from "~/assets/services/shopping";
export default {
components: {
shopcart,
cartcontrol
},
props: {
seller: {
default: {}
}
},
data() {
return {
goods: [],
listHeight: [],
scrollY: 0,
classMap: ["decrease", "discount", "special", "invoice", "guarantee"],
currentIndex: 0,
isScroll: false
};
},
computed: {
selectFoods() {
let foods = [];
this.goods.forEach(good => {
good.foods.forEach(food => {
if (food.count) {
foods.push(food);
}
});
});
return foods;
}
},
created() {},
mounted() {
shoppingApi.goods().then(res => {
if (res.code === 0) {
this.goods = res.data;
}
});
//菜品滚动选择类目
document.querySelector(".foods-wrapper").addEventListener(
"scroll",
this.throttle(() => {
// 防止手动选择的时候误操作
if (this.isScroll) {
return;
}
this.goods.map((item, index) => {
const rect_top = document
.querySelector("#a" + index)
.getBoundingClientRect().top;
const container_top = document
.querySelector(".foods-wrapper")
.getBoundingClientRect().top;
if (
rect_top - container_top < 100 &&
rect_top - container_top > -100
) {
this.currentIndex = index;
}
});
}, 50)
);
},
methods: {
selectMenu(index) {
if (index === this.currentIndex) {
return;
}
this.currentIndex = index;
this.animateScroll("#a" + index, ".foods-wrapper", 50);
},
// 平滑滚动方法
animateScroll(element, container, speed) {
this.isScroll = true;
let rect =
document.querySelector(element).getBoundingClientRect().top -
document.querySelector(container).getBoundingClientRect().top;
//获取元素相对窗口的top值,此处应加上窗口本身的偏移
let top = rect + document.querySelector(container).scrollTop;
let currentTop = 0;
let requestId;
//采用requestAnimationFrame,平滑动画
const step = timestamp => {
if (currentTop <= top) {
document.querySelector(container).scrollTo(0, currentTop);
requestId = window.requestAnimationFrame(step);
} else {
window.cancelAnimationFrame(requestId);
this.isScroll = false;
}
currentTop += speed;
};
window.requestAnimationFrame(step);
},
// 函数防抖
throttle(method, delay) {
var timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
method.apply(this, arguments);
}, delay);
};
}
},
};
</script>
<style lang="scss">
@import "../../../../assets/styles/mixin";
.goods-page {
display: flex;
background: #fff;
width: 100%;
.menu-wrapper {
flex: 0 0 80px;
width: 80px;
height: calc(100vh - 38px);
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
background: #f8f8f8;
.menu-item {
display: table;
height: 54px;
padding: 0 12px;
line-height: 14px;
&.current {
position: relative;
margin-top: -1px;
z-index: 10;
background: #ffffff;
.text {
color: #333;
}
}
.icon {
display: inline-block;
vertical-align: middle;
width: 12px;
height: 12px;
margin-right: 2px;
background-size: 12px 12px;
background-repeat: no-repeat;
// &.decrease {
// bg-image('decrease_3');
// }
// &.discount {
// bg-image('discount_3');
// }
// &.guarantee {
// bg-image('guarantee_3');
// }
// &.invoice {
// bg-image('invoice_3');
// }
// &.special {
// bg-image('special_3');
// }
}
.text {
display: table-cell;
width: 56px;
vertical-align: middle;
font-size: 12px;
position: relative;
color: #666;
}
}
}
.foods-wrapper {
width: calc(100vw - 80px);
height: calc(100vh - 38px);
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding-bottom: 60px;
.title {
padding-left: 14px;
height: 30px;
line-height: 30px;
font-size: 12px;
color: #666;
}
.food-item {
display: flex;
margin: 10px;
padding-bottom: 18px;
position: relative;
&:after {
display: block;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
content: " ";
}
&:last-child {
margin-bottom: 0;
&:after {
display: none;
}
}
.icon {
flex: 0 0 80px;
margin-right: 10px;
}
.content {
flex: 1;
position: relative;
.name {
margin: 2px 0 8px 0px;
height: 14px;
line-height: 14px;
font-size: 14px;
color: rgb(7, 17, 27);
}
.desc,
.extra {
line-height: 10px;
font-size: 12px;
color: rgb(147, 153, 159);
transform: scale(0.9) translateX(-6%);
}
.desc {
margin-bottom: 8px;
line-height: 12px;
max-width: px2rem(350px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.extra {
.count {
margin-right: 12px;
}
}
.price {
width: 100%;
font-weight: 700;
position: absolute;
bottom: 0;
@include fj(space-between);
.now {
margin-right: 8px;
font-size: 14px;
color: rgb(255, 83, 57);
}
.old {
text-decoration: line-through;
font-size: 10px;
color: rgb(147, 153, 159);
}
b {
font-weight: normal;
font-size: 18px;
}
}
}
}
}
}
</style>
This diff is collapsed.
<template>
<div class="shop-header">
<div class="head">
<nav :style="`background-image: url('${banner}');`">
<i
class="mintui mintui-back"
@click="$router.go(-1);"/>
<img
:src="seller.avatar"
class="shop-logo">
</nav>
</div>
</div>
</template>
<script>
import config from "~/config";
export default {
props: {
seller: {
default: {}
}
},
computed: {
banner: function () {
return config.IMG_URL + this.seller.banner;
}
}
};
</script>
<style lang="scss">
@import "../../../assets/styles/mixin";
.shop-header {
background: #fff;
.head {
height: px2rem(200px);
nav {
height: px2rem(200px);
background-position: 50%;
background-size: cover;
background-repeat: no-repeat;
padding: px2rem(10px);
position: relative;
.mintui-back {
font-size: px2rem(46px);
color: #fff;
}
.shop-logo {
width: px2rem(150px);
height: px2rem(150px);
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
}
}
}
.content {
font-size: px2rem(24px);
margin-top: px2rem(50px);
text-align: center;
h2 {
font-size: px2rem(40px);
}
.info {
color: #666;
span {
margin: 0 px2rem(10px);
}
}
}
.foot {
padding: 0 px2rem(70px);
margin-top: 10px;
font-size: px2rem(24px);
.mint-badge {
transform: scale(0.8) translateX(-10%);
border-radius: 1px;
}
.announcement {
display: inline-block;
width: 100%;
color: #666;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
</style>
<template>
<div class="ratings-page">
<div class="ratings-content">
<div class="overview">
<div class="overview-left">
<h1 class="score">{{ seller.score }}</h1>
<div class="title">
商家评分
<rating-star :rating="seller.score" />
</div>
</div>
<div class="overview-right">
<div class="score-wrapper">
<span class="title">味道</span>
<p class="score">{{ seller.serviceScore }}</p>
</div>
<div class="score-wrapper">
<span class="title">包装</span>
<p class="score">{{ seller.foodScore }}</p>
</div>
<div class="score-wrapper">
<span class="title">配送</span>
<p class="score">{{ seller.deliveryTime }}</p>
</div>
</div>
</div>
<div class="placeholder"/>
<ratingselect
:select-type="selectType"
:only-content="onlyContent"
:ratings="ratings"
@select="selectRating"
@toggle="toggleContent" />
<div class="rating-wrapper">
<ul>
<li
v-for="(rating, index) in ratings"
v-show="needShow(rating.rateType, rating.text)"
:key="index"
class="rating-item">
<div class="avatar">
<span :style="'background-position: 0 '+rating.avatar"/>
</div>
<div class="content">
<h1 class="name">{{ rating.username }}</h1>
<div class="star-wrapper">
<rating-star
:size="24"
:rating="rating.score" />
</div>
<p class="text">{{ rating.text }}</p>
<div
v-show="rating.recommend && rating.recommend.length"
class="recommend">
<span
v-for="(item, index) in rating.recommend"
:key="index"
class="item">{{ item }}</span>
</div>
<div class="time">
{{ rating.rateTime }}
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import ratingStar from "~/components/ratingStar";
import ratingselect from "./ratingselect";
import * as shoppingApi from "~/assets/services/shopping";
import moment from "moment";
export default {
components: {
ratingStar,
ratingselect
},
props: {
seller: {
default: {}
}
},
data() {
return {
ratings: [],
selectType: 2,
onlyContent: true
};
},
mounted() {
shoppingApi.ratings().then(res => {
if (res.code === 0) {
this.ratings = res.data;
this.ratings.map(item => {
item.rateTime = moment(item.rateTime).format("YYYY/M/D");
});
}
});
},
methods: {
needShow(type, text) {
if (this.onlyContent && !text) {
return false;
}
if (this.selectType === 2) {
return true;
} else {
return type === this.selectType;
}
},
selectRating(type) {
this.selectType = type;
},
toggleContent() {
this.onlyContent = !this.onlyContent;
}
},
};
</script>
<style lang="scss">
@import "../../../../assets/styles/mixin";
.ratings-page {
background: #fff;
.placeholder {
height: px2rem(20px);
background: #f5f5f5;
}
.overview {
display: flex;
padding: 18px 0;
.overview-left {
width: px2rem(340px);
@include fj(center);
align-items: center;
text-align: center;
.score {
font-size: px2rem(80px);
margin-right: px2rem(20px);
color: #ff6000;
font-weight: 400;
}
.title {
font-size: 12px;
}
}
.overview-right {
flex: 1;
@include fj(space-around);
align-items: center;
text-align: center;
color: #666;
.score-wrapper {
.title {
display: inline-block;
}
.score {
font-size: px2rem(40px);
}
}
}
}
.rating-wrapper {
padding: 0 18px;
.rating-item {
display: flex;
padding: 18px 0;
.avatar {
flex: 0 0 28px;
width: 28px;
margin-right: 12px;
span {
border-radius: 50%;
display: inline-block;
width: 30px;
height: 30px;
background: url("../../../../assets/images/sprite-avatar.png");
background-position: 0 0;
background-size: 30px;
}
}
.content {
position: relative;
flex: 1;
font-size: px2rem(28px);
.name {
margin-bottom: 4px;
line-height: 12px;
color: rgb(7, 17, 27);
}
.star-wrapper {
margin-bottom: 6px;
.star {
display: inline-block;
margin-right: 6px;
vertical-align: top;
}
}
.text {
margin: 8px 0;
line-height: 18px;
color: rgb(7, 17, 27);
}
.recommend {
line-height: 16px;
font-size: 0;
.icon-thumb_up,
.item {
display: inline-block;
margin: 0 8px 4px 0;
font-size: 9px;
}
.icon-thumb_up {
color: rgb(0, 160, 220);
}
.item {
padding: 0 6px;
border: 1px solid rgba(7, 17, 27, 0.1);
border-radius: 1px;
color: rgb(147, 153, 159);
background: #fff;
}
}
.time {
position: absolute;
top: 0;
right: 0;
line-height: 12px;
font-size: 10px;
color: rgb(147, 153, 159);
}
}
}
}
}
</style>
<template>
<div class="ratingselect">
<div class="rating-type border-1px">
<span
:class="{'active':selectType===2}"
class="block positive"
@click="select(2,$event)">{{ desc.all }}
<span class="count">{{ ratings.length }}</span>
</span>
<span
:class="{'active':selectType===0}"
class="block positive"
@click="select(0,$event)">{{ desc.positive }}<span
class="count">{{ positives.length }}</span></span>
<span
:class="{'active':selectType===1}"
class="block negative"
@click="select(1,$event)">{{ desc.negative }}<span
class="count">{{ negatives.length }}</span></span>
</div>
<div
:class="{'on':onlyContent}"
class="switch"
@click="toggleContent">
<!-- <span class="icon-check_circle"></span> -->
<svg
width="12"
height="12"
class="check">
<use xlink:href="#select"/>
</svg>
<span class="text">只看有内容的评价</span>
</div>
</div>
</template>
<script>
export default {
props: {
ratings: {
type: Array,
default () {
return [];
}
},
selectType: {
type: Number,
default: 2
},
onlyContent: {
type: Boolean,
default: false
},
desc: {
type: Object,
default () {
return {
all: "全部",
positive: "满意",
negative: "不满意"
};
}
}
},
computed: {
positives() {
return this.ratings.filter(rating => {
return rating.rateType === 0;
});
},
negatives() {
return this.ratings.filter(rating => {
return rating.rateType === 1;
});
}
},
methods: {
select(type, event) {
this.$emit("select", type);
},
toggleContent(event) {
this.$emit("toggle");
}
}
};
</script>
<style lang="scss">
.ratingselect {
.rating-type {
padding: 18px 0;
margin: 0 18px;
font-size: 0;
.block {
display: inline-block;
padding: 8px 12px;
margin-right: 8px;
line-height: 16px;
border-radius: 1px;
font-size: 12px;
color: rgb(77, 85, 93);
&.active {
color: #fff;
}
.count {
margin-left: 2px;
font-size: 12px;
}
&.positive {
background: rgba(0, 160, 220, 0.2);
&.active {
background: rgb(0, 160, 220);
}
}
&.negative {
background: rgba(77, 85, 93, 0.2);
&.active {
background: rgb(77, 85, 93);
}
}
}
}
.switch {
display: flex;
align-items: center;
padding: 12px 18px;
line-height: 24px;
border-bottom: 1px solid rgba(7, 17, 27, 0.1);
color: rgb(147, 153, 159);
font-size: 0;
svg {
margin-right: 5px;
fill: #e8e8e8;
}
&.on {
.check {
fill: #76d572;
}
}
.icon-check_circle {
display: inline-block;
vertical-align: top;
margin-right: 4px;
font-size: 24px;
}
.text {
display: inline-block;
vertical-align: top;
font-size: 12px;
}
}
}
</style>
<template>
<div class="seller-page">
<div class="logo">
<img
:src="banner"
alt="">
</div>
<h2>{{ seller.name }}</h2>
<p>{{ seller.bulletin }}</p>
<a
:href="seller.brandstory"
class="brandstory">查看品牌故事</a>
<div class="placeholder"/>
<h2>配送信息</h2>
<p>由蜂鸟快送提供配送,约{{ seller.deliveryTime }}分钟送达,距离2.1km</p>
<p>配送费¥{{ seller.deliveryPrice }}</p>
</div>
</template>
<script>
import config from "~/config";
export default {
props: {
seller: {
default: {}
}
},
computed: {
banner: function () {
return config.IMG_URL + this.seller.banner;
}
}
};
</script>
<style lang="scss">
@import "../../../assets/styles/mixin";
.seller-page {
background: #fff;
padding-bottom: px2rem(30px);
.logo {
padding: px2rem(30px) px2rem(30px) 0 px2rem(30px);
}
h2 {
font-size: px2rem(32px);
margin-top: px2rem(40px);
padding: 0 px2rem(30px) px2rem(20px) px2rem(30px);
}
p {
padding: 0 px2rem(30px);
color: #666;
font-size: px2rem(26px);
line-height: 1.5;
}
.brandstory {
display: block;
line-height: px2rem(100px);
margin-top: px2rem(50px);
color: #666;
font-size: px2rem(28px);
text-align: center;
}
.placeholder {
height: px2rem(20px);
background: #f5f5f5;
}
}
</style>
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
@next="next" @next="next"
@change="changeBanner" @change="changeBanner"
@click="bannerClick"/> @click="bannerClick"/>
<div class="main-padding">{{ totalCount }}个营地</div>
<ul <ul
v-if="dataDetail.length" v-if="dataDetail.length"
id="scroll-area" id="scroll-area"
...@@ -40,7 +39,7 @@ ...@@ -40,7 +39,7 @@
class="loading">加载中……</p> class="loading">加载中……</p>
<p <p
v-if="touchend" v-if="touchend"
class="empty_data">——没有更多了——</p> class="empty_data">——{{ totalCount }}个房车营地——</p>
<go-top/> <go-top/>
<Footer v-if="touchend"/> <Footer v-if="touchend"/>
</div> </div>
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
class="loading">加载中……</p> class="loading">加载中……</p>
<p <p
v-if="touchend" v-if="touchend"
class="empty_data">——没有更多了——</p> class="empty_data">——{{ totalCount }}篇新闻资讯——</p>
<go-top/> <go-top/>
<Footer v-if="touchend"/> <Footer v-if="touchend"/>
</div> </div>
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
@next="next" @next="next"
@change="changeBanner" @change="changeBanner"
@click="bannerClick"/> @click="bannerClick"/>
<div class="main-padding total-div">{{ totalCount }}个旅行路线</div>
<ul <ul
v-if="dataDetail.length" v-if="dataDetail.length"
id="scroll-area" id="scroll-area"
...@@ -38,7 +37,7 @@ ...@@ -38,7 +37,7 @@
class="loading">加载中……</p> class="loading">加载中……</p>
<p <p
v-if="touchend" v-if="touchend"
class="empty_data">——没有更多了——</p> class="empty_data">——{{ totalCount }}个旅行路线——</p>
<go-top/> <go-top/>
<Footer v-if="touchend"/> <Footer v-if="touchend"/>
</div> </div>
......
<template>
<div class="cartcontrol">
<svg
v-show="food.count>0"
class="inner"
fill="rgb(35, 149, 255)"
@click.stop.prevent="decreaseCart"><use xlink:href="#cart-minus"/></svg>
<div
v-show="food.count>0"
class="cart-count">{{ food.count }}</div>
<svg
width="24"
height="24"
fill="rgb(35, 149, 255)"
@click="addCart"><use xlink:href="#cart-add"/></svg>
</div>
</template>
<script>
import Vue from "vue";
export default {
props: ['food'],
methods: {
addCart(event) {
if (!this.food.count) {
Vue.set(this.food, "count", 1);
} else {
this.food.count++;
}
this.$emit("add", event.target);
},
decreaseCart(event) {
if (this.food.count) {
this.food.count--;
}
}
}
};
</script>
<style lang="scss">
.cartcontrol {
display: flex;
align-items: center;
.inner {
width: 24px;
height: 24px;
}
.cart-count {
display: inline-block;
vertical-align: top;
width: 25px;
text-align: center;
font-size: 15px;
color: #333;
}
.cart-add {
display: inline-block;
padding: 6px;
line-height: 24px;
font-size: 24px;
color: rgb(0, 160, 220);
}
}
</style>
<template>
<div class="goods-page">
<div class="menu-wrapper">
<ul>
<li
v-for="(item, index) in goods"
:key="index"
:class="{'current':currentIndex === index}"
class="menu-item"
@click="selectMenu(index,$event)">
<span class="text">
<!-- <span v-show="item.type>0" class="icon" :class="classMap[item.type]"></span> -->
{{ item.name }}
</span>
</li>
</ul>
</div>
<div class="foods-wrapper">
<ul>
<li
v-for="(item, index) in goods"
:key="index"
class="food-list food-list-hook">
<h1
:id="'a'+index"
class="title">{{ item.name }}</h1>
<ul>
<li
v-for="(food, index) in item.foods"
:key="index"
class="food-item border-1px">
<div class="icon">
<img :src="food.icon" >
</div>
<div class="content">
<h2 class="name">{{ food.name }}</h2>
<p class="desc">{{ food.description }}</p>
<div class="extra">
<span class="count">月售{{ food.sellCount }}</span><span>好评率{{ food.rating }}%</span>
</div>
<div class="price">
<span class="now"><b>{{ food.price }}</b></span>
<cartcontrol :food="food" />
</div>
</div>
</li>
</ul>
</li>
</ul>
</div>
<shopcart
ref="shopcart"
:select-foods="selectFoods"
:delivery-price="seller.deliveryPrice"
:min-price="seller.minPrice"/>
</div>
</template>
<script>
import shopcart from "./shopcart";
import cartcontrol from "./cartcontrol";
import * as shoppingApi from "~/assets/services/shopping";
export default {
components: {
shopcart,
cartcontrol
},
props: {
seller: {
default: {}
}
},
data() {
return {
goods: [],
listHeight: [],
scrollY: 0,
classMap: ["decrease", "discount", "special", "invoice", "guarantee"],
currentIndex: 0,
isScroll: false
};
},
computed: {
selectFoods() {
let foods = [];
this.goods.forEach(good => {
good.foods.forEach(food => {
if (food.count) {
foods.push(food);
}
});
});
return foods;
}
},
created() {},
mounted() {
shoppingApi.goods().then(res => {
if (res.code === 0) {
this.goods = res.data;
}
});
//菜品滚动选择类目
document.querySelector(".foods-wrapper").addEventListener(
"scroll",
this.throttle(() => {
// 防止手动选择的时候误操作
if (this.isScroll) {
return;
}
this.goods.map((item, index) => {
const rect_top = document
.querySelector("#a" + index)
.getBoundingClientRect().top;
const container_top = document
.querySelector(".foods-wrapper")
.getBoundingClientRect().top;
if (
rect_top - container_top < 100 &&
rect_top - container_top > -100
) {
this.currentIndex = index;
}
});
}, 50)
);
},
methods: {
selectMenu(index) {
if (index === this.currentIndex) {
return;
}
this.currentIndex = index;
this.animateScroll("#a" + index, ".foods-wrapper", 50);
},
// 平滑滚动方法
animateScroll(element, container, speed) {
this.isScroll = true;
let rect =
document.querySelector(element).getBoundingClientRect().top -
document.querySelector(container).getBoundingClientRect().top;
//获取元素相对窗口的top值,此处应加上窗口本身的偏移
let top = rect + document.querySelector(container).scrollTop;
let currentTop = 0;
let requestId;
//采用requestAnimationFrame,平滑动画
const step = timestamp => {
if (currentTop <= top) {
document.querySelector(container).scrollTo(0, currentTop);
requestId = window.requestAnimationFrame(step);
} else {
window.cancelAnimationFrame(requestId);
this.isScroll = false;
}
currentTop += speed;
};
window.requestAnimationFrame(step);
},
// 函数防抖
throttle(method, delay) {
var timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
method.apply(this, arguments);
}, delay);
};
}
},
};
</script>
<style lang="scss">
@import "../../../../assets/styles/mixin";
.goods-page {
display: flex;
background: #fff;
width: 100%;
.menu-wrapper {
flex: 0 0 80px;
width: 80px;
height: calc(100vh - 38px);
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
background: #f8f8f8;
.menu-item {
display: table;
height: 54px;
padding: 0 12px;
line-height: 14px;
&.current {
position: relative;
margin-top: -1px;
z-index: 10;
background: #ffffff;
.text {
color: #333;
}
}
.icon {
display: inline-block;
vertical-align: middle;
width: 12px;
height: 12px;
margin-right: 2px;
background-size: 12px 12px;
background-repeat: no-repeat;
// &.decrease {
// bg-image('decrease_3');
// }
// &.discount {
// bg-image('discount_3');
// }
// &.guarantee {
// bg-image('guarantee_3');
// }
// &.invoice {
// bg-image('invoice_3');
// }
// &.special {
// bg-image('special_3');
// }
}
.text {
display: table-cell;
width: 56px;
vertical-align: middle;
font-size: 12px;
position: relative;
color: #666;
}
}
}
.foods-wrapper {
width: calc(100vw - 80px);
height: calc(100vh - 38px);
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding-bottom: 60px;
.title {
padding-left: 14px;
height: 30px;
line-height: 30px;
font-size: 12px;
color: #666;
}
.food-item {
display: flex;
margin: 10px;
padding-bottom: 18px;
position: relative;
&:after {
display: block;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
content: " ";
}
&:last-child {
margin-bottom: 0;
&:after {
display: none;
}
}
.icon {
flex: 0 0 80px;
margin-right: 10px;
}
.content {
flex: 1;
position: relative;
.name {
margin: 2px 0 8px 0px;
height: 14px;
line-height: 14px;
font-size: 14px;
color: rgb(7, 17, 27);
}
.desc,
.extra {
line-height: 10px;
font-size: 12px;
color: rgb(147, 153, 159);
transform: scale(0.9) translateX(-6%);
}
.desc {
margin-bottom: 8px;
line-height: 12px;
max-width: px2rem(350px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.extra {
.count {
margin-right: 12px;
}
}
.price {
width: 100%;
font-weight: 700;
position: absolute;
bottom: 0;
@include fj(space-between);
.now {
margin-right: 8px;
font-size: 14px;
color: rgb(255, 83, 57);
}
.old {
text-decoration: line-through;
font-size: 10px;
color: rgb(147, 153, 159);
}
b {
font-weight: normal;
font-size: 18px;
}
}
}
}
}
}
</style>
This diff is collapsed.
<template>
<div class="shop-header">
<div class="head">
<nav :style="`background-image: url('${banner}');`">
<i
class="mintui mintui-back"
@click="$router.go(-1);"/>
<img
:src="seller.avatar"
class="shop-logo">
</nav>
</div>
</div>
</template>
<script>
import config from "~/config";
export default {
props: {
seller: {
default: {}
}
},
computed: {
banner: function () {
return config.IMG_URL + this.seller.banner;
}
}
};
</script>
<style lang="scss">
@import "../../../assets/styles/mixin";
.shop-header {
background: #fff;
.head {
height: px2rem(200px);
nav {
height: px2rem(200px);
background-position: 50%;
background-size: cover;
background-repeat: no-repeat;
padding: px2rem(10px);
position: relative;
.mintui-back {
font-size: px2rem(46px);
color: #fff;
}
.shop-logo {
width: px2rem(150px);
height: px2rem(150px);
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
}
}
}
.content {
font-size: px2rem(24px);
margin-top: px2rem(50px);
text-align: center;
h2 {
font-size: px2rem(40px);
}
.info {
color: #666;
span {
margin: 0 px2rem(10px);
}
}
}
.foot {
padding: 0 px2rem(70px);
margin-top: 10px;
font-size: px2rem(24px);
.mint-badge {
transform: scale(0.8) translateX(-10%);
border-radius: 1px;
}
.announcement {
display: inline-block;
width: 100%;
color: #666;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
</style>
<template>
<div class="ratings-page">
<div class="ratings-content">
<div class="overview">
<div class="overview-left">
<h1 class="score">{{ seller.score }}</h1>
<div class="title">
商家评分
<rating-star :rating="seller.score" />
</div>
</div>
<div class="overview-right">
<div class="score-wrapper">
<span class="title">味道</span>
<p class="score">{{ seller.serviceScore }}</p>
</div>
<div class="score-wrapper">
<span class="title">包装</span>
<p class="score">{{ seller.foodScore }}</p>
</div>
<div class="score-wrapper">
<span class="title">配送</span>
<p class="score">{{ seller.deliveryTime }}</p>
</div>
</div>
</div>
<div class="placeholder"/>
<ratingselect
:select-type="selectType"
:only-content="onlyContent"
:ratings="ratings"
@select="selectRating"
@toggle="toggleContent" />
<div class="rating-wrapper">
<ul>
<li
v-for="(rating, index) in ratings"
v-show="needShow(rating.rateType, rating.text)"
:key="index"
class="rating-item">
<div class="avatar">
<span :style="'background-position: 0 '+rating.avatar"/>
</div>
<div class="content">
<h1 class="name">{{ rating.username }}</h1>
<div class="star-wrapper">
<rating-star
:size="24"
:rating="rating.score" />
</div>
<p class="text">{{ rating.text }}</p>
<div
v-show="rating.recommend && rating.recommend.length"
class="recommend">
<span
v-for="(item, index) in rating.recommend"
:key="index"
class="item">{{ item }}</span>
</div>
<div class="time">
{{ rating.rateTime }}
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import ratingStar from "~/components/ratingStar";
import ratingselect from "./ratingselect";
import * as shoppingApi from "~/assets/services/shopping";
import moment from "moment";
export default {
components: {
ratingStar,
ratingselect
},
props: {
seller: {
default: {}
}
},
data() {
return {
ratings: [],
selectType: 2,
onlyContent: true
};
},
mounted() {
shoppingApi.ratings().then(res => {
if (res.code === 0) {
this.ratings = res.data;
this.ratings.map(item => {
item.rateTime = moment(item.rateTime).format("YYYY/M/D");
});
}
});
},
methods: {
needShow(type, text) {
if (this.onlyContent && !text) {
return false;
}
if (this.selectType === 2) {
return true;
} else {
return type === this.selectType;
}
},
selectRating(type) {
this.selectType = type;
},
toggleContent() {
this.onlyContent = !this.onlyContent;
}
},
};
</script>
<style lang="scss">
@import "../../../../assets/styles/mixin";
.ratings-page {
background: #fff;
.placeholder {
height: px2rem(20px);
background: #f5f5f5;
}
.overview {
display: flex;
padding: 18px 0;
.overview-left {
width: px2rem(340px);
@include fj(center);
align-items: center;
text-align: center;
.score {
font-size: px2rem(80px);
margin-right: px2rem(20px);
color: #ff6000;
font-weight: 400;
}
.title {
font-size: 12px;
}
}
.overview-right {
flex: 1;
@include fj(space-around);
align-items: center;
text-align: center;
color: #666;
.score-wrapper {
.title {
display: inline-block;
}
.score {
font-size: px2rem(40px);
}
}
}
}
.rating-wrapper {
padding: 0 18px;
.rating-item {
display: flex;
padding: 18px 0;
.avatar {
flex: 0 0 28px;
width: 28px;
margin-right: 12px;
span {
border-radius: 50%;
display: inline-block;
width: 30px;
height: 30px;
background: url("../../../../assets/images/sprite-avatar.png");
background-position: 0 0;
background-size: 30px;
}
}
.content {
position: relative;
flex: 1;
font-size: px2rem(28px);
.name {
margin-bottom: 4px;
line-height: 12px;
color: rgb(7, 17, 27);
}
.star-wrapper {
margin-bottom: 6px;
.star {
display: inline-block;
margin-right: 6px;
vertical-align: top;
}
}
.text {
margin: 8px 0;
line-height: 18px;
color: rgb(7, 17, 27);
}
.recommend {
line-height: 16px;
font-size: 0;
.icon-thumb_up,
.item {
display: inline-block;
margin: 0 8px 4px 0;
font-size: 9px;
}
.icon-thumb_up {
color: rgb(0, 160, 220);
}
.item {
padding: 0 6px;
border: 1px solid rgba(7, 17, 27, 0.1);
border-radius: 1px;
color: rgb(147, 153, 159);
background: #fff;
}
}
.time {
position: absolute;
top: 0;
right: 0;
line-height: 12px;
font-size: 10px;
color: rgb(147, 153, 159);
}
}
}
}
}
</style>
<template>
<div class="ratingselect">
<div class="rating-type border-1px">
<span
:class="{'active':selectType===2}"
class="block positive"
@click="select(2,$event)">{{ desc.all }}
<span class="count">{{ ratings.length }}</span>
</span>
<span
:class="{'active':selectType===0}"
class="block positive"
@click="select(0,$event)">{{ desc.positive }}<span
class="count">{{ positives.length }}</span></span>
<span
:class="{'active':selectType===1}"
class="block negative"
@click="select(1,$event)">{{ desc.negative }}<span
class="count">{{ negatives.length }}</span></span>
</div>
<div
:class="{'on':onlyContent}"
class="switch"
@click="toggleContent">
<!-- <span class="icon-check_circle"></span> -->
<svg
width="12"
height="12"
class="check">
<use xlink:href="#select"/>
</svg>
<span class="text">只看有内容的评价</span>
</div>
</div>
</template>
<script>
export default {
props: {
ratings: {
type: Array,
default () {
return [];
}
},
selectType: {
type: Number,
default: 2
},
onlyContent: {
type: Boolean,
default: false
},
desc: {
type: Object,
default () {
return {
all: "全部",
positive: "满意",
negative: "不满意"
};
}
}
},
computed: {
positives() {
return this.ratings.filter(rating => {
return rating.rateType === 0;
});
},
negatives() {
return this.ratings.filter(rating => {
return rating.rateType === 1;
});
}
},
methods: {
select(type, event) {
this.$emit("select", type);
},
toggleContent(event) {
this.$emit("toggle");
}
}
};
</script>
<style lang="scss">
.ratingselect {
.rating-type {
padding: 18px 0;
margin: 0 18px;
font-size: 0;
.block {
display: inline-block;
padding: 8px 12px;
margin-right: 8px;
line-height: 16px;
border-radius: 1px;
font-size: 12px;
color: rgb(77, 85, 93);
&.active {
color: #fff;
}
.count {
margin-left: 2px;
font-size: 12px;
}
&.positive {
background: rgba(0, 160, 220, 0.2);
&.active {
background: rgb(0, 160, 220);
}
}
&.negative {
background: rgba(77, 85, 93, 0.2);
&.active {
background: rgb(77, 85, 93);
}
}
}
}
.switch {
display: flex;
align-items: center;
padding: 12px 18px;
line-height: 24px;
border-bottom: 1px solid rgba(7, 17, 27, 0.1);
color: rgb(147, 153, 159);
font-size: 0;
svg {
margin-right: 5px;
fill: #e8e8e8;
}
&.on {
.check {
fill: #76d572;
}
}
.icon-check_circle {
display: inline-block;
vertical-align: top;
margin-right: 4px;
font-size: 24px;
}
.text {
display: inline-block;
vertical-align: top;
font-size: 12px;
}
}
}
</style>
<template>
<div class="seller-page">
<div class="logo">
<img
:src="banner"
alt="">
</div>
<h2>{{ seller.name }}</h2>
<p>{{ seller.bulletin }}</p>
<a
:href="seller.brandstory"
class="brandstory">查看品牌故事</a>
<div class="placeholder"/>
<h2>配送信息</h2>
<p>由蜂鸟快送提供配送,约{{ seller.deliveryTime }}分钟送达,距离2.1km</p>
<p>配送费¥{{ seller.deliveryPrice }}</p>
</div>
</template>
<script>
import config from "~/config";
export default {
props: {
seller: {
default: {}
}
},
computed: {
banner: function () {
return config.IMG_URL + this.seller.banner;
}
}
};
</script>
<style lang="scss">
@import "../../../assets/styles/mixin";
.seller-page {
background: #fff;
padding-bottom: px2rem(30px);
.logo {
padding: px2rem(30px) px2rem(30px) 0 px2rem(30px);
}
h2 {
font-size: px2rem(32px);
margin-top: px2rem(40px);
padding: 0 px2rem(30px) px2rem(20px) px2rem(30px);
}
p {
padding: 0 px2rem(30px);
color: #666;
font-size: px2rem(26px);
line-height: 1.5;
}
.brandstory {
display: block;
line-height: px2rem(100px);
margin-top: px2rem(50px);
color: #666;
font-size: px2rem(28px);
text-align: center;
}
.placeholder {
height: px2rem(20px);
background: #f5f5f5;
}
}
</style>
This diff is collapsed.
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
@next="next" @next="next"
@change="changeBanner" @change="changeBanner"
@click="bannerClick"/> @click="bannerClick"/>
<div class="main-padding">{{ totalCount }}款车型</div>
<ul <ul
v-if="dataDetail.length" v-if="dataDetail.length"
id="scroll-area" id="scroll-area"
...@@ -59,7 +58,7 @@ ...@@ -59,7 +58,7 @@
class="loading">加载中……</p> class="loading">加载中……</p>
<p <p
v-if="touchend" v-if="touchend"
class="empty_data">——没有更多了——</p> class="empty_data">——{{ totalCount }}款车型——</p>
<go-top/> <go-top/>
<Footer v-if="touchend"/> <Footer v-if="touchend"/>
</div> </div>
......
...@@ -254,7 +254,7 @@ ...@@ -254,7 +254,7 @@
if(path == '/vehicleDetail'){ if(path == '/vehicleDetail'){
var menuTop = document.querySelector('#nav').offsetTop; var menuTop = document.querySelector('#nav').offsetTop;
//滑动到指定位置菜单吸顶 //滑动到指定位置菜单吸顶
if (scrollTop > menuTop-45) { if (scrollTop > menuTop+180) {
this.searchBarFixed = true; this.searchBarFixed = true;
} }
...@@ -263,17 +263,17 @@ ...@@ -263,17 +263,17 @@
var top2 = document.querySelector('#lastestDubbing').offsetTop; var top2 = document.querySelector('#lastestDubbing').offsetTop;
var top3 = document.querySelector('#rankLlistDetail').offsetTop; var top3 = document.querySelector('#rankLlistDetail').offsetTop;
var top4 = document.querySelector('#modelsDetails').offsetTop; var top4 = document.querySelector('#modelsDetails').offsetTop;
if (scrollTop < top1-110) { if (scrollTop < top1+180) {
this.active = 'activity'; this.active = 'activity';
this.searchBarFixed = false; this.searchBarFixed = false;
} }
if (scrollTop < top2-110) { if (scrollTop < top2+180) {
this.active = 'activity'; this.active = 'activity';
} else if (scrollTop >= top2-110 && scrollTop < top3-110) { } else if (scrollTop >= top2+180 && scrollTop < top3+180) {
this.active = 'lastest'; this.active = 'lastest';
} else if (scrollTop >= top3-110 && scrollTop < top4-110) { } else if (scrollTop >= top3+180 && scrollTop < top4+180) {
this.active = 'rank'; this.active = 'rank';
} else if (scrollTop >= top4-110) { } else if (scrollTop >= top4+180) {
this.active = 'model'; this.active = 'model';
} }
} }
...@@ -283,9 +283,9 @@ ...@@ -283,9 +283,9 @@
let top1 = document.querySelector('#lastestDubbing').offsetTop; let top1 = document.querySelector('#lastestDubbing').offsetTop;
let top = document.querySelector('#activityIntro').offsetTop; let top = document.querySelector('#activityIntro').offsetTop;
if(this.searchBarFixed){ if(this.searchBarFixed){
document.documentElement.scrollTop = top1 - 105; document.documentElement.scrollTop = top1 +180;
} else { } else {
document.documentElement.scrollTop = top-37; document.documentElement.scrollTop = top1+130;
} }
this.searchBarFixed = true; this.searchBarFixed = true;
}, },
...@@ -295,9 +295,9 @@ ...@@ -295,9 +295,9 @@
let top = document.querySelector('#nav').offsetTop; let top = document.querySelector('#nav').offsetTop;
var top1 = document.querySelector('#activityIntro').offsetTop; var top1 = document.querySelector('#activityIntro').offsetTop;
if(this.searchBarFixed){ if(this.searchBarFixed){
document.documentElement.scrollTop = top1-105; document.documentElement.scrollTop = top1 +180;
} else { } else {
document.documentElement.scrollTop = top-88; document.documentElement.scrollTop = top1 +130;
} }
this.searchBarFixed = true; this.searchBarFixed = true;
}, },
...@@ -306,9 +306,9 @@ ...@@ -306,9 +306,9 @@
this.active = "rank"; this.active = "rank";
let top1 = document.querySelector('#rankLlistDetail').offsetTop; let top1 = document.querySelector('#rankLlistDetail').offsetTop;
if(this.searchBarFixed){ if(this.searchBarFixed){
document.documentElement.scrollTop = top1 - 105; document.documentElement.scrollTop = top1 +180;
} else { } else {
document.documentElement.scrollTop = top1-160; document.documentElement.scrollTop = top1 +130;
} }
this.searchBarFixed = true; this.searchBarFixed = true;
}, },
...@@ -317,9 +317,9 @@ ...@@ -317,9 +317,9 @@
this.active = "model"; this.active = "model";
let top1 = document.querySelector('#modelsDetails').offsetTop; let top1 = document.querySelector('#modelsDetails').offsetTop;
if(this.searchBarFixed){ if(this.searchBarFixed){
document.documentElement.scrollTop = top1 - 105; document.documentElement.scrollTop = top1 +180;
} else { } else {
document.documentElement.scrollTop = top1-160; document.documentElement.scrollTop = top1+130;
} }
this.searchBarFixed = true; this.searchBarFixed = true;
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment