鸿宇研学生前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

241 lines
5.1 KiB

<template>
<view class="product"
@touchstart="onTouchstart"
@touchmove="onTouchmove"
@touchend="onTouchend"
>
<image class="product-img" :src="data.image" mode="aspectFill"></image>
<view class="flex flex-column product-info">
<view class="product-info-top">
<view class="product-name text-ellipsis-2">{{ data.name }}</view>
<view class="product-desc text-ellipsis">{{ data.desc }}</view>
</view>
<view class="flex product-info-bottom">
<view class="product-detail">
<view class="flex product-price">
<view class="product-price-val">
<text>¥</text>
<text class="highlight">{{ priceInt }}</text>
<text>{{ `${priceFrac}` }}</text>
</view>
<view class="product-price-bef" v-if="data.originalPrice">
{{ `¥${data.originalPrice}` }}
</view>
</view>
<view class="product-registered">
{{ `${data.registered}人已报名` }}
</view>
</view>
<button class="btn" @click="onRegistrate">报名</button>
</view>
</view>
<button class="flex btn-collect"
:style="collectBtnStyle"
@click.stop="onCollect"
@touchstart.stop="() => {}"
>
<view>{{ isCollected ? '移除收藏' : '收藏' }}</view>
</button>
</view>
</template>
<script>
export default {
props: {
data: {
type: Object,
default() {
return {}
}
},
isCollected: {
type: Boolean,
default: false,
}
},
data() {
return {
isMove: false,
startClientX: null,
displayX: 0,
}
},
computed: {
priceInt() {
return parseInt(this.data.currentPrice)
},
priceFrac() {
return (this.data.currentPrice % this.priceInt).toFixed(2).slice(1)
},
collectBtnStyle() {
const width = this.isCollected ? 80 : 56
const background = this.isCollected ? '#26334E' : '#FF9035'
let display = Math.ceil(this.displayX / this.collectBtnWidth * 100)
display > 100 && (display = 100)
const translateX = 100 - display
return `width: ${width}px; transform: translateX(${translateX}%); background: ${background};`
}
},
methods: {
onTouchstart(e) {
const clientX = e.changedTouches[0].clientX
this.isMove = false
this.startClientX = clientX
this.displayX = 0
},
onTouchmove(e) {
const clientX = e.changedTouches[0].clientX
if (clientX < this.startClientX) {
this.displayX = this.startClientX - clientX
} else {
this.displayX = 0
}
this.isMove = true
},
onTouchend() {
if (this.displayX < 100) {
this.displayX = 0
}
this.isMove = false
},
showCollectBtn() {
this.displayX = 100
},
hiddenCollectBtn() {
this.displayX = 0
},
onCollect() {
console.log('onCollect')
if (this.isCollected) {
// todo: fetch cancel collect
uni.showToast({
icon: 'success',
title: '已移除收藏',
});
} else {
// todo: fetch collect
uni.showToast({
icon: 'success',
title: '已收藏',
});
}
this.hiddenCollectBtn()
},
onRegistrate() {
this.$utils.navigateTo(`/pages_order/product/productDetail?id=${this.data.id}`)
},
},
}
</script>
<style scoped lang="scss">
.product {
position: relative;
height: 464rpx;
background: #FFFFFF;
border: 2rpx solid #FFFFFF;
border-radius: 32rpx;
overflow: hidden;
font-size: 0;
&-img {
width: 100%;
height: 220rpx;
}
&-info {
height: 244rpx;
padding: 16rpx 16rpx 24rpx 16rpx;
box-sizing: border-box;
justify-content: space-between;
&-top {
}
&-bottom {
width: 100%;
justify-content: space-between;
}
}
&-name {
font-size: 28rpx;
font-weight: 500;
color: #000000;
}
&-desc {
margin-top: 8rpx;
font-size: 24rpx;
color: #8B8B8B;
}
&-detail {
}
&-price {
justify-content: flex-start;
align-items: baseline;
column-gap: 12rpx;
&-val {
font-size: 24rpx;
font-weight: 500;
color: #FF4800;
.highlight {
font-size: 32rpx;
}
}
&-bef {
text-decoration: line-through;
font-size: 24rpx;
color: #8B8B8B;
}
}
&-registered {
font-size: 24rpx;
color: #8B8B8B;
}
.btn {
padding: 11rpx 16rpx;
font-size: 26rpx;
font-weight: 500;
color: #FFFFFF;
background: #00A9FF;
border-radius: 24rpx;
}
}
.btn-collect {
position: absolute;
top: 0;
right: 0;
row-gap: 8rpx;
// width: 112rpx;
height: 100%;
font-size: 24rpx;
line-height: 1;
color: #FFFFFF;
// background: #FF9035;
}
</style>