suke-mp/src/pages/mall/subs/shoppingcart/index.vue
Waiting 74dba2ef29 充值页面调整
商品折扣显示逻辑调整
增加公众号跳转修改资料逻辑
2024-05-10 17:51:30 +08:00

334 lines
9.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class='content'>
<view class='c-flex-row'>
<text class='manage' @click.stop='isEditMode = !isEditMode' :style='isEditMode?"color:#F32B2B":"color:#333333"'>
{{ isEditMode ? '退出管理' : '管理' }}
</text>
</view>
<view class='card-view' v-if='totalCount>0'>
<scroll-view>
<view class='c-flex-column' v-for='(item, index) in shoppingCartList' :key='index'>
<view class='c-flex-row'>
<image class='checkbox'
:src='assetsUrl(item.checked?"ic_checkbox_active_red.png":"ic_checkbox_normal.png")'
@click.stop='handleCheck(item)' />
<image class='goods-image' :src='item.images||defaultImage' />
<view class='c-flex-column'>
<text>{{ item.name }}</text>
<view class='c-flex-row'>
<view class='sku-view' @click.stop='showSkuDialog(index)'>
<text>{{ item?.checkedStock?.colorName }}{{ item?.checkedStock?.sizeName }}
x{{ item?.checkedStock?.count }}
</text>
<image :src='assetsUrl("ic_arrow_down_gray.png")' />
</view>
</view>
<text style='margin-top: 50rpx'>
¥{{ (item?.price * ((userInfo.levelEntity?.discount || 100) / 100)).toFixed(2) }}
<text v-if='userInfo.levelEntity?.discount>0&&userInfo.levelEntity?.discount<100'
style='text-decoration: line-through;color: #999999;font-size: 25rpx'>¥{{ item?.price }}
</text>
</text>
<view class='count-change-view c-flex-row'>
<view class='count-image' @click.stop='countChange(index,false)'>
<image :src='assetsUrl("ic_reduce.png")' />
</view>
<text>{{ item?.checkedStock?.count || 0 }}</text>
<view class='count-image' @click.stop='countChange(index,true)'>
<image :src='assetsUrl("ic_plus.png")' />
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<u-empty v-else text='暂无数据' margin-top='100' />
<view class='bottom-view c-flex-row'>
<view class='c-flex-row' @click.stop='handleAllCheck'>
<image :src='assetsUrl(checkedAll?"ic_checkbox_active.png":"ic_checkbox_normal.png")' />
<text>全选</text>
</view>
<view style='flex: 1' />
<text v-if='isEditMode' class='settlement' @click.stop='deleteShoppingCart'>删除</text>
<view v-else class='c-flex-row'>
<text>合计
<text>{{ totalPayPrice.toFixed(2) }}</text>
</text>
<text class='settlement' @click.stop='settlement'>结算</text>
</view>
</view>
</view>
<sku-dialog ref='skuDialogRef' :bean='temporaryGoodsBean' :exists='temporaryStockBean' />
</template>
<script lang='ts' setup>
import { assetsUrl, defaultImage } from '@/utils/assets';
import useShoppingCartStore from '@/store/modules/shoppingcart';
import { goPath, showToast } from '@/utils';
import { GoodsBean, StockBean } from '@/api/goods/types';
import SkuDialog from '@/components/sku-dialog.vue';
import { ref } from 'vue';
import { useUserStore } from '@/store';
const isEditMode = ref(false);
const checkedAll = ref(false);
const shoppingCartStore = useShoppingCartStore();
const { shoppingCartList, totalCount } = storeToRefs(shoppingCartStore);
const userStore = useUserStore();
const { userInfo } = storeToRefs(userStore);
const skuDialogRef = ref();
const temporaryGoodsBean = ref<GoodsBean>();
const temporaryStockBean = ref<StockBean>();
const totalPayPrice = computed(() => {
return shoppingCartList.value.filter(res => res.checked).reduce((a, b) => a + b.consumePrice * b.checkedStock.count, 0) || 0;
});
const handleCheck = (item: any) => {
item.checked = !item.checked;
if(!item.checked) {
checkedAll.value = false;
} else {
checkedAll.value = shoppingCartList.value.every(res => res.checked);
}
};
const handleAllCheck = () => {
checkedAll.value = !checkedAll.value;
shoppingCartList.value.forEach(res => {
res.checked = checkedAll.value;
});
};
const deleteShoppingCart = () => {
shoppingCartStore.deleteIfChecked();
checkedAll.value = false;
isEditMode.value = false;
};
const showSkuDialog = (index: number) => {
new Promise((resolve, _) => {
temporaryGoodsBean.value = shoppingCartList.value[index];
temporaryStockBean.value = shoppingCartList.value[index].checkedStock;
resolve(temporaryGoodsBean.value);
}).then((res: any) => {
skuDialogRef.value.show(res.id, (e: GoodsBean) => {
//重新选择sku后判断当前购物中是否存在相同sku的商品
const existsIndex = shoppingCartStore.getSameGoodsIndex(res?.id || '', e.checkedStock.colorId, e.checkedStock.sizeId);
//不存在则更新当前商品sku
if(existsIndex < 0) {
shoppingCartStore.updateStock(index, e.checkedStock);
}
//如果已存在,则更新已存在商品数量,并删除当前商品
else {
shoppingCartStore.updateCount(existsIndex, e.checkedStock.count - (temporaryGoodsBean?.value?.checkedStock?.count || 0));
if(existsIndex != index) {
shoppingCartStore.delete(index);
}
}
});
});
};
const countChange = (index: number, isPlus: Boolean) => {
if(isPlus) {
shoppingCartStore.updateCount(index, 1);
} else {
if(shoppingCartList.value[index].checkedStock.count > 1) {
shoppingCartStore.updateCount(index, -1);
}
}
};
const settlement = () => {
if(shoppingCartList.value.filter(res => res.checked).length == 0) {
showToast('请选择商品');
return;
}
const orderBean = {
totalPrice: totalPayPrice.value,
orderGoods: shoppingCartList.value.filter(res => res.checked)
};
goPath(`/pages/mall/subs/order/order-confirm?orderBean=${encodeURIComponent(JSON.stringify(orderBean))}`);
};
</script>
<style lang='scss' scoped>
.content {
position: relative;
.manage {
width: 100%;
font-weight: 400;
font-size: 30rpx;
color: #333333;
background: #FFFFFF;
align-self: flex-end;
padding: 20rpx 30rpx;
text-align: end;
}
.card-view {
margin: 30rpx 30rpx 180rpx 30rpx;
border-radius: 10rpx;
background: #FFFFFF;
padding: 10rpx 20rpx 10rpx 17rpx;
.c-flex-column:nth-of-type(1) {
margin: 20rpx 0;
}
view:nth-of-type(1) {
.checkbox {
width: 35rpx;
height: 35rpx;
margin-right: 20rpx;
}
.goods-image {
width: 186rpx;
height: 186rpx;
border-radius: 10rpx;
}
.c-flex-column {
flex: 1;
height: 186rpx;
margin-left: 20rpx;
position: relative;
text:nth-of-type(1) {
font-weight: 400;
font-size: 30rpx;
color: #333333;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
overflow: hidden;
}
.sku-view {
display: flex;
flex-direction: row;
position: relative;
background: #F2F2F2;
margin-top: 10rpx;
align-items: center;
border-radius: 22rpx;
padding: 5rpx 20rpx;
text {
font-weight: 400;
font-size: 24rpx;
color: #999999;
}
image {
width: 20rpx;
height: 20rpx;
margin-left: 13rpx;
}
}
text:nth-of-type(2) {
display: flex;
font-weight: bold;
font-size: 32rpx;
color: #333333;
margin-top: 20rpx;
}
.count-change-view {
position: absolute;
right: 0;
bottom: 0;
.count-image {
display: flex;
align-items: center;
justify-content: center;
width: 54rpx;
height: 54rpx;
background: #FBFBFB;
image {
width: 15rpx;
height: 2rpx;
}
}
.count-image:nth-of-type(2) image {
width: 17rpx;
height: 17rpx;
}
text {
display: flex;
width: 54rpx;
height: 54rpx;
align-items: center;
justify-content: center;
font-weight: 400;
font-size: 30rpx;
color: #333333;
background: #F2F2F2;
}
}
}
}
}
.bottom-view {
background: #FFFFFF;
position: fixed;
padding: 12rpx 30rpx 78rpx 30rpx;
bottom: 0;
left: 0;
right: 0;
image {
width: 35rpx;
height: 35rpx;
}
.c-flex-row:nth-of-type(1) {
text {
margin-left: 10rpx;
font-size: 28rpx;
color: #333333;
}
}
text:nth-of-type(1) {
font-size: 30rpx;
text {
font-weight: bold;
font-size: 36rpx;
color: #F32B2B;
}
}
.settlement {
display: flex;
background: #F32B2B;
border-radius: 43rpx;
padding: 17rpx 75rpx;
font-weight: bold;
font-size: 30rpx;
color: #FFFFFF;
margin-left: 37rpx;
align-items: center;
justify-content: center;
}
}
}
</style>