Files
jdt-user/src/components/Cart.vue
YuanHuakk 8ca7001e3f
All checks were successful
continuous-integration/drone/push Build is passing
feat(custom): 商家详情整改增加未登录引导弹窗
2025-06-18 21:43:16 +08:00

399 lines
9.0 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;
discount_price: string;
price: number;
exchange: number;
discount_integral: 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,
bid: string = props.merInfo.bid,
) => {
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(bid);
} 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,
discount_price: 0,
exchange: 0,
discount_integral: 0,
});
const get_cart_list = async (bid: string = props.merInfo.bid) => {
try {
const res = await getCart({
Bid: bid,
});
card_list.value = res.data.data || [];
cartInfo.value = {
count: 0,
price: 0,
discount_price: 0,
exchange: 0,
discount_integral: 0,
};
card_list.value.forEach((item: CardList) => {
cartInfo.value.count += Number(item.number);
cartInfo.value.discount_price += Number(item.price);
cartInfo.value.exchange += Number(item.exchange);
cartInfo.value.discount_integral += Number(item.discount_integral);
});
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 user_info = Taro.getStorageSync('userInfo');
const data = await getUserPoint({
phone: user_info.data.phone,
bid: props.merInfo.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=${props.merInfo.bid}&OrderType=1`,
});
}
}
Taro.showToast({
title: res.msg,
icon: 'none',
});
} catch (e) {
if (e.msg === '请先设置交易密码') {
Taro.navigateTo({
url: '/pages/users/pwd/index',
});
}
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="https://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-[28px]">
<text>总金额: {{ cartInfo.discount_price.toFixed(2) }}</text>
<text v-if="!IsPendingOrder"
>积分抵扣: {{ cartInfo.discount_integral.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="https://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 v-if="item.discount_integral > 0" class="ml-2"
>积分:{{ item.discount_integral }}</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('https://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>