template-project/components/shopping-carts/cart-slide.vue

363 lines
12 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view>
<view class="slide-box mar-x20 animated" v-for="(item, index) in listData" :key="index" :class="item.ifExit ? 'fadeInUp' : 'fadeOutDown'" :style="{display: item.ifShow ? 'flex' : 'none'}">
<view class="slide-list"
@touchstart="touchStart($event, index)"
@touchend="touchEnd($event, index)"
@touchmove="touchMove($event, index)"
@tap="recover(index)"
:style="{ transform: 'translate3d(' + item.slide_x + 'px, 0, 0)' }">
<view class="now-message-info" :style="{ width: windowWidth + 'px' }" @click="clickItemMethod(item)">
<view class="mo-item flexs" @tap.stop="chooseEv(index)" :class="item.ifcheck ? 'active-item' : ''"></view>
<view class="shopp-img imgH mar-zy20" @tap.stop="chooseEv(index)">
<image class="shopp-img imgH width100" :src="item.image" mode="aspectFill"></image>
</view>
<view class="imgH disjb fc fon24 width100">
<view class="">
<view class="fon28 bold clips2">{{item.title}}</view>
<view class="clips2 line-h40">{{item.content}}</view>
</view>
<view class="disjbac">
<!-- 商品价格 -->
<view class="fon24">¥:<span class="fon28 colf8 bold">{{$toolAll.tools.addXiaoShu(item.price)}}</span></view>
<!-- 商品数量 -->
<view class="disac">
<!-- 减数量 -->
<i class="icon icon-cut countBtn disjcac" @tap.stop="addCutEv(index,0)" :style="{backgroundColor: item.num==minNum || item.slide_x!=0 ? '#cccccc' : '#000000'}"></i>
<!-- 实际数量 -->
<input type="digit" @blur="blurEv(index,$event)" @focus="focusEv(item.num)" class="fon24 tcenter countInput" :disabled="item.slide_x!=0" v-model="item.num">
<!-- 加数量 -->
<i class="icon icon-add countBtn disjcac" @tap.stop="addCutEv(index,1)" :style="{backgroundColor: item.num==maxNum || item.slide_x!=0 ? '#cccccc' : '#000000'}"></i>
</view>
</view>
</view>
</view>
<view class="group-btn">
<view class="btn-div" v-for="(value, key) in button" :key="key"
@tap.stop="clickMethod(item, value, index,key)" :style="{background: value.background}">
{{value.title}}
</view>
</view>
</view>
</view>
<!-- 底部导航 -->
<view class="disjbac cart-foot-box fon24">
<view>合计:<span class="fon38 colf8 bold">{{allPrice}}</span></view>
<view class="fon38 cart-submit-btn" :style="{backgroundColor: !delNum ? '#cccccc' : '#FF0000'}" @tap="submitEv">{{allPrice=='0.00' ? '去购物' : '去结算'}}</view>
</view>
<nothing-page v-if="!ifLoading && !listData.length" content="你的购物车:这也空空,那也空空(*^▽^*)"></nothing-page>
</view>
</template>
<script>
export default {
name: 'mark-slide-list',
props: {
list: { //数据list
type: Array,
default () {
return [
{id: 1,image: 'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',title: '标题',content: '描述描述描述描述描述描述',slide_x: 0,price:199,num:1,ifcheck:false,ifExit:true,ifShow:true},
{id: 1,image: 'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',title: '标题',content: '描述描述描述描述描述描述',slide_x: 0,price:199,num:1,ifcheck:false,ifExit:true,ifShow:true},
{id: 1,image: 'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',title: '标题',content: '描述描述描述描述描述描述',slide_x: 0,price:199,num:1,ifcheck:false,ifExit:true,ifShow:true},
{id: 1,image: 'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',title: '标题',content: '描述描述描述描述描述描述',slide_x: 0,price:199,num:1,ifcheck:false,ifExit:true,ifShow:true},
{id: 1,image: 'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',title: '标题',content: '描述描述描述描述描述描述',slide_x: 0,price:199,num:1,ifcheck:false,ifExit:true,ifShow:true},
{id: 1,image: 'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',title: '标题',content: '描述描述描述描述描述描述',slide_x: 0,price:199,num:1,ifcheck:false,ifExit:true,ifShow:true},
];
}
},
button: { //按钮数据list
type: Array,
default () {
return [
{title: '分享',background: '#c4c7cd'},
{title: '删除',background: '#ff3b32'}
];
}
},
},
computed: {
windowWidth() {
return uni.getSystemInfoSync().windowWidth - 20;
},
// 总价及合计
allPrice() {
let allPrice = 0;
this.listData.forEach(item=>{
if(item.ifcheck) {
allPrice += this.$toolAll.tools.operationEv(item.price,item.num,'*',2)*1;
}
})
return this.$toolAll.tools.addXiaoShu(allPrice);
},
// 要删除的数量
delNum() {
let delNum = 0;
this.listData.forEach(item=>{
if(item.ifcheck) {
delNum += 1;
}
})
return delNum;
}
},
data() {
return {
listData: [],
start_slide_x: 0,
btnWidth: 0,
startX: 0,
LastX: 0,
startTime: 0,
itemIndex: 0,
ifSelectAll:false,//是否全选
originalNum:0,//当前输入框原值
maxNum:20,//最大可输入数量
minNum:1,//最小可输入数量
ifLoading:true
};
},
mounted() {
this.listData = this.list;
this.ifLoading = false;
},
methods: {
// 去购物、去结算、删除
submitEv(){
if(this.allPrice=='0.00') {
// 去购物
console.log('去购物');
} else {
// 去结算
console.log('去结算');
}
},
// 选中事件
chooseEv(index) {
this.listData[index].ifcheck = !this.listData[index].ifcheck;
},
// 去商品详情事件
goDetail(id){
uni.navigateTo({
url:''
})
},
// 数量加减事件
addCutEv(index,num) {
if(this.listData[index].slide_x==0){
if(num) {
// 加 ,如果当前商品数量不等于最大值
if(this.listData[index].num != this.maxNum) {
this.listData[index].num++;
}
} else {
// 减 ,如果当前商品数量大于最小值
if(this.listData[index].num > this.minNum) {
this.listData[index].num--;
}
}
console.log(this.allPrice,'总价');
}
},
// 输入框获取焦点事件
focusEv(num) {
// 储存当前商品的原始数值
this.originalNum = num;
},
// 输入框失去焦点事件
blurEv(index,e) {
// 失去焦点时,获取当前输入框里的数值
let currentNum = e.detail.value*1;
// 如果当前输入框的值不等于0或空并且当前输入框的值大于最大值当前商品的数量 = 最大值, 否则为当前输入框输入的值
this.listData[index].num = currentNum ? currentNum > this.maxNum ? this.maxNum : currentNum : this.originalNum;
},
clone(data) {
const type = typeof data
let obj;
if (type === 'array') {
obj = [];
} else if (type === 'object') {
obj = {};
} else {
// 不再具有下一层次
return data;
}
if (type === 'array') {
for (let i = 0, len = data.length; i < len; i++) {
obj.push(this.clone(data[i]));
}
} else if (type === 'object') {
// 对原型上的方法也拷贝了....
for (const key in data) {
obj[key] = this.clone(data[key]);
}
}
return obj;
},
// 滑动开始
touchStart(e, index) {
if (this.itemIndex == index) {
this.itemIndex = index
}
//记录手指放上去的时间
this.startTime = e.timeStamp;
//记录滑块的初始位置
this.start_slide_x = this.listData[index].slide_x;
// 按钮宽度
//#ifdef MP-WEIXIN
uni.createSelectorQuery().in(this).selectAll('.group-btn').boundingClientRect(res => {
if (res != null) {
this.btnWidth = res[index].width * -1;
}
}).exec();
//#endif
//#ifdef H5 || APP-PLUS
uni.createSelectorQuery()
.selectAll('.group-btn')
.boundingClientRect()
.exec(res => {
if (res[0] != null) {
this.btnWidth = res[0][index].width * -1;
}
});
//#endif
// 记录上一次开始时手指所处位置
this.startX = e.touches[0].pageX;
// 记录上一次手指位置
this.lastX = this.startX;
//初始化非当前滑动消息列的位置
for (var i in this.listData) {
if (index != i) {
this.listData[i].slide_x = 0;
}
}
},
// 滑动中
touchMove(e, index) {
const endX = e.touches[0].pageX;
const distance = endX - this.lastX;
// 预测滑块所处位置
const duang = this.listData[index].slide_x + distance;
// 如果在可行区域内
if (duang <= 0 && duang >= this.btnWidth) {
this.listData[index].slide_x = duang;
}
// 此处手指所处位置将成为下次手指移动时的上一次位置
this.lastX = endX;
},
// 滑动结束
touchEnd(e, index) {
let distance = 10;
const endTime = e.timeStamp;
const x_end_distance = this.startX - this.lastX;
if (Math.abs(endTime - this.startTime) > 200) {
distance = this.btnWidth / -2;
}
// 判断手指最终位置与手指开始位置的位置差距
if (x_end_distance > distance) {
this.listData[index].slide_x = this.btnWidth;
} else if (x_end_distance < distance * -1) {
this.listData[index].slide_x = 0;
} else {
this.listData[index].slide_x = this.start_slide_x;
}
},
// 点击回复原状
recover(index) {
this.listData[index].slide_x = 0;
},
/**
* 点击按钮触发事件
* @param {Object} item 列表数据
* @param {Object} buttonItem 按钮数据
* @param {Object} index 列表数据key
*/
clickMethod(item, buttonItem, index,key) {
// this.$emit("change", item, buttonItem, index);
if(key) {
// 进入删除
// 修改为不存在的商品
this.listData[index].ifExit = false;
// 修改该商品不被选中
this.listData[index].ifcheck = false;
setTimeout(()=>{
// 隐藏该商品
this.listData[index].ifShow = false;
},1000)
setTimeout(()=>{
// 重构数组列表,去除不存在的商品
this.listData = this.listData.filter(item=>item.ifExit==true);
},1000)
}
},
/**
* 点击按钮触发事件
* @param {Object} item 列表数据
*/
clickItemMethod(item) {
this.$emit("click", item)
}
}
};
</script>
<style>
.slide-box {
width: 100%;
overflow: hidden;
border-radius: 10rpx;
}
.slide-list {
transition: all 100ms;
transition-timing-function: ease-out;
min-width: 200%;
}
.now-message-info {
position: relative;
box-sizing: border-box;
display: flex;
align-items: center;
clear: both;
padding: 20rpx;
background: #ffffff;
float: left;
}
.imgH{height: 180rpx;}
.shopp-img{width: 180rpx;border-radius: 10rpx;}
.group-btn {
float: left;
display: flex;
flex-direction: row;
height: 220rpx;
min-width: 100rpx;
align-items: center;
}
.btn-div {
height: 220rpx;
color: #fff;
text-align: center;
padding: 0 50rpx;
font-size: 34rpx;
line-height: 220rpx;
}
.top {
background-color: #c4c7cd;
}
.removeM {
background-color: #ff3b32;
}
.countBtn{font-size: 36rpx;width: 40rpx;height: 40rpx;background-color: #000000;color: #FFFFFF; border-radius: 10rpx;}
.countInput{background-color: #F5F5F5;width: 80rpx;border-radius: 10rpx;padding: 10rpx 0;margin: 0 10rpx;}
.cart-foot-box{position: fixed;bottom: 0;right: 0;left: 0;background-color: #FFFFFF; padding: 20rpx 40rpx;box-shadow: -6rpx 0rpx 10rpx rgba(0, 0, 0, .3);}
.cart-submit-btn{color: #FFFFFF;background-color: #cccccc;padding: 10rpx 40rpx;border-radius: 40rpx;}
.shopping-manage{position: fixed;right: 20rpx;bottom: 320rpx;width: 80rpx;height: 80rpx; border-radius: 100%;background-color: rgba(0, 0, 0, .6);color: #FFFFFF;font-size: 24rpx;display: flex;justify-content: center;align-items: center;}
</style>