358 lines
7.9 KiB
Vue
358 lines
7.9 KiB
Vue
<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>
|