Files
jdt-user/src/pages/cart/index.vue
2023-11-28 17:59:45 +08:00

358 lines
7.9 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>
<view v-if="list.length > 0">
<nut-cell-group v-for="(itm, idx) in list" :key="idx">
<nut-cell>
<nut-checkbox
v-model="itm.state.checkbox"
:indeterminate="itm.state.indeterminate"
@change="(val: boolean) => changeBoxAll(val,idx)"
>{{ itm.StoreName }}
</nut-checkbox>
</nut-cell>
<nut-checkbox-group
v-model="itm.state.checkboxgroup"
:ref="(el) => getGroup(el, idx)"
@change="(label) => changeBox(label, itm)"
>
<nut-cell v-for="(item, idx1) in itm.Goods" :key="idx1">
<nut-checkbox :label="item.gid" style="width: 10%"></nut-checkbox>
<view class="box">
<view class="box-left">
<img class="cover" :src="item.cover" alt="" />
<view class="center">
<view>{{ item.name }}</view>
<view class="price">
<view>{{ item.price }} </view>
<view>{{ item.exchange }} 积分</view>
</view>
</view>
</view>
<nut-input-number
v-model="item.number"
readonly
:min="-1"
@add.stop="() => onAdd(item)"
@reduce.stop="() => onReduce(item)"
/>
</view>
</nut-cell>
</nut-checkbox-group>
</nut-cell-group>
</view>
<nut-empty v-else description="购物车暂无数据"></nut-empty>
<view>
<view style="height: 100rpx"></view>
</view>
<view class="bottom-box">
<view class="left">
<!-- <nut-checkbox v-model="selectAllVal" @change="selectAll"
>全选
</nut-checkbox> -->
<view>
<view class="text-box">
总金额
<nut-price
v-model:price="localCount.price"
size="normal"
:need-symbol="false"
/>
</view>
<view class="text-box">
总积分
<nut-price
v-model:price="localCount.exchange"
size="normal"
:need-symbol="false"
/>
</view>
</view>
</view>
<nut-button type="primary" @click="sub">去结算</nut-button>
</view>
<!-- 支付 -->
<Pay
:is-show-pay="isShowPay"
:interval="true"
v-model:jfInfo="orderData"
@closePay="closePay"
/>
</view>
</template>
<script lang="ts" setup>
import { nextTick, ref } from "vue";
import Taro from "@tarojs/taro";
import { addCart, getAllCart } from "@/api/cart";
import { createActiveOrder } from "@/api/goods";
import Pay from "@/components/Pay.vue";
interface CardList {
name: string;
cover: string;
bid: string;
gid: string;
number: string;
price: number;
exchange: number;
}
// const selectAllVal = ref(false);
interface List {
StoreName: string;
Goods: CardList[];
state: {
checkbox: boolean;
indeterminate: boolean;
checkboxgroup: string[];
};
}
const list = ref<List[]>([]);
const groupList = ref(new Map());
const localCount = ref({
price: 0,
exchange: 0,
});
const getGroup = (el: any, idx: number) => {
return groupList.value.set(idx, el);
};
const changeBoxAll = async (value: boolean, idx: number) => {
await nextTick(() => {
groupList.value.get(idx).toggleAll(value);
});
};
const changeBox = (label: string[], item: any) => {
localCount.value = {
price: 0,
exchange: 0,
};
item["Count"] = {
priceCount: 0,
exchangeCount: 0,
};
if (label.length > 0) {
label.forEach((id: string) => {
item.Goods.forEach((itm: any) => {
if (itm.gid === id) {
item["Count"].priceCount += itm.price * itm.number;
item["Count"].exchangeCount += itm.exchange * itm.number;
}
});
});
}
list.value.forEach((item: any) => {
localCount.value.price += item.Count.priceCount;
localCount.value.exchange += item.Count.exchangeCount;
});
if (label.length === item.Goods.length) {
item.state.checkbox = true;
item.state.indeterminate = false;
} else if (label.length && label.length < item.Goods.length) {
item.state.indeterminate = true;
} else {
item.state.indeterminate = false;
item.state.checkbox = false;
}
};
Taro.useDidShow(() => {
getList();
});
// const selectAll = () => {
// localCount.value = {
// price: 0,
// exchange: 0,
// };
// groupList.value.forEach((item: any) => {
// item.toggleAll(selectAllVal.value);
// });
// list.value.forEach((item: any) => {
// if (item.state.checkboxgroup.length > 0) {
// item.Goods.forEach((itm: any) => {
// localCount.value.price += itm.price;
// localCount.value.exchange += itm.exchange;
// });
// }
// });
// };
const isShowPay = ref(false);
const orderData = ref<any>([]);
const sub = async () => {
const arr: any = list.value.filter(
(item: any) => item.state.checkboxgroup.length > 0
);
if (arr.length === 0) {
Taro.showToast({
title: "请选择商品",
icon: "none",
});
return;
}
try {
const { data: res } = await createActiveOrder({
Bid: arr.map((item: any) => item.StoreBid),
});
if (res.oid) {
orderData.value = res?.oid;
isShowPay.value = true;
}
} catch (e) {
Taro.showToast({
title: e.msg,
icon: "none",
});
}
};
const closePay = async (val: boolean) => {
isShowPay.value = val;
orderData.value = [];
await getList();
Taro.navigateTo({
url: "/pages/users/order_list/index?type=0",
});
};
const getList = async () => {
localCount.value = {
price: 0,
exchange: 0,
};
const res = await getAllCart();
list.value = res.data.data || [];
if (list.value.length > 0) {
list.value = list.value.map((item: any) => ({
...item,
Goods: item.Goods.sort(
(a: CardList, b: CardList) => Number(a.gid) - Number(b.gid)
),
state: {
indeterminate: false,
checkbox: false,
checkboxgroup: [],
},
Count: {
priceCount: 0,
exchangeCount: 0,
},
}));
}
};
// const toPage = () => {
// Taro.switchTab({
// url: "/pages/index/index",
// });
// };
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);
};
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 getList();
} catch (e) {
Taro.showToast({
title: e.msg,
icon: "none",
});
}
};
</script>
<style lang="scss">
.index {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
}
.box {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.box-left {
display: flex;
align-items: center;
.cover {
width: 130rpx;
height: 130rpx;
margin-right: 15rpx;
border-radius: 20rpx;
}
.center {
display: flex;
flex-direction: column;
justify-content: space-around;
.price {
display: flex;
flex-direction: column;
color: red;
}
}
}
}
.bottom-box {
box-sizing: border-box;
background-color: #fff;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 100rpx;
z-index: 9999;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20rpx;
box-shadow: 100rpx 104rpx 288rpx rgba(0, 0, 0, 0.01);
border-top: 1rpx solid #f5f5f5;
.left {
display: flex;
align-items: center;
.text-box {
margin-left: 10rpx;
}
}
}
</style>