Files
jdt-user/src/components/Cart.vue
Huakk 8f3b158032
All checks were successful
continuous-integration/drone/push Build is passing
wip: 4.0
2024-05-16 14:27:57 +08:00

380 lines
8.5 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.

<script setup lang="ts">
import {ref} from 'vue';
import Taro from '@tarojs/taro';
import {addCart, getCart, clearCart} from '@/api/cart';
import {Plus, Minus} from '@nutui/icons-vue-taro';
import {createActiveOrder} from '@/api/goods';
import {createAfterOrder, getUserPoint} from '@/api/admin';
import Pay from '@/components/Pay.vue';
interface CardList {
name: string;
cover: string;
bid: string;
gid: string;
number: string;
price: number;
exchange: number;
}
const show = ref(false);
const props = defineProps({
merInfo: {
required: true,
type: Object,
},
IsPendingOrder: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['updateCart']);
const openModal = async () => {
await get_cart_list();
if (card_list.value.length === 0) return;
show.value = !show.value;
};
const add_cart = async (item: CardList, num: number = 1) => {
try {
const res = await addCart({
Bid: item.bid,
Gid: item.gid,
Number: Number(num),
});
Taro.showToast({
title: res.msg,
icon: 'none',
});
await get_cart_list();
} catch (e) {
Taro.showToast({
title: e.msg,
icon: 'none',
});
}
};
const onAdd = async (item: CardList) => {
await add_cart(item, Number(item.number) + 1);
};
const onReduce = async (item: CardList) => {
await add_cart(item, Number(item.number) - 1);
if (card_list.value.length === 0) show.value = false;
};
const card_list = ref<CardList[]>([]);
const cartInfo = ref({
count: 0,
price: 0,
exchange: 0,
});
const get_cart_list = async () => {
try {
const res = await getCart({
Bid: props.merInfo.bid,
});
card_list.value = res.data.data || [];
cartInfo.value = {
count: 0,
price: 0,
exchange: 0,
};
card_list.value.forEach((item: CardList) => {
cartInfo.value.count += Number(item.number);
cartInfo.value.price += Number(item.price);
cartInfo.value.exchange += Number(item.exchange);
});
emit('updateCart', res.data.data || []);
} catch (e) {
Taro.showToast({
title: e.msg,
icon: 'none',
});
}
};
const clear_cart = async () => {
try {
await clearCart({
Bid: props.merInfo.bid,
});
await get_cart_list();
} catch (e) {
Taro.showToast({
title: e.msg,
icon: 'none',
});
}
show.value = false;
};
const isShowPay = ref(false);
const orderData = ref<any>([]);
const closePay = (val: boolean) => {
isShowPay.value = val;
orderData.value = [];
Taro.redirectTo({
url: '/pages/users/order_list/index?type=0',
});
};
const create_order = async () => {
try {
show.value = false;
let res;
if (props.IsPendingOrder) {
const data = props.merInfo;
delete data.$taroTimestamp;
delete data.type;
res = await createAfterOrder(data);
await get_cart_list();
Taro.navigateTo({
url: `/pages/admin/add_order/pending_order/pending_order_detail/index?oid=${res.data.oid}&bid=${props.merInfo.bid}`,
});
} else {
const mer_info = Taro.getStorageSync('mer_info');
const user_info = Taro.getStorageSync('userInfo');
const data = await getUserPoint({
phone: user_info.data.phone,
bid: mer_info.bid,
});
res = await createActiveOrder({
Bid: [props.merInfo.bid],
custID: data.data.store_user_id,
});
if (res.data.oid) {
orderData.value = {
jh_info: data.data,
oid: res.data.oid,
};
// isShowPay.value = true;
Taro.navigateTo({
url: `/pages/goods/pay/index?oid=${res.data.oid}&bid=${mer_info.bid}`,
});
}
}
Taro.showToast({
title: res.msg,
icon: 'none',
});
} catch (e) {
Taro.showToast({
title: e.msg,
icon: 'none',
});
}
};
defineExpose({
add_cart,
get_cart_list,
});
</script>
<template>
<view>
<view class="cart" @click.stop="openModal">
<view class="container flex items-center">
<!-- <view>购物车数量: {{ cartInfo.count }}</view> -->
<view class="cardImg">
<image
src="http://p1.meituan.net/csc/929f447a96a44b09a09b2e0055433222717.png">
</image>
<view class="count-text" v-if="cartInfo.count > 0">
<text>{{ cartInfo.count }}</text>
</view>
</view>
<view class="ml-1">
<text>总金额: {{ cartInfo.price.toFixed(2) }}</text>
<text v-if="!IsPendingOrder"
>总积分: {{ cartInfo.exchange.toFixed(2) }}</text
>
</view>
</view>
<view v-if="cartInfo.count > 0" class="payBtn" @click.stop="create_order"
>去结算</view
>
</view>
<!-- 购物车弹窗 -->
<nut-popup
:style="{padding: '15px'}"
round
position="bottom"
z-index="1"
:catch-move="true"
:safe-area-inset-bottom="true"
v-model:visible="show">
<view class="list-header">
<view class="left" @click.stop="clear_cart">
<!-- <Del2 color="#666666" /> -->
<image
class="w-[20px] h-[20px]"
src="http://p0.meituan.net/csc/db4d11fd744b69435c6ffdc6bfc868c5684.png" />
<text class="text-[20px]" style="color: #666666">清空购物车</text>
</view>
</view>
<scroll-view :scroll-y="true" class="cart-list">
<view class="item" v-for="(item, index) in card_list" :key="index">
<view class="left">
<image :src="item.cover" />
<view class="center">
<view class="name">{{ item.name }}</view>
<view class="price flex">
<view>现金:{{ item.price }}</view>
<view class="ml-2">积分:{{ item.exchange }}</view>
</view>
</view>
</view>
<nut-input-number
v-model="item.number"
readonly
:min="-1"
@add="() => onAdd(item)"
@reduce="() => onReduce(item)">
<template #left-icon>
<view class="btn" @click.stop="onReduce(item)">
<Minus />
</view>
</template>
<template #right-icon>
<view class="btn" @click.stop="onAdd(item)">
<Plus />
</view>
</template>
</nut-input-number>
</view>
</scroll-view>
<view style="height: 140px"></view>
</nut-popup>
<!-- 支付 -->
<Pay
:is-show-pay="isShowPay"
v-model:jfInfo="orderData"
@closePay="closePay"
@successPay="closePay" />
</view>
</template>
<style lang="scss">
$h-border-radius: 50px;
.cart {
position: fixed;
bottom: 50px;
left: 50%;
transform: translateX(-50%);
z-index: 9999;
width: 95%;
background-color: #262323;
border-radius: $h-border-radius;
color: #fff;
height: 100px;
display: flex;
justify-content: space-between;
align-items: center;
.container {
margin-left: 30px;
.cardImg {
position: relative;
image {
width: 60px;
height: 60px;
}
.count-text {
position: absolute;
top: -10px;
right: -10px;
background-image: url('http://p0.meituan.net/csc/80b0e11d4270d09324df0b802d4c479b986.png');
background-size: 100% 100%;
// padding: 0 8px;
width: 35px;
height: 35px;
text-align: center;
line-height: 35px;
text {
margin: auto;
font-size: 25px;
}
}
}
}
.payBtn {
width: 200px;
height: 100px;
line-height: 100px;
text-align: center;
background-color: #f83d3d;
border-radius: 0 $h-border-radius $h-border-radius 0;
}
}
.list-header {
margin: 15px 0;
.left {
display: flex;
align-items: center;
}
}
.cart-list {
height: 290px;
.item {
display: flex;
align-items: flex-end;
margin-bottom: 10px;
justify-content: space-between;
.left {
display: flex;
justify-content: space-between;
image {
width: 130px;
height: 130px;
border-radius: 15px;
margin-right: 10px;
}
.center {
height: 130px;
display: flex;
flex-direction: column;
justify-content: space-between;
.price {
color: red;
// margin-bottom: 0px;
}
}
}
}
}
.btn {
background-color: #ff0000;
color: #fff;
border-radius: 50%;
text-align: center;
line-height: 65px;
width: 45px;
height: 45px;
}
</style>